Revision: 10675
Author:   mlow...@google.com
Date:     Fri Sep 30 10:03:13 2011
Log: Exporting a map of obfuscated CSS names to full class names into a build
artifact CSV file. This will allow CSS names to be found in the DOM for
frontend testing.

Review by: unn...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10675

Added:
 /trunk/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java
Modified:
 /trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
 /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java

=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/resources/rg/CssOutputTestCase.java Fri Sep 30 10:03:13 2011
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2011 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.resources.rg;
+
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.GeneratedResource;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JMethod;
+import com.google.gwt.dev.util.UnitTestTreeLogger;
+import com.google.gwt.resources.ext.ResourceContext;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Tests output functions.
+ */
+public class CssOutputTestCase extends TestCase {
+
+  public void testOutputCssMapArtifact() throws UnableToCompleteException {
+ UnitTestTreeLogger testLogger = new UnitTestTreeLogger.Builder().createLogger(); + ResourceContext mockResourceContext = EasyMock.createMock(ResourceContext.class);
+    Map<JMethod, String> testMap = new HashMap<JMethod, String>();
+ OutputStream mockOutputStream = EasyMock.createMock(OutputStream.class); + GeneratorContext mockGeneratorContext = EasyMock.createMock(GeneratorContext.class); + GeneratedResource mockGeneratedResource = EasyMock.createMock(GeneratedResource.class);
+
+ EasyMock.expect(mockResourceContext.getGeneratorContext()).andReturn(mockGeneratorContext);
+    EasyMock.expectLastCall().times(2);
+    EasyMock.expect(mockGeneratorContext.tryCreateResource(
+ testLogger, "cssResource/test-file-name.cssmap")).andReturn(mockOutputStream); + EasyMock.expect(mockGeneratorContext.commitResource(testLogger, mockOutputStream)).andReturn(
+        mockGeneratedResource);
+    EasyMock.replay(mockResourceContext);
+    EasyMock.replay(mockGeneratorContext);
+
+    CssResourceGenerator crg = new CssResourceGenerator();
+ crg.outputCssMapArtifact(testLogger, mockResourceContext, testMap, "test-file-name");
+
+    testLogger.assertCorrectLogEntries();
+    EasyMock.verify(mockResourceContext);
+    EasyMock.verify(mockGeneratorContext);
+  }
+
+ public void testOutputCssMapArtifactThrowOnTryCreateResource() throws UnableToCompleteException {
+    UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder();
+ builder.expectError("Could not create resource: cssResource/test-file2.cssmap", null);
+    UnitTestTreeLogger testLogger =  builder.createLogger();
+ ResourceContext mockResourceContext = EasyMock.createMock(ResourceContext.class);
+    Map<JMethod, String> testMap = new HashMap<JMethod, String>();
+ OutputStream mockOutputStream = EasyMock.createMock(OutputStream.class); + GeneratorContext mockGeneratorContext = EasyMock.createMock(GeneratorContext.class); + GeneratedResource mockGeneratedResource = EasyMock.createMock(GeneratedResource.class);
+
+ EasyMock.expect(mockResourceContext.getGeneratorContext()).andReturn(mockGeneratorContext);
+    EasyMock.expect(mockGeneratorContext.tryCreateResource(
+ testLogger, "cssResource/test-file2.cssmap")).andThrow(new UnableToCompleteException());
+    EasyMock.replay(mockResourceContext);
+    EasyMock.replay(mockGeneratorContext);
+
+    CssResourceGenerator crg = new CssResourceGenerator();
+ crg.outputCssMapArtifact(testLogger, mockResourceContext, testMap, "test-file2");
+
+    testLogger.assertCorrectLogEntries();
+    EasyMock.verify(mockResourceContext);
+    EasyMock.verify(mockGeneratorContext);
+  }
+
+ public void testOutputCssMapArtifactReturnNullOutputString() throws UnableToCompleteException {
+    UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder();
+ builder.expectError("Created resource is null: cssResource/test-file3.cssmap", null);
+    UnitTestTreeLogger testLogger =  builder.createLogger();
+ ResourceContext mockResourceContext = EasyMock.createMock(ResourceContext.class);
+    Map<JMethod, String> testMap = new HashMap<JMethod, String>();
+ OutputStream mockOutputStream = EasyMock.createMock(OutputStream.class); + GeneratorContext mockGeneratorContext = EasyMock.createMock(GeneratorContext.class); + GeneratedResource mockGeneratedResource = EasyMock.createMock(GeneratedResource.class);
+
+ EasyMock.expect(mockResourceContext.getGeneratorContext()).andReturn(mockGeneratorContext);
+    EasyMock.expect(mockGeneratorContext.tryCreateResource(
+        testLogger, "cssResource/test-file3.cssmap")).andReturn(null);
+    EasyMock.replay(mockResourceContext);
+    EasyMock.replay(mockGeneratorContext);
+
+    CssResourceGenerator crg = new CssResourceGenerator();
+ crg.outputCssMapArtifact(testLogger, mockResourceContext, testMap, "test-file3");
+
+    testLogger.assertCorrectLogEntries();
+    EasyMock.verify(mockResourceContext);
+    EasyMock.verify(mockGeneratorContext);
+  }
+
+ public void testOutputCssMapArtifactThrowOnCommitResource() throws UnableToCompleteException {
+    UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder();
+ builder.expectError("Error trying to commit artifact: cssResource/test-file4.cssmap", null);
+    UnitTestTreeLogger testLogger =  builder.createLogger();
+ ResourceContext mockResourceContext = EasyMock.createMock(ResourceContext.class);
+    Map<JMethod, String> testMap = new HashMap<JMethod, String>();
+ OutputStream mockOutputStream = EasyMock.createMock(OutputStream.class); + GeneratorContext mockGeneratorContext = EasyMock.createMock(GeneratorContext.class); + GeneratedResource mockGeneratedResource = EasyMock.createMock(GeneratedResource.class);
+
+ EasyMock.expect(mockResourceContext.getGeneratorContext()).andReturn(mockGeneratorContext);
+    EasyMock.expectLastCall().times(2);
+    EasyMock.expect(mockGeneratorContext.tryCreateResource(
+ testLogger, "cssResource/test-file4.cssmap")).andReturn(mockOutputStream); + EasyMock.expect(mockGeneratorContext.commitResource(testLogger, mockOutputStream)).andThrow(
+        new UnableToCompleteException());
+    EasyMock.replay(mockResourceContext);
+    EasyMock.replay(mockGeneratorContext);
+
+    CssResourceGenerator crg = new CssResourceGenerator();
+ crg.outputCssMapArtifact(testLogger, mockResourceContext, testMap, "test-file4");
+
+    testLogger.assertCorrectLogEntries();
+    EasyMock.verify(mockResourceContext);
+    EasyMock.verify(mockGeneratorContext);
+  }
+
+ public void testOutputCssMapArtifactWithTestData() throws UnableToCompleteException { + UnitTestTreeLogger testLogger = new UnitTestTreeLogger.Builder().createLogger(); + ResourceContext mockResourceContext = EasyMock.createMock(ResourceContext.class);
+    JMethod mockJMethod1 = EasyMock.createMock(JMethod.class);
+    JMethod mockJMethod2 = EasyMock.createMock(JMethod.class);
+    JMethod mockJMethod3 = EasyMock.createMock(JMethod.class);
+    JClassType mockJClassType1 = EasyMock.createMock(JClassType.class);
+    JClassType mockJClassType2 = EasyMock.createMock(JClassType.class);
+    JClassType mockJClassType3 = EasyMock.createMock(JClassType.class);
+    Map<JMethod, String> testMap = new LinkedHashMap<JMethod, String>();
+    testMap.put(mockJMethod1, "TESTCSSNAME1");
+    testMap.put(mockJMethod2, "TESTCSSNAME2");
+    testMap.put(mockJMethod3, "TESTCSSNAME3");
+    ByteArrayOutputStream testOutputStream = new ByteArrayOutputStream();
+ GeneratorContext mockGeneratorContext = EasyMock.createMock(GeneratorContext.class); + GeneratedResource mockGeneratedResource = EasyMock.createMock(GeneratedResource.class);
+
+ EasyMock.expect(mockResourceContext.getGeneratorContext()).andReturn(mockGeneratorContext);
+    EasyMock.expectLastCall().times(2);
+    EasyMock.expect(mockGeneratorContext.tryCreateResource(
+ testLogger, "cssResource/test-file5.cssmap")).andReturn(testOutputStream); + EasyMock.expect(mockJMethod1.getEnclosingType()).andReturn(mockJClassType1); + EasyMock.expect(mockJClassType1.getQualifiedSourceName()).andReturn("test.class.type.1");
+    EasyMock.expect(mockJMethod1.getName()).andReturn("basename1");
+ EasyMock.expect(mockJMethod2.getEnclosingType()).andReturn(mockJClassType2); + EasyMock.expect(mockJClassType2.getQualifiedSourceName()).andReturn("test.class.type.2");
+    EasyMock.expect(mockJMethod2.getName()).andReturn("basename2");
+ EasyMock.expect(mockJMethod3.getEnclosingType()).andReturn(mockJClassType3); + EasyMock.expect(mockJClassType3.getQualifiedSourceName()).andReturn("test.class.type.3");
+    EasyMock.expect(mockJMethod3.getName()).andReturn("basename3");
+ EasyMock.expect(mockGeneratorContext.commitResource(testLogger, testOutputStream)).andReturn(
+        mockGeneratedResource);
+    EasyMock.replay(mockResourceContext);
+    EasyMock.replay(mockGeneratorContext);
+    EasyMock.replay(mockJMethod1);
+    EasyMock.replay(mockJMethod2);
+    EasyMock.replay(mockJMethod3);
+    EasyMock.replay(mockJClassType1);
+    EasyMock.replay(mockJClassType2);
+    EasyMock.replay(mockJClassType3);
+
+    CssResourceGenerator crg = new CssResourceGenerator();
+ crg.outputCssMapArtifact(testLogger, mockResourceContext, testMap, "test-file5");
+    String expectedOutput = "test-class-type-1-basename1,TESTCSSNAME1\n" +
+        "test-class-type-2-basename2,TESTCSSNAME2\n" +
+        "test-class-type-3-basename3,TESTCSSNAME3\n";
+    assertEquals(expectedOutput, testOutputStream.toString());
+
+    testLogger.assertCorrectLogEntries();
+    EasyMock.verify(mockResourceContext);
+    EasyMock.verify(mockGeneratorContext);
+    EasyMock.verify(mockJMethod1);
+    EasyMock.verify(mockJMethod2);
+    EasyMock.verify(mockJMethod3);
+    EasyMock.verify(mockJClassType1);
+    EasyMock.verify(mockJClassType2);
+    EasyMock.verify(mockJClassType3);
+  }
+
+}
=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java Thu Sep 22 13:53:31 2011 +++ /trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java Fri Sep 30 10:03:13 2011
@@ -21,6 +21,7 @@
 import com.google.gwt.core.ext.PropertyOracle;
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JMethod;
 import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
@@ -74,6 +75,10 @@
 import com.google.gwt.user.rebind.SourceWriter;
 import com.google.gwt.user.rebind.StringSourceWriter;

+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.Serializable;
 import java.net.URL;
 import java.util.ArrayList;
@@ -437,10 +442,13 @@
     JClassType cssResourceSubtype = method.getReturnType().isInterface();
     assert cssResourceSubtype != null;
     CssStylesheet stylesheet = stylesheetMap.get(method);
-
+
     // Optimize the stylesheet, recording the class selector obfuscations
Map<JMethod, String> actualReplacements = optimize(logger, context, method);

+    outputCssMapArtifact(logger, context, actualReplacements,
+        cssResourceSubtype.getQualifiedSourceName());
+
     outputAdditionalArtifacts(logger, context, method, actualReplacements,
         cssResourceSubtype, stylesheet);

@@ -577,11 +585,55 @@
* Output additional artifacts. Does nothing in this baseclass, but is a hook
    * for subclasses to do so.
    */
-  protected void outputAdditionalArtifacts(TreeLogger logger,
-      ResourceContext context, JMethod method,
+  protected void outputAdditionalArtifacts(TreeLogger logger,
+      ResourceContext context, JMethod method,
Map<JMethod, String> actualReplacements, JClassType cssResourceSubtype,
       CssStylesheet stylesheet) throws UnableToCompleteException {
   }
+
+  /**
+ * Builds a CSV file mapping obfuscated CSS class names to their qualified source name and
+   * outputs it as a private build artifact.
+   */
+ protected void outputCssMapArtifact(TreeLogger logger, ResourceContext context,
+      Map<JMethod, String> actualReplacements, String outputFileName) {
+    String mappingFileName = "cssResource/" + outputFileName + ".cssmap";
+
+    OutputStream os = null;
+    try {
+ os = context.getGeneratorContext().tryCreateResource(logger, mappingFileName);
+    } catch (UnableToCompleteException e) {
+ logger.log(TreeLogger.ERROR, "Could not create resource: " + mappingFileName);
+      return;
+    }
+
+    if (os == null) {
+ logger.log(TreeLogger.ERROR, "Created resource is null: " + mappingFileName);
+      return;
+    }
+
+    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os));
+    try {
+ for (Map.Entry<JMethod, String> replacement : actualReplacements.entrySet()) { + String qualifiedName = replacement.getKey().getEnclosingType().getQualifiedSourceName();
+        String baseName = replacement.getKey().getName();
+ writer.write(qualifiedName.replaceAll("[.$]", "-") + "-" + baseName);
+        writer.write(",");
+        writer.write(replacement.getValue());
+        writer.newLine();
+      }
+      writer.flush();
+      writer.close();
+    } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Error writing artifact: " + mappingFileName);
+    }
+
+    try {
+ context.getGeneratorContext().commitResource(logger, os).setVisibility(Visibility.Private);
+    } catch (UnableToCompleteException e) {
+ logger.log(TreeLogger.ERROR, "Error trying to commit artifact: " + mappingFileName);
+    }
+  }

   protected void writeGetName(JMethod method, SourceWriter sw) {
     sw.println("public String getName() {");
=======================================
--- /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java Wed Jan 26 06:01:10 2011 +++ /trunk/user/test/com/google/gwt/resources/ResourcesSuite.java Fri Sep 30 10:03:13 2011
@@ -33,6 +33,7 @@
 import com.google.gwt.resources.css.UnknownAtRuleTest;
 import com.google.gwt.resources.ext.ResourceGeneratorUtilTest;
 import com.google.gwt.resources.rg.CssClassNamesTestCase;
+import com.google.gwt.resources.rg.CssOutputTestCase;

 import junit.framework.Test;

@@ -46,6 +47,7 @@
     suite.addTestSuite(CssClassNamesTestCase.class);
     suite.addTestSuite(CssExternalTest.class);
     suite.addTestSuite(CssNodeClonerTest.class);
+    suite.addTestSuite(CssOutputTestCase.class);
     suite.addTestSuite(CssReorderTest.class);
     suite.addTestSuite(CSSResourceTest.class);
     suite.addTestSuite(CssRtlTest.class);

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

Reply via email to