com.gorillalogic.monkeytalk.processor.command.tests.VerifyImageCommandTest.java Source code

Java tutorial

Introduction

Here is the source code for com.gorillalogic.monkeytalk.processor.command.tests.VerifyImageCommandTest.java

Source

/*  MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */
package com.gorillalogic.monkeytalk.processor.command.tests;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;

import com.gorillalogic.monkeytalk.Command;
import com.gorillalogic.monkeytalk.processor.PlaybackResult;
import com.gorillalogic.monkeytalk.processor.PlaybackStatus;
import com.gorillalogic.monkeytalk.processor.Scope;
import com.gorillalogic.monkeytalk.processor.ScriptProcessor;
import com.gorillalogic.monkeytalk.processor.command.VerifyImage;
import com.gorillalogic.monkeytalk.server.JsonServer;
import com.gorillalogic.monkeytalk.utils.Base64;
import com.gorillalogic.monkeytalk.utils.ImageUtils;

public class VerifyImageCommandTest extends BaseCommandHelper {

    File scriptDir;

    @Before
    public void before2() throws IOException {
        this.scriptDir = new File(tempDir(), this.getClass().getSimpleName() + "_scripts");
        if (scriptDir.exists()) {
            scriptDir.delete();
        }
        scriptDir.mkdirs();
    }

    @Test
    public void testWithMissingExpected() throws IOException {
        tempScript("foo.mt", "Device * VerifyImage", scriptDir);

        ScriptProcessor processor = new ScriptProcessor(HOST, PORT, scriptDir);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);
        PlaybackResult result = processor.runScript("foo.mt");

        assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR));
        assertThat(result.getMessage(),
                is("command 'Device * VerifyImage' must have a file path as its first arg"));

        assertThat(output, containsString("START"));
        assertThat(output, containsString(
                "COMPLETE : ERROR : command 'Device * VerifyImage' must have a file path as its first arg"));
    }

    @Test
    public void testWithDirectoryAsExpected() throws IOException {
        String directoryName = "testVerifyWithDirectoryAsExpected_directory";
        File directory = new File(scriptDir, directoryName);
        directory.mkdirs();
        tempScript("foo.mt", "Device * VerifyImage " + directoryName, scriptDir);

        ScriptProcessor processor = new ScriptProcessor(HOST, PORT, scriptDir);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);
        PlaybackResult result = processor.runScript("foo.mt");

        assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR));
        assertThat(result.getMessage(), is("command 'Device * VerifyImage " + directoryName
                + "' - expectedImageFile '" + directoryName + "' is not a regular file, perhaps a folder?"));

        assertThat(output, containsString("START"));
        assertThat(output, containsString("COMPLETE : ERROR : command 'Device * VerifyImage " + directoryName
                + "' - expectedImageFile '" + directoryName + "' is not a regular file, perhaps a folder?"));
    }

    @Test
    public void testWithAbsoluteAsExpected() throws IOException {
        String absoluteName = "/testWithAbsoluteAsExpected_directory/1/2/3/banana.png";
        tempScript("foo.mt", "Device * VerifyImage " + absoluteName, scriptDir);

        ScriptProcessor processor = new ScriptProcessor(HOST, PORT, scriptDir);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);
        PlaybackResult result = processor.runScript("foo.mt");

        assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR));
        assertThat(result.getMessage(),
                is("command 'Device * VerifyImage " + absoluteName + "' - expectedImageFile '" + absoluteName
                        + "' is an absolute path reference"
                        + "' - the expected image file path must be specified relative to the project directory"));

        assertThat(output, containsString("START"));
        assertThat(output,
                containsString("COMPLETE : ERROR : command 'Device * VerifyImage " + absoluteName
                        + "' - expectedImageFile '" + absoluteName + "' is an absolute path reference"
                        + "' - the expected image file path must be specified relative to the project directory"));
    }

    @Test
    public void testWithBadTolerance() throws IOException {
        doTestWithBadTolerance("rewrewrew");
        doTestWithBadTolerance("-1");
        doTestWithBadTolerance("-32876");
        doTestWithBadTolerance("256");
        doTestWithBadTolerance("25632");
        doTestWithBadTolerance("256323398219038209182098312");
        doTestWithBadTolerance("-256323398219038209182098312");
        doTestWithBadTolerance("16.8328");
        doTestWithBadTolerance("-116.8328");
        doTestWithBadTolerance("-0.8328");
        doTestWithBadTolerance(".8328");
        doTestWithBadTolerance("047AFE");
    }

    private void doTestWithBadTolerance(String badTolerance) throws IOException {
        tempScript("foo.mt", "Device * VerifyImage dummy.file " + badTolerance, scriptDir);

        ScriptProcessor processor = new ScriptProcessor(HOST, PORT, scriptDir);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);
        PlaybackResult result = processor.runScript("foo.mt");

        assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR));
        assertThat(result.getMessage(),
                is("command 'Device * VerifyImage dummy.file " + badTolerance + "' - tolerance '" + badTolerance
                        + "' is invalid: must be an integer" + " between " + ImageUtils.MIN_TOLERANCE + " and "
                        + ImageUtils.MAX_TOLERANCE));

        assertThat(output, containsString("START"));
        assertThat(output,
                containsString("COMPLETE : ERROR : command 'Device * VerifyImage dummy.file " + badTolerance
                        + "' - tolerance '" + badTolerance + "' is invalid: must be an integer" + " between "
                        + ImageUtils.MIN_TOLERANCE + " and " + ImageUtils.MAX_TOLERANCE));
    }

    @Test
    public void testWithAgentError() throws IOException {
        doTestWithErrorResponse("Device * VerifyImage testWithAgentError.png", " - SOME ERROR");
    }

    @Test
    public void testWithEmptyAgentMessage() throws IOException {
        doTestWithErrorResponse("Device * VerifyImage testWithEmptyAgentMessage.png", " - no message from agent");
    }

    @Test
    public void testWithNullAgentMessage() throws IOException {
        doTestWithErrorResponse("Device * VerifyImage testWithEmptyAgentMessageOk.png", " - no message from agent");
        doTestWithErrorResponse("Device * VerifyImage testWithEmptyAgentMessageError.png",
                " - no message from agent");
    }

    @Test
    public void testWithFailedScreenshot() throws IOException {
        doTestWithErrorResponse("Device * VerifyImage testWithFailedScreenshot.png",
                " - screenshot could not be taken");
    }

    @Test
    public void testWithMissingScreenshot() throws IOException {
        doTestWithOkResponse("Device * VerifyImage testWithMissingScreenshot.png", " - file '" + scriptDir.getPath()
                + "/testWithMissingScreenshot.png' was not found, creating it with the just-captured image");
        doTestWithOkResponse("Device * VerifyImage testWithMissingImage.png", " - file '" + scriptDir.getPath()
                + "/testWithMissingImage.png' was not found, creating it with the just-captured image");
        doTestWithErrorResponse("Device * VerifyImage testWithMissingScreenshotAndImage.png",
                " - no screenshot received");
    }

    @Test
    public void testWithInvalidScreenshot() throws IOException {
        doTestWithErrorResponse("Device * VerifyImage testWithInvalidScreenshot.png", " - error cropping image");
    }

    @Test
    public void testWithUnparseableCropBounds() throws IOException {
        PlaybackResult result = doTestWithOkResponse("Device * VerifyImage testWithUnparseableCropBounds.png",
                " - file '" + scriptDir.getPath()
                        + "/testWithUnparseableCropBounds.png' was not found, creating it with the just-captured image");

        assertThat(result.getWarning(), containsString("could not parse component rectangle from this string: "));
    }

    @Test
    public void testWithFailedComparison() throws IOException {
        byte[] fff = Base64.decode(GOOD_SCREENSHOT_STRING);
        FileUtils.writeByteArrayToFile(new File(scriptDir, "GOODSCREENSHOT2.PNG"), fff);

        PlaybackResult result = doTestWithFailureResponse("Device * VerifyImage GOODSCREENSHOT2.PNG",
                " - expected and captured images do not match.");
        assertNull(result.getWarning());
    }

    @Test
    public void testWithSuccessfulComparison() throws IOException {
        byte[] fff = Base64.decode(GOOD_SCREENSHOT_STRING);
        FileUtils.writeByteArrayToFile(new File(scriptDir, "GOODSCREENSHOT.PNG"), fff);

        String cmd = "Device * VerifyImage GOODSCREENSHOT.PNG";
        PlaybackResult result = doTestWithOkResponse(cmd, null);
        assertThat(result.getMessage(), is(""));
    }

    @Test
    public void testInvalidComponent() throws IOException {
        File dir = tempDir();
        tempScript("foo.mt", "Fred * VerifyImage fred.png", dir);
        ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir);
        CommandServer server = new CommandServer(PORT);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);

        PlaybackResult result = processor.runScript("foo.mt");

        server.stop();

        assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR));

        assertThat(output, containsString("START"));
        assertThat(output, containsString("Fred * VerifyImage fred.png"));
        // assertThat(output, containsString("Unrecognized component type: Fred"));
    }

    public PlaybackResult doTestWithFailureResponse(String script, String message) throws IOException {
        return doTestWithAgentResponse(script, message, PlaybackStatus.FAILURE);
    }

    public PlaybackResult doTestWithOkResponse(String script, String message) throws IOException {
        return doTestWithAgentResponse(script, message, PlaybackStatus.OK);
    }

    public PlaybackResult doTestWithErrorResponse(String script, String errormessage) throws IOException {
        return doTestWithAgentResponse(script, errormessage, PlaybackStatus.ERROR);
    }

    public PlaybackResult doTestWithAgentResponse(String script, String errormessage, PlaybackStatus expectedStatus)
            throws IOException {

        String host = "localhost";
        int port = 5432;
        // tempScript("foo.mt", script, scriptDir);
        Command command = new Command(script);

        ScriptProcessor processor = new ScriptProcessor(host, port, scriptDir);
        processor.setPlaybackListener(LISTENER_WITH_OUTPUT);

        VerifyImageServer agentMock = new VerifyImageServer(port);
        PlaybackResult result = null;
        try {
            Scope scope = new Scope();
            scope.setCurrentCommand(command);
            result = new VerifyImage(command, scope, LISTENER_WITH_OUTPUT, processor, scriptDir).verifyImage();
        } finally {
            agentMock.stop();
        }

        assertThat("FAIL: " + result, result.getStatus(), is(expectedStatus));

        if (errormessage != null) {
            String _errormessage = "command '" + script + "'" + errormessage;
            assertThat(result.getMessage(), is(_errormessage));
            assertThat(output, containsString(expectedStatus.name() + " : " + _errormessage));

        }

        assertThat(agentMock.getCommands().toString(), containsString(script));

        return result;
    }

    public static class CommandServer extends JsonServer {
        private List<Command> commands;
        private List<String> jsons;

        public CommandServer(int port) throws IOException {
            super(port);
            commands = new ArrayList<Command>();
            jsons = new ArrayList<String>();
        }

        /**
         * Get the list of all captured MonkeyTalk commands.
         * 
         * @return the commands
         */
        public List<Command> getCommands() {
            return commands;
        }

        /**
         * Get the list of all captured MonkeyTalk commands in their raw JSON format.
         * 
         * @return the commands
         */
        public List<String> getRawJSONCommands() {
            return jsons;
        }

        @Override
        public Response serve(String uri, String method, Map<String, String> headers, JSONObject json) {

            jsons.add(json.toString());
            Command cmd = new Command(json);

            // ignore blank commands (aka PINGs)
            if (!"* * *".equals(cmd.toString())) {
                commands.add(new Command(json));
            }

            return new Response(HttpStatus.OK, "{result:\"OK\"}");
        }
    }

    private static class VerifyImageServer extends CommandServer {
        VerifyImageServer(int port) throws IOException {
            super(port);
        }

        @Override
        public Response serve(String uri, String method, Map<String, String> headers, JSONObject json) {
            super.serve(uri, method, headers, json);
            if (json.toString().contains("AgentError")) {
                return new Response(HttpStatus.OK, "{result:\"ERROR\",message=\"SOME ERROR\"}");

            } else if (json.toString().contains("FailedScreenshot")) {
                return new Response(HttpStatus.OK, "{result:\"ERROR\",message=\"screenshot could not be taken\"}");

            } else if (json.toString().contains("EmptyAgentMessage")) {
                return new Response(HttpStatus.OK, "{result:\"ERROR\",message=\"\"}");

            } else if (json.toString().contains("NullAgentMessageOk")) {
                return new Response(HttpStatus.OK, "{result:\"OK\"}");

            } else if (json.toString().contains("NullAgentMessageError")) {
                return new Response(HttpStatus.OK, "{result:\"ERROR\"}");

            } else if (json.toString().contains("MissingImage")) {
                return new Response(HttpStatus.OK, "{\"result\":\"OK\"," + "\"message\":\"2 2 20 20\","
                        + "\"screenshot\"=\"" + GOOD_SCREENSHOT_STRING + "\"}");

            } else if (json.toString().contains("MissingScreenshotAndImage")) {
                return new Response(HttpStatus.OK, "{\"result\":\"OK\"," + "\"message\":\"2 2 400 500\"}");

            } else if (json.toString().contains("MissingScreenshot")) {
                return new Response(HttpStatus.OK, "{\"result\":\"OK\"," + "\"message\":\"2 2 20 20\","
                        + "\"image\"=\"" + GOOD_SCREENSHOT_STRING + "\"}");
            } else if (json.toString().contains("InvalidScreenshot")) {
                return new Response(HttpStatus.OK,
                        "{\"result\":\"OK\"," + "\"message\":\"2 2 20 20\","
                                + "\"screenshot\"=\"iVBORw0KGg48i8JgP8PcEwFnYsg4J4AAAAASUVORK5CYII=\","
                                + "\"image\"=\"iVBORw0KGg48i8JgP8PcEwFnYsg4J4AAAAASUVORK5CYII=\"}");
            } else if (json.toString().contains("UnparseableCropBounds")) {
                return new Response(HttpStatus.OK,
                        "{\"result\":\"OK\"," + "\"message\":\"this_is_a_bunch_of crap\"," + "\"screenshot\"=\""
                                + GOOD_SCREENSHOT_STRING + "\"," + "\"image\"=\"" + GOOD_SCREENSHOT_STRING + "\"}");
            } else if (json.toString().contains("GOODSCREENSHOT.PNG")) {
                return new Response(HttpStatus.OK,
                        "{\"result\":\"OK\"," + "\"message\":\"0 0 50 22\"," + "\"screenshot\"=\""
                                + GOOD_SCREENSHOT_STRING + "\"," + "\"image\"=\"" + GOOD_SCREENSHOT_STRING + "\"}");
            } else if (json.toString().contains("GOODSCREENSHOT2.PNG")) {
                return new Response(HttpStatus.OK,
                        "{\"result\":\"OK\"," + "\"message\":\"2 2 20 20\"," + "\"screenshot\"=\""
                                + GOOD_SCREENSHOT_STRING2 + "\"," + "\"image\"=\"" + GOOD_SCREENSHOT_STRING2
                                + "\"}");
            }
            return new Response(HttpStatus.OK,
                    "{\"result\":\"OK\"," + "\"message\":\"2 2 20 20\"," + "\"screenshot\"=\""
                            + GOOD_SCREENSHOT_STRING + "\"," + "\"image\"=\"" + GOOD_SCREENSHOT_STRING + "\"}");
        }
    }

    private static final String GOOD_SCREENSHOT_STRING = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAWCAYAAACCAs"
            + "+RAAADOUlEQVR42u2WSSh1YRjHr8zEgitDxsTCRpQMCSULWZDuwkISiVAUF1lYYKEsxEqKrEh"
            + "KptzFpdQ1JFaIopQxw0YyZvh//Z+v83b18X26Vr7Ov06d9/Se93l+z3SOAf+JDDqIDqKDfA3k6ekJx8fHeH5"
            + "+xsPDw88EGRwchNFoRElJCQYGBhAXF/czQdLT01FXVycPfixIZWUlfH19ERMTg87Ozj9ALi8vYTKZ4O/"
            + "vj6ioKNnz8vKCq6srpKWlYWtrS/ZdXFzIenR0VL1bWlqKiYkJud/b20NeXh5CQ0ORm5uL1dVVtW9qagr0Y3"
            + "JyEvHx8djd3cXZ2RnMZrPYjI2NRXt7O97e3j4HWVxcFIiKigpsbGy8A+GLPJiGbTYbxsbGBIiHUtHR0ejr65N"
            + "7OmwwGFBUVCTru7s7uLq6Ynt7W6D9/PyQn5+P2dlZNDc3w9vbG5ubm6oKgoOD5eyamhrZX11djYKCAiwtLaG3"
            + "txeBgYEYGRn5e2klJSUph+xBZmZmxDlmRVN/fz98fHwEsqqqSjne0NCAjIwMhIWFyXp+fh4hISFy39raioiIi"
            + "HcRzc7ORn19vbJJOwykJoL39PSo9dzcnFwOgXR0dEi27LW+vi5GT05OJAvh4eHyPCUlRcDd3d1xeHiItrY2K"
            + "S0qJydHbHR1dakrMzNTnms2WXL24uBhRplFBu/09PTfzf4ZCCPGyNmLUSPI0dERrq+v4ezsjP39fSmV29tbyQ"
            + "pLICsrS5VCYmIiEhISpFzsr+7u7k8HzOvrKywWC4qLixEQEAAXFxcpS4dAmFoOAja3fWl5eHioZ6mpqaitr"
            + "UVycrKsmYny8nJ4eXmpkiwsLFTR17S8vCx99xHIzc0NhoeHBYbit43DgFl0COTg4EDSq0X28fFRHOdg0E"
            + "TH6XRjY6OsFxYW4OnpKVnQND4+LvBWq1VBsHnp7Ecg7KXIyEj5vmkBo82ysjLHQKihoSFxlBOKTc6S4VTR"
            + "xKnCUpuenpb1/f093Nzc0NLS8s4QQZ2cnKRM2EdNTU2q+T8qLdrlOUFBQdI/HO07Ozvf+9diqtfW1uQX5jt"
            + "iAFZWVuSb89X9zN75+bn+96uD6CA6yG/9ApyxZm12V7NxAAAAAElFTkSuQmCC";

    private static final String GOOD_SCREENSHOT_STRING2 = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAdCAIAAABnp6gFAAABY0lEQVR42u2WsWvCUBCHHTJkzOCQoUMdBRfBQddAF6GD2RQcSqYSn"
            + "KSDZBPpFDoUpyJuz0FwEXSzf1u/ePIa7GAEY0J5xxuS8y75vPu9e6lUjBkzZuyiDYYDtVK7/U6tld/zS8HkPXmH7wNA47dxNImarWa"
            + "WLPfBJTFHLFDAqjfqV2WFozD+jHPEmr3PwOLfZ0+xbXuz3eSF1Wl34o8YSYEli8rpn6JpRGdFcPidqqObjkensOj+jbH8vr9YLnh0"
            + "8BJwjUcXg0UheeX8a04AYZKF+NgiiRxXihRWRjneoImJ1KzfW4pKjH493NwWr63uc5cYPTtKgGUlEDJE6FfBWH93Q/FY0jJRNHpCZ2"
            + "yI4rEAOvOUoolyFqVjgtcyVOs4RR3nND9rjzVmWBoLIwBneojkjiW1AY6Dj1kPARdnWHKSUjDmLcq7y060EjKpGSNevhSoTRqLWpIo"
            + "NSPYfBwaM/bP7Ad1jBSGO1V5MAAAAABJRU5ErkJggg==";

}