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

Reply via email to