Improves JUnit's local web test performance by setting the user-agent property to exactly the single value required by the running hosted browser. This means one single permutation is created, instead of the current total, based on the number of user-agents defined in UserAgent.gwt.xml.

Benchmarking this shows that, consistently across the sizes of tests/modules, the startup overhead is reduced by a whopping 50%. For example, ListBoxTest normally takes 33 seconds to start and less than one second to actually execute. With this change, ListBoxTest starts in 15 seconds, cutting its execution time in half.

Future work: update the BrowserManagerServers such that they could provide the user-agent strings to their clients.

Patch by: tobyr, scottb
Review by: tobyr


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1653 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/GWTShell.java b/dev/core/src/com/google/gwt/dev/GWTShell.java
index 10c80a5..9080797 100644
--- a/dev/core/src/com/google/gwt/dev/GWTShell.java
+++ b/dev/core/src/com/google/gwt/dev/GWTShell.java
@@ -235,11 +235,15 @@
     public BrowserWidgetHostImpl() {
     }
 
+    public void compile(ModuleDef moduleDef) throws UnableToCompleteException {
+      GWTShell.this.compile(getLogger(), moduleDef);
+    }
+
     public void compile(String[] moduleNames) throws UnableToCompleteException {
       for (int i = 0; i < moduleNames.length; i++) {
         String moduleName = moduleNames[i];
         ModuleDef moduleDef = loadModule(moduleName, getLogger());
-        GWTShell.this.compile(getLogger(), moduleDef);
+        compile(moduleDef);
       }
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
index 6678470..1d5448c 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
@@ -279,6 +279,8 @@
     return host;
   }
 
+  public abstract String getUserAgent();
+
   /**
    * Go to a given url, possibly rewriting it if it can be served from any
    * project's public directory.
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java b/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
index 45e9984..8c557e0 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.cfg.ModuleDef;
 
 /**
  * Interface that unifies access to the <code>BrowserWidget</code>,
@@ -25,6 +26,8 @@
 public interface BrowserWidgetHost {
   void compile(String[] modules) throws UnableToCompleteException;
 
+  void compile(ModuleDef module) throws UnableToCompleteException;
+
   // Factor this out if BrowserWidget becomes decoupled from hosted mode
   ModuleSpaceHost createModuleSpaceHost(BrowserWidget widget, String moduleName)
       throws UnableToCompleteException;
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
index 937bbe1..d7c8cc6 100644
--- a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
+++ b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
@@ -123,4 +123,9 @@
     });
   }
 
+  @Override
+  public String getUserAgent() {
+    // OLD Mozilla. See UserAgent.gwt.xml
+    return "gecko";
+  }
 }
diff --git a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
index d23cab8..406fc14 100644
--- a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
+++ b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
@@ -177,4 +177,9 @@
     });
   }
 
+  @Override
+  public String getUserAgent() {
+    // See UserAgent.gwt.xml
+    return "safari";
+  }
 }
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
index ee15d81..cabc8a9 100644
--- a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
+++ b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
@@ -233,4 +233,10 @@
     //
     LowLevelIE6.init();
   }
+
+  @Override
+  public String getUserAgent() {
+    // See UserAgent.gwt.xml
+    return "ie6";
+  }
 }
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index 11495a7..a9b3b98 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -21,6 +21,8 @@
 import com.google.gwt.dev.GWTShell;
 import com.google.gwt.dev.cfg.ModuleDef;
 import com.google.gwt.dev.cfg.ModuleDefLoader;
+import com.google.gwt.dev.cfg.Properties;
+import com.google.gwt.dev.cfg.Property;
 import com.google.gwt.dev.shell.BrowserWidgetHost;
 import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
 import com.google.gwt.junit.benchmarks.BenchmarkReport;
@@ -422,10 +424,19 @@
     return !runStyle.wasInterrupted();
   }
 
-  void compileForWebMode(String moduleName) throws UnableToCompleteException {
+  void compileForWebMode(String moduleName, String userAgentString)
+      throws UnableToCompleteException {
+    ModuleDef module = doLoadModule(getTopLogger(), moduleName);
+    if (userAgentString != null) {
+      Properties props = module.getProperties();
+      Property userAgent = props.find("user.agent");
+      if (userAgent != null) {
+        userAgent.setActiveValue(userAgentString);
+      }
+    }
     BrowserWidgetHost browserHost = getBrowserHost();
     assert (browserHost != null);
-    browserHost.compile(new String[] {moduleName});
+    browserHost.compile(module);
   }
 
   /**
diff --git a/user/src/com/google/gwt/junit/RunStyleLocalHosted.java b/user/src/com/google/gwt/junit/RunStyleLocalHosted.java
index 7701ab1..38097c8 100644
--- a/user/src/com/google/gwt/junit/RunStyleLocalHosted.java
+++ b/user/src/com/google/gwt/junit/RunStyleLocalHosted.java
@@ -48,6 +48,13 @@
     }
   }
 
+  protected BrowserWidget getBrowserWindow() throws UnableToCompleteException {
+    if (browserWindow == null) {
+      browserWindow = shell.openNewBrowserWindow();
+    }
+    return browserWindow;
+  }
+
   /**
    * Launches a URL in the browser window.
    * 
@@ -55,9 +62,6 @@
    * @throws UnableToCompleteException
    */
   protected void launchUrl(String url) throws UnableToCompleteException {
-    if (browserWindow == null) {
-      browserWindow = shell.openNewBrowserWindow();
-    }
-    browserWindow.go(url);
+    getBrowserWindow().go(url);
   }
 }
diff --git a/user/src/com/google/gwt/junit/RunStyleLocalWeb.java b/user/src/com/google/gwt/junit/RunStyleLocalWeb.java
index 035ed34..cb5dde4 100644
--- a/user/src/com/google/gwt/junit/RunStyleLocalWeb.java
+++ b/user/src/com/google/gwt/junit/RunStyleLocalWeb.java
@@ -16,6 +16,7 @@
 package com.google.gwt.junit;
 
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.shell.BrowserWidget;
 
 /**
  * Runs locally in web mode.
@@ -38,7 +39,8 @@
   public void maybeLaunchModule(String moduleName, boolean forceLaunch)
       throws UnableToCompleteException {
     if (forceLaunch) {
-      shell.compileForWebMode(moduleName);
+      BrowserWidget browserWindow = getBrowserWindow();
+      shell.compileForWebMode(moduleName, browserWindow.getUserAgent());
       launchUrl(moduleName + "/?" + PROP_GWT_HYBRID_MODE);
     }
   }
diff --git a/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java b/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
index 25044fd..d82f3d2 100644
--- a/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
+++ b/user/src/com/google/gwt/junit/RunStyleRemoteWeb.java
@@ -67,7 +67,7 @@
       throws UnableToCompleteException {
 
     if (forceLaunch || !running) {
-      shell.compileForWebMode(moduleName);
+      shell.compileForWebMode(moduleName, null);
       String localhost;
 
       try {
@@ -117,4 +117,4 @@
     return false;
   }
 
-}
\ No newline at end of file
+}