com.gorillalogic.monkeytalk.ant.RunTask.java Source code

Java tutorial

Introduction

Here is the source code for com.gorillalogic.monkeytalk.ant.RunTask.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.ant;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import com.gorillalogic.monkeytalk.CommandWorld;
import com.gorillalogic.monkeytalk.agents.AndroidEmulatorAgent;
import com.gorillalogic.monkeytalk.processor.Globals;
import com.gorillalogic.monkeytalk.processor.PlaybackListener;
import com.gorillalogic.monkeytalk.processor.PlaybackResult;
import com.gorillalogic.monkeytalk.processor.PlaybackStatus;
import com.gorillalogic.monkeytalk.processor.Runner;
import com.gorillalogic.monkeytalk.processor.Scope;
import com.gorillalogic.monkeytalk.processor.SuiteListener;
import com.gorillalogic.monkeytalk.processor.report.Report;
import com.gorillalogic.monkeytalk.sender.Response;
import com.gorillalogic.monkeytalk.utils.AndroidUtils;
import com.gorillalogic.monkeytalk.utils.FileUtils;

public class RunTask extends Task {
    private String agent;
    private File script;
    private File suite;
    private String host;
    private int port;
    private File adb;
    private String callbackurl;
    private String jobrefparams;
    private String adbSerial;
    private int adbLocalPort;
    private int adbRemotePort;
    private File reportdir;
    private String text;
    private boolean verbose = false;
    private int timeout;
    private int thinktime;
    private int startup;
    private boolean screenshots = false;
    private boolean screenshotOnError = true;
    private String globals;
    private static final String TEMP_FILE = ".tmp" + CommandWorld.SCRIPT_EXT;

    private final PlaybackListener scriptListener = new PlaybackListener() {
        private String indent = "";

        @Override
        public void onScriptStart(Scope scope) {
            onPrint((adbSerial != null ? adbSerial + ": " : "") + indent.replaceAll(" ", "-") + "-run: "
                    + (scope.getFilename() == null ? "commands" : scope.getFilename()));
            indent += "  ";
        }

        @Override
        public void onScriptComplete(Scope scope, PlaybackResult result) {
            indent = indent.substring(2);
            onPrint((adbSerial != null ? adbSerial + ": " : "") + indent.replaceAll(" ", "-") + "-end: "
                    + (scope.getFilename() == null ? "commands" : scope.getFilename()));
        }

        @Override
        public void onStart(Scope scope) {
            if (!"debug".equalsIgnoreCase(scope.getCurrentCommand().getComponentType())) {
                onPrint((adbSerial != null ? adbSerial + ": " : "") + indent + scope.getCurrentCommand());
            }
        }

        @Override
        public void onComplete(Scope scope, Response response) {
            if (response.getMessage() != null && response.getMessage().length() > 0) {
                onPrint((adbSerial != null ? adbSerial + ": " : "") + indent + "-> " + response.getStatus() + " : "
                        + response.getMessage());
            }
        }

        @Override
        public void onPrint(String message) {
            log(message.endsWith("\n") ? message.substring(0, message.length() - 1) : message);
        }
    };

    private final PlaybackListener scriptListenerForSuite = new PlaybackListener() {
        private String indent = "";

        @Override
        public void onScriptStart(Scope scope) {
            indent += "  ";
        }

        @Override
        public void onScriptComplete(Scope scope, PlaybackResult result) {
            indent = indent.substring(2);
        }

        @Override
        public void onStart(Scope scope) {
            if (verbose) {
                onPrint((adbSerial != null ? adbSerial + ": " : "") + indent + scope.getCurrentCommand());
            }
        }

        @Override
        public void onComplete(Scope scope, Response response) {
            if (verbose && response.getMessage() != null && response.getMessage().length() > 0) {
                onPrint((adbSerial != null ? adbSerial + ": " : "") + indent + "-> " + response.getStatus() + " : "
                        + response.getMessage());
            }
        }

        @Override
        public void onPrint(String message) {
            log(message);
        }
    };

