Revision: 7322
Author: b...@google.com
Date: Wed Dec 16 17:16:05 2009
Log: Add class and method resymbolization to JUnitShell to improve  
production-mode stack traces for continuous builds.
Turns on emulated stack traces across all browsers to ensure consistent  
behavior when running GWTTestCases.

Patch by: bobv
Review by: jat, scottb, rjrjr
http://code.google.com/p/google-web-toolkit/source/detail?r=7322

Added:
  /trunk/user/src/com/google/gwt/junit/linker
  /trunk/user/src/com/google/gwt/junit/linker/JUnitSymbolMapsLinker.java
Deleted:
   
/trunk/user/test/com/google/gwt/core/client/impl/EmulatedStackTraceTest.java
Modified:
  /trunk/dev/core/src/com/google/gwt/core/linker/IFrameLinker.java
  /trunk/user/src/com/google/gwt/junit/JUnit.gwt.xml
  /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
  /trunk/user/test/com/google/gwt/core/CoreSuite.java
  /trunk/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/junit/linker/JUnitSymbolMapsLinker.java      
 
Wed Dec 16 17:16:05 2009
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.junit.linker;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.CompilationResult;
+import com.google.gwt.core.ext.linker.EmittedArtifact;
+import com.google.gwt.core.linker.SymbolMapsLinker;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Emits the symbol maps into the application output directory so that the
+ * JUnitHostImpl servlet can read them.
+ */
+public class JUnitSymbolMapsLinker extends SymbolMapsLinker {
+  @Override
+  protected void doEmitSymbolMap(TreeLogger logger, ArtifactSet artifacts,
+      CompilationResult result, ByteArrayOutputStream out)
+      throws UnableToCompleteException {
+    // Collaborate with JUnitHostImpl.loadSymbolMap
+    String partialPath = ".junit_symbolMaps/" + result.getStrongName()
+        + STRONG_NAME_SUFFIX;
+
+    EmittedArtifact symbolMapArtifact = emitBytes(logger,  
out.toByteArray(),
+        partialPath);
+
+    artifacts.add(symbolMapArtifact);
+  }
+
+}
=======================================
---  
/trunk/user/test/com/google/gwt/core/client/impl/EmulatedStackTraceTest.java    
 
Tue Jul 28 09:27:08 2009
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
- * use this file except in compliance with the License. You may obtain a  
copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations  
under
- * the License.
- */
-package com.google.gwt.core.client.impl;
-
-/**
- * Reuses the existing StackTraceCreatorTest, but forces emulated JS stack  
trace
- * code to be emitted..
- */
-public class EmulatedStackTraceTest extends StackTraceCreatorTest {
-
-  @Override
-  public String getModuleName() {
-    return "com.google.gwt.core.EmulateJsStack";
-  }
-
-}
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/linker/IFrameLinker.java    Wed  
Oct 21 13:20:55 2009
+++ /trunk/dev/core/src/com/google/gwt/core/linker/IFrameLinker.java    Wed  
Dec 16 17:16:05 2009
@@ -259,7 +259,7 @@
      out.newlineOpt();

      // Setup the well-known variables.
-    out.print("<head><script>");
+    out.print("<head><meta charset=\"UTF-8\" /><script>");
      out.newlineOpt();
      out.print("var $gwt_version = \"" + About.getGwtVersionNum() + "\";");
      out.newlineOpt();
=======================================
--- /trunk/user/src/com/google/gwt/junit/JUnit.gwt.xml  Wed Aug 19 11:04:00  
2009
+++ /trunk/user/src/com/google/gwt/junit/JUnit.gwt.xml  Wed Dec 16 17:16:05  
2009
@@ -31,15 +31,12 @@
      <when-type-assignable class="com.google.gwt.junit.client.GWTTestCase"/>
    </generate-with>

-  <!-- We want to provide good stack traces on browsers that don't provide  
good native stack traces. -->
+  <!-- We want to provide consistent stack traces across all browsers. -->
    <set-configuration-property  
