/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.junit;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.ArgProcessorBase;
import com.google.gwt.dev.Compiler;
import com.google.gwt.dev.DevMode;
import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.Properties;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.jetty.JettyLauncher;
import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization;
import com.google.gwt.dev.util.arg.ArgHandlerDisableCastChecking;
import com.google.gwt.dev.util.arg.ArgHandlerDisableClassMetadata;
import com.google.gwt.dev.util.arg.ArgHandlerDisableRunAsync;
import com.google.gwt.dev.util.arg.ArgHandlerDraftCompile;
import com.google.gwt.dev.util.arg.ArgHandlerEnableAssertions;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
import com.google.gwt.dev.util.arg.ArgHandlerMaxPermsPerPrecompile;
import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
import com.google.gwt.junit.JUnitMessageQueue.ClientStatus;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.junit.client.TimeoutException;
import com.google.gwt.junit.client.impl.JUnitResult;
import com.google.gwt.junit.client.impl.JUnitHost.TestInfo;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerInt;
import com.google.gwt.util.tools.ArgHandlerString;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import junit.framework.TestResult;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppContext;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class is responsible for hosting JUnit test case execution. There are
 * three main pieces to the JUnit system.
 * 
 * <ul>
 * <li>Test environment</li>
 * <li>Client classes</li>
 * <li>Server classes</li>
 * </ul>
 * 
 * <p>
 * The test environment consists of this class and the non-translatable version
 * of {@link com.google.gwt.junit.client.GWTTestCase}. These two classes
 * integrate directly into the real JUnit test process.
 * </p>
 * 
 * <p>
 * The client classes consist of the translatable version of
 * {@link com.google.gwt.junit.client.GWTTestCase}, translatable JUnit classes,
 * and the user's own {@link com.google.gwt.junit.client.GWTTestCase}-derived
 * class. The client communicates to the server via RPC.
 * </p>
 * 
 * <p>
 * The server consists of {@link com.google.gwt.junit.server.JUnitHostImpl}, an
 * RPC servlet which communicates back to the test environment through a
 * {@link JUnitMessageQueue}, thus closing the loop.
 * </p>
 */
public class JUnitShell extends DevMode {

  /**
   * A strategy for running the test.
   */
  public interface Strategy {
    String getModuleInherit();

    String getSyntheticModuleExtension();

    void processModule(ModuleDef module);

    void processResult(TestCase testCase, JUnitResult result);
  }

  class ArgProcessor extends ArgProcessorBase {

    @SuppressWarnings("deprecation")
    public ArgProcessor() {
      /*
       * ----- Options from DevModeBase -------
       */
      // DISABLE: ArgHandlerNoServerFlag.
      registerHandler(new ArgHandlerPort(options) {
        @Override
        public String[] getDefaultArgs() {
          // Override port to auto by default.
          return new String[]{"-port", "auto"};
        }
      });
      registerHandler(new ArgHandlerWhitelist());
      registerHandler(new ArgHandlerBlacklist());
      registerHandler(new ArgHandlerLogDir(options));
      registerHandler(new ArgHandlerLogLevel(options));
      registerHandler(new ArgHandlerGenDir(options));
      // DISABLE: ArgHandlerBindAddress.
      registerHandler(new ArgHandlerCodeServerPort(options) {
        @Override
        public String[] getDefaultArgs() {
          // Override code server port to auto by default.
          return new String[]{this.getTag(), "auto"};
        }
      });
      // DISABLE: ArgHandlerRemoteUI.

      /*
       * ----- Options from DevMode -------
       */
      // Hard code the server.
      options.setServletContainerLauncher(new MyJettyLauncher());
      // DISABLE: ArgHandlerStartupURLs
      registerHandler(new com.google.gwt.dev.ArgHandlerOutDirDeprecated(options));
      registerHandler(new ArgHandlerWarDir(options) {
        @Override
        public String[] getDefaultArgs() {
          // If an outDir was already specified, don't clobber it.
          if (options.getOutDir() != null) {
            return null;
          }
          return super.getDefaultArgs();
        }
      });
      registerHandler(new ArgHandlerExtraDir(options));
      registerHandler(new ArgHandlerWorkDirOptional(options));
      // DISABLE: ArgHandlerModuleName

      /*
       * ----- Additional options from Compiler not already included -------
       */
      registerHandler(new ArgHandlerScriptStyle(options));
      registerHandler(new ArgHandlerEnableAssertions(options));
      registerHandler(new ArgHandlerDisableAggressiveOptimization(options));
      registerHandler(new ArgHandlerDisableClassMetadata(options));
      registerHandler(new ArgHandlerDisableCastChecking(options));
      registerHandler(new ArgHandlerDisableRunAsync(options));
      registerHandler(new ArgHandlerDraftCompile(options));
      registerHandler(new ArgHandlerMaxPermsPerPrecompile(options));
      registerHandler(new ArgHandlerLocalWorkers(options));

      /*
       * ----- Options specific to JUnitShell -----
       */

      // Override log level to set WARN by default..
      registerHandler(new ArgHandlerLogLevel(options) {
        @Override
        protected Type getDefaultLogLevel() {
          return TreeLogger.WARN;
        }
      });

      registerHandler(new ArgHandlerFlag() {
        @Override
        public String getPurpose() {
          return "Synonym for -prod (deprecated)";
        }

        @Override
        public String getTag() {
          return "-web";
        }

        @Override
        public boolean isUndocumented() {
          return true;
        }

        @Override
        public boolean setFlag() {
          developmentMode = false;
          return true;
        }
      });

      registerHandler(new ArgHandlerFlag() {
        @Override
        public String getPurpose() {
          return "Causes your test to run in production (compiled) mode (defaults to development mode)";
        }

        @Override
        public String getTag() {
          return "-prod";
        }

        @Override
        public boolean setFlag() {
          developmentMode = false;
          return true;
        }
      });

      registerHandler(new ArgHandlerInt() {
        @Override
        public String[] getDefaultArgs() {
          return new String[]{getTag(), "5"};
        }

        @Override
        public String getPurpose() {
          return "Set the test method timeout, in minutes";
        }

        @Override
        public String getTag() {
          return "-testMethodTimeout";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"minutes"};
        }

        @Override
        public boolean isUndocumented() {
          return false;
        }

        @Override
        public void setInt(int minutes) {
          baseTestMethodTimeoutMillis = minutes * 60 * 1000;
        }
      });

      registerHandler(new ArgHandlerInt() {
        @Override
        public String[] getDefaultArgs() {
          return new String[]{getTag(), "1"};
        }

        @Override
        public String getPurpose() {
          return "Set the test begin timeout (time for clients to contact "
              + "server), in minutes";
        }

        @Override
        public String getTag() {
          return "-testBeginTimeout";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"minutes"};
        }

        @Override
        public boolean isUndocumented() {
          return false;
        }

        @Override
        public void setInt(int minutes) {
          baseTestBeginTimeoutMillis = minutes * 60 * 1000;
        }
      });

      registerHandler(new ArgHandlerString() {
        @Override
        public String getPurpose() {
          return "Selects the runstyle to use for this test.  The name is "
              + "a suffix of com.google.gwt.junit.RunStyle or is a fully "
              + "qualified class name, and may be followed with a colon and "
              + "an argument for this runstyle.  The specified class must"
              + "extend RunStyle.";
        }

        @Override
        public String getTag() {
          return "-runStyle";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"runstyle[:args]"};
        }

        @Override
        public boolean isUndocumented() {
          return false;
        }

        @Override
        public boolean setString(String runStyleArg) {
          runStyleName = runStyleArg;
          return true;
        }
      });

      registerHandler(new ArgHandlerString() {
        @Override
        public String getPurpose() {
          return "Configure batch execution of tests";
        }

        @Override
        public String getTag() {
          return "-batch";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"none|class|module"};
        }

        @Override
        public boolean isUndocumented() {
          return true;
        }

        @Override
        public boolean setString(String str) {
          if (str.equals("none")) {
            batchingStrategy = new NoBatchingStrategy();
          } else if (str.equals("class")) {
            batchingStrategy = new ClassBatchingStrategy();
          } else if (str.equals("module")) {
            batchingStrategy = new ModuleBatchingStrategy();
          } else {
            return false;
          }
          return true;
        }
      });

      registerHandler(new ArgHandlerFlag() {
        @Override
        public String getPurpose() {
          return "Causes the log window and browser windows to be displayed; useful for debugging";
        }

        @Override
        public String getTag() {
          return "-notHeadless";
        }

        @Override
        public boolean setFlag() {
          JUnitShell.this.setHeadless(false);
          return true;
        }
      });

      registerHandler(new ArgHandlerString() {
        @Override
        public String getPurpose() {
          return "Precompile modules as tests are running (speeds up remote tests but requires more memory)";
        }

        @Override
        public String getTag() {
          return "-precompile";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"simple|all|parallel"};
        }

        @Override
        public boolean isUndocumented() {
          return true;
        }

        @Override
        public boolean setString(String str) {
          if (str.equals("simple")) {
            compileStrategy = new SimpleCompileStrategy(JUnitShell.this);
          } else if (str.equals("all")) {
            compileStrategy = new PreCompileStrategy(JUnitShell.this);
          } else if (str.equals("parallel")) {
            compileStrategy = new ParallelCompileStrategy(JUnitShell.this);
          } else {
            return false;
          }
          return true;
        }
      });

      registerHandler(new ArgHandlerFlag() {
        @Override
        public String getPurpose() {
          return "Use CSS standards mode (rather than quirks mode) for the hosting page";
        }

        @Override
        public String getTag() {
          return "-standardsMode";
        }

        @Override
        public boolean setFlag() {
          setStandardsMode(true);
          return true;
        }
      });

      registerHandler(new ArgHandlerInt() {
        @Override
        public String getPurpose() {
          return "EXPERIMENTAL: Sets the maximum number of attempts for running each test method";
        }

        @Override
        public String getTag() {
          return "-Xtries";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"1"};
        }

        @Override
        public boolean isRequired() {
          return false;
        }

        @Override
        public boolean isUndocumented() {
          return false;
        }

        @Override
        public void setInt(int value) {
          tries = value;
        }
      });

      registerHandler(new ArgHandlerString() {
        @Override
        public String getPurpose() {
          return "Specify the user agents to reduce the number of permutations for remote browser tests;"
              + " e.g. ie6,ie8,safari,gecko,gecko1_8,opera";
        }

        @Override
        public String getTag() {
          return "-userAgents";
        }

        @Override
        public String[] getTagArgs() {
          return new String[]{"userAgents"};
        }

        @Override
        public boolean setString(String str) {
          remoteUserAgents = str.split(",");
          for (int i = 0; i < remoteUserAgents.length; i++) {
            remoteUserAgents[i] = remoteUserAgents[i].trim();
          }
          return true;
        }
      });
    }

    @Override
    protected String getName() {
      return JUnitShell.class.getName();
    }
  }

  private final class MyJettyLauncher extends JettyLauncher {

    /**
     * Adds in special JUnit stuff.
     */
    @Override
    protected JettyServletContainer createServletContainer(TreeLogger logger,
        File appRootDir, Server server, WebAppContext wac, int localPort) {
      // Don't bother shutting down cleanly.
      server.setStopAtShutdown(false);
      // Save off the Context so we can add our own servlets later.
      JUnitShell.this.wac = wac;
      return super.createServletContainer(logger, appRootDir, server, wac,
          localPort);
    }

    /**
     * Ignore DevMode's normal WEB-INF classloader rules and just allow the
     * system classloader to dominate. This makes JUnitHostImpl live in the
     * right classloader (mine).
     */
    @Override
    protected WebAppContext createWebAppContext(TreeLogger logger,
        File appRootDir) {
      return new WebAppContext(appRootDir.getAbsolutePath(), "/") {
        {
          // Prevent file locking on Windows; pick up file changes.
          getInitParams().put(
              "org.mortbay.jetty.servlet.Default.useFileMappedBuffer", "false");

          // Prefer the parent class loader so that JUnit works.
          setParentLoaderPriority(true);
        }
      };
    }
  }

  /**
   * This is a system property that, when set, emulates command line arguments.
   */
  private static final String PROP_GWT_ARGS = "gwt.args";

  /**
   * Singleton object for hosting unit tests. All test case instances executed
   * by the TestRunner will use the single unitTestShell.
   */
  private static JUnitShell unitTestShell;

  /**
   * Called by {@link com.google.gwt.junit.server.JUnitHostImpl} to get an
   * interface into the test process.
   * 
   * @return The {@link JUnitMessageQueue} interface that belongs to the
   *         singleton {@link JUnitShell}, or <code>null</code> if no such
   *         singleton exists.
   */
  public static JUnitMessageQueue getMessageQueue() {
    if (unitTestShell == null) {
      return null;
    }
    return unitTestShell.messageQueue;
  }

  /**
   * Get the list of remote user agents to compile. This method returns null
   * until all clients have connected.
   * 
   * @return the list of remote user agents
   */
  public static String[] getRemoteUserAgents() {
    if (unitTestShell == null) {
      return null;
    }
    return unitTestShell.remoteUserAgents;
  }

  /**
   * Checks if a testCase should not be executed. Currently, a test is either
   * executed on all clients (mentioned in this test) or on no clients.
   * 
   * @param testInfo the test info to check
   * @return true iff the test should not be executed on any of the specified
   *         clients.
   */
  public static boolean mustNotExecuteTest(TestInfo testInfo) {
    if (unitTestShell == null) {
      throw new IllegalStateException(
          "mustNotExecuteTest cannot be called before runTest()");
    }
    try {
      Class<?> testClass = TestCase.class.getClassLoader().loadClass(
          testInfo.getTestClass());
      return unitTestShell.mustNotExecuteTest(getBannedPlatforms(testClass,
          testInfo.getTestMethod()));
    } catch (ClassNotFoundException e) {
      throw new IllegalArgumentException("Could not load test class: "
          + testInfo.getTestClass());
    }
  }

  /**
   * Entry point for {@link com.google.gwt.junit.client.GWTTestCase}. Gets or
   * creates the singleton {@link JUnitShell} and invokes its
   * {@link #runTestImpl(GWTTestCase, TestResult)}.
   */
  public static void runTest(GWTTestCase testCase, TestResult testResult)
      throws UnableToCompleteException {
    getUnitTestShell().runTestImpl(testCase, testResult);
  }

  /**
   * Entry point for {@link com.google.gwt.junit.client.GWTTestCase}. Gets or
   * creates the singleton {@link JUnitShell} and invokes its
   * {@link #runTestImpl(GWTTestCase, TestResult)}.
   * 
   * @deprecated use {@link #runTest(GWTTestCase, TestResult)} instead
   */
  @Deprecated
  public static void runTest(String moduleName, TestCase testCase,
      TestResult testResult) throws UnableToCompleteException {
    runTest(moduleName, testCase, testResult,
        ((GWTTestCase) testCase).getStrategy());
  }

  /**
   * @deprecated use {@link #runTest(GWTTestCase, TestResult)} instead
   */
  @Deprecated
  public static void runTest(String moduleName, TestCase testCase,
      TestResult testResult, Strategy strategy)
      throws UnableToCompleteException {
    GWTTestCase gwtTestCase = (GWTTestCase) testCase;
    assert moduleName != null : "moduleName cannot be null";
    assert strategy != null : "strategy cannot be null";
    assert moduleName.equals(gwtTestCase.getModuleName()) : "moduleName does not match GWTTestCase#getModuleName()";
    assert strategy.equals(gwtTestCase.getStrategy()) : "strategy does not match GWTTestCase#getStrategy()";
    runTest(gwtTestCase, testResult);
  }

  /**
   * Retrieves the JUnitShell. This should only be invoked during TestRunner
   * execution of JUnit tests.
   */
  static JUnitShell getUnitTestShell() {
    if (unitTestShell == null) {
      unitTestShell = new JUnitShell();
      unitTestShell.lastLaunchFailed = true;
      String[] args = unitTestShell.synthesizeArgs();
      ArgProcessor argProcessor = unitTestShell.new ArgProcessor();
      if (!argProcessor.processArgs(args)) {
        throw new JUnitFatalLaunchException("Error processing shell arguments");
      }
      // Always bind to the wildcard address and substitute the host address in
      // URLs. Note that connectAddress isn't actually used here, as we
      // override it from the runsStyle in getModuleUrl, but we set it to match
      // what will actually be used anyway to avoid confusion.
      unitTestShell.options.setBindAddress("0.0.0.0");
      try {
        unitTestShell.options.setConnectAddress(InetAddress.getLocalHost().getHostAddress());
      } catch (UnknownHostException e) {
        throw new JUnitFatalLaunchException("Unable to resolve my address", e);
      }
      if (!unitTestShell.startUp()) {
        throw new JUnitFatalLaunchException("Shell failed to start");
      }
      // TODO: install a shutdown hook? Not necessary with GWTShell.
      unitTestShell.lastLaunchFailed = false;
    }
    unitTestShell.checkArgs();
    return unitTestShell;
  }

  /**
   * Sanity check; if the type we're trying to run did not actually wind up in
   * the type oracle, there's no way this test can possibly run. Bail early
   * instead of failing on the client.
   */
  private static JUnitFatalLaunchException checkTestClassInCurrentModule(
      CompilationState compilationState, String moduleName, TestCase testCase) {
    TypeOracle typeOracle = compilationState.getTypeOracle();
    String typeName = testCase.getClass().getName();
    typeName = typeName.replace('$', '.');
    JClassType foundType = typeOracle.findType(typeName);
    if (foundType != null) {
      return null;
    }
    Map<String, CompilationUnit> unitMap = compilationState.getCompilationUnitMap();
    CompilationUnit unit = unitMap.get(typeName);
    String errMsg;
    if (unit == null) {
      errMsg = "The test class '" + typeName + "' was not found in module '"
          + moduleName + "'; no compilation unit for that type was seen";
    } else if (unit.isError()) {
      errMsg = "The test class '" + typeName
          + "' had compile errors; check log for details";
    } else {
      errMsg = "Unexpected error: the test class '"
          + typeName
          + "' appears to be valid, but no corresponding type was found in TypeOracle; please contact GWT support";
    }
    return new JUnitFatalLaunchException(errMsg);
  }

  /**
   * Returns the set of banned {@code Platform} for a test method.
   * 
   * @param testClass the testClass
   * @param methodName the name of the test method
   */
  private static Set<Platform> getBannedPlatforms(Class<?> testClass,
      String methodName) {
    Set<Platform> bannedSet = EnumSet.noneOf(Platform.class);
    if (testClass.isAnnotationPresent(DoNotRunWith.class)) {
      bannedSet.addAll(Arrays.asList(testClass.getAnnotation(DoNotRunWith.class).value()));
    }
    try {
      Method testMethod = testClass.getMethod(methodName);
      if (testMethod.isAnnotationPresent(DoNotRunWith.class)) {
        bannedSet.addAll(Arrays.asList(testMethod.getAnnotation(
            DoNotRunWith.class).value()));
      }
    } catch (SecurityException e) {
      // should not happen
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      // should not happen
      e.printStackTrace();
    }
    return bannedSet;
  }

  /**
   * Our server's web app context; used to dynamically add servlets.
   */
  WebAppContext wac;

  /**
   * The amount of time to wait for all clients to have contacted the server and
   * begin running the test. "Contacted" does not necessarily mean "the test has
   * begun," e.g. for linker errors stopping the test initialization.
   */
  private long baseTestBeginTimeoutMillis;

  /**
   * The amount of time to wait for all clients to complete a single test
   * method, in milliseconds, measured from when the <i>last</i> client connects
   * (and thus starts the test). Set by the -testMethodTimeout argument.
   */
  private long baseTestMethodTimeoutMillis;

  /**
   * Determines how to batch up tests for execution.
   */
  private BatchingStrategy batchingStrategy = new NoBatchingStrategy();

  /**
   * Determines how modules are compiled.
   */
  private CompileStrategy compileStrategy = new SimpleCompileStrategy(
      JUnitShell.this);

  /**
   * A type oracle for the current module, used to validate class existence.
   */
  private CompilationState currentCompilationState;

  /**
   * Name of the module containing the current/last module to run.
   */
  private ModuleDef currentModule;

  /**
   * The name of the current test case being run.
   */
  private TestInfo currentTestInfo;

  /**
   * True if we are running the test in development mode.
   */
  private boolean developmentMode = true;

  /**
   * If true, no launches have yet been successful.
   */
  private boolean firstLaunch = true;

  /**
   * If true, the last attempt to launch failed.
   */
  private boolean lastLaunchFailed;

  /**
   * We need to keep a hard reference to the last module that was launched until
   * all client browsers have successfully transitioned to the current module.
   * Failure to do so allows the last module to be GC'd, which transitively
   * kills the {@link com.google.gwt.junit.server.JUnitHostImpl} servlet. If the
   * servlet dies, the client browsers will be unable to transition.
   */
  @SuppressWarnings("unused")
  private ModuleDef lastModule;

  /**
   * Records what servlets have been loaded at which paths.
   */
  private final Map<String, String> loadedServletsByPath = new HashMap<String, String>();

  /**
   * Portal to interact with the servlet.
   */
  private JUnitMessageQueue messageQueue;

  /**
   * An exception that should by fired the next time runTestImpl runs.
   */
  private UnableToCompleteException pendingException;

  /**
   * The remote user agents that have connected. Populated after all user agents
   * have connected so we can limit permutations for remote tests.
   */
  private String[] remoteUserAgents;

  /**
   * What type of test we're running; Local development, local production, or
   * remote production.
   */
  private RunStyle runStyle = null;

  /**
   * The argument passed to -runStyle. This is parsed later so we can pass in a
   * logger.
   */
  private String runStyleName = "HtmlUnit";

  private boolean standardsMode = false;

  /**
   * Test method timeout as modified by the batching strategy.
   */
  private long testBatchingMethodTimeoutMillis;

  /**
   * The time the test actually began.
   */
  private long testBeginTime;

  /**
   * The time at which the current test will fail if the client has not yet
   * started the test.
   */
  private long testBeginTimeout;

  /**
   * Timeout for individual test method. If System.currentTimeMillis() is later
   * than this timestamp, then we need to pack up and go home. Zero for "not yet
   * set" (at the start of a test). This interval begins when the
   * testBeginTimeout interval is done.
   */
  private long testMethodTimeout;

  /**
   * Max number of times a test method must be tried.
   */
  private int tries;

  /**
   * Enforce the singleton pattern. The call to {@link GWTShell}'s ctor forces
   * server mode and disables processing extra arguments as URLs to be shown.
   */
  private JUnitShell() {
    setRunTomcat(true);
    setHeadless(true);
  }

  public String getModuleUrl(String moduleName) {
    // TODO(jat): consider using DevModeBase.processUrl instead
    String localhost = runStyle.getLocalHostName();
    String url = "http://" + localhost + ":" + getPort() + "/" + moduleName
        + (standardsMode ? "/junit-standards.html" : "/junit.html");
    if (developmentMode) {
      // CHECKSTYLE_OFF
      url += "?gwt.codesvr=" + localhost + ":" + codeServerPort;
      // CHECKSTYLE_ON
    }
    return url;
  }

  /**
   * Check for updates once a minute.
   */
  @Override
  protected long checkForUpdatesInterval() {
    return CheckForUpdates.ONE_MINUTE;
  }

  @Override
  protected boolean doStartup() {
    if (!super.doStartup()) {
      return false;
    }
    int numClients = createRunStyle(runStyleName);
    if (numClients < 0) {
      // RunStyle already logged reasons for its failure
      return false;
    }
    messageQueue = new JUnitMessageQueue(numClients);

    if (tries >= 1) {
      runStyle.setTries(tries);
    }

    if (!runStyle.setupMode(getTopLogger(), developmentMode)) {
      getTopLogger().log(
          TreeLogger.ERROR,
          "Run style does not support "
              + (developmentMode ? "development" : "production") + " mode");
      return false;
    }
    return true;
  }

  @Override
  protected void ensureCodeServerListener() {
    if (developmentMode) {
      super.ensureCodeServerListener();
      listener.setIgnoreRemoteDeath(true);
    }
  }

  @Override
  protected void inferStartupUrls() {
    // do nothing -- JUnitShell isn't expected to have startup URLs
  }

  @Override
  protected ModuleDef loadModule(TreeLogger logger, String moduleName,
      boolean refresh) throws UnableToCompleteException {
    // Never refresh modules in JUnit.
    return super.loadModule(logger, moduleName, false);
  }

  /**
   * Checks to see if this test run is complete.
   */
  protected boolean notDone() {
    int activeClients = messageQueue.getNumClientsRetrievedTest(currentTestInfo);
    int expectedClients = messageQueue.getNumClients();
    if (firstLaunch && runStyle instanceof RunStyleManual) {
      String[] newClients = messageQueue.getNewClients();
      int printIndex = activeClients - newClients.length + 1;
      for (String newClient : newClients) {
        System.out.println(printIndex + " - " + newClient);
        ++printIndex;
      }
      if (activeClients != expectedClients) {
        // Wait forever for first contact; user-driven.
        return true;
      }
    }

    // Limit permutations after all clients have connected.
    if (remoteUserAgents == null
        && messageQueue.getNumConnectedClients() == expectedClients) {
      remoteUserAgents = messageQueue.getUserAgents();
      String userAgentList = "";
      for (int i = 0; i < remoteUserAgents.length; i++) {
        if (i > 0) {
          userAgentList += ", ";
        }
        userAgentList += remoteUserAgents[i];
      }
      getTopLogger().log(
          TreeLogger.INFO,
          "All clients connected (Limiting future permutations to: "
              + userAgentList + ")");
    }

    long currentTimeMillis = System.currentTimeMillis();
    if (activeClients >= expectedClients) {
      if (activeClients > expectedClients) {
        getTopLogger().log(
            TreeLogger.WARN,
            "Too many clients: expected " + expectedClients + ", found "
                + activeClients);
      }
      firstLaunch = false;

      /*
       * It's now safe to release any reference to the last module since all
       * clients have transitioned to the current module.
       */
      lastModule = currentModule;
      if (testMethodTimeout == 0) {
        testMethodTimeout = currentTimeMillis + testBatchingMethodTimeoutMillis;
      } else if (testMethodTimeout < currentTimeMillis) {
        double elapsed = (currentTimeMillis - testBeginTime) / 1000.0;
        throw new TimeoutException(
            "The browser did not complete the test method "
                + currentTestInfo.toString() + " in "
                + testBatchingMethodTimeoutMillis
                + "ms.\n  We have no results from:\n"
                + messageQueue.getWorkingClients(currentTestInfo)
                + "Actual time elapsed: " + elapsed + " seconds.\n"
                + "Try increasing this timeout using the '-testMethodTimeout minutes' option\n");
      }
    } else if (testBeginTimeout < currentTimeMillis) {
      double elapsed = (currentTimeMillis - testBeginTime) / 1000.0;
      throw new TimeoutException(
          "The browser did not contact the server within "
              + baseTestBeginTimeoutMillis + "ms.\n"
              + messageQueue.getUnretrievedClients(currentTestInfo)
              + "\n Actual time elapsed: " + elapsed + " seconds.\n"
              + "Try increasing this timeout using the '-testBeginTimeout minutes' option\n"
              + "The default value of minutes is 1, i.e., the server waits 1 minute or 60 seconds.\n");
    }

    // Check that we haven't lost communication with a remote host.
    String[] interruptedHosts = runStyle.getInterruptedHosts();
    if (interruptedHosts != null) {
      StringBuilder msg = new StringBuilder();
      msg.append("A remote browser died a mysterious death.\n");
      msg.append("  We lost communication with:");
      for (String host : interruptedHosts) {
        msg.append("\n  ").append(host);
      }
      throw new TimeoutException(msg.toString());
    }

    if (messageQueue.hasResults(currentTestInfo)) {
      return false;
    } else if (pendingException == null) {
      // Instead of waiting around for results, try to compile the next module.
      try {
        compileStrategy.maybeCompileAhead();
      } catch (UnableToCompleteException e) {
        pendingException = e;
      }
    }
    return true;
  }

  @Override
  protected void warnAboutNoStartupUrls() {
    // do nothing -- JUnitShell isn't expected to have startup URLs
  }

  void compileForWebMode(ModuleDef module, String... userAgents)
      throws UnableToCompleteException {
    if (userAgents != null && userAgents.length > 0) {
      Properties props = module.getProperties();
      Property userAgent = props.find("user.agent");
      if (userAgent instanceof BindingProperty) {
        BindingProperty bindingProperty = (BindingProperty) userAgent;
        bindingProperty.setAllowedValues(bindingProperty.getRootCondition(),
            userAgents);
      }
    }
    if (!new Compiler(options).run(getTopLogger(), module)) {
      throw new UnableToCompleteException();
    }
    // TODO(scottb): prepopulate currentCompilationState somehow?
  }

  void maybeCompileForWebMode(ModuleDef module, String... userAgents)
      throws UnableToCompleteException {
    // Load any declared servlets.
    for (String path : module.getServletPaths()) {
      String servletClass = module.findServletForPath(path);
      path = '/' + module.getName() + path;
      if (!servletClass.equals(loadedServletsByPath.get(path))) {
        try {
          Class<?> clazz = wac.loadClass(servletClass);
          wac.addServlet(clazz, path);
          loadedServletsByPath.put(path, servletClass);
        } catch (ClassNotFoundException e) {
          getTopLogger().log(
              TreeLogger.WARN,
              "Failed to load servlet class '" + servletClass
                  + "' declared in '" + module.getName() + "'", e);
        }
      }
    }
    if (developmentMode) {
      // BACKWARDS COMPATIBILITY: many linkers currently fail in dev mode.
      try {
        if (!module.getActivePrimaryLinker().newInstance().supportsDevMode()) {
          if (module.getLinker("std") != null) {
            // TODO: unfortunately, this could be race condition between dev/prod
            module.addLinker("std");
          }
        }
      } catch (Exception e) {
        getTopLogger().log(TreeLogger.WARN, "Failed to instantiate linker: " + e);
      }
      super.link(getTopLogger(), module);
    } else {
      compileForWebMode(module, userAgents);
    }
  }

  /**
   * @deprecated TODO(fabbott) delete me
   */
  @Deprecated
  @SuppressWarnings("unused")
  void setNumClients(int numClients) {
    throw new UnsupportedOperationException("This method should be deleted.");
  }

  void setStandardsMode(boolean standardsMode) {
    this.standardsMode = standardsMode;
  }

  private void checkArgs() {
    if (runStyle.getTries() > 1
        && !(batchingStrategy instanceof NoBatchingStrategy)) {
      throw new JUnitFatalLaunchException(
          "Batching does not work with tries > 1");
    }
  }

  /**
   * Create the specified (or default) runStyle.
   * 
   * @param runStyleName the argument passed to -runStyle
   * @return the number of clients, or -1 if initialization was unsuccessful
   */
  private int createRunStyle(String runStyleName) {
    String args = null;
    String name = runStyleName;
    int colon = name.indexOf(':');
    if (colon >= 0) {
      args = name.substring(colon + 1);
      name = name.substring(0, colon);
    }
    if (name.indexOf('.') < 0) {
      name = RunStyle.class.getName() + name;
    }
    Throwable caught = null;
    try {
      Class<?> clazz = Class.forName(name);
      Class<? extends RunStyle> runStyleClass = clazz.asSubclass(RunStyle.class);
      Constructor<? extends RunStyle> ctor = runStyleClass.getConstructor(JUnitShell.class);
      runStyle = ctor.newInstance(JUnitShell.this);
      return runStyle.initialize(args);
    } catch (ClassNotFoundException e) {
      // special error message for CNFE since it is likely a typo
      String msg = "Unable to create runStyle \"" + runStyleName + "\"";
      if (runStyleName.indexOf('.') < 0 && runStyleName.length() > 0
          && Character.isLowerCase(runStyleName.charAt(0))) {
        // apparently using a built-in runstyle with an initial lowercase letter
        msg += " - did you mean \""
            + Character.toUpperCase(runStyleName.charAt(0))
            + runStyleName.substring(1) + "\"?";
      } else {
        msg += " -- is it spelled correctly?";
      }
      getTopLogger().log(TreeLogger.ERROR, msg);
      return -1;
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (InstantiationException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e;
    }
    getTopLogger().log(TreeLogger.ERROR,
        "Unable to create runStyle \"" + runStyleName + "\"", caught);
    return -1;
  }

  private boolean mustNotExecuteTest(Set<Platform> bannedPlatforms) {
    // TODO (amitmanjhi): Remove this hard-coding. A RunStyle somehow needs to
    // specify how it interacts with the platforms.
    if (runStyle instanceof RunStyleHtmlUnit
        && (bannedPlatforms.contains(Platform.HtmlUnitUnknown)
            || bannedPlatforms.contains(Platform.HtmlUnitLayout) || bannedPlatforms.contains(Platform.HtmlUnitBug))) {
      return true;
    }

    if (developmentMode) {
      if (bannedPlatforms.contains(Platform.Devel)) {
        return true;
      }
    } else {
      // Prod mode
      if (bannedPlatforms.contains(Platform.Prod)) {
        return true;
      }
    }

    return false;
  }

  private boolean mustRetry(int numTries) {
    if (numTries >= runStyle.getTries()) {
      return false;
    }
    assert (batchingStrategy instanceof NoBatchingStrategy);
    // checked in {@code checkArgs()}
    /*
     * If a batching strategy is being used, the client will already have moved
     * passed the failed test case. The whole block could be re-executed, but it
     * would be more complicated.
     */
    return true;
  }

  private void processTestResult(TestCase testCase, TestResult testResult,
      Strategy strategy) {

    Map<ClientStatus, JUnitResult> results = messageQueue.getResults(currentTestInfo);
    assert results != null;
    assert results.size() == messageQueue.getNumClients() : results.size()
        + " != " + messageQueue.getNumClients();

    for (Entry<ClientStatus, JUnitResult> entry : results.entrySet()) {
      ClientStatus client = entry.getKey();
      JUnitResult result = entry.getValue();
      assert (result != null);
      Throwable exception = result.getException();

      // Let the user know the browser in which the failure happened.
      if (exception != null) {
        String msg = "Remote test failed at " + client.getDesc();
        if (exception instanceof AssertionFailedError) {
          String oldMessage = exception.getMessage();
          if (oldMessage != null) {
            msg += "\n" + exception.getMessage();
          }
          AssertionFailedError newException = new AssertionFailedError(msg);
          newException.setStackTrace(exception.getStackTrace());
          newException.initCause(exception.getCause());
          exception = newException;
        } else {
          exception = new RuntimeException(msg, exception);
        }
      }

      // A "successful" failure.
      if (exception instanceof AssertionFailedError) {
        testResult.addFailure(testCase, (AssertionFailedError) exception);
      } else if (exception != null) {
        // A real failure
        if (exception instanceof JUnitFatalLaunchException) {
          lastLaunchFailed = true;
        }
        testResult.addError(testCase, exception);
      }

      strategy.processResult(testCase, result);
    }
  }

  private void runTestImpl(GWTTestCase testCase, TestResult testResult)
      throws UnableToCompleteException {
    runTestImpl(testCase, testResult, 0);
  }

  /**
   * Runs a particular test case.
   */
  private void runTestImpl(GWTTestCase testCase, TestResult testResult,
      int numTries) throws UnableToCompleteException {

    testBatchingMethodTimeoutMillis = batchingStrategy.getTimeoutMultiplier()
        * baseTestMethodTimeoutMillis;
    if (mustNotExecuteTest(getBannedPlatforms(testCase.getClass(),
        testCase.getName()))) {
      return;
    }

    if (lastLaunchFailed) {
      throw new UnableToCompleteException();
    }

    String moduleName = testCase.getModuleName();
    String syntheticModuleName = testCase.getSyntheticModuleName();
    Strategy strategy = testCase.getStrategy();
    boolean sameTest = (currentModule != null)
        && syntheticModuleName.equals(currentModule.getName());
    if (sameTest && lastLaunchFailed) {
      throw new UnableToCompleteException();
    }

    // Get the module definition for the current test.
    if (!sameTest) {
      currentModule = compileStrategy.maybeCompileModule(moduleName,
          syntheticModuleName, strategy, batchingStrategy, getTopLogger());
      currentCompilationState = currentModule.getCompilationState(getTopLogger());
    }
    assert (currentModule != null);

    JUnitFatalLaunchException launchException = checkTestClassInCurrentModule(
        currentCompilationState, moduleName, testCase);
    if (launchException != null) {
      testResult.addError(testCase, launchException);
      return;
    }

    currentTestInfo = new TestInfo(currentModule.getName(),
        testCase.getClass().getName(), testCase.getName());
    numTries++;
    if (messageQueue.hasResults(currentTestInfo)) {
      // Already have a result.
      processTestResult(testCase, testResult, strategy);
      return;
    }
    compileStrategy.maybeAddTestBlockForCurrentTest(testCase, batchingStrategy);

    try {
      if (firstLaunch) {
        runStyle.launchModule(currentModule.getName());
      }
    } catch (UnableToCompleteException e) {
      lastLaunchFailed = true;
      testResult.addError(testCase, new JUnitFatalLaunchException(e));
      return;
    }

    boolean mustRetry = mustRetry(numTries);
    // Wait for test to complete
    try {
      // Set a timeout period to automatically fail if the servlet hasn't been
      // contacted; something probably went wrong (the module failed to load?)
      testBeginTime = System.currentTimeMillis();
      testBeginTimeout = testBeginTime + baseTestBeginTimeoutMillis;
      testMethodTimeout = 0; // wait until test execution begins
      while (notDone()) {
        messageQueue.waitForResults(1000);
      }
      if (!mustRetry && pendingException != null) {
        UnableToCompleteException e = pendingException;
        pendingException = null;
        throw e;
      }
    } catch (TimeoutException e) {
      if (!mustRetry) {
        lastLaunchFailed = true;
        testResult.addError(testCase, e);
        return;
      }
    }

    if (mustRetry) {
      if (messageQueue.needsRerunning(currentTestInfo)) {
        // remove the result if it is present and rerun
        messageQueue.removeResults(currentTestInfo);
        getTopLogger().log(TreeLogger.WARN,
            currentTestInfo + " is being retried, retry attempt = " + numTries);
        runTestImpl(testCase, testResult, numTries);
        return;
      }
    }
    assert (messageQueue.hasResults(currentTestInfo));
    processTestResult(testCase, testResult, testCase.getStrategy());
  }

  /**
   * Synthesize command line arguments from a system property.
   */
  private String[] synthesizeArgs() {
    ArrayList<String> argList = new ArrayList<String>();

    String args = System.getProperty(PROP_GWT_ARGS);
    if (args != null) {
      // Match either a non-whitespace, non start of quoted string, or a
      // quoted string that can have embedded, escaped quoting characters
      //
      Pattern pattern = Pattern.compile("[^\\s\"]+|\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"");
      Matcher matcher = pattern.matcher(args);
      Pattern quotedArgsPattern = Pattern.compile("^([\"'])(.*)([\"'])$");

      while (matcher.find()) {
        // Strip leading and trailing quotes from the arg
        String arg = matcher.group();
        Matcher qmatcher = quotedArgsPattern.matcher(arg);
        if (qmatcher.matches()) {
          argList.add(qmatcher.group(2));
        } else {
          argList.add(arg);
        }
      }
    }

    return argList.toArray(new String[argList.size()]);
  }
}