    private final SuiteListener suiteListener = new SuiteListener() {

        @Override
        public void onRunStart(int total) {
        }

        @Override
        public void onRunComplete(PlaybackResult result, Report report) {
        }

        @Override
        public void onTestStart(String name, int num, int total) {
            log((adbSerial != null ? adbSerial + ": " : "") + "  " + num + " : " + name);
        }

        @Override
        public void onTestComplete(PlaybackResult result, Report report) {
            log((adbSerial != null ? adbSerial + ": " : "") + "  -> " + result.getStatus()
                    + (result.getMessage() != null && result.getMessage().length() > 0 ? " : " + result.getMessage()
                            : ""));
        }

        @Override
        public void onSuiteStart(int total) {
            log((adbSerial != null ? adbSerial + ": " : "") + "-start suite (" + total
                    + (total == 1 ? " test" : " tests") + ")");
        }

        @Override
        public void onSuiteComplete(PlaybackResult result, Report report) {
            log((adbSerial != null ? adbSerial + ": " : "") + "-end suite");
            if (callbackurl != null) {
                sendReport();
            }
        }
    };

    public RunTask() {
        port = -1;
        adbLocalPort = -1;
        adbRemotePort = -1;
        timeout = -1;
        thinktime = -1;
        startup = -1;
    }

    public void execute() throws BuildException {
        Runner runner = new Runner(agent, host, port);

        if (adb != null) {
            runner.setAdb(adb);
        } else if (agent != null && agent.equalsIgnoreCase("AndroidEmulator")) {
            File adb = AndroidUtils.getAdb();
            runner.setAdb(adb);
        }
        if (adbSerial != null) {
            runner.setAgentProperty(AndroidEmulatorAgent.ADB_SERIAL_PROP, adbSerial);
        }
        if (adbLocalPort > 0) {
            runner.setAgentProperty(AndroidEmulatorAgent.ADB_LOCAL_PORT_PROP, Integer.toString(adbLocalPort));
        }
        if (adbRemotePort > 0) {
            runner.setAgentProperty(AndroidEmulatorAgent.ADB_REMOTE_PORT_PROP, Integer.toString(adbRemotePort));
        }

        runner.setReportdir(reportdir);
        runner.setScriptListener(scriptListener);
        runner.setSuiteListener(suiteListener);
        runner.setVerbose(false);
        runner.setGlobalTimeout(timeout);
        runner.setGlobalThinktime(thinktime);
        runner.setGlobalScreenshotOnError(screenshotOnError);
        runner.setTakeAfterScreenshot(screenshots);
        runner.setTakeAfterMetrics(screenshots);
        PlaybackResult result = null;

        try {
            if (script != null && suite != null) {
                throw new BuildException("You cannot specify both script and suite in the run task.");
            } else if (script != null && text != null) {
                throw new BuildException("You cannot specify both script and inline commands in the run task.");
            } else if (suite != null && text != null) {
                throw new BuildException("You cannot specify both suite and inline commands in the run task.");
            }

            if (!runner.waitUntilReady(startup)) {
                throw new BuildException(
                        "Unable to startup MonkeyTalk connection - timeout after " + startup + "s");
            }

            if (script != null) {
                if (verbose) {
                    log("running script " + script.getName() + "...");
                }
                result = runner.run(script, Globals.parse(globals));
            } else if (suite != null) {
                if (verbose) {
                    log("running suite " + suite.getName() + "...");
                }
                runner.setScriptListener(scriptListenerForSuite);
                result = runner.run(suite, Globals.parse(globals));
            } else if (text != null) {
                File tmp = new File(getProject().getBaseDir(), TEMP_FILE);
                String subbed = getProject().replaceProperties(text.trim());

                try {
                    FileUtils.writeFile(tmp, subbed);
                } catch (IOException ex) {
                    throw new BuildException(ex);
                }

                result = runner.run(tmp, Globals.parse(globals));

                tmp.delete();
            } else {
                throw new BuildException("Nothing to run.");
            }
        } catch (RuntimeException ex) {
            throw new BuildException(ex.getMessage());
        }

        if (result.getStatus() != PlaybackStatus.OK) {
            throw new BuildException(result.toString());
        }

        if (verbose) {
            log("...done");
        }
    }

    public void setAgent(String agent) {
        this.agent = agent;
    }

    public void setScript(File script) {
        if (script.getName().endsWith(CommandWorld.SUITE_EXT)) {
            // user gave us a suite instead of a script, so fix it for them
            this.suite = script;
            this.script = null;
        } else {
            this.script = script;
        }
    }

    public void setSuite(File suite) {
        this.suite = suite;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setAdb(File adb) {
        this.adb = adb;
    }

    public void setAdbSerial(String adbSerial) {
        this.adbSerial = adbSerial;
    }

    public void setAdbLocalPort(int adbLocalPort) {
        this.adbLocalPort = adbLocalPort;
    }

    public void setAdbRemotePort(int adbRemotePort) {
        this.adbRemotePort = adbRemotePort;
    }

    public void setReportdir(File reportdir) {
        this.reportdir = reportdir;
    }

    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    public void setScreenshots(boolean screenshots) {
        this.screenshots = screenshots;
    }

    public void setScreenshotOnError(boolean screenshotOnError) {
        this.screenshotOnError = screenshotOnError;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setThinktime(int thinktime) {
        this.thinktime = thinktime;
    }

    public void setStartup(int startup) {
        this.startup = startup;
    }

    public void setGlobals(String globals) {
        this.globals = globals;
    }

    public void setCallbackurl(String callbackurl) {
        this.callbackurl = callbackurl;
    }

    public void setJobrefparams(String jobrefparams) {
        this.jobrefparams = jobrefparams;
    }

    public void addText(String text) {
        this.text = text;
    }

    public void sendReport() {
        try {
            File zippedReports = FileUtils.zipDirectory(reportdir, true, false);
            System.out.println(zippedReports.getAbsolutePath());
            Map<String, String> additionalParams = new HashMap<String, String>();
            StringTokenizer st2 = new StringTokenizer(jobrefparams, ",");

            while (st2.hasMoreElements()) {
                String param = (String) st2.nextElement();
                StringTokenizer st3 = new StringTokenizer(param, ":");
                additionalParams.put((String) st3.nextElement(), (String) st3.nextElement());

            }

            sendFormPost(callbackurl, zippedReports, additionalParams);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private String sendFormPost(String url, File proj, Map<String, String> additionalParams) throws IOException {

        HttpClient base = new DefaultHttpClient();
        SSLContext ctx = null;

        try {
            ctx = SSLContext.getInstance("TLS");
        } catch (NoSuchAlgorithmException ex) {
            log("exception in sendFormPost():");
        }

        X509TrustManager tm = new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
                    throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
                    throws java.security.cert.CertificateException {
            }
        };

        try {
            ctx.init(null, new TrustManager[] { tm }, null);
        } catch (KeyManagementException ex) {
            log("exception in sendFormPost():");
        }

        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = base.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));

        HttpClient client = new DefaultHttpClient(ccm, base.getParams());
        try {
            HttpPost post = new HttpPost(url);

            MultipartEntity multipart = new MultipartEntity();
            for (String key : additionalParams.keySet())
                multipart.addPart(key, new StringBody(additionalParams.get(key), Charset.forName("UTF-8")));

            if (proj != null) {
                multipart.addPart("uploaded_file", new FileBody(proj));
            }

            post.setEntity(multipart);

            HttpResponse resp = client.execute(post);

            HttpEntity out = resp.getEntity();

            InputStream in = out.getContent();
            return FileUtils.readStream(in);
        } catch (Exception ex) {
            throw new IOException("POST failed", ex);
        } finally {
            try {
                client.getConnectionManager().shutdown();
            } catch (Exception ex) {
                // ignore
            }
        }
    }
}