Revision: 7155 Author: sco...@google.com Date: Tue Nov 24 12:23:12 2009 Log: Fixes JUnit sessions to not use Cookies, which can be problematic.
- The session id is passed through RPC - Session ids are now ints. Suggested by: jlabanca Review by: jlabanca http://code.google.com/p/google-web-toolkit/source/detail?r=7155 Modified: /trunk/user/src/com/google/gwt/junit/JUnitMessageQueue.java /trunk/user/src/com/google/gwt/junit/JUnitShell.java /trunk/user/src/com/google/gwt/junit/client/impl/ExceptionWrapper.java /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHost.java /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHostAsync.java /trunk/user/src/com/google/gwt/junit/client/impl/JUnitResult.java /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java /trunk/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/impl/GWTRunner.java /trunk/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java ======================================= --- /trunk/user/src/com/google/gwt/junit/JUnitMessageQueue.java Tue Nov 24 01:02:15 2009 +++ /trunk/user/src/com/google/gwt/junit/JUnitMessageQueue.java Tue Nov 24 12:23:12 2009 @@ -15,15 +15,16 @@ */ package com.google.gwt.junit; -import com.google.gwt.dev.util.collect.HashSet; -import com.google.gwt.dev.util.collect.IdentityHashMap; import com.google.gwt.junit.client.TimeoutException; import com.google.gwt.junit.client.impl.JUnitResult; +import com.google.gwt.junit.client.impl.JUnitHost.ClientInfo; import com.google.gwt.junit.client.impl.JUnitHost.TestBlock; import com.google.gwt.junit.client.impl.JUnitHost.TestInfo; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -44,19 +45,53 @@ * </p> */ public class JUnitMessageQueue { + + /** + * Server-side client info that includes a description. + */ + public static class ClientInfoExt extends ClientInfo { + /** + * A description of this client. + */ + private final String desc; + + public ClientInfoExt(int sessionId, String userAgent, String desc) { + super(sessionId, userAgent); + this.desc = desc; + } + + public String getDesc() { + return desc; + } + } /** * Holds the state of an individual client. */ public static class ClientStatus { - public int blockIndex = 0; - public final String clientId; - public String clientDesc; - public boolean isNew = true; - - public ClientStatus(String clientId, String clientDesc) { - this.clientId = clientId; - this.clientDesc = clientDesc; + private int blockIndex = 0; + private ClientInfoExt clientInfo; + private boolean isNew = true; + + public ClientStatus(ClientInfoExt clientInfo) { + this.clientInfo = clientInfo; + } + + public String getDesc() { + return clientInfo.getDesc(); + } + + public int getId() { + return clientInfo.getSessionId(); + } + + @Override + public String toString() { + return clientInfo.getDesc(); + } + + public void updateClientInfo(ClientInfoExt clientInfo) { + this.clientInfo = clientInfo; } } @@ -72,7 +107,7 @@ /** * Records results for each client; must lock before accessing. */ - private final Map<String, ClientStatus> clientStatuses = new HashMap<String, ClientStatus>(); + private final Map<Integer, ClientStatus> clientStatuses = new HashMap<Integer, ClientStatus>(); /** * The lock used to synchronize access to clientStatuses. @@ -117,19 +152,18 @@ /** * Called by the servlet to query for for the next block to test. * - * @param clientId the ID of the client - * @param userAgent the user agent property of the client + * @param clientInfo information about the client * @param blockIndex the index of the test block to get * @param timeout how long to wait for an answer * @return the next test to run, or <code>null</code> if * <code>timeout</code> is exceeded or the next test does not match * <code>testClassName</code> */ - public TestBlock getTestBlock(String clientId, String clientDesc, - String userAgent, int blockIndex, long timeout) throws TimeoutException { + public TestBlock getTestBlock(ClientInfoExt clientInfo, int blockIndex, + long timeout) throws TimeoutException { synchronized (clientStatusesLock) { - userAgents.add(userAgent); - ClientStatus clientStatus = ensureClientStatus(clientId, clientDesc); + userAgents.add(clientInfo.getUserAgent()); + ClientStatus clientStatus = ensureClientStatus(clientInfo); clientStatus.blockIndex = blockIndex; // The client has finished all of the tests. @@ -145,8 +179,8 @@ double elapsed = (System.currentTimeMillis() - startTime) / 1000.0; throw new TimeoutException("The servlet did not respond to the " + "next query to test within " + timeout + "ms.\n" - + " Client id: " + clientId + "\n" + " Actual time elapsed: " - + elapsed + " seconds.\n"); + + " Client description: " + clientInfo.getDesc() + "\n" + + " Actual time elapsed: " + elapsed + " seconds.\n"); } try { clientStatusesLock.wait(timeToWait); @@ -170,32 +204,36 @@ } } - public void reportFatalLaunch(String clientId, String clientDesc, String userAgent, - JUnitResult result) { + /** + * Reports a failure from a client that cannot startup. + * + * @param clientInfo information about the client + * @param result the failure result + */ + public void reportFatalLaunch(ClientInfoExt clientInfo, JUnitResult result) { // Fatal launch error, cause this client to fail the whole block. - ClientStatus clientStatus = ensureClientStatus(clientId, clientDesc); + ClientStatus clientStatus = ensureClientStatus(clientInfo); Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); for (TestInfo testInfo : testBlocks.get(clientStatus.blockIndex)) { results.put(testInfo, result); } - reportResults(clientId, clientDesc, userAgent, results); + reportResults(clientInfo, results); } /** * Called by the servlet to report the results of the last test to run. * - * @param clientId the ID of the client - * @param userAgent the user agent property of the client + * @param clientInfo information about the client * @param results the result of running the test block */ - public void reportResults(String clientId, String clientDesc, String userAgent, + public void reportResults(ClientInfoExt clientInfo, Map<TestInfo, JUnitResult> results) { synchronized (clientStatusesLock) { if (results == null) { throw new IllegalArgumentException("results cannot be null"); } - userAgents.add(userAgent); - ClientStatus clientStatus = ensureClientStatus(clientId, clientDesc); + userAgents.add(clientInfo.getUserAgent()); + ClientStatus clientStatus = ensureClientStatus(clientInfo); // Cache the test results. for (Map.Entry<TestInfo, JUnitResult> entry : results.entrySet()) { @@ -240,7 +278,7 @@ List<String> results = new ArrayList<String>(); for (ClientStatus clientStatus : clientStatuses.values()) { if (clientStatus.isNew) { - results.add(clientStatus.clientDesc); + results.add(clientStatus.getDesc()); // Record that this client is no longer new. clientStatus.isNew = false; } @@ -323,7 +361,7 @@ } else { buf.append(" - (ok): "); } - buf.append(clientStatus.clientDesc); + buf.append(clientStatus.getDesc()); ++lineCount; } int difference = numClients - getNumClientsRetrievedTest(testInfo); @@ -365,7 +403,7 @@ if (results != null) { for (Map.Entry<ClientStatus, JUnitResult> entry : results.entrySet()) { if (entry.getValue() == null) { - buf.append(entry.getKey().clientDesc); + buf.append(entry.getKey().getDesc()); buf.append("\n"); itemCount++; } @@ -454,14 +492,15 @@ * @param clientId the id of the client * @return the {...@link ClientStatus} for the client */ - private ClientStatus ensureClientStatus(String clientId, String clientDesc) { - ClientStatus clientStatus = clientStatuses.get(clientId); + private ClientStatus ensureClientStatus(ClientInfoExt clientInfo) { + int id = clientInfo.getSessionId(); + ClientStatus clientStatus = clientStatuses.get(id); if (clientStatus == null) { - clientStatus = new ClientStatus(clientId, clientDesc); - clientStatuses.put(clientId, clientStatus); + clientStatus = new ClientStatus(clientInfo); + clientStatuses.put(id, clientStatus); } else { - // Maybe update the description (ip might change if through a proxy). - clientStatus.clientDesc = clientDesc; + // Maybe update the client info (IP might change if through a proxy). + clientStatus.updateClientInfo(clientInfo); } return clientStatus; } ======================================= --- /trunk/user/src/com/google/gwt/junit/JUnitShell.java Tue Nov 24 01:02:15 2009 +++ /trunk/user/src/com/google/gwt/junit/JUnitShell.java Tue Nov 24 12:23:12 2009 @@ -1068,7 +1068,7 @@ // Let the user know the browser in which the failure happened. if (exception != null) { - String msg = "Remote test failed at " + client.clientDesc; + String msg = "Remote test failed at " + client.getDesc(); if (exception instanceof AssertionFailedError) { String oldMessage = exception.getMessage(); if (oldMessage != null) { ======================================= --- /trunk/user/src/com/google/gwt/junit/client/impl/ExceptionWrapper.java Wed Oct 31 11:36:48 2007 +++ /trunk/user/src/com/google/gwt/junit/client/impl/ExceptionWrapper.java Tue Nov 24 12:23:12 2009 @@ -15,13 +15,13 @@ */ package com.google.gwt.junit.client.impl; -import com.google.gwt.user.client.rpc.IsSerializable; +import java.io.Serializable; /** * A helper class for converting a generic {...@link Throwable} into an Object that * can be serialized for RPC. */ -public final class ExceptionWrapper implements IsSerializable { +public final class ExceptionWrapper implements Serializable { /** * Corresponds to {...@link Throwable#getCause()}. ======================================= --- /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHost.java Tue Sep 15 11:52:45 2009 +++ /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHost.java Tue Nov 24 12:23:12 2009 @@ -16,9 +16,9 @@ package com.google.gwt.junit.client.impl; import com.google.gwt.junit.client.TimeoutException; -import com.google.gwt.user.client.rpc.IsSerializable; import com.google.gwt.user.client.rpc.RemoteService; +import java.io.Serializable; import java.util.HashMap; /** @@ -26,13 +26,81 @@ * communicate with the test process through RPC. */ public interface JUnitHost extends RemoteService { + + /** + * Information about the client browser. + */ + public static class ClientInfo implements Serializable { + /** + * This client's unique session id. + */ + private int sessionId; + + /** + * The GWT user.agent property of this client, e.g. "ie6", "safari", etc. + */ + private String userAgent; + + public ClientInfo(int sessionId, String userAgent) { + this.sessionId = sessionId; + this.userAgent = userAgent; + } + + /** + * Constructor for serialization. + */ + ClientInfo() { + } + + public int getSessionId() { + return sessionId; + } + + public String getUserAgent() { + return userAgent; + } + } + + /** + * An initial response that sets the client session id. + */ + public static class InitialResponse implements Serializable { + /** + * The unique client session id. + */ + private int sessionId; + + /** + * The first test block to run. + */ + private TestBlock testBlock; + + public InitialResponse(int sessionId, TestBlock testBlock) { + this.sessionId = sessionId; + this.testBlock = testBlock; + } + + /** + * Constructor for serialization. + */ + InitialResponse() { + } + + public int getSessionId() { + return sessionId; + } + + public TestBlock getTestBlock() { + return testBlock; + } + } /** * Returned from the server to tell the system what test to run next. */ - public static class TestBlock implements IsSerializable { - private TestInfo[] tests; + public static class TestBlock implements Serializable { private int index; + private TestInfo[] tests; public TestBlock(TestInfo[] tests, int index) { this.tests = tests; @@ -57,7 +125,7 @@ /** * Returned from the server to tell the system what test to run next. */ - public static class TestInfo implements IsSerializable { + public static class TestInfo implements Serializable { private String testClass; private String testMethod; private String testModule; @@ -112,11 +180,12 @@ * Gets a specific block of tests to run. * * @param blockIndex the index of the test block to retrieve - * @param userAgent the user agent property of this client - * @return the test block + * @param clientInfo the info for this client + * @return the initial response * @throws TimeoutException if the wait for the next method times out. */ - TestBlock getTestBlock(int blockIndex, String userAgent) throws TimeoutException; + InitialResponse getTestBlock(int blockIndex, ClientInfo clientInfo) + throws TimeoutException; /** * Reports results for the last method run and gets the name of next method to @@ -124,11 +193,11 @@ * * @param results the results of executing the test * @param blockIndex the index of the test block to retrieve - * @param userAgent the user agent property of this client + * @param clientInfo the info for this client * @return the next test block * @throws TimeoutException if the wait for the next method times out. */ TestBlock reportResultsAndGetTestBlock( - HashMap<TestInfo, JUnitResult> results, int blockIndex, String userAgent) - throws TimeoutException; -} + HashMap<TestInfo, JUnitResult> results, int blockIndex, + ClientInfo clientInfo) throws TimeoutException; +} ======================================= --- /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHostAsync.java Tue Sep 15 11:52:45 2009 +++ /trunk/user/src/com/google/gwt/junit/client/impl/JUnitHostAsync.java Tue Nov 24 12:23:12 2009 @@ -15,6 +15,8 @@ */ package com.google.gwt.junit.client.impl; +import com.google.gwt.junit.client.impl.JUnitHost.ClientInfo; +import com.google.gwt.junit.client.impl.JUnitHost.InitialResponse; import com.google.gwt.junit.client.impl.JUnitHost.TestBlock; import com.google.gwt.junit.client.impl.JUnitHost.TestInfo; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -30,12 +32,11 @@ * Gets a specific block of tests to run. * * @param blockIndex the index of the test block to retrieve - * @param userAgent the user agent property of this client - * @param callBack the object that will receive the name of the next method to - * run + * @param clientInfo the info for this client + * @param callBack the object that will receive the initial response */ - void getTestBlock(int blockIndex, String userAgent, - AsyncCallback<TestBlock> callBack); + void getTestBlock(int blockIndex, ClientInfo clientInfo, + AsyncCallback<InitialResponse> callBack); /** * Reports results for the last method run and gets the name of next method to @@ -43,10 +44,9 @@ * * @param results the results of executing the test * @param blockIndex the index of the test block to retrieve - * @param userAgent the user agent property of this client - * @param callBack the object that will receive the name of the next method to - * run + * @param clientInfo the info for this client + * @param callBack the object that will receive the next test block */ void reportResultsAndGetTestBlock(HashMap<TestInfo, JUnitResult> results, - int blockIndex, String userAgent, AsyncCallback<TestBlock> callBack); -} + int blockIndex, ClientInfo clientInfo, AsyncCallback<TestBlock> callBack); +} ======================================= --- /trunk/user/src/com/google/gwt/junit/client/impl/JUnitResult.java Thu Feb 28 00:19:47 2008 +++ /trunk/user/src/com/google/gwt/junit/client/impl/JUnitResult.java Tue Nov 24 12:23:12 2009 @@ -15,7 +15,7 @@ */ package com.google.gwt.junit.client.impl; -import com.google.gwt.user.client.rpc.IsSerializable; +import java.io.Serializable; /** * Encapsulates the results of the execution of a single benchmark. A TestResult @@ -28,7 +28,7 @@ * @see com.google.gwt.junit.JUnitMessageQueue * @see com.google.gwt.junit.JUnitShell */ -public class JUnitResult implements IsSerializable { +public class JUnitResult implements Serializable { // Computed at the server, via HTTP header. private transient String agent; ======================================= --- /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java Tue Nov 24 01:02:15 2009 +++ /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java Tue Nov 24 12:23:12 2009 @@ -18,6 +18,7 @@ import com.google.gwt.junit.JUnitFatalLaunchException; import com.google.gwt.junit.JUnitMessageQueue; import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.JUnitMessageQueue.ClientInfoExt; import com.google.gwt.junit.client.TimeoutException; import com.google.gwt.junit.client.impl.ExceptionWrapper; import com.google.gwt.junit.client.impl.JUnitHost; @@ -31,10 +32,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.ServletException; -import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -57,7 +57,10 @@ */ private static final int TIME_TO_WAIT_FOR_TESTNAME = 300000; - private static final AtomicLong uniqueSessionId = new AtomicLong(); + /** + * Monotonic increase counter to create unique client session ids. + */ + private static final AtomicInteger uniqueSessionId = new AtomicInteger(); /** * Tries to grab the GWTUnitTestShell sHost environment to communicate with @@ -85,28 +88,32 @@ fld.set(obj, value); } - public TestBlock getTestBlock(int blockIndex, String userAgent) + public InitialResponse getTestBlock(int blockIndex, ClientInfo clientInfo) throws TimeoutException { - return getHost().getTestBlock( - getClientId(getThreadLocalRequest(), getThreadLocalResponse()), - getClientDesc(getThreadLocalRequest()), userAgent, blockIndex, - TIME_TO_WAIT_FOR_TESTNAME); + ClientInfoExt clientInfoExt; + if (clientInfo.getSessionId() < 0) { + clientInfoExt = createNewClientInfo(clientInfo.getUserAgent()); + } else { + clientInfoExt = createClientInfo(clientInfo); + } + TestBlock initialTestBlock = getHost().getTestBlock(clientInfoExt, + blockIndex, TIME_TO_WAIT_FOR_TESTNAME); + // Send back the updated session id. + return new InitialResponse(clientInfoExt.getSessionId(), initialTestBlock); } public TestBlock reportResultsAndGetTestBlock( - HashMap<TestInfo, JUnitResult> results, int testBlock, String userAgent) - throws TimeoutException { + HashMap<TestInfo, JUnitResult> results, int testBlock, + ClientInfo clientInfo) throws TimeoutException { for (JUnitResult result : results.values()) { initResult(getThreadLocalRequest(), result); ExceptionWrapper ew = result.getExceptionWrapper(); result.setException(deserialize(ew)); } JUnitMessageQueue host = getHost(); - String clientId = getClientId(getThreadLocalRequest(), - getThreadLocalResponse()); - String clientDesc = getClientDesc(getThreadLocalRequest()); - host.reportResults(clientId, clientDesc, userAgent, results); - return host.getTestBlock(clientId, clientDesc, userAgent, testBlock, + ClientInfoExt clientInfoExt = createClientInfo(clientInfo); + host.reportResults(clientInfoExt, results); + return host.getTestBlock(clientInfoExt, testBlock, TIME_TO_WAIT_FOR_TESTNAME); } @@ -119,12 +126,26 @@ JUnitResult result = new JUnitResult(); initResult(request, result); result.setException(new JUnitFatalLaunchException(requestPayload)); - getHost().reportFatalLaunch(getClientId(request, response), - getClientDesc(request), null, result); + getHost().reportFatalLaunch(createNewClientInfo(null), result); } else { super.service(request, response); } } + + private ClientInfoExt createClientInfo(ClientInfo clientInfo) { + assert (clientInfo.getSessionId() >= 0); + return new ClientInfoExt(clientInfo.getSessionId(), + clientInfo.getUserAgent(), getClientDesc(getThreadLocalRequest())); + } + + private ClientInfoExt createNewClientInfo(String userAgent) { + return new ClientInfoExt(createSessionId(), userAgent, + getClientDesc(getThreadLocalRequest())); + } + + private int createSessionId() { + return uniqueSessionId.getAndIncrement(); + } /** * Deserializes an ExceptionWrapper back into a Throwable. @@ -232,29 +253,14 @@ return result; } + /** + * Returns a client description for the current request. + */ private String getClientDesc(HttpServletRequest request) { String machine = request.getRemoteHost(); String agent = request.getHeader("User-Agent"); return machine + " / " + agent; } - - /** - * Returns a "client id" for the current request. - */ - private String getClientId(HttpServletRequest request, - HttpServletResponse response) { - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if ("gwt.junit.sessionCookie".equals(cookie.getName())) { - return cookie.getValue(); - } - } - } - String cookie = String.valueOf(uniqueSessionId.getAndIncrement()); - response.addCookie(new Cookie("gwt.junit.sessionCookie", cookie)); - return cookie; - } private void initResult(HttpServletRequest request, JUnitResult result) { String agent = request.getHeader("User-Agent"); ======================================= --- /trunk/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/impl/GWTRunner.java Tue Nov 24 01:02:15 2009 +++ /trunk/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/impl/GWTRunner.java Tue Nov 24 12:23:12 2009 @@ -19,10 +19,11 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.http.client.UrlBuilder; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.junit.client.impl.JUnitHost.ClientInfo; +import com.google.gwt.junit.client.impl.JUnitHost.InitialResponse; import com.google.gwt.junit.client.impl.JUnitHost.TestBlock; import com.google.gwt.junit.client.impl.JUnitHost.TestInfo; import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Cookies; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; @@ -39,12 +40,33 @@ * returned. This process repeats until the next method to run is null. */ public abstract class GWTRunner implements EntryPoint { + + private final class InitialResponseListener implements + AsyncCallback<InitialResponse> { + + /** + * Delegate to the {...@link TestBlockListener}. + */ + public void onFailure(Throwable caught) { + testBlockListener.onFailure(caught); + } + + /** + * Update our client info with the server-provided session id then delegate + * to the {...@link TestBlockListener}. + */ + public void onSuccess(InitialResponse result) { + clientInfo = new ClientInfo(result.getSessionId(), + clientInfo.getUserAgent()); + testBlockListener.onSuccess(result.getTestBlock()); + } + } /** * The RPC callback object for {...@link GWTRunner#junitHost}. When * {...@link #onSuccess} is called, it's time to run the next test case. */ - private final class JUnitHostListener implements AsyncCallback<TestBlock> { + private final class TestBlockListener implements AsyncCallback<TestBlock> { /** * The number of times we've failed to communicate with the server on the @@ -99,12 +121,12 @@ /** * The singleton instance. */ - private static GWTRunner sInstance; + static GWTRunner sInstance; /** * A query param specifying my unique session cookie. */ - private static final String SESSIONCOOKIE_QUERY_PARAM = "gwt.junit.sessionCookie"; + private static final String SESSIONID_QUERY_PARAM = "gwt.junit.sessionId"; /** * A query param specifying the test class to run, for serverless mode. @@ -130,6 +152,11 @@ public static GWTRunner get() { return sInstance; } + + /** + * This client's info. + */ + private ClientInfo clientInfo; /** * The current block of tests to execute. @@ -157,9 +184,14 @@ private final JUnitHostAsync junitHost = (JUnitHostAsync) GWT.create(JUnitHost.class); /** - * Handles all RPC responses. + * Handles all {...@link InitialResponse InitialResponses}. */ - private final JUnitHostListener junitHostListener = new JUnitHostListener(); + private final InitialResponseListener initialResponseListener = new InitialResponseListener(); + + /** + * Handles all {...@link TestBlock TestBlocks}. + */ + private final TestBlockListener testBlockListener = new TestBlockListener(); /** * The maximum number of times to retry communication with the server per @@ -187,12 +219,8 @@ } public void onModuleLoad() { - // Try to import a session cookie from the previous module. - String value = Window.Location.getParameter(SESSIONCOOKIE_QUERY_PARAM); - if (value != null) { - Cookies.setCookie(SESSIONCOOKIE_QUERY_PARAM, value); - } - + clientInfo = new ClientInfo(parseQueryParamInteger( + SESSIONID_QUERY_PARAM, -1), getUserAgentProperty()); maxRetryCount = parseQueryParamInteger(RETRYCOUNT_QUERY_PARAM, -1); currentBlock = checkForQueryParamTestToRun(); if (currentBlock != null) { @@ -278,10 +306,10 @@ builder.setParameter(BLOCKINDEX_QUERY_PARAM, Integer.toString(currentBlock.getIndex())).setPath( newModule + pathSuffix); - // Hand off the session cookie to the next module. - String sessionCookie = Cookies.getCookie(SESSIONCOOKIE_QUERY_PARAM); - if (sessionCookie != null) { - builder.setParameter(SESSIONCOOKIE_QUERY_PARAM, sessionCookie); + // Hand off the session id to the next module. + if (clientInfo.getSessionId() >= 0) { + builder.setParameter(SESSIONID_QUERY_PARAM, + String.valueOf(clientInfo.getSessionId())); } Window.Location.replace(builder.buildString()); currentBlock = null; @@ -348,12 +376,11 @@ private void syncToServer() { if (currentBlock == null) { int firstBlockIndex = parseQueryParamInteger(BLOCKINDEX_QUERY_PARAM, 0); - junitHost.getTestBlock(firstBlockIndex, getUserAgentProperty(), - junitHostListener); + junitHost.getTestBlock(firstBlockIndex, clientInfo, + initialResponseListener); } else { junitHost.reportResultsAndGetTestBlock(currentResults, - currentBlock.getIndex() + 1, getUserAgentProperty(), - junitHostListener); + currentBlock.getIndex() + 1, clientInfo, testBlockListener); } } ======================================= --- /trunk/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java Tue Nov 24 01:02:15 2009 +++ /trunk/user/test/com/google/gwt/junit/JUnitMessageQueueTest.java Tue Nov 24 12:23:12 2009 @@ -16,6 +16,7 @@ package com.google.gwt.junit; import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.junit.JUnitMessageQueue.ClientInfoExt; import com.google.gwt.junit.JUnitMessageQueue.ClientStatus; import com.google.gwt.junit.client.impl.JUnitResult; import com.google.gwt.junit.client.impl.JUnitHost.TestBlock; @@ -24,7 +25,9 @@ import junit.framework.TestCase; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -91,25 +94,25 @@ // Add some clients in a few ways. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertEquals(3, queue.getNumConnectedClients()); } // Add duplicate clients. { - queue.getTestBlock("client3", "desc3", "ie6", 0, timeout); - queue.reportFatalLaunch("client3", "desc3", "ie6", null); - queue.reportResults("client4", "desc3", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(3, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(3, "ie6"), null); + queue.reportResults(createClientInfo(4, "safari"), createTestResults(0)); assertEquals(5, queue.getNumConnectedClients()); } // Add existing clients. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertEquals(5, queue.getNumConnectedClients()); } } @@ -134,7 +137,7 @@ // First client retrieves the first test block. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); assertEquals(1, queue.getNumClientsRetrievedTest(test0_0)); assertEquals(1, queue.getNumClientsRetrievedTest(test0_1)); assertEquals(1, queue.getNumClientsRetrievedTest(test0_2)); @@ -145,7 +148,7 @@ // Second client retrieves the first test block. { - queue.getTestBlock("client1", "desc1", "ie6", 0, timeout); + queue.getTestBlock(createClientInfo(1, "ie6"), 0, timeout); assertEquals(2, queue.getNumClientsRetrievedTest(test0_0)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_1)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_2)); @@ -156,7 +159,7 @@ // First client retrieves the second test block. { - queue.getTestBlock("client0", "desc0", "ie6", 1, timeout); + queue.getTestBlock(createClientInfo(0, "ie6"), 1, timeout); assertEquals(2, queue.getNumClientsRetrievedTest(test0_0)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_1)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_2)); @@ -167,7 +170,7 @@ // First client retrieves the second test block again. { - queue.getTestBlock("client0", "desc0", "ie6", 1, timeout); + queue.getTestBlock(createClientInfo(0, "ie6"), 1, timeout); assertEquals(2, queue.getNumClientsRetrievedTest(test0_0)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_1)); assertEquals(2, queue.getNumClientsRetrievedTest(test0_2)); @@ -194,21 +197,21 @@ { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, result0); - queue.reportResults("client0", "desc0", "ie6", results); + queue.reportResults(createClientInfo(0, "ie6"), results); } // Client 1 reports results for first test case. { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, result1); - queue.reportResults("client1", "desc1", "ie6", results); + queue.reportResults(createClientInfo(1, "ie6"), results); } // Client 2 reports results for first test case. { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, result2); - queue.reportResults("client2", "desc2", "ie6", results); + queue.reportResults(createClientInfo(2, "ie6"), results); } // Get the results @@ -217,14 +220,19 @@ for (Entry<ClientStatus, JUnitResult> entry : results.entrySet()) { ClientStatus client = entry.getKey(); JUnitResult result = entry.getValue(); - if ("client0".equals(client.clientId)) { - assertEquals(result0, result); - } else if ("client1".equals(client.clientId)) { - assertEquals(result1, result); - } else if ("client2".equals(client.clientId)) { - assertEquals(result2, result); - } else { - fail("Unexpected client"); + switch (client.getId()) { + case 0: + assertEquals(result0, result); + break; + case 1: + assertEquals(result1, result); + break; + case 2: + assertEquals(result2, result); + break; + default: + fail("Unexpected client"); + break; } } } @@ -237,7 +245,7 @@ // Get the first test block. { - TestBlock block = queue.getTestBlock("client0", "desc0", "ie6", 0, + TestBlock block = queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); assertEquals(testBlock0, block.getTests()); assertEquals(0, block.getIndex()); @@ -245,7 +253,7 @@ // Get the second test block. { - TestBlock block = queue.getTestBlock("client0", "desc0", "ie6", 1, + TestBlock block = queue.getTestBlock(createClientInfo(0, "ie6"), 1, timeout); assertEquals(testBlock1, block.getTests()); assertEquals(1, block.getIndex()); @@ -253,7 +261,7 @@ // Get the third test block. { - assertNull(queue.getTestBlock("client0", "desc0", "ie6", 2, timeout)); + assertNull(queue.getTestBlock(createClientInfo(0, "ie6"), 2, timeout)); } } @@ -264,28 +272,28 @@ // Add some clients in a few ways. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertSimilar(new String[] {"ie6", "gecko", "safari"}, queue.getUserAgents()); } // Add duplicate clients. { - queue.getTestBlock("client3", "desc3", "ie7", 0, timeout); - queue.reportFatalLaunch("client3", "desc3", "ie7", null); - queue.reportResults("client4", "desc4", "gecko1_8", createTestResults(0)); - queue.getTestBlock("client3", "desc3", "ie7", 0, timeout); + queue.getTestBlock(createClientInfo(3, "ie7"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(3, "ie7"), null); + queue.reportResults(createClientInfo(4, "gecko1_8"), createTestResults(0)); + queue.getTestBlock(createClientInfo(3, "ie7"), 0, timeout); assertSimilar(new String[] {"ie6", "ie7", "gecko", "gecko1_8", "safari"}, queue.getUserAgents()); } // Add existing clients. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertSimilar(new String[] {"ie6", "ie7", "gecko", "gecko1_8", "safari"}, queue.getUserAgents()); } @@ -312,7 +320,7 @@ { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, new JUnitResult()); - queue.reportResults("client0", "desc0", "ie6", results); + queue.reportResults(createClientInfo(0, "ie6"), results); assertFalse(queue.hasResults(test0_0)); assertFalse(queue.hasResults(test0_1)); assertFalse(queue.hasResults(test0_2)); @@ -325,7 +333,7 @@ { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, new JUnitResult()); - queue.reportResults("client1", "desc1", "ie6", results); + queue.reportResults(createClientInfo(1, "ie6"), results); assertFalse(queue.hasResults(test0_0)); assertFalse(queue.hasResults(test0_1)); assertFalse(queue.hasResults(test0_2)); @@ -338,7 +346,7 @@ { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_1, new JUnitResult()); - queue.reportResults("client0", "desc0", "ie6", results); + queue.reportResults(createClientInfo(0, "ie6"), results); assertFalse(queue.hasResults(test0_0)); assertFalse(queue.hasResults(test0_1)); assertFalse(queue.hasResults(test0_2)); @@ -351,7 +359,7 @@ { Map<TestInfo, JUnitResult> results = new HashMap<TestInfo, JUnitResult>(); results.put(test0_0, new JUnitResult()); - queue.reportResults("client2", "desc2", "ie6", results); + queue.reportResults(createClientInfo(2, "ie6"), results); assertTrue(queue.hasResults(test0_0)); assertFalse(queue.hasResults(test0_1)); assertFalse(queue.hasResults(test0_2)); @@ -370,12 +378,12 @@ JUnitResult junitResult = new JUnitResult(); junitResult.setException(new UnableToCompleteException()); results.put(testInfo, junitResult); - queue.reportResults("client0", "desc0", "ie6", results); + queue.reportResults(createClientInfo(0, "ie6"), results); results = new HashMap<TestInfo, JUnitResult>(); junitResult = new JUnitResult(); junitResult.setException(new JUnitFatalLaunchException()); results.put(testInfo, junitResult); - queue.reportResults("client1", "desc1", "ff3", + queue.reportResults(createClientInfo(1, "ff3"), createTestResults(ONE_TEST_PER_BLOCK)); assertTrue(queue.needsRerunning(testInfo)); @@ -385,8 +393,8 @@ junitResult = new JUnitResult(); junitResult.setException(new JUnitFatalLaunchException()); results.put(testInfo, junitResult); - queue.reportResults("client0", "desc0", "ie6", results); - queue.reportResults("client1", "desc1", "ff3", + queue.reportResults(createClientInfo(0, "ie6"), results); + queue.reportResults(createClientInfo(1, "ff3"), createTestResults(ONE_TEST_PER_BLOCK)); assertFalse(queue.needsRerunning(testInfo)); } @@ -398,11 +406,11 @@ // incomplete results assertTrue(queue.needsRerunning(testInfo)); - queue.reportResults("client0", "desc0", "ff3", createTestResults(1)); + queue.reportResults(createClientInfo(0, "ff3"), createTestResults(1)); assertTrue(queue.needsRerunning(testInfo)); // complete results - queue.reportResults("client1", "desc1", "ie7", createTestResults(1)); + queue.reportResults(createClientInfo(1, "ie7"), createTestResults(1)); assertFalse(queue.needsRerunning(testInfo)); } @@ -413,9 +421,9 @@ // Add some clients in a few ways. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertSimilar(new String[] {"desc0", "desc1", "desc2"}, queue.getNewClients()); assertEquals(0, queue.getNewClients().length); @@ -423,19 +431,19 @@ // Add duplicate clients. { - queue.getTestBlock("client3", "desc3", "ie6", 0, timeout); - queue.reportFatalLaunch("client3", "desc3", "ie6", null); - queue.reportResults("client4", "desc4", "safari", createTestResults(0)); - queue.getTestBlock("client3", "desc3", "ie6", 0, timeout); + queue.getTestBlock(createClientInfo(3, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(3, "ie6"), null); + queue.reportResults(createClientInfo(4, "safari"), createTestResults(0)); + queue.getTestBlock(createClientInfo(3, "ie6"), 0, timeout); assertSimilar(new String[] {"desc3", "desc4"}, queue.getNewClients()); assertEquals(0, queue.getNewClients().length); } // Add existing clients. { - queue.getTestBlock("client0", "desc0", "ie6", 0, timeout); - queue.reportFatalLaunch("client1", "desc1", "gecko", null); - queue.reportResults("client2", "desc2", "safari", createTestResults(0)); + queue.getTestBlock(createClientInfo(0, "ie6"), 0, timeout); + queue.reportFatalLaunch(createClientInfo(1, "gecko"), null); + queue.reportResults(createClientInfo(2, "safari"), createTestResults(0)); assertEquals(0, queue.getNewClients().length); } } @@ -446,10 +454,10 @@ TestInfo testInfo = queue.getTestBlocks().get(0)[0]; assertFalse(queue.hasResults(testInfo)); - queue.reportResults("client0", "desc0", "ie6", + queue.reportResults(createClientInfo(0, "ie6"), createTestResults(ONE_TEST_PER_BLOCK)); assertFalse(queue.hasResults(testInfo)); - queue.reportResults("client1", "desc1", "ff3", + queue.reportResults(createClientInfo(1, "ff3"), createTestResults(ONE_TEST_PER_BLOCK)); assertTrue(queue.hasResults(testInfo)); @@ -465,7 +473,7 @@ JUnitResult junitResult = new JUnitResult(); junitResult.setException(new AssertionError()); results.put(testInfo, junitResult); - queue.reportResults("client0", "desc0", "ff3", results); + queue.reportResults(createClientInfo(0, "ff3"), results); assertTrue(queue.needsRerunning(testInfo)); Map<ClientStatus, JUnitResult> queueResults = queue.getResults(testInfo); assertEquals(1, queueResults.size()); @@ -475,9 +483,9 @@ queue.removeResults(testInfo); - queue.reportResults("client0", "desc0", "ff3", + queue.reportResults(createClientInfo(0, "ff3"), createTestResults(ONE_TEST_PER_BLOCK)); - queue.reportResults("client1", "desc1", "ie6", + queue.reportResults(createClientInfo(1, "ie6"), createTestResults(ONE_TEST_PER_BLOCK)); assertFalse(queue.needsRerunning(testInfo)); // check that the updated result appears now. @@ -496,17 +504,12 @@ * @param actual the actual array */ private void assertSimilar(String[] expected, String[] actual) { - assertEquals(expected.length, actual.length); - for (int i = 0; i < expected.length; i++) { - String expectedItem = expected[i]; - boolean matched = false; - for (int j = 0; j < actual.length; j++) { - if (expectedItem == actual[j]) { - matched = true; - } - } - assertTrue(matched); - } + assertEquals(new HashSet<String>(Arrays.asList(expected)), + new HashSet<String>(Arrays.asList(actual))); + } + + private ClientInfoExt createClientInfo(int sessionId, String userAgent) { + return new ClientInfoExt(sessionId, userAgent, "desc" + sessionId); } /** -- http://groups.google.com/group/Google-Web-Toolkit-Contributors