| /* |
| * Copyright 2017 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.i18n.rebind; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.typeinfo.JClassType; |
| import com.google.gwt.core.ext.typeinfo.JMethod; |
| import com.google.gwt.core.ext.typeinfo.JPrimitiveType; |
| import com.google.gwt.core.ext.typeinfo.JType; |
| import com.google.gwt.core.ext.typeinfo.TypeOracle; |
| import com.google.gwt.core.ext.typeinfo.TypeOracleException; |
| import com.google.gwt.dev.javac.TypeOracleTestingUtils; |
| import com.google.gwt.dev.javac.testing.impl.MockJavaResource; |
| import com.google.gwt.dev.shell.FailErrorLogger; |
| import com.google.gwt.i18n.rebind.AbstractResource.ResourceList; |
| import com.google.gwt.i18n.server.GwtLocaleFactoryImpl; |
| import com.google.gwt.i18n.shared.GwtLocale; |
| import com.google.gwt.i18n.shared.GwtLocaleFactory; |
| import com.google.gwt.user.rebind.SourceWriter; |
| import com.google.gwt.user.rebind.StringSourceWriter; |
| |
| import junit.framework.TestCase; |
| |
| import static org.mockito.Matchers.anyString; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| /** |
| * Tests for {@link ConstantsWithLookupImplCreator}. |
| */ |
| public class ConstantsWithLookupImplCreatorTest extends TestCase { |
| |
| private static final int TEST_PARTITION_SIZE = 3; |
| |
| private static final MockJavaResource SINGLE_ENTRY_MESSAGES = new MockJavaResource( |
| "foo.SingleEntryMessage") { |
| @Override |
| public CharSequence getContent() { |
| StringBuffer code = new StringBuffer(); |
| code.append("package foo;\n"); |
| code.append("public interface SingleEntryMessage extends foo.Lookup {\n"); |
| code.append(" String stringEntry();\n"); |
| code.append(" int intEntry();\n"); |
| code.append("}"); |
| return code; |
| } |
| }; |
| |
| private static final MockJavaResource FOUR_ENTRY_MESSAGES = new MockJavaResource( |
| "foo.FourEntryMessage") { |
| @Override |
| public CharSequence getContent() { |
| StringBuffer code = new StringBuffer(); |
| code.append("package foo;\n"); |
| code.append("public interface FourEntryMessage extends foo.Lookup {\n"); |
| code.append(" String first();\n"); |
| code.append(" String second();\n"); |
| code.append(" String third();\n"); |
| code.append(" String fourth();\n"); |
| code.append("}"); |
| return code; |
| } |
| }; |
| private static final MockJavaResource PARTITION_SIZE_ENTRY_MESSAGES = new MockJavaResource( |
| "foo.PartitionSizeEntryMessage") { |
| @Override |
| public CharSequence getContent() { |
| StringBuffer code = new StringBuffer(); |
| code.append("package foo;\n"); |
| code.append("public interface PartitionSizeEntryMessage extends foo.Lookup {\n"); |
| for (int i = 1; i <= TEST_PARTITION_SIZE; i++) { |
| code.append(" String lookupMethod"); |
| code.append(i); |
| code.append("();\n"); |
| } |
| code.append("}"); |
| return code; |
| } |
| }; |
| |
| private static final MockJavaResource LOOKUP = new MockJavaResource("foo.Lookup") { |
| @Override |
| public CharSequence getContent() { |
| StringBuffer code = new StringBuffer(); |
| code.append("package foo;\n"); |
| code.append("public interface Lookup {\n"); |
| code.append(" String getString(String arg0);\n"); |
| code.append(" int getInt(String arg0);\n"); |
| code.append("}"); |
| return code; |
| } |
| }; |
| |
| private TreeLogger logger = new FailErrorLogger(); |
| |
| private GwtLocale locale; |
| |
| private ConstantsWithLookupImplCreator constantsWithLookupImplCreator; |
| |
| private SourceWriter sw = new StringSourceWriter(); |
| |
| private TypeOracle oracle; |
| |
| private JMethod stringMethod; |
| |
| private JMethod intMethod; |
| |
| @Override |
| public void setUp() throws TypeOracleException, UnableToCompleteException { |
| GwtLocaleFactory factory = new GwtLocaleFactoryImpl(); |
| locale = factory.fromString("en"); |
| oracle = TypeOracleTestingUtils.buildStandardTypeOracleWith(logger, SINGLE_ENTRY_MESSAGES, |
| FOUR_ENTRY_MESSAGES, LOOKUP, PARTITION_SIZE_ENTRY_MESSAGES); |
| initLookupMethodCreator(SINGLE_ENTRY_MESSAGES); |
| } |
| |
| public void testClassEpilogCallCreatesNeededPartitonLookups() { |
| List<JMethod> missingPartition0 = Arrays.asList(stringMethod, intMethod); |
| List<List<JMethod>> methodToCreatePartitionLookups = new ArrayList<>(); |
| methodToCreatePartitionLookups.add(missingPartition0); |
| constantsWithLookupImplCreator.addNeededPartitionLookups(stringMethod, |
| methodToCreatePartitionLookups); |
| |
| constantsWithLookupImplCreator.classEpilog(); |
| |
| String actual = sw.toString().trim(); |
| |
| assertTrue("Missing partition lookup method (getStringFromPartition0).", actual.contains( |
| "java.lang.String getStringFromPartition0(java.lang.String arg0) {")); |
| } |
| |
| public void testCodeForIntIsGeneratedSameAsWithoutPartitions() throws TypeOracleException, |
| UnableToCompleteException { |
| initLookupMethodCreator(SINGLE_ENTRY_MESSAGES); |
| constantsWithLookupImplCreator.emitMethodBody(logger, intMethod, locale); |
| |
| // Same generated code as in version 2.8.1 |
| SourceWriter expected = new StringSourceWriter(); |
| expected.println("Integer target = (Integer) cache.get(arg0);"); |
| expected.println("if (target != null) {"); |
| expected.indent(); |
| expected.println("return target.intValue();"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("if (arg0.equals(\"intEntry\")) {"); |
| expected.indent(); |
| expected.println("int answer = intEntry();"); |
| // Needed because the return template use '\n' |
| expected.outdent(); |
| expected.println("cache.put(\"intEntry\",new Integer(answer));"); |
| expected.println("return answer;"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("throw new java.util.MissingResourceException(" |
| + "\"Cannot find constant '\" +arg0 + \"'; expecting a method name\", \"foo.SingleEntryMessage\", arg0);"); |
| expected.outdent(); |
| |
| String actual = sw.toString(); |
| assertEquals("Wrong source Lookup created.", expected.toString(), actual); |
| } |
| |
| public void testCodeIsGeneratedSameAsWithoutPartitions() throws TypeOracleException, |
| UnableToCompleteException { |
| initLookupMethodCreator(PARTITION_SIZE_ENTRY_MESSAGES); |
| constantsWithLookupImplCreator.emitMethodBody(logger, stringMethod, locale); |
| |
| // Same generated code as in version 2.8.1 |
| SourceWriter expected = new StringSourceWriter(); |
| expected.println("java.lang.String target = (java.lang.String) cache.get(arg0);"); |
| expected.println("if (target != null) {"); |
| expected.indent(); |
| expected.println("return target;"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("if (arg0.equals(\"lookupMethod1\")) {"); |
| expected.indent(); |
| expected.print("String answer = lookupMethod1();"); |
| expected.print("\n"); |
| expected.print("cache.put(\"lookupMethod1\",answer);"); |
| expected.print("\n"); |
| expected.println("return answer;"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("if (arg0.equals(\"lookupMethod2\")) {"); |
| expected.indent(); |
| expected.print("String answer = lookupMethod2();"); |
| expected.print("\n"); |
| expected.print("cache.put(\"lookupMethod2\",answer);"); |
| expected.print("\n"); |
| expected.println("return answer;"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("if (arg0.equals(\"lookupMethod3\")) {"); |
| expected.indent(); |
| expected.print("String answer = lookupMethod3();"); |
| expected.print("\n"); |
| expected.print("cache.put(\"lookupMethod3\",answer);"); |
| expected.print("\n"); |
| expected.println("return answer;"); |
| expected.outdent(); |
| expected.println("}"); |
| |
| expected.println("throw new java.util.MissingResourceException(" |
| + "\"Cannot find constant '\" +arg0 + \"'; expecting a method name\", \"foo.PartitionSizeEntryMessage\", arg0);"); |
| expected.outdent(); |
| |
| String actual = sw.toString(); |
| assertEquals("Wrong source Lookup created.", expected.toString(), actual); |
| } |
| |
| public void testCreateMethodForJMethodForSingleEntry() throws UnableToCompleteException { |
| constantsWithLookupImplCreator.emitMethodBody(logger, stringMethod, locale); |
| |
| assertFalse("No partition lookup should created.", sw.toString().contains( |
| "java.lang.String getString0(java.lang.String arg0) {")); |
| } |
| |
| public void testCreateMethodForJMethodForSingleIntEntry() throws UnableToCompleteException { |
| constantsWithLookupImplCreator.emitMethodBody(logger, intMethod, locale); |
| |
| String createdSource = sw.toString(); |
| assertTrue("Lookup for intMethod not created.", createdSource.contains( |
| "int answer = intEntry();")); |
| } |
| |
| public void testCreateMethodForPartitionSizeEntriesNoPartitionNeeded() throws TypeOracleException, |
| UnableToCompleteException { |
| initLookupMethodCreator(PARTITION_SIZE_ENTRY_MESSAGES); |
| constantsWithLookupImplCreator.emitMethodBody(logger, stringMethod, locale); |
| |
| String actual = sw.toString(); |
| |
| assertFalse("Missing partition lookup method (getStringFromPartitionN).", actual.contains( |
| "getStringFromPartition")); |
| } |
| |
| public void testCreatePartitionMethodName() { |
| String partitionMethodName = constantsWithLookupImplCreator.createPartitionMethodName( |
| stringMethod, 1); |
| String expectedPartitionMethodName = "getStringFromPartition1"; |
| assertEquals(expectedPartitionMethodName, partitionMethodName); |
| } |
| |
| public void testEmitClassWithMultiMessageEntryCreateOneAdditionalPartition() |
| throws TypeOracleException, UnableToCompleteException { |
| initLookupMethodCreator(FOUR_ENTRY_MESSAGES); |
| constantsWithLookupImplCreator.emitClass(logger, locale); |
| |
| String actual = sw.toString().trim(); |
| |
| assertTrue("Missing partition lookup method (getStringFromPartition0).", actual.contains( |
| "java.lang.String getStringFromPartition0(java.lang.String arg0) {")); |
| } |
| |
| public void testEmitMethodBodyForJMethodForMultiMessageEntryNeedOneAdditionalPartition() |
| throws TypeOracleException, UnableToCompleteException { |
| initLookupMethodCreator(FOUR_ENTRY_MESSAGES); |
| constantsWithLookupImplCreator.emitMethodBody(logger, stringMethod, locale); |
| |
| String actual = sw.toString().trim(); |
| |
| assertTrue("Method should end with call partition lookup method.", actual.endsWith( |
| "return getStringFromPartition0(arg0);")); |
| assertFalse("Partition method should not be created", actual.contains( |
| "java.lang.String getStringFromPartition0(java.lang.String arg0) {")); |
| |
| assertEquals(1, constantsWithLookupImplCreator.getNeededPartitionLookups().size()); |
| } |
| |
| public void testFindMethodsToCreate() throws TypeOracleException { |
| initLookupMethodCreator(SINGLE_ENTRY_MESSAGES); |
| |
| JType intType = oracle.parse(int.class.getName()); |
| List<JMethod> intMethods = constantsWithLookupImplCreator.findAllMethodsToCreate(intMethod, |
| intType); |
| |
| JMethod expectedIntMethod = oracle.findType(SINGLE_ENTRY_MESSAGES.getTypeName()).findMethod( |
| "intEntry", new JType[0]); |
| |
| assertEquals(1, intMethods.size()); |
| assertEquals(expectedIntMethod, intMethods.get(0)); |
| } |
| |
| public void testFindMethodsToCreateWithDifferentTargetMethod() throws TypeOracleException { |
| initLookupMethodCreator(SINGLE_ENTRY_MESSAGES); |
| |
| JType intType = oracle.parse(int.class.getName()); |
| List<JMethod> foundMethods = constantsWithLookupImplCreator.findAllMethodsToCreate(stringMethod, |
| intType); |
| |
| JMethod expectedIntMethod = oracle.findType(SINGLE_ENTRY_MESSAGES.getTypeName()).findMethod( |
| "intEntry", new JType[0]); |
| |
| assertEquals(2, foundMethods.size()); |
| assertTrue(foundMethods.contains(intMethod)); |
| assertTrue(foundMethods.contains(expectedIntMethod)); |
| } |
| |
| public void testGetReturnTypeNameForPrimitveTypes() { |
| for (JPrimitiveType primitiveType : JPrimitiveType.values()) { |
| LookupMethodCreator primitiveMethodCreator = new LookupMethodCreator(null, primitiveType); |
| String returnType = primitiveMethodCreator.getReturnTypeName(); |
| String expectedType = primitiveType.getQualifiedBoxedSourceName().substring("java.lang." |
| .length()); |
| assertEquals("Wrong Return Type for primitve type", expectedType, returnType); |
| } |
| } |
| |
| private void initLookupMethodCreator(MockJavaResource resource) throws TypeOracleException { |
| initLookupMethodCreator(resource, TEST_PARTITION_SIZE); |
| } |
| |
| private void initLookupMethodCreator(MockJavaResource resource, int partitionsSize) |
| throws TypeOracleException { |
| JClassType clazz = oracle.findType(resource.getTypeName()); |
| try { |
| ResourceList resourceList = mock(ResourceList.class); |
| when(resourceList.getRequiredStringExt(anyString(), anyString())).thenReturn( |
| "Required value"); |
| constantsWithLookupImplCreator = new ConstantsWithLookupImplCreator(logger, sw, clazz, |
| resourceList, oracle, partitionsSize); |
| |
| JType stringType = oracle.parse(String.class.getName()); |
| stringMethod = oracle.findType(LOOKUP.getTypeName()).findMethod("getString", new JType[] { |
| stringType}); |
| intMethod = oracle.findType(LOOKUP.getTypeName()).findMethod("getInt", new JType[] { |
| stringType}); |
| } catch (UnableToCompleteException e) { |
| fail(e.getMessage()); |
| } |
| } |
| |
| } |