name="compiler.emulatedStack.recordFileNames" value="true" />
-  <set-property name="compiler.emulatedStack" value="true" >
-    <none>
-      <when-property-is name="user.agent" value="gecko" />
-      <when-property-is name="user.agent" value="gecko1_8" />
-      <when-property-is name="user.agent" value="opera" />
-    </none>
-  </set-property>
+  <set-property name="compiler.emulatedStack" value="true" />
+
+  <!-- Override the regular symbolMaps linker to put the data somewhere we  
can find it -->
+  <define-linker name="symbolMaps"  
class="com.google.gwt.junit.linker.JUnitSymbolMapsLinker" />

    <servlet path='/junithost'  
class='com.google.gwt.junit.server.JUnitHostImpl'/>

=======================================
--- /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java      Tue Nov 
 
24 12:23:12 2009
+++ /trunk/user/src/com/google/gwt/junit/server/JUnitHostImpl.java      Wed Dec 
 
16 17:16:05 2009
@@ -15,6 +15,8 @@
   */
  package com.google.gwt.junit.server;

+import com.google.gwt.dev.util.JsniRef;
+import com.google.gwt.dev.util.StringKey;
  import com.google.gwt.junit.JUnitFatalLaunchException;
  import com.google.gwt.junit.JUnitMessageQueue;
  import com.google.gwt.junit.JUnitShell;
@@ -28,10 +30,14 @@
  import com.google.gwt.user.server.rpc.HybridServiceServlet;
  import com.google.gwt.user.server.rpc.RPCServletUtils;

+import java.io.BufferedReader;
  import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Field;
  import java.util.HashMap;
+import java.util.Map;
  import java.util.concurrent.atomic.AtomicInteger;

  import javax.servlet.ServletException;
@@ -45,6 +51,18 @@
   */
  public class JUnitHostImpl extends HybridServiceServlet implements  
JUnitHost {

+  private static class StrongName extends StringKey {
+    protected StrongName(String value) {
+      super(value);
+    }
+  }
+
+  private static class SymbolName extends StringKey {
+    protected SymbolName(String value) {
+      super(value);
+    }
+  }
+
    /**
     * A hook into GWTUnitTestShell, the underlying unit test process.
     */
@@ -87,6 +105,8 @@
      fld.setAccessible(true);
      fld.set(obj, value);
    }
+
+  private Map<StrongName, Map<SymbolName, String>> symbolMaps = new  
HashMap<StrongName, Map<SymbolName, String>>();

    public InitialResponse getTestBlock(int blockIndex, ClientInfo  
clientInfo)
        throws TimeoutException {
@@ -216,8 +236,9 @@
     */
    private StackTraceElement deserialize(StackTraceWrapper stw) {
      StackTraceElement ste = null;
-    Object[] args = new Object[] {
-        stw.className, stw.methodName, stw.fileName, stw.lineNumber};
+
+    Object[] args = resymbolize(stw);
+
      try {
        try {
          // Try the 4-arg ctor (JRE 1.5)
@@ -268,4 +289,71 @@
      String machine = request.getRemoteHost();
      result.setHost(machine);
    }
-}
+
+  private synchronized Map<SymbolName, String> loadSymbolMap(
+      StrongName strongName) {
+    Map<SymbolName, String> toReturn = symbolMaps.get(strongName);
+    if (toReturn != null) {
+      return toReturn;
+    }
+    toReturn = new HashMap<SymbolName, String>();
+
+    /*
+     * Collaborate with SymbolMapsLinker for the location of the symbol  
data
+     * because the -aux directory isn't accessible via the servlet context.
+     */
+    String path = getRequestModuleBasePath() + "/.junit_symbolMaps/"
+        + strongName.get() + ".symbolMap";
+    InputStream in = getServletContext().getResourceAsStream(path);
+    if (in == null) {
+      symbolMaps.put(strongName, null);
+      return null;
+    }
+
+    BufferedReader bin = new BufferedReader(new InputStreamReader(in));
+    String line;
+    try {
+      while ((line = bin.readLine()) != null) {
+        if (line.charAt(0) == '#') {
+          continue;
+        }
+        int idx = line.indexOf(',');
+        toReturn.put(new SymbolName(line.substring(0, idx)),
+            line.substring(idx + 1));
+      }
+    } catch (IOException e) {
+      toReturn = null;
+    }
+
+    symbolMaps.put(strongName, toReturn);
+    return toReturn;
+  }
+
+  /**
+   * @return {className, methodName, fileName, lineNumber}
+   */
+  private Object[] resymbolize(StackTraceWrapper stw) {
+    Object[] toReturn;
+    StrongName strongName = new StrongName(getPermutationStrongName());
+    Map<SymbolName, String> map = loadSymbolMap(strongName);
+    String symbolData = map == null ? null : map.get(new SymbolName(
+        stw.methodName));
+
+    if (symbolData != null) {
+      // jsniIdent, className, memberName, sourceUri, sourceLine
+      String[] parts = symbolData.split(",");
+      assert parts.length == 5 : "Expected 5, have " + parts.length;
+
+      JsniRef ref = JsniRef.parse(parts[0].substring(0,
+          parts[0].lastIndexOf(')') + 1));
+      toReturn = new Object[] {
+          ref.className(), ref.memberName(), stw.fileName, stw.lineNumber};
+
+    } else {
+      // Use the raw data from the client
+      toReturn = new Object[] {
+          stw.className, stw.methodName, stw.fileName, stw.lineNumber};
+    }
+    return toReturn;
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/core/CoreSuite.java Tue Dec 15 13:40:53  
2009
+++ /trunk/user/test/com/google/gwt/core/CoreSuite.java Wed Dec 16 17:16:05  
2009
@@ -21,7 +21,6 @@
  import com.google.gwt.core.client.JsArrayTest;
  import com.google.gwt.core.client.SchedulerTest;
  import com.google.gwt.core.client.impl.AsyncFragmentLoaderTest;
-import com.google.gwt.core.client.impl.EmulatedStackTraceTest;
  import com.google.gwt.core.client.impl.SchedulerImplTest;
  import com.google.gwt.core.client.impl.StackTraceCreatorTest;
  import com.google.gwt.core.client.impl.XhrLoadingStrategyTest;
@@ -38,7 +37,6 @@

      // $JUnit-BEGIN$
      suite.addTestSuite(AsyncFragmentLoaderTest.class);
-    suite.addTestSuite(EmulatedStackTraceTest.class);
      suite.addTestSuite(GWTTest.class);
      suite.addTestSuite(HttpThrowableReporterTest.class);
      suite.addTestSuite(JavaScriptExceptionTest.class);
=======================================
---  
/trunk/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java     
 
Mon Oct 26 18:35:41 2009
+++  
/trunk/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java     
 
Wed Dec 16 17:16:05 2009
@@ -53,7 +53,7 @@
      if (!GWT.isScript()) {
        myName = "testJavaScriptException";
      } else {
-      myName = testJavaScriptExceptionName();
+      myName =  
Impl.getNameOf("@com.google.gwt.core.client.impl.StackTraceCreatorTest::testJavaScriptException()");
      }

      checkStack(myName, t);
@@ -97,7 +97,7 @@
      if (!GWT.isScript()) {
        myName = "testStackTraces";
      } else {
-      myName = testStackTracesName();
+      myName =  
Impl.getNameOf("@com.google.gwt.core.client.impl.StackTraceCreatorTest::testStackTraces()");
      }

      checkStack(myName, t);
@@ -159,16 +159,6 @@
      }
    }

-  private static native String testJavaScriptExceptionName() /*-{
-    var fn =  
@com.google.gwt.core.client.impl.StackTraceCreatorTest::testJavaScriptException();
-    return  
@com.google.gwt.core.client.impl.StackTraceCreator::extractNameFromToString(Ljava/lang/String;)(fn.toString());
-  }-*/;
-
-  private static native String testStackTracesName() /*-{
-    var fn =  
@com.google.gwt.core.client.impl.StackTraceCreatorTest::testStackTraces();
-    return  
@com.google.gwt.core.client.impl.StackTraceCreator::extractNameFromToString(Ljava/lang/String;)(fn.toString());
-  }-*/;
-
    private static native void throwNative() /*-{
      null.a();
    }-*/;

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to