Re-rolling r7955: JUnitShell now subclasses DevMode instead of GWTShell.
http://gwt-code-reviews.appspot.com/361801/show
Review by: jlabanca,jat,spoon,fabbott,amitmanjhi
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7971 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java
index 7024343..31d8286 100644
--- a/dev/core/src/com/google/gwt/dev/Compiler.java
+++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -165,6 +165,16 @@
}
public boolean run(TreeLogger logger) throws UnableToCompleteException {
+ ModuleDef[] modules = new ModuleDef[options.getModuleNames().size()];
+ int i = 0;
+ for (String moduleName : options.getModuleNames()) {
+ modules[i++] = ModuleDefLoader.loadFromClassPath(logger, moduleName, true);
+ }
+ return run(logger, modules);
+ }
+
+ public boolean run(TreeLogger logger, ModuleDef... modules)
+ throws UnableToCompleteException {
PerfLogger.start("compile");
boolean tempWorkDir = false;
try {
@@ -176,10 +186,8 @@
options.setExtraDir(new File("extras"));
}
- for (String moduleName : options.getModuleNames()) {
- ModuleDef module = ModuleDefLoader.loadFromClassPath(logger,
- moduleName, true);
-
+ for (ModuleDef module : modules) {
+ String moduleName = module.getCanonicalName();
if (options.isValidateOnly()) {
if (!Precompile.validate(logger, options, module,
options.getGenDir(), options.getDumpSignatureFile())) {
diff --git a/dev/core/src/com/google/gwt/dev/DevMode.java b/dev/core/src/com/google/gwt/dev/DevMode.java
index 4b1f0b0..5dda46e 100644
--- a/dev/core/src/com/google/gwt/dev/DevMode.java
+++ b/dev/core/src/com/google/gwt/dev/DevMode.java
@@ -155,7 +155,10 @@
}
}
- static class ArgProcessor extends DevModeBase.ArgProcessor {
+ /**
+ * The argument processor.
+ */
+ protected static class ArgProcessor extends DevModeBase.ArgProcessor {
public ArgProcessor(HostedModeOptions options) {
super(options, false);
registerHandler(new ArgHandlerServer(options));
@@ -177,7 +180,11 @@
}
}
- interface HostedModeOptions extends HostedModeBaseOptions, CompilerOptions {
+ /**
+ * Options controlling dev mode.
+ */
+ protected interface HostedModeOptions extends HostedModeBaseOptions,
+ CompilerOptions {
ServletContainerLauncher getServletContainerLauncher();
String getServletContainerLauncherArgs();
@@ -190,11 +197,10 @@
/**
* Concrete class to implement all hosted mode options.
*/
- static class HostedModeOptionsImpl extends HostedModeBaseOptionsImpl
- implements HostedModeOptions {
+ protected static class HostedModeOptionsImpl extends
+ HostedModeBaseOptionsImpl implements HostedModeOptions {
private File extraDir;
private int localWorkers;
- private File outDir;
private ServletContainerLauncher scl;
private String sclArgs;
private File warDir;
@@ -209,7 +215,7 @@
@Deprecated
public File getOutDir() {
- return outDir;
+ return warDir;
}
public ServletContainerLauncher getServletContainerLauncher() {
@@ -234,7 +240,7 @@
@Deprecated
public void setOutDir(File outDir) {
- this.outDir = outDir;
+ this.warDir = outDir;
}
public void setServletContainerLauncher(ServletContainerLauncher scl) {
@@ -300,7 +306,7 @@
/**
* Default constructor for testing; no public API yet.
*/
- DevMode() {
+ protected DevMode() {
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/DevModeBase.java b/dev/core/src/com/google/gwt/dev/DevModeBase.java
index b7a9eb7..2d1f2a7 100644
--- a/dev/core/src/com/google/gwt/dev/DevModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/DevModeBase.java
@@ -62,7 +62,7 @@
* The main executable class for the hosted mode shell. This class must not have
* any GUI dependencies.
*/
-abstract class DevModeBase implements DoneCallback {
+public abstract class DevModeBase implements DoneCallback {
/**
* Implementation of BrowserWidgetHost that supports the abstract UI
@@ -165,6 +165,9 @@
* Handles the -blacklist command line argument.
*/
protected static class ArgHandlerBlacklist extends ArgHandlerString {
+ public ArgHandlerBlacklist() {
+ }
+
@Override
public String getPurpose() {
return "Prevents the user browsing URLs that match the specified regexes (comma or space separated)";
@@ -343,6 +346,9 @@
}
}
+ /**
+ * Handles the -remoteUI command line flag.
+ */
protected static class ArgHandlerRemoteUI extends ArgHandlerString {
private final HostedModeBaseOptions options;
@@ -407,6 +413,9 @@
* Handles the -whitelist command line flag.
*/
protected static class ArgHandlerWhitelist extends ArgHandlerString {
+ public ArgHandlerWhitelist() {
+ }
+
@Override
public String getPurpose() {
return "Allows the user to browse URLs that match the specified regexes (comma or space separated)";
@@ -428,6 +437,9 @@
}
}
+ /**
+ * Base options for dev mode.
+ */
protected interface HostedModeBaseOptions extends JJSOptions, OptionLogDir,
OptionLogLevel, OptionGenDir, OptionNoServer, OptionPort,
OptionCodeServerPort, OptionStartupURLs, OptionRemoteUI,
@@ -548,6 +560,9 @@
}
}
+ /**
+ * Controls what local address to bind to.
+ */
protected interface OptionBindAddress {
String getBindAddress();
@@ -558,6 +573,9 @@
void setConnectAddress(String connectAddress);
}
+ /**
+ * Controls what port the code server listens on.
+ */
protected interface OptionCodeServerPort {
int getCodeServerPort();
@@ -626,7 +644,10 @@
List<String> getStartupURLs();
}
- abstract static class ArgProcessor extends ArgProcessorBase {
+ /**
+ * The base dev mode argument processor.
+ */
+ protected abstract static class ArgProcessor extends ArgProcessorBase {
public ArgProcessor(HostedModeBaseOptions options, boolean forceServer) {
if (!forceServer) {
registerHandler(new ArgHandlerNoServerFlag(options));
diff --git a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java
index 4663d23..3dedb92 100644
--- a/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java
+++ b/dev/core/src/com/google/gwt/dev/shell/jetty/JettyLauncher.java
@@ -533,8 +533,7 @@
server.addConnector(connector);
// Create a new web app in the war directory.
- WebAppContext wac = new WebAppContextWithReload(logger,
- appRootDir.getAbsolutePath(), "/");
+ WebAppContext wac = createWebAppContext(logger, appRootDir);
RequestLogHandler logHandler = new RequestLogHandler();
logHandler.setRequestLog(new JettyRequestLogger(logger, getBaseLogLevel()));
@@ -546,8 +545,18 @@
// Now that we're started, log to the top level logger.
Log.setLog(new JettyTreeLogger(logger));
- return new JettyServletContainer(logger, server, wac,
- connector.getLocalPort(), appRootDir);
+ return createServletContainer(logger, appRootDir, server, wac,
+ connector.getLocalPort());
+ }
+
+ protected JettyServletContainer createServletContainer(TreeLogger logger,
+ File appRootDir, Server server, WebAppContext wac, int localPort) {
+ return new JettyServletContainer(logger, server, wac, localPort, appRootDir);
+ }
+
+ protected WebAppContext createWebAppContext(TreeLogger logger, File appRootDir) {
+ return new WebAppContextWithReload(logger, appRootDir.getAbsolutePath(),
+ "/");
}
protected AbstractConnector getConnector() {
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWarDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWarDir.java
index 5077850..1f14f90 100644
--- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWarDir.java
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWarDir.java
@@ -22,7 +22,7 @@
/**
* Argument handler for processing the output directory flag.
*/
-public final class ArgHandlerWarDir extends ArgHandlerDir {
+public class ArgHandlerWarDir extends ArgHandlerDir {
private final OptionWarDir option;
diff --git a/eclipse/user/.classpath b/eclipse/user/.classpath
index 9f5fd37..0765257 100644
--- a/eclipse/user/.classpath
+++ b/eclipse/user/.classpath
@@ -31,5 +31,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/gwt-dev"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-r5607/htmlunit-r5607.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-r5607/htmlunit-r5607-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-r5607/htmlunit-core-js-r5607.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-r5607/htmlunit-core-js-r5607-sources.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/jetty/jetty-6.1.11.jar" sourcepath="/GWT_TOOLS/lib/jetty/jetty-6.1.11-src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/user/build.xml b/user/build.xml
index 8af9a42..cac355b 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -36,13 +36,6 @@
<property name="test.args.web.selenium" value="${test.args}" />
<!--
- Only IFrameLinker actually supports -noserver mode; run the other linker
- tests if and when they are supported
- -->
- <property name="gwt.junit.testcase.noserver.includes" value="**/IFrameLinkerTest.class" />
- <property name="gwt.junit.testcase.noserver.excludes" value="" />
-
- <!--
Whether I18NSuite should test e.g. Foo$InnerMsgs_fr.properties (if the
value is "dollar") or Foo_Inner_fr.properties (for "bar")
-->
@@ -394,22 +387,6 @@
<echo message="DEPRECATED: test.hosted has been renamed test.dev"/>
</target>
- <target name="test.noserver"
- depends="compile, compile.tests"
- description="Run noserver tests for this project."
- unless="test.noserver.disable">
- <fileset id="test.noserver.tests" dir="${javac.junit.out}"
- includes="${gwt.junit.testcase.noserver.includes}"
- excludes="${gwt.junit.testcase.noserver.excludes}" />
- <gwt.junit test.name="test.noserver"
- test.args="${test.args} -prod -standardsMode -noserver"
- test.out="${junit.out}/noserver" test.cases="test.noserver.tests">
- <extraclasspaths>
- <path refid="test.extraclasspath" />
- </extraclasspaths>
- </gwt.junit>
- </target>
-
<target name="test.web.htmlunit"
depends="compile, compile.tests"
description="Run web-mode tests with HtmlUnit."
@@ -489,7 +466,6 @@
<antcall target="test.web.selenium"/>
<antcall target="test.draft.selenium"/>
<antcall target="test.nometa.selenium"/>
- <antcall target="test.noserver"/>
<antcall target="test.dev.htmlunit"/>
<antcall target="test.emma.htmlunit"/>
<antcall target="test.web.htmlunit"/>
@@ -516,7 +492,6 @@
<antcall target="test.web.htmlunit"/>
<antcall target="test.draft.htmlunit"/>
<antcall target="test.nometa.htmlunit"/>
- <antcall target="test.noserver"/>
</parallel>
</limit>
</target>
diff --git a/user/src/com/google/gwt/junit/CompileStrategy.java b/user/src/com/google/gwt/junit/CompileStrategy.java
index b6917b7..cc62ecd 100644
--- a/user/src/com/google/gwt/junit/CompileStrategy.java
+++ b/user/src/com/google/gwt/junit/CompileStrategy.java
@@ -181,7 +181,7 @@
strategy.processModule(moduleDef);
- junitShell.maybeCompileForWebMode(syntheticModuleName,
+ junitShell.maybeCompileForWebMode(moduleDef,
JUnitShell.getRemoteUserAgents());
return moduleDef;
diff --git a/user/src/com/google/gwt/junit/JUnit.gwt.xml b/user/src/com/google/gwt/junit/JUnit.gwt.xml
index 8963a34..c2ae43c 100644
--- a/user/src/com/google/gwt/junit/JUnit.gwt.xml
+++ b/user/src/com/google/gwt/junit/JUnit.gwt.xml
@@ -38,7 +38,7 @@
<!-- Override the regular symbolMaps linker to put the data somewhere we can find it -->
<define-linker name="symbolMaps" class="com.google.gwt.junit.linker.JUnitSymbolMapsLinker" />
- <servlet path='/junithost' class='com.google.gwt.junit.server.JUnitHostImpl'/>
+ <servlet path='/junithost/*' class='com.google.gwt.junit.server.JUnitHostImpl'/>
<inherits name="com.google.gwt.benchmarks.Benchmarks"/>
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index 4c0e927..2c2ff0f 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -20,26 +20,31 @@
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.GWTCompiler;
-import com.google.gwt.dev.GWTShell;
-import com.google.gwt.dev.LegacyCompilerOptions;
-import com.google.gwt.dev.GWTCompiler.GWTCompilerOptionsImpl;
+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.ModuleDefLoader;
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;
@@ -53,6 +58,10 @@
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;
@@ -61,6 +70,7 @@
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;
@@ -96,8 +106,7 @@
* {@link JUnitMessageQueue}, thus closing the loop.
* </p>
*/
-@SuppressWarnings("deprecation")
-public class JUnitShell extends GWTShell {
+public class JUnitShell extends DevMode {
/**
* A strategy for running the test.
@@ -112,54 +121,73 @@
void processResult(TestCase testCase, JUnitResult result);
}
- class ArgProcessor extends GWTShell.ArgProcessor {
+ class ArgProcessor extends ArgProcessorBase {
+ @SuppressWarnings("deprecation")
public ArgProcessor() {
- super(options, true, true);
+ /*
+ * ----- 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));
- // Override port to set auto by default.
- registerHandler(new ArgHandlerPort(options) {
- @Override
- public String[] getDefaultArgs() {
- return new String[]{"-port", "auto"};
- }
- });
-
- // Override port to set auto by default.
- registerHandler(new ArgHandlerCodeServerPort(options) {
- @Override
- public String[] getDefaultArgs() {
- return new String[]{this.getTag(), "auto"};
- }
- });
-
- // Disable -bindAddress, fail if it is given
- // TODO(jat): support -bindAddress in JUnitShell, which will probably
- // require changes to the RunStyle API.
- registerHandler(new ArgHandlerBindAddress(options) {
- @Override
- public String[] getDefaultArgs() {
- return null;
- }
-
- @Override
- public boolean isUndocumented() {
- return true;
- }
-
- @Override
- public boolean setString(String value) {
- System.err.println("-bindAddress is not supported for JUnitShell");
- return false;
- }
- });
+ /*
+ * ----- Options specific to JUnitShell -----
+ */
// Override log level to set WARN by default..
registerHandler(new ArgHandlerLogLevel(options) {
@@ -172,24 +200,6 @@
registerHandler(new ArgHandlerFlag() {
@Override
public String getPurpose() {
- return "Causes your test to run in -noserver development mode (defaults to development mode)";
- }
-
- @Override
- public String getTag() {
- return "-noserver";
- }
-
- @Override
- public boolean setFlag() {
- shouldAutoGenerateResources = false;
- return true;
- }
- });
-
- registerHandler(new ArgHandlerFlag() {
- @Override
- public String getPurpose() {
return "Synonym for -prod (deprecated)";
}
@@ -374,7 +384,7 @@
@Override
public boolean setFlag() {
- setHeadlessAccessor(false);
+ JUnitShell.this.setHeadless(false);
return true;
}
});
@@ -492,6 +502,49 @@
}
});
}
+
+ @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).
+ */
+ @SuppressWarnings("unchecked")
+ @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);
+ }
+ };
+ }
}
/**
@@ -597,6 +650,39 @@
}
/**
+ * 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");
+ }
+ 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.
@@ -660,37 +746,9 @@
}
/**
- * Retrieves the JUnitShell. This should only be invoked during TestRunner
- * execution of JUnit tests.
+ * Our server's web app context; used to dynamically add servlets.
*/
- private 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");
- }
- 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;
- }
+ WebAppContext wac;
/**
* The amount of time to wait for all clients to have contacted the server and
@@ -758,6 +816,11 @@
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;
@@ -785,8 +848,6 @@
*/
private String runStyleName = "HtmlUnit";
- private boolean shouldAutoGenerateResources = true;
-
private boolean standardsMode = false;
/**
@@ -987,20 +1048,12 @@
}
@Override
- protected boolean shouldAutoGenerateResources() {
- return shouldAutoGenerateResources;
- }
-
- @Override
protected void warnAboutNoStartupUrls() {
// do nothing -- JUnitShell isn't expected to have startup URLs
}
- void compileForWebMode(String moduleName, String... userAgents)
+ void compileForWebMode(ModuleDef module, String... userAgents)
throws UnableToCompleteException {
- // Never fresh during JUnit.
- ModuleDef module = ModuleDefLoader.loadFromClassPath(getTopLogger(),
- moduleName, false);
if (userAgents != null && userAgents.length > 0) {
Properties props = module.getProperties();
Property userAgent = props.find("user.agent");
@@ -1010,28 +1063,41 @@
userAgents);
}
}
- LegacyCompilerOptions newOptions = new GWTCompilerOptionsImpl(options);
- if (!new GWTCompiler(newOptions).run(getTopLogger(), module)) {
+ if (!new Compiler(options).run(getTopLogger(), module)) {
throw new UnableToCompleteException();
}
// TODO(scottb): prepopulate currentCompilationState somehow?
}
- void maybeCompileForWebMode(String moduleName, String... userAgents)
+ void maybeCompileForWebMode(ModuleDef module, String... userAgents)
throws UnableToCompleteException {
- if (!developmentMode || !shouldAutoGenerateResources) {
- compileForWebMode(moduleName, userAgents);
+ // 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);
+ }
+ }
}
- }
-
- /**
- * Accessor method to DevModeBase.setHeadless -- without this, we get
- * IllegalAccessError from the -notHeadless arg handler. Compiler bug?
- *
- * @param headlessMode
- */
- void setHeadlessAccessor(boolean headlessMode) {
- setHeadless(headlessMode);
+ if (developmentMode) {
+ // BACKWARDS COMPATIBILITY: most linkers currently fail in dev mode.
+ if (module.getLinker("std") != null) {
+ // TODO: unfortunately, this could be race condition between dev/prod
+ module.addLinker("std");
+ }
+ super.link(getTopLogger(), module);
+ } else {
+ compileForWebMode(module, userAgents);
+ }
}
/**
diff --git a/user/src/com/google/gwt/junit/server/JUnitHostImpl.java b/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
index 958d05a..1915918 100644
--- a/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
+++ b/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
@@ -111,10 +111,11 @@
public InitialResponse getTestBlock(int blockIndex, ClientInfo clientInfo)
throws TimeoutException {
ClientInfoExt clientInfoExt;
+ HttpServletRequest request = getThreadLocalRequest();
if (clientInfo.getSessionId() < 0) {
- clientInfoExt = createNewClientInfo(clientInfo.getUserAgent());
+ clientInfoExt = createNewClientInfo(clientInfo.getUserAgent(), request);
} else {
- clientInfoExt = createClientInfo(clientInfo);
+ clientInfoExt = createClientInfo(clientInfo, request);
}
TestBlock initialTestBlock = getHost().getTestBlock(clientInfoExt,
blockIndex, TIME_TO_WAIT_FOR_TESTNAME);
@@ -131,7 +132,8 @@
result.setException(deserialize(ew));
}
JUnitMessageQueue host = getHost();
- ClientInfoExt clientInfoExt = createClientInfo(clientInfo);
+ ClientInfoExt clientInfoExt = createClientInfo(clientInfo,
+ getThreadLocalRequest());
host.reportResults(clientInfoExt, results);
return host.getTestBlock(clientInfoExt, testBlock,
TIME_TO_WAIT_FOR_TESTNAME);
@@ -146,21 +148,23 @@
JUnitResult result = new JUnitResult();
initResult(request, result);
result.setException(new JUnitFatalLaunchException(requestPayload));
- getHost().reportFatalLaunch(createNewClientInfo(null), result);
+ getHost().reportFatalLaunch(createNewClientInfo(null, request), result);
} else {
super.service(request, response);
}
}
- private ClientInfoExt createClientInfo(ClientInfo clientInfo) {
+ private ClientInfoExt createClientInfo(ClientInfo clientInfo,
+ HttpServletRequest request) {
assert (clientInfo.getSessionId() >= 0);
return new ClientInfoExt(clientInfo.getSessionId(),
- clientInfo.getUserAgent(), getClientDesc(getThreadLocalRequest()));
+ clientInfo.getUserAgent(), getClientDesc(request));
}
- private ClientInfoExt createNewClientInfo(String userAgent) {
+ private ClientInfoExt createNewClientInfo(String userAgent,
+ HttpServletRequest request) {
return new ClientInfoExt(createSessionId(), userAgent,
- getClientDesc(getThreadLocalRequest()));
+ getClientDesc(request));
}
private int createSessionId() {
@@ -346,12 +350,12 @@
JsniRef ref = JsniRef.parse(parts[0].substring(0,
parts[0].lastIndexOf(')') + 1));
- toReturn = new Object[] {
+ toReturn = new Object[]{
ref.className(), ref.memberName(), stw.fileName, stw.lineNumber};
} else {
// Use the raw data from the client
- toReturn = new Object[] {
+ toReturn = new Object[]{
stw.className, stw.methodName, stw.fileName, stw.lineNumber};
}
return toReturn;
diff --git a/user/test-super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java b/user/test-super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java
new file mode 100644
index 0000000..ffdda16
--- /dev/null
+++ b/user/test-super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 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.client;
+
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+import junit.framework.TestCase;
+
+/**
+ * Translatable trivial implementation.
+ */
+@DoNotRunWith(Platform.Prod)
+public class DevModeOnCompiledScriptTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.junit.DevModeWithCompiledScriptTest";
+ }
+
+ public void testSomethingTrivial() {
+ assertTrue(true);
+ }
+}
diff --git a/user/test/com/google/gwt/core/ext/test/XSLinkerTest.java b/user/test/com/google/gwt/core/ext/test/XSLinkerTest.java
index 9b9d019..64da6cd 100644
--- a/user/test/com/google/gwt/core/ext/test/XSLinkerTest.java
+++ b/user/test/com/google/gwt/core/ext/test/XSLinkerTest.java
@@ -15,9 +15,13 @@
*/
package com.google.gwt.core.ext.test;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
/**
* Tests the cross-site linker.
*/
+@DoNotRunWith(Platform.Devel)
public class XSLinkerTest extends LinkerTest {
@Override
public String getModuleName() {
diff --git a/user/test/com/google/gwt/dev/jjs/RunAsyncFailure.gwt.xml b/user/test/com/google/gwt/dev/jjs/RunAsyncFailure.gwt.xml
index 9e5ae07..0fa0e34 100644
--- a/user/test/com/google/gwt/dev/jjs/RunAsyncFailure.gwt.xml
+++ b/user/test/com/google/gwt/dev/jjs/RunAsyncFailure.gwt.xml
@@ -15,7 +15,7 @@
<module>
<inherits name="com.google.gwt.core.Core" />
<source path="test" />
- <servlet path="/runAsyncFailure"
+ <servlet path="/runAsyncFailure/*"
class="com.google.gwt.user.server.runasync.RunAsyncFailureServlet" />
<set-configuration-property name="iframe.linker.deferredjs.subdir"
value="runAsyncFailure/deferredjs" />
diff --git a/user/test/com/google/gwt/http/RequestBuilderTest.gwt.xml b/user/test/com/google/gwt/http/RequestBuilderTest.gwt.xml
index 0a5e76f..9e01f79 100644
--- a/user/test/com/google/gwt/http/RequestBuilderTest.gwt.xml
+++ b/user/test/com/google/gwt/http/RequestBuilderTest.gwt.xml
@@ -15,6 +15,6 @@
<module>
<inherits name='com.google.gwt.user.User' />
- <servlet path='/testRequestBuilder'
+ <servlet path='/testRequestBuilder/*'
class='com.google.gwt.http.server.RequestBuilderTestServlet' />
</module>
diff --git a/user/test/com/google/gwt/http/ResponseTest.gwt.xml b/user/test/com/google/gwt/http/ResponseTest.gwt.xml
index e3c0479..55735ff 100644
--- a/user/test/com/google/gwt/http/ResponseTest.gwt.xml
+++ b/user/test/com/google/gwt/http/ResponseTest.gwt.xml
@@ -15,6 +15,6 @@
<module>
<inherits name='com.google.gwt.user.User' />
- <servlet path='/testResponse'
+ <servlet path='/testResponse/*'
class='com.google.gwt.http.server.ResponseTestServlet' />
</module>
diff --git a/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java b/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
index e07692b..abfef22 100644
--- a/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
+++ b/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
@@ -30,10 +30,6 @@
*/
public class RequestBuilderTestServlet extends HttpServlet {
- private static String getPathInfoBase() {
- return "/com.google.gwt.http.RequestBuilderTest.JUnit/testRequestBuilder/";
- }
-
@Override
protected void doDelete(HttpServletRequest request,
HttpServletResponse response) {
@@ -49,7 +45,7 @@
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String pathInfo = request.getPathInfo();
- if (pathInfo.equals(getPathInfoBase() + "setRequestHeader")) {
+ if (pathInfo.equals("/setRequestHeader")) {
String value = request.getHeader("Foo");
if (value.equals("Bar1")) {
response.setStatus(HttpServletResponse.SC_OK);
@@ -57,13 +53,13 @@
} else {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
- } else if (pathInfo.equals(getPathInfoBase() + "send_GET")) {
+ } else if (pathInfo.equals("/send_GET")) {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write(RequestBuilderTest.SERVLET_GET_RESPONSE);
- } else if (pathInfo.equals(getPathInfoBase() + "sendRequest_GET")) {
+ } else if (pathInfo.equals("/sendRequest_GET")) {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write(RequestBuilderTest.SERVLET_GET_RESPONSE);
- } else if (pathInfo.equals(getPathInfoBase() + "setTimeout/timeout")) {
+ } else if (pathInfo.equals("/setTimeout/timeout")) {
// cause a timeout on the client
try {
Thread.sleep(5000);
@@ -71,7 +67,7 @@
}
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(RequestBuilderTest.SERVLET_GET_RESPONSE);
- } else if (pathInfo.equals(getPathInfoBase() + "setTimeout/noTimeout")) {
+ } else if (pathInfo.equals("/setTimeout/noTimeout")) {
// wait but not long enough to timeout
try {
Thread.sleep(1000);
@@ -79,7 +75,7 @@
}
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(RequestBuilderTest.SERVLET_GET_RESPONSE);
- } else if (pathInfo.equals(getPathInfoBase() + "user/pass")) {
+ } else if (pathInfo.equals("/user/pass")) {
String auth = request.getHeader("Authorization");
if (auth == null) {
response.setHeader("WWW-Authenticate", "BASIC");
@@ -111,7 +107,7 @@
*/
response.getWriter().print(RequestBuilderTest.SERVLET_POST_RESPONSE);
response.setStatus(HttpServletResponse.SC_OK);
- } else if (request.getPathInfo().equals(getPathInfoBase() + "simplePost")) {
+ } else if (request.getPathInfo().equals("/simplePost")) {
response.getWriter().print(RequestBuilderTest.SERVLET_POST_RESPONSE);
response.setStatus(HttpServletResponse.SC_OK);
} else {
diff --git a/user/test/com/google/gwt/junit/DevModeOnCompiledScriptTest.gwt.xml b/user/test/com/google/gwt/junit/DevModeOnCompiledScriptTest.gwt.xml
new file mode 100644
index 0000000..a4c0532
--- /dev/null
+++ b/user/test/com/google/gwt/junit/DevModeOnCompiledScriptTest.gwt.xml
@@ -0,0 +1,17 @@
+<!-- -->
+<!-- Copyright 2010 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 -->
+<!-- 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. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+
+<module>
+ <inherits name='com.google.gwt.junit.JUnitTest' />
+</module>
diff --git a/user/test/com/google/gwt/junit/JUnitBridge.java b/user/test/com/google/gwt/junit/JUnitBridge.java
new file mode 100644
index 0000000..cb69546
--- /dev/null
+++ b/user/test/com/google/gwt/junit/JUnitBridge.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 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.UnableToCompleteException;
+import com.google.gwt.dev.cfg.ModuleDef;
+
+/**
+ * Provides access to {@link JUnitShell}.
+ */
+public class JUnitBridge {
+ public static void compileForWebMode(ModuleDef module)
+ throws UnableToCompleteException {
+ JUnitShell.getUnitTestShell().compileForWebMode(module,
+ JUnitShell.getRemoteUserAgents());
+ }
+
+}
diff --git a/user/test/com/google/gwt/junit/JUnitSuite.java b/user/test/com/google/gwt/junit/JUnitSuite.java
index 79833e1..4a198cd 100644
--- a/user/test/com/google/gwt/junit/JUnitSuite.java
+++ b/user/test/com/google/gwt/junit/JUnitSuite.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.junit;
+import com.google.gwt.junit.client.DevModeOnCompiledScriptTest;
import com.google.gwt.junit.client.GWTTestCaseTest;
import com.google.gwt.junit.client.PropertyDefiningGWTTest;
import com.google.gwt.junit.tools.GWTTestSuite;
@@ -33,6 +34,7 @@
// Suppressed due to flakiness on Linux
// suite.addTestSuite(BenchmarkTest.class);
suite.addTestSuite(GWTTestCaseTest.class);
+ suite.addTestSuite(DevModeOnCompiledScriptTest.class);
// Must run after a GWTTestCase so JUnitShell is initialized.
suite.addTestSuite(BatchingStrategyTest.class);
diff --git a/user/test/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java b/user/test/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java
new file mode 100644
index 0000000..f9aefe8
--- /dev/null
+++ b/user/test/com/google/gwt/junit/client/DevModeOnCompiledScriptTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 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.client;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.cfg.ModuleDef;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.JUnitBridge;
+import com.google.gwt.junit.Platform;
+import com.google.gwt.junit.JUnitShell.Strategy;
+import com.google.gwt.junit.client.impl.JUnitResult;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that we can run a test in dev mode even when the selection script is
+ * from a compile. Note that this is the VM-only version of the class; there is
+ * a translatable version for the client side.
+ */
+@DoNotRunWith(Platform.Prod)
+public class DevModeOnCompiledScriptTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.junit.DevModeOnCompiledScriptTest";
+ }
+
+ /**
+ * GWT-unfriendly, forcing us to use a translatable class.
+ */
+ @Override
+ public Strategy getStrategy() {
+ final Strategy impl = super.getStrategy();
+ return new Strategy() {
+ public String getModuleInherit() {
+ return impl.getModuleInherit();
+ }
+
+ public String getSyntheticModuleExtension() {
+ return impl.getSyntheticModuleExtension();
+ }
+
+ public void processModule(ModuleDef module) {
+ impl.processModule(module);
+ try {
+ JUnitBridge.compileForWebMode(module);
+ } catch (UnableToCompleteException e) {
+ throw new RuntimeException("Failed to manually compile test module",
+ e);
+ }
+ }
+
+ public void processResult(TestCase testCase, JUnitResult result) {
+ impl.processResult(testCase, result);
+ }
+ };
+ }
+
+ public void testSomethingTrivial() {
+ assertTrue(true);
+ }
+}