RunStyleHtmlUnit was not setting the number of clients.
- Changed API to force all RunStyles to return the number of clients, preventing future bugs like this.
- JUnitMessageQueue now holds numClients as a final variable, preventing state mismatch.
Review by: jlabanca (desk)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6945 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/junit/JUnitMessageQueue.java b/user/src/com/google/gwt/junit/JUnitMessageQueue.java
index 6e3fca4..b8f671a 100644
--- a/user/src/com/google/gwt/junit/JUnitMessageQueue.java
+++ b/user/src/com/google/gwt/junit/JUnitMessageQueue.java
@@ -107,7 +107,8 @@
/**
* Only instantiable within this package.
*/
- JUnitMessageQueue() {
+ JUnitMessageQueue(int numClients) {
+ this.numClients = numClients;
}
/**
@@ -246,6 +247,10 @@
}
}
+ int getNumClients() {
+ return numClients;
+ }
+
/**
* Returns how many clients have requested the currently-running test.
*
@@ -431,22 +436,6 @@
}
}
- /**
- * Set the number of clients. This must be called before adding any tests.
- *
- * @param numClients The number of parallel clients being served by this
- * queue.
- */
- void setNumClients(int numClients) {
- synchronized (clientStatusesLock) {
- if (testBlocks.size() > 0) {
- throw new IllegalStateException(
- "Cannot change number of clients after adding tests");
- }
- this.numClients = numClients;
- }
- }
-
void waitForResults(int millis) {
synchronized (clientStatusesLock) {
try {
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index 72e5c32..07ba2e4 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -603,8 +603,6 @@
if (!argProcessor.processArgs(args)) {
throw new JUnitFatalLaunchException("Error processing shell arguments");
}
- unitTestShell.messageQueue = new JUnitMessageQueue();
-
if (!unitTestShell.startUp()) {
throw new JUnitFatalLaunchException("Shell failed to start");
}
@@ -680,13 +678,6 @@
private JUnitMessageQueue messageQueue;
/**
- * The number of test clients executing in parallel. With -remoteweb, users
- * can specify a number of parallel test clients, but by default we only have
- * 1.
- */
- private int numClients = 1;
-
- /**
* An exception that should by fired the next time runTestImpl runs.
*/
private UnableToCompleteException pendingException;
@@ -775,10 +766,12 @@
if (!super.doStartup()) {
return false;
}
- if (!createRunStyle(runStyleName)) {
+ 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);
@@ -807,6 +800,7 @@
*/
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;
@@ -814,7 +808,7 @@
System.out.println(printIndex + " - " + newClient);
++printIndex;
}
- if (activeClients != this.numClients) {
+ if (activeClients != expectedClients) {
// Wait forever for first contact; user-driven.
return true;
}
@@ -822,7 +816,7 @@
// Limit permutations after all clients have connected.
if (remoteUserAgents == null
- && messageQueue.getNumConnectedClients() == numClients) {
+ && messageQueue.getNumConnectedClients() == expectedClients) {
remoteUserAgents = messageQueue.getUserAgents();
String userAgentList = "";
for (int i = 0; i < remoteUserAgents.length; i++) {
@@ -838,11 +832,11 @@
}
long currentTimeMillis = System.currentTimeMillis();
- if (activeClients >= numClients) {
- if (activeClients > numClients) {
+ if (activeClients >= expectedClients) {
+ if (activeClients > expectedClients) {
getTopLogger().log(
TreeLogger.WARN,
- "Too many clients: expected " + numClients + ", found "
+ "Too many clients: expected " + expectedClients + ", found "
+ activeClients);
}
firstLaunch = false;
@@ -941,16 +935,12 @@
}
/**
- * Set the expected number of clients.
- *
- * <p>
- * Should only be called by RunStyle subtypes.
- *
- * @param numClients
+ * @deprecated TODO(fabbott) delete me
*/
+ @Deprecated
+ @SuppressWarnings("unused")
void setNumClients(int numClients) {
- this.numClients = numClients;
- messageQueue.setNumClients(numClients);
+ throw new UnsupportedOperationException("This method should be deleted.");
}
void setStandardsMode(boolean standardsMode) {
@@ -969,9 +959,9 @@
* Create the specified (or default) runStyle.
*
* @param runStyleName the argument passed to -runStyle
- * @return true if the runStyle was successfully created/initialized
+ * @return the number of clients, or -1 if initialization was unsuccessful
*/
- private boolean createRunStyle(String runStyleName) {
+ private int createRunStyle(String runStyleName) {
String args = null;
String name = runStyleName;
int colon = name.indexOf(':');
@@ -1034,7 +1024,8 @@
Map<String, JUnitResult> results = messageQueue.getResults(currentTestInfo);
assert results != null;
- assert results.size() == numClients : results.size() + " != " + numClients;
+ assert results.size() == messageQueue.getNumClients() : results.size()
+ + " != " + messageQueue.getNumClients();
for (Entry<String, JUnitResult> entry : results.entrySet()) {
String clientId = entry.getKey();
diff --git a/user/src/com/google/gwt/junit/RunStyle.java b/user/src/com/google/gwt/junit/RunStyle.java
index d669294..bed70d2 100644
--- a/user/src/com/google/gwt/junit/RunStyle.java
+++ b/user/src/com/google/gwt/junit/RunStyle.java
@@ -31,7 +31,7 @@
*/
protected final JUnitShell shell;
- protected int tries = 1;
+ private int tries = 1;
/**
* Constructor for RunStyle. Any subclass must provide a constructor with the
@@ -77,15 +77,13 @@
}
/**
- * Initialize the runstyle with any supplied arguments.
+ * Initialize the runstyle with any supplied arguments, and return the number
+ * of clients this runstyle controls.
*
* @param args arguments passed in -runStyle option, null if none supplied
- * @return true if this runstyle is initialized successfully, false if it was
- * unsuccessful
+ * @return the number of clients, or -1 if initialization was unsuccessful
*/
- public boolean initialize(String args) {
- return true;
- }
+ public abstract int initialize(String args);
/**
* Requests initial launch of the browser. This should only be called once per
diff --git a/user/src/com/google/gwt/junit/RunStyleExternalBrowser.java b/user/src/com/google/gwt/junit/RunStyleExternalBrowser.java
index 64246bc..adf4af8 100644
--- a/user/src/com/google/gwt/junit/RunStyleExternalBrowser.java
+++ b/user/src/com/google/gwt/junit/RunStyleExternalBrowser.java
@@ -97,17 +97,16 @@
}
@Override
- public boolean initialize(String args) {
+ public int initialize(String args) {
if (args == null || args.length() == 0) {
getLogger().log(
TreeLogger.ERROR,
"ExternalBrowser runstyle requires an "
+ "argument listing one or more executables of external browsers to "
+ "launch");
- return false;
+ return -1;
}
String browsers[] = args.split(",");
- shell.setNumClients(browsers.length);
synchronized (this) {
this.externalBrowsers = new ExternalBrowser[browsers.length];
for (int i = 0; i < browsers.length; ++i) {
@@ -115,7 +114,7 @@
}
}
Runtime.getRuntime().addShutdownHook(new ShutdownCb());
- return true;
+ return browsers.length;
}
@Override
diff --git a/user/src/com/google/gwt/junit/RunStyleHtmlUnit.java b/user/src/com/google/gwt/junit/RunStyleHtmlUnit.java
index 4f94186..f5519e3 100644
--- a/user/src/com/google/gwt/junit/RunStyleHtmlUnit.java
+++ b/user/src/com/google/gwt/junit/RunStyleHtmlUnit.java
@@ -192,12 +192,7 @@
}
@Override
- public int getTries() {
- return tries;
- }
-
- @Override
- public boolean initialize(String args) {
+ public int initialize(String args) {
if (args == null || args.length() == 0) {
// If no browsers specified, default to Firefox 3.
args = "FF3";
@@ -210,14 +205,14 @@
TreeLogger.ERROR,
"RunStyleHtmlUnit: Unknown browser " + "name " + browserName
+ ", expected browser name: one of " + BROWSER_MAP.keySet());
- return false;
+ return -1;
}
browserSet.add(browser);
}
browsers = Collections.unmodifiableSet(browserSet);
setTries(DEFAULT_TRIES); // set to the default value for this RunStyle
- return true;
+ return browsers.size();
}
@Override
diff --git a/user/src/com/google/gwt/junit/RunStyleManual.java b/user/src/com/google/gwt/junit/RunStyleManual.java
index c4b4de6..668e1a9 100644
--- a/user/src/com/google/gwt/junit/RunStyleManual.java
+++ b/user/src/com/google/gwt/junit/RunStyleManual.java
@@ -31,7 +31,7 @@
}
@Override
- public boolean initialize(String args) {
+ public int initialize(String args) {
numClients = 1;
if (args != null) {
try {
@@ -39,11 +39,10 @@
} catch (NumberFormatException e) {
getLogger().log(TreeLogger.ERROR,
"Error parsing argument \"" + args + "\"", e);
- return false;
+ return -1;
}
}
- shell.setNumClients(numClients);
- return true;
+ return numClients;
}
@Override
diff --git a/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java b/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
index 90c7741..e1a1968 100644
--- a/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
+++ b/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
@@ -168,11 +168,11 @@
}
@Override
- public boolean initialize(String args) {
+ public int initialize(String args) {
if (args == null || args.length() == 0) {
getLogger().log(TreeLogger.ERROR,
"RemoteWeb runstyle requires comma-separated RMI URLs");
- return false;
+ return -1;
}
String[] urls = args.split(",");
try {
@@ -180,10 +180,9 @@
} catch (IOException e) {
getLogger().log(TreeLogger.ERROR,
"RemoteWeb: Error initializing RMISocketFactory", e);
- return false;
+ return -1;
}
int numClients = urls.length;
- shell.setNumClients(numClients);
BrowserManager[] browserManagers = new BrowserManager[numClients];
for (int i = 0; i < numClients; ++i) {
long callStart = System.currentTimeMillis();
@@ -200,7 +199,7 @@
cause = e.getCause();
}
getLogger().log(TreeLogger.ERROR, message, cause);
- return false;
+ return -1;
}
}
synchronized (this) {
@@ -210,7 +209,7 @@
}
}
Runtime.getRuntime().addShutdownHook(new ShutdownCb());
- return true;
+ return numClients;
}
@Override
diff --git a/user/src/com/google/gwt/junit/RunStyleSelenium.java b/user/src/com/google/gwt/junit/RunStyleSelenium.java
index 7e3bfd2..d3259b7 100644
--- a/user/src/com/google/gwt/junit/RunStyleSelenium.java
+++ b/user/src/com/google/gwt/junit/RunStyleSelenium.java
@@ -119,11 +119,11 @@
}
@Override
- public boolean initialize(String args) {
+ public int initialize(String args) {
if (args == null || args.length() == 0) {
getLogger().log(TreeLogger.ERROR,
"Selenium runstyle requires comma-separated Selenium-RC targets");
- return false;
+ return -1;
}
String[] targetsIn = args.split(",");
SeleniumWrapper targets[] = new SeleniumWrapper[targetsIn.length];
@@ -133,12 +133,11 @@
targets[i] = createSeleniumWrapper(targetsIn[i]);
} catch (IllegalArgumentException e) {
getLogger().log(TreeLogger.ERROR, e.getMessage());
- return false;
+ return -1;
}
}
this.remotes = targets;
- shell.setNumClients(targets.length);
// Install a shutdown hook that will close all of our outstanding Selenium
// sessions.
@@ -158,7 +157,7 @@
}
});
start();
- return true;
+ return targets.length;
}
@Override
diff --git a/user/test/com/google/gwt/junit/CompileStrategyTest.java b/user/test/com/google/gwt/junit/CompileStrategyTest.java
index 308c104..8792940 100644
--- a/user/test/com/google/gwt/junit/CompileStrategyTest.java
+++ b/user/test/com/google/gwt/junit/CompileStrategyTest.java
@@ -120,7 +120,7 @@
private List<TestInfo[]> testBlocks;
public MockJUnitMessageQueue() {
- super();
+ super(1);
}
@Override
diff --git a/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java b/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java
index 96dd50b..0f5a525 100644
--- a/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java
+++ b/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java
@@ -37,8 +37,7 @@
private final static int ONE_TEST_PER_BLOCK = 1;
public void testAddTestBlocks() {
- JUnitMessageQueue queue = new JUnitMessageQueue();
- queue.setNumClients(10);
+ JUnitMessageQueue queue = new JUnitMessageQueue(10);
assertEquals(0, queue.getTestBlocks().size());
List<TestInfo[]> expectedBlocks = new ArrayList<TestInfo[]>();
@@ -460,17 +459,6 @@
assertTrue(queue.getResults(testInfo).get("client0").getException() == null);
}
- public void testSetNumClients() {
- JUnitMessageQueue queue = new JUnitMessageQueue();
- queue.addTestBlocks(createTestBlocks(ONE_BLOCK, ONE_TEST_PER_BLOCK), true);
- try {
- queue.setNumClients(2);
- fail("Expected IllegalStateException");
- } catch (IllegalStateException e) {
- // expected.
- }
- }
-
/**
* Assert that two arrays are the same size and contain the same elements.
* Ordering does not matter.
@@ -502,8 +490,7 @@
*/
private JUnitMessageQueue createQueue(int numClients, int numBlocks,
int testsPerBlock) {
- JUnitMessageQueue queue = new JUnitMessageQueue();
- queue.setNumClients(numClients);
+ JUnitMessageQueue queue = new JUnitMessageQueue(numClients);
queue.addTestBlocks(createTestBlocks(numBlocks, testsPerBlock), true);
return queue;
}