Revision: 6425 Author: [email protected] Date: Tue Oct 20 11:31:25 2009 Log: Adding a feature that allows users to define compile properties on test methods in GwtTestCases. A synthetic module will be created using the test module plus the specified properties.
Patch by: pmuetschard Review by: jlabanca http://code.google.com/p/google-web-toolkit/source/detail?r=6425 Added: /trunk/user/src/com/google/gwt/junit/PropertyDefiningStrategy.java /trunk/user/src/com/google/gwt/junit/client/WithProperties.java /trunk/user/test/com/google/gwt/junit/JUnitTestWithProperties.gwt.xml /trunk/user/test/com/google/gwt/junit/PropertyDefiningStrategyTest.java /trunk/user/test/com/google/gwt/junit/client/PropertyDefiningGWTTest.java Modified: /trunk/user/src/com/google/gwt/benchmarks/client/Benchmark.java /trunk/user/src/com/google/gwt/junit/CompileStrategy.java /trunk/user/src/com/google/gwt/junit/JUnitShell.java /trunk/user/src/com/google/gwt/junit/client/GWTTestCase.java /trunk/user/src/com/google/gwt/junit/tools/GWTTestSuite.java /trunk/user/test/com/google/gwt/junit/JUnitSuite.java ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/junit/PropertyDefiningStrategy.java Tue Oct 20 11:31:25 2009 @@ -0,0 +1,133 @@ +/* + * 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; + +import com.google.gwt.dev.cfg.BindingProperty; +import com.google.gwt.dev.cfg.ModuleDef; +import com.google.gwt.dev.cfg.Properties; +import com.google.gwt.dev.util.Util; +import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.junit.client.WithProperties; +import com.google.gwt.junit.client.WithProperties.Property; + +import junit.framework.TestCase; + +import java.lang.reflect.Method; +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/** + * A {...@link JUnitShell.Strategy} that will alter the module the tests are run + * in by defining module properties as requested by annotations on the tests. + */ +public class PropertyDefiningStrategy extends GWTTestCase.BaseStrategy { + private TestCase testCase; + private Set<Property> properties; + + public PropertyDefiningStrategy(TestCase testCase) { + this.testCase = testCase; + } + + protected String getBaseModuleExtension() { + return super.getSyntheticModuleExtension(); + } + + @Override + public String getSyntheticModuleExtension() { + String extension = getBaseModuleExtension(); + computePropertiesMap(); + if (properties.size() > 0) { + StringBuilder sb = new StringBuilder(); + for (Property property : properties) { + sb.append(".").append(property.name()).append( + "$").append(property.value()); + } + extension += sb.toString(); + } + return extension; + } + + @Override + public void processModule(ModuleDef module) { + super.processModule(module); + computePropertiesMap(); + if (properties.size() > 0) { + Properties props = module.getProperties(); + for (Property property : properties) { + BindingProperty binding = props.createBinding(property.name()); + if (!binding.isDefinedValue(property.value())) { + binding.addDefinedValue( + binding.getRootCondition(), property.value()); + } + binding.setAllowedValues( + binding.getRootCondition(), property.value()); + } + } + } + + private Property checkProperty(Property property) { + String[] tokens = (property.name() + ". ").split("\\."); + for (int i = 0; i < tokens.length - 1; i++) { + if (!Util.isValidJavaIdent(tokens[i])) { + throw new AssertionError( + "Property name invalid: " + property.name()); + } + } + + if (!Util.isValidJavaIdent(property.value())) { + throw new AssertionError( + "Property value invalid: " + property.value()); + } + + return property; + } + + private void computePropertiesMap() { + if (properties == null) { + Set<Property> props = new TreeSet<Property>( + new Comparator<Property>() { + public int compare(Property p1, Property p2) { + int r = p1.name().compareTo(p2.name()); + if (r == 0) { + r = p1.value().compareTo(p2.value()); + } + return r; + } + }); + try { + String name = testCase.getName(); + if (name != null) { + Method testMethod = testCase.getClass().getMethod(testCase.getName()); + if (testMethod.isAnnotationPresent(WithProperties.class)) { + WithProperties annotation = + testMethod.getAnnotation(WithProperties.class); + for (Property property : annotation.value()) { + props.add(checkProperty(property)); + } + } + } + } catch (SecurityException e) { + // should not happen + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // should not happen + e.printStackTrace(); + } + properties = props; + } + } +} ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/junit/client/WithProperties.java Tue Oct 20 11:31:25 2009 @@ -0,0 +1,41 @@ +/* + * 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.client; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation indicating that a test method inside a {...@link GWTTestCase} + * requires a set of binding properties to be set in its module. + */ +...@target(ElementType.METHOD) +...@retention(RetentionPolicy.RUNTIME) +public @interface WithProperties { + Property[] value(); + + /** + * Annotation defining a binding property. + */ + @Retention(RetentionPolicy.RUNTIME) + public static @interface Property { + String name(); + + String value(); + } +} ======================================= --- /dev/null +++ /trunk/user/test/com/google/gwt/junit/JUnitTestWithProperties.gwt.xml Tue Oct 20 11:31:25 2009 @@ -0,0 +1,37 @@ +<!-- --> +<!-- 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 --> +<!-- 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. License for the specific language governing permissions and --> +<!-- limitations under the License. --> + +<!-- This module is for the PropertyDefiningGWTTest --> +<module> + <inherits name="com.google.gwt.user.User" /> + <define-property name="my.property" values="one,two" /> + + <replace-with class="com.google.gwt.junit.client.PropertyDefiningGWTTest$TestImplOne"> + <when-type-is class="com.google.gwt.junit.client.PropertyDefiningGWTTest$TestInterface" /> + <when-property-is name="my.property" value="one" /> + </replace-with> + <replace-with class="com.google.gwt.junit.client.PropertyDefiningGWTTest.TestImplOne"> + <when-type-is class="com.google.gwt.junit.client.PropertyDefiningGWTTest.TestInterface" /> + <when-property-is name="my.property" value="one" /> + </replace-with> + + <replace-with class="com.google.gwt.junit.client.PropertyDefiningGWTTest$TestImplTwo"> + <when-type-is class="com.google.gwt.junit.client.PropertyDefiningGWTTest$TestInterface" /> + <when-property-is name="my.property" value="two" /> + </replace-with> + <replace-with class="com.google.gwt.junit.client.PropertyDefiningGWTTest.TestImplTwo"> + <when-type-is class="com.google.gwt.junit.client.PropertyDefiningGWTTest.TestInterface" /> + <when-property-is name="my.property" value="two" /> + </replace-with> +</module> ======================================= --- /dev/null +++ /trunk/user/test/com/google/gwt/junit/PropertyDefiningStrategyTest.java Tue Oct 20 11:31:25 2009 @@ -0,0 +1,113 @@ +/* + * 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; + +import com.google.gwt.dev.cfg.BindingProperty; +import com.google.gwt.dev.cfg.ModuleDef; +import com.google.gwt.junit.client.WithProperties; +import com.google.gwt.junit.client.WithProperties.Property; + +import junit.framework.TestCase; + +import java.util.SortedSet; + +/** + * Tests the {...@link PropertyDefiningStrategy}. + */ +public class PropertyDefiningStrategyTest extends TestCase { + private static class PropertyValue { + public String name, value; + + public PropertyValue(String name, String value) { + this.name = name; + this.value = value; + } + } + + @WithProperties({...@property(name = "name", value = "value")}) + public void methodWithSingleProperty() { + } + + @WithProperties({ + @Property(name = "name2", value = "value2"), + @Property(name = "name1", value = "value1")}) + public void methodWithTwoProperties() { + } + + public void methodWithoutProperties() { + } + + public void testGetSyntheticModuleExtension() { + assertEquals("JUnit.name$value", + getStrategyForSingleProperty().getSyntheticModuleExtension()); + assertEquals("JUnit.name1$value1.name2$value2", + getStrategyForTwoProperties().getSyntheticModuleExtension()); + assertEquals("JUnit", + getStrategyForNoProperty().getSyntheticModuleExtension()); + } + + public void testProcessModuleForTestCaseWithSingleProperty() { + ModuleDef module = new ModuleDef("myModule"); + getStrategyForSingleProperty().processModule(module); + assertProperties(module, p("name", "value")); + } + + public void testProcessModuleForTestCaseWithTwoProperties() { + ModuleDef module = new ModuleDef("myModule"); + getStrategyForTwoProperties().processModule(module); + assertProperties(module, p("name1", "value1"), p("name2", "value2")); + } + + public void testProcessModuleForTestCaseWithoutProperties() { + ModuleDef module = new ModuleDef("myModule"); + getStrategyForNoProperty().processModule(module); + assertProperties(module); + } + + private void assertProperties(ModuleDef module, PropertyValue... props) { + SortedSet<BindingProperty> properties = module.getProperties().getBindingProperties(); + assertEquals(props.length, properties.size()); + int i = 0; + for (BindingProperty property : properties) { + assertEquals("property " + i, props[i].name, property.getName()); + assertEquals("property " + i, props[i].value, + property.getConstrainedValue()); + i++; + } + } + + private static PropertyValue p(String name, String value) { + return new PropertyValue(name, value); + } + + private PropertyDefiningStrategy getStrategyForSingleProperty() { + TestCase result = new PropertyDefiningStrategyTest(); + result.setName("methodWithSingleProperty"); + return new PropertyDefiningStrategy(result); + } + + private PropertyDefiningStrategy getStrategyForTwoProperties() { + TestCase result = new PropertyDefiningStrategyTest(); + result.setName("methodWithTwoProperties"); + return new PropertyDefiningStrategy(result); + } + + private PropertyDefiningStrategy getStrategyForNoProperty() { + TestCase result = new PropertyDefiningStrategyTest(); + result.setName("methodWithoutProperties"); + return new PropertyDefiningStrategy(result); + } +} ======================================= --- /dev/null +++ /trunk/user/test/com/google/gwt/junit/client/PropertyDefiningGWTTest.java Tue Oct 20 11:31:25 2009 @@ -0,0 +1,75 @@ +/* + * 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.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.junit.client.WithProperties.Property; + +import java.util.Date; + +/** + * A {...@link GWTTestCase} that defines module properties. + */ +public class PropertyDefiningGWTTest extends GWTTestCase { + /** + * Base interface used for testing. + */ + public static interface TestInterface { + String value(); + } + + /** + * Implementation used in one deferred binding. + */ + public static class TestImplOne implements TestInterface { + public String value() { + return "one"; + } + } + + /** + * Implementation used in the other deferred binding. + */ + public static class TestImplTwo implements TestInterface { + public String value() { + return "two"; + } + } + + @Override + public String getModuleName() { + return "com.google.gwt.junit.JUnitTestWithProperties"; + } + + @WithProperties({ + @Property(name = "locale", value = "en_US"), + @Property(name = "my.property", value = "one") + }) + public void testInUSLocaleAndPropertyOne() { + assertEquals("June", DateTimeFormat.getFormat("MMMM").format(new Date(99, 5, 13))); + assertEquals("one", GWT.<TestInterface> create(TestInterface.class).value()); + } + + @WithProperties({ + @Property(name = "locale", value = "de_CH"), + @Property(name = "my.property", value = "two") + }) + public void testInSwissLocaleAndPropertyTwo() { + assertEquals("Juni", DateTimeFormat.getFormat("MMMM").format(new Date(99, 5, 13))); + assertEquals("two", GWT.<TestInterface> create(TestInterface.class).value()); + } +} ======================================= --- /trunk/user/src/com/google/gwt/benchmarks/client/Benchmark.java Tue Sep 15 11:52:45 2009 +++ /trunk/user/src/com/google/gwt/benchmarks/client/Benchmark.java Tue Oct 20 11:31:25 2009 @@ -17,6 +17,7 @@ import com.google.gwt.benchmarks.BenchmarkShell; import com.google.gwt.benchmarks.client.impl.BenchmarkResults; +import com.google.gwt.junit.PropertyDefiningStrategy; import com.google.gwt.junit.JUnitShell.Strategy; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.junit.client.impl.JUnitResult; @@ -107,31 +108,34 @@ /** * The {...@link Strategy} used for benchmarking. */ - private static Strategy BENCHMARK_STRATEGY = new Strategy() { + public static class BenchmarkStrategy extends PropertyDefiningStrategy { + public BenchmarkStrategy(TestCase test) { + super(test); + } + + @Override public String getModuleInherit() { return "com.google.gwt.benchmarks.Benchmarks"; } - public String getSyntheticModuleExtension() { - return "Benchmarks"; - } - + @Override public void processResult(TestCase testCase, JUnitResult result) { + super.processResult(testCase, result); if (result instanceof BenchmarkResults) { BenchmarkShell.getReport().addBenchmarkResults(testCase, (BenchmarkResults) result); } } - }; - - /** - * Get the {...@link Strategy} to use when compiling and running this test. - * - * @return the test {...@link Strategy} - */ + + @Override + protected String getBaseModuleExtension() { + return "Benchmarks"; + } + } + @Override - public Strategy getStrategy() { - return BENCHMARK_STRATEGY; + protected Strategy createStrategy() { + return new BenchmarkStrategy(this); } /** ======================================= --- /trunk/user/src/com/google/gwt/junit/CompileStrategy.java Tue Oct 13 16:57:19 2009 +++ /trunk/user/src/com/google/gwt/junit/CompileStrategy.java Tue Oct 20 11:31:25 2009 @@ -182,6 +182,8 @@ "junit.moduleName", false); moduleNameProp.setValue(syntheticModuleName); + strategy.processModule(moduleDef); + junitShell.maybeCompileForWebMode(syntheticModuleName); return moduleDef; ======================================= --- /trunk/user/src/com/google/gwt/junit/JUnitShell.java Tue Oct 13 16:57:19 2009 +++ /trunk/user/src/com/google/gwt/junit/JUnitShell.java Tue Oct 20 11:31:25 2009 @@ -94,6 +94,8 @@ String getSyntheticModuleExtension(); + void processModule(ModuleDef module); + void processResult(TestCase testCase, JUnitResult result); } ======================================= --- /trunk/user/src/com/google/gwt/junit/client/GWTTestCase.java Wed Sep 30 12:07:05 2009 +++ /trunk/user/src/com/google/gwt/junit/client/GWTTestCase.java Tue Oct 20 11:31:25 2009 @@ -15,7 +15,9 @@ */ package com.google.gwt.junit.client; +import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.junit.JUnitShell; +import com.google.gwt.junit.PropertyDefiningStrategy; import com.google.gwt.junit.JUnitShell.Strategy; import com.google.gwt.junit.client.impl.JUnitResult; import com.google.gwt.junit.client.impl.JUnitHost.TestInfo; @@ -43,6 +45,25 @@ * </p> */ public abstract class GWTTestCase extends TestCase { + + /** + * The base class for strategies to use for tests. + */ + public static class BaseStrategy implements Strategy { + public String getModuleInherit() { + return "com.google.gwt.junit.JUnit"; + } + + public String getSyntheticModuleExtension() { + return "JUnit"; + } + + public void processModule(ModuleDef module) { + } + + public void processResult(TestCase testCase, JUnitResult result) { + } + } /** * Information about a synthetic module used for testing. @@ -103,22 +124,6 @@ */ private static final Object ALL_GWT_TESTS_LOCK = new Object(); - /** - * The default strategy to use for tests. - */ - private static final Strategy DEFAULT_STRATEGY = new Strategy() { - public String getModuleInherit() { - return "com.google.gwt.junit.JUnit"; - } - - public String getSyntheticModuleExtension() { - return "JUnit"; - } - - public void processResult(TestCase testCase, JUnitResult result) { - } - }; - /** * Get the names of all test modules. * @@ -158,6 +163,11 @@ */ protected TestResult testResult = null; + /** + * The {...@link Strategy} used by this test. + */ + private Strategy strategy; + /** * A new instance of your subclass is constructed for each test method that is * to be run. You should avoid running code in your subclass constructor, @@ -246,7 +256,10 @@ * @return the test {...@link Strategy} */ public Strategy getStrategy() { - return DEFAULT_STRATEGY; + if (strategy == null) { + strategy = createStrategy(); + } + return strategy; } /** @@ -289,6 +302,13 @@ new TestInfo(syntheticModuleName, getClass().getName(), getName())); } } + + /** + * Creates the test strategy to use (see {...@link #getStrategy()}). + */ + protected Strategy createStrategy() { + return new PropertyDefiningStrategy(this); + } /** * Put the current test in asynchronous mode. If the test method completes ======================================= --- /trunk/user/src/com/google/gwt/junit/tools/GWTTestSuite.java Tue Jun 23 17:40:28 2009 +++ /trunk/user/src/com/google/gwt/junit/tools/GWTTestSuite.java Tue Oct 20 11:31:25 2009 @@ -80,7 +80,7 @@ if (test instanceof GWTTestCase) { GWTTestCase gwtTest = (GWTTestCase) test; - String moduleName = gwtTest.getModuleName(); + String moduleName = gwtTest.getSyntheticModuleName(); if (moduleName != null) { TestSuite suite = moduleSuites.get(moduleName); if (suite == null) { ======================================= --- /trunk/user/test/com/google/gwt/junit/JUnitSuite.java Thu Oct 1 10:34:33 2009 +++ /trunk/user/test/com/google/gwt/junit/JUnitSuite.java Tue Oct 20 11:31:25 2009 @@ -16,6 +16,7 @@ package com.google.gwt.junit; import com.google.gwt.junit.client.GWTTestCaseTest; +import com.google.gwt.junit.client.PropertyDefiningGWTTest; import com.google.gwt.junit.tools.GWTTestSuite; import junit.framework.Test; @@ -50,6 +51,9 @@ // Run manually only, launches servers that die on port contention // suite.addTestSuite(BrowserManagerServerTest.class); + suite.addTestSuite(PropertyDefiningStrategyTest.class); + suite.addTestSuite(PropertyDefiningGWTTest.class); + return suite; } } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
