blob: c1e8d03ff88b6610afd5af418c426f490a4dce8e [file] [log] [blame]
/*
* 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());
}
}
}