/*
 * 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.Linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.shared.SerializableThrowable;
import com.google.gwt.dev.ArgProcessorBase;
import com.google.gwt.dev.Compiler;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.CompilerOptions;
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.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.shell.jetty.JettyLauncher;
import com.google.gwt.dev.util.arg.ArgHandlerClosureFormattedOutput;
import com.google.gwt.dev.util.arg.ArgHandlerDeployDir;
import com.google.gwt.dev.util.arg.ArgHandlerDeprecatedDisableUpdateCheck;
import com.google.gwt.dev.util.arg.ArgHandlerDeprecatedOptimizeDataflow;
import com.google.gwt.dev.util.arg.ArgHandlerDisableCastChecking;
import com.google.gwt.dev.util.arg.ArgHandlerDisableClassMetadata;
import com.google.gwt.dev.util.arg.ArgHandlerDisableClusterSimilarFunctions;
import com.google.gwt.dev.util.arg.ArgHandlerDisableInlineLiteralParameters;
import com.google.gwt.dev.util.arg.ArgHandlerDisableOrdinalizeEnums;
import com.google.gwt.dev.util.arg.ArgHandlerDisableRemoveDuplicateFunctions;
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.ArgHandlerFilterJsInteropExports;
import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
import com.google.gwt.dev.util.arg.ArgHandlerGenerateJsInteropExports;
import com.google.gwt.dev.util.arg.ArgHandlerIncrementalCompile;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
import com.google.gwt.dev.util.arg.ArgHandlerNamespace;
import com.google.gwt.dev.util.arg.ArgHandlerOptimize;
import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
import com.google.gwt.dev.util.arg.ArgHandlerSetProperties;
import com.google.gwt.dev.util.arg.ArgHandlerSourceLevel;
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.JUnitHost.TestInfo;
import com.google.gwt.junit.client.impl.JUnitResult;
import com.google.gwt.thirdparty.guava.common.base.Splitter;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
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.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.webapp.WebAppContext;

import java.io.File;
import java.io.IOException;
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.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

/**
 * 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 getSyntheticModuleExtension();

    void processModule(ModuleDef module);
  }

  private static class ArgHandlerRunCompiledJavascript extends ArgHandlerFlag {

    private JUnitShell shell;

    public ArgHandlerRunCompiledJavascript(JUnitShell shell) {
      this.shell = shell;

      addTagValue("-web", false);
      addTagValue("-prod", false);
    }

    @Override
    public String getPurposeSnippet() {
      return "Runs tests in Development Mode, using the Java virtual machine.";
    }

    @Override
    public String getLabel() {
      return "devMode";
    }

    @Override
    public boolean setFlag(boolean enabled) {
      shell.developmentMode = enabled;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return shell.developmentMode;
    }
  }

  private static class ArgHandlerShowWindows extends ArgHandlerFlag {

    private JUnitShell shell;

    public ArgHandlerShowWindows(JUnitShell shell) {
      this.shell = shell;

      addTagValue("-notHeadless", true);
    }

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

    @Override
    public String getLabel() {
      return "showUi";
    }

    @Override
    public boolean setFlag(boolean enabled) {
      shell.setHeadless(!enabled);
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return !shell.isHeadless();
    }
  }

  static class ArgProcessor extends ArgProcessorBase {

    @SuppressWarnings("deprecation")
    public ArgProcessor(final JUnitShell shell) {
      final HostedModeOptions options = shell.options;
      /*
       * ----- 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 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(shell.new MyJettyLauncher());
      // DISABLE: ArgHandlerStartupURLs
      registerHandler(new ArgHandlerWarDir(options) {
        private static final String OUT_TAG = "-out";

        @Override
        public String[] getTags() {
          return new String[] {getTag(), OUT_TAG};
        }

        @Override
        public int handle(String[] args, int tagIndex) {
          if (OUT_TAG.equals(args[tagIndex])) {
            // -out is deprecated. Print a warning message
            System.err.println("The -out option is deprecated. This option will be removed in " +
                "future GWT release and will throw an error if it is still used. Please use -war " +
                "option instead.");
          }
          return super.handle(args, tagIndex);
        }
      });

      registerHandler(new ArgHandlerDeployDir(options));
      registerHandler(new ArgHandlerExtraDir(options));
      registerHandler(new ArgHandlerWorkDirOptional(options));
      registerHandler(new ArgHandlerSourceLevel(options));

      // DISABLE: ArgHandlerModuleName

      /*
       * ----- Additional options from Compiler not already included -------
       */
      registerHandler(new ArgHandlerScriptStyle(options));
      registerHandler(new ArgHandlerEnableAssertions(options));
      registerHandler(new ArgHandlerDisableCastChecking(options));
      registerHandler(new ArgHandlerDisableClassMetadata(options));
      registerHandler(new ArgHandlerDisableClusterSimilarFunctions(options));
      registerHandler(new ArgHandlerDisableInlineLiteralParameters(options));
      registerHandler(new ArgHandlerDeprecatedOptimizeDataflow(options));
      registerHandler(new ArgHandlerDisableOrdinalizeEnums(options));
      registerHandler(new ArgHandlerDisableRemoveDuplicateFunctions(options));
      registerHandler(new ArgHandlerDisableRunAsync(options));
      registerHandler(new ArgHandlerDeprecatedDisableUpdateCheck());
      registerHandler(new ArgHandlerDraftCompile(options));
      registerHandler(new ArgHandlerLocalWorkers(options));
      registerHandler(new ArgHandlerNamespace(options));
      registerHandler(new ArgHandlerOptimize(options));
      registerHandler(new ArgHandlerIncrementalCompile(options));
      registerHandler(new ArgHandlerGenerateJsInteropExports(options));
      registerHandler(new ArgHandlerFilterJsInteropExports(options));
      registerHandler(new ArgHandlerSetProperties(options));
      registerHandler(new ArgHandlerClosureFormattedOutput(options));

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

      // Override log level to set WARN by default.
      registerHandler(new ArgHandlerLogLevel(options, TreeLogger.WARN));

      registerHandler(new ArgHandlerRunCompiledJavascript(shell));

      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) {
          shell.baseTestMethodTimeoutMillis = minutes * 60 * 1000;
        }
      });

      registerHandler(new ArgHandlerInt() {
        @Override
        public String[] getDefaultArgs() {
          return new String[]{getTag(), String.valueOf(DEFAULT_BEGIN_TIMEOUT_MINUTES)};
        }

        @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) {
          shell.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) {
          shell.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")) {
            shell.batchingStrategy = new NoBatchingStrategy();
          } else if (str.equals("class")) {
            shell.batchingStrategy = new ClassBatchingStrategy();
          } else if (str.equals("module")) {
            shell.batchingStrategy = new ModuleBatchingStrategy();
          } else {
            return false;
          }
          return true;
        }
      });

      registerHandler(new ArgHandlerShowWindows(shell));

      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")) {
            shell.compileStrategy = new SimpleCompileStrategy(shell);
          } else if (str.equals("all")) {
            shell.compileStrategy = new PreCompileStrategy(shell);
          } else if (str.equals("parallel")) {
            shell.compileStrategy = new ParallelCompileStrategy(shell);
          } else {
            return false;
          }
          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) {
          shell.tries = value;
        }

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

      registerHandler(new ArgHandlerString() {

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

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

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

        @Override
        public boolean setString(String str) {
          Splitter splitter = Splitter.on(",").omitEmptyStrings().trimResults();
          shell.userAgentsOpt = ImmutableSet.copyOf(splitter.split(str));
          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.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");

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

  /**
   * How many minutes to wait for the browser to contact the test system.
   */
  private static final int DEFAULT_BEGIN_TIMEOUT_MINUTES = 1;

  /**
   * 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 set of remote user agents to compile.
   *
   * @return the set of remote user agents
   */
  public static Set<String> getRemoteUserAgents() {
    if (unitTestShell == null) {
      return null;
    }
    return unitTestShell.runStyle.getUserAgents();
  }

  /**
   * Get the compiler options
   *
   * @return the compiler options that have been set.
   */
  public static CompilerOptions getCompilerOptions() {
    if (unitTestShell == null) {
      return null;
    }
    return unitTestShell.options;
  }

  /**
   * 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);
  }

  /**
   * 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 = new ArgProcessor(unitTestShell);
      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(TreeLogger logger,
      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 {
      CompilationProblemReporter.logErrorTrace(logger, TreeLogger.ERROR,
          compilationState.getCompilerContext(), typeName, true);
      errMsg = "The test class '" + typeName
          + "' had compile errors; check log for details";
    }
    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 = false;

  /**
   * Used to make sure we don't start the runStyle more than once.
   */
  private boolean runStyleStarted;

  /**
   * If true, we haven't started all the clients yet. (Used for manual mode.)
   */
  private boolean waitingForClients = 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 so we can limit permutations for remote tests.
   */
  Set<String> userAgentsOpt; // Visible for testing

  /**
   * 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";

  /**
   * 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;

  /**
   * Visible for testing only. (See {@link #getUnitTestShell}.)
   */
  JUnitShell() {
    setRunTomcat(true);
    setHeadless(true);
  }

  public String getModuleUrl(String moduleName) {
    // TODO(manolo): consider using DevModeBase.normalizeURL
    // and DevModeBase.makeStartupUrl instead.
    String localhost = runStyle.getLocalHostName();
    int codeServerPort = developmentMode ? listener.getSocketPort() : 0;
    return getModuleUrl(localhost, getPort(), moduleName, codeServerPort);
  }

  public CompilerContext getCompilerContext() {
    return compilerContext;
  }

  @Override
  protected HostedModeOptions createOptions() {
    HostedModeOptions options = super.createOptions();
    options.setSuperDevMode(false);
    options.setIncrementalCompileEnabled(false);
    return options;
  }

  @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 (userAgentsOpt != null) {
      runStyle.setUserAgents(userAgentsOpt);
    }

    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 (runStyle instanceof RunStyleManual && waitingForClients) {
      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;
      }
      waitingForClients = false;
    }

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

      /*
       * 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, Set<String> userAgents)
      throws UnableToCompleteException {
    if (userAgents != null && !userAgents.isEmpty()) {
      Properties props = module.getProperties();
      Property userAgent = props.find("user.agent");
      if (userAgent instanceof BindingProperty) {
        BindingProperty bindingProperty = (BindingProperty) userAgent;
        bindingProperty.setRootGeneratedValues(userAgents.toArray(new String[0]));
      }
    }

    if (options.isClosureCompilerFormatEnabled()) {
      module.addLinker("closureHelpers");
    }

    boolean success = false;
    try {
      success = Compiler.compile(getTopLogger(), options, module);
    } catch (Exception e) {
      getTopLogger().log(Type.ERROR, "Compiler aborted with an exception ", e);
    }
    if (!success) {
      throw new UnableToCompleteException();
    }
    // TODO(scottb): prepopulate currentCompilationState somehow?
  }

  String getModuleUrl(String hostName, int port, String moduleName, int codeServerPort) {
    String url = "http://" + hostName + ":" + port + "/" + moduleName + "/junit.html";
    if (developmentMode) {
      url += "?gwt.codesvr=" + hostName + ":" + codeServerPort;
    }
    return url;
  }

  void maybeCompileForWebMode(ModuleDef module, Set<String> userAgents)
      throws UnableToCompleteException {
    compilerContext = compilerContextBuilder.module(module).build();
    // 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 {
          // We should load the class ourselves because otherwise if Jetty tries and fails to load
          // by itself, it will be left in a broken state (looks like this is fixed in Jetty 9).
          Class<? extends Servlet> clazz = wac.loadClass(servletClass).asSubclass(Servlet.class);
          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);
        }
      }
    }
    BindingProperty strictCspTestingEnabledProperty =
        module.getProperties().findBindingProp("gwt.strictCspTestingEnabled");

    if (strictCspTestingEnabledProperty != null &&
        "true".equals(strictCspTestingEnabledProperty.getConstrainedValue())) {
      addCspFilter("/" + module.getName() + "/*");
    }
    if (developmentMode) {
      // BACKWARDS COMPATIBILITY: many linkers currently fail in dev mode.
      try {
        Linker l = module.getActivePrimaryLinker().newInstance();
        StandardLinkerContext context = new StandardLinkerContext(
            getTopLogger(), module, compilerContext.getPublicResourceOracle(),
            JsOutputOption.PRETTY);
        if (!l.supportsDevModeInJunit(context)) {
          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);
    }
  }

  /**
   * Adds a filter to the server that automatically adds Content-Security-Policy HTTP headers to
   * responses on the given path.
   */
  private void addCspFilter(String path) {
    wac.addFilter(new FilterHolder(new Filter() {
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {

        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.addHeader("Content-Security-Policy",
            "script-src 'nonce-gwt-nonce' 'unsafe-inline' 'strict-dynamic' https: http: " +
            "'unsafe-eval' 'report-sample'");

        chain.doFilter(request, response);
      }

      @Override
      public void init(FilterConfig arg0) throws ServletException { }

      @Override
      public void destroy() { }
    }), path, EnumSet.of(DispatcherType.REQUEST));
  }

  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) {
    if (!Collections.disjoint(bannedPlatforms, runStyle.getPlatforms())) {
      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) {

    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()) {
      JUnitResult result = entry.getValue();
      assert (result != null);

      if (result.isAnyException()) {
        if (result.isExceptionOf(AssertionFailedError.class)) {
          testResult.addFailure(testCase, toAssertionFailedError(result.getException()));
        } else {
          testResult.addError(testCase, result.getException());
        }
      }
    }
  }

  private AssertionFailedError toAssertionFailedError(SerializableThrowable thrown) {
    AssertionFailedError error = new AssertionFailedError(thrown.getMessage());
    error.setStackTrace(thrown.getStackTrace());
    if (thrown.getCause() != null) {
      error.initCause(thrown.getCause());
    }
    return error;
  }

  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) {
      try {
        currentModule = compileStrategy.maybeCompileModule(moduleName,
            syntheticModuleName, strategy, batchingStrategy, getTopLogger());
        compilerContext = compilerContextBuilder.module(currentModule).build();
        currentCompilationState = currentModule.getCompilationState(getTopLogger(),
            compilerContext);
      } catch (UnableToCompleteException e) {
        lastLaunchFailed = true;
        throw e;
      }
    }
    assert (currentModule != null);

    JUnitFatalLaunchException launchException = checkTestClassInCurrentModule(getTopLogger(),
        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);
      return;
    }
    compileStrategy.maybeAddTestBlockForCurrentTest(testCase, batchingStrategy);

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

    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);
  }

  /**
   * 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()]);
  }
}
