| /* |
| * Copyright 2008 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.tools.apichecker; |
| |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.typeinfo.JAbstractMethod; |
| import com.google.gwt.dev.javac.testing.impl.StaticJavaResource; |
| import com.google.gwt.dev.resource.Resource; |
| import com.google.gwt.dev.util.log.AbstractTreeLogger; |
| import com.google.gwt.dev.util.log.PrintWriterTreeLogger; |
| |
| import junit.framework.TestCase; |
| |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * Test {@link ApiContainer}. |
| */ |
| public class ApiContainerTest extends TestCase { |
| |
| class TestA { |
| public TestA(String args) { |
| } |
| |
| protected TestA(TestA a) { |
| } |
| |
| public String valueOf(Object o) { |
| return "a"; |
| } |
| |
| public String valueOf(String s) { |
| return ""; |
| } |
| } |
| class TestB extends TestA { |
| public TestB(TestA a) { |
| super(a); |
| } |
| |
| public void main(String args[]) { |
| TestA x1 = new TestA("test"); |
| x1.valueOf("ab"); |
| TestB x2 = new TestB(x1); |
| new TestB(x2); |
| } |
| } |
| |
| public static StaticJavaResource[] getScuArray() { |
| return new StaticJavaResource[] { |
| new StaticJavaResource("test.apicontainer.ApiClass", getSourceForApiClass()), |
| new StaticJavaResource("test.apicontainer.NonApiClass", getSourceForNonApiClass()), |
| new StaticJavaResource("test.nonapipackage.TestClass", getSourceForTestClass()), |
| new StaticJavaResource("java.lang.Object", getSourceForObject()), |
| new StaticJavaResource("test.apicontainer.OneMoreApiClass", getSourceForOneMoreApiClass()), |
| new StaticJavaResource("java.newpackage.Test", getSourceForTest()),}; |
| } |
| |
| private static JAbstractMethod getMethodByName(String name, ApiClass apiClass) { |
| return (apiClass.getApiMethodsByName(name, ApiClass.MethodType.METHOD).toArray( |
| new ApiAbstractMethod[0])[0]).getMethod(); |
| } |
| |
| private static String getSourceForApiClass() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package test.apicontainer;\n"); |
| sb.append("public class ApiClass extends NonApiClass {\n"); |
| sb.append("\tpublic void apiMethod() { };\n"); |
| sb.append("\tpublic java.lang.Object checkParametersAndReturnTypes(ApiClass a) { return this; };\n"); |
| sb.append("\tpublic final java.lang.Object checkParametersAndReturnTypesFinalVersion(ApiClass a) { return this; };\n"); |
| sb.append("};\n"); |
| return sb.toString(); |
| } |
| |
| private static String getSourceForNonApiClass() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package test.apicontainer;\n"); |
| sb.append("class NonApiClass extends java.lang.Object {\n"); |
| sb.append("\tpublic void methodInNonApiClass(NonApiClass a) { };\n"); |
| sb.append("\tpublic int fieldInNonApiClass = 3;\n"); |
| sb.append("\tprotected class ApiClassInNonApiClass {\n"); |
| sb.append("\tprotected ApiClassInNonApiClass() { }\n"); |
| sb.append("\t}\n"); |
| sb.append("\tprotected final class AnotherApiClassInNonApiClass {\n"); |
| sb.append("\tprivate AnotherApiClassInNonApiClass() { }\n"); |
| sb.append("\t}\n"); |
| sb.append("}\n"); |
| return sb.toString(); |
| } |
| |
| private static String getSourceForObject() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package java.lang;\n"); |
| sb.append("public class Object {\n"); |
| sb.append("\tpublic void apiMethod() { }\n"); |
| sb.append("\tprivate void internalMethod() { }\n"); |
| sb.append("\tprotected native long protectedMethod();\n"); |
| sb.append("\tprotected void checkOverloadedAndOverridableDetection(java.lang.Object b) { }\n"); |
| sb.append("\tprotected final void checkOverloadedMethodAccounted(java.lang.Object b) { }\n"); |
| sb.append("\tpublic int apiField = 0;\n"); |
| sb.append("\tprotected transient int apiFieldWillBeMissing = 1;\n"); |
| sb.append("\tprivate int internalField = 0;\n"); |
| sb.append("\tprotected int protectedField=2;\n"); |
| sb.append("}\n"); |
| return sb.toString(); |
| } |
| |
| private static String getSourceForOneMoreApiClass() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package test.apicontainer;\n"); |
| sb.append("public class OneMoreApiClass extends java.lang.Object {\n"); |
| sb.append("\tprotected final void checkOverloadedMethodAccounted(test.apicontainer.OneMoreApiClass b) { }\n"); |
| sb.append("\tpublic void testUncheckedExceptions () { }\n"); |
| sb.append("};\n"); |
| return sb.toString(); |
| } |
| |
| private static String getSourceForTest() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package java.newpackage;\n"); |
| sb.append("public class Test { }\n"); |
| return sb.toString(); |
| } |
| |
| private static String getSourceForTestClass() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package test.nonapipackage;\n"); |
| sb.append("class TestClass extends java.lang.Object {\n"); |
| sb.append("\tpublic void method() { }\n"); |
| sb.append("}\n"); |
| return sb.toString(); |
| } |
| |
| ApiContainer apiCheck = null; |
| AbstractTreeLogger logger = new PrintWriterTreeLogger(); |
| |
| /** |
| * Class hierarchy. public java.lang.Object -- test.apicontainer.NonApiClass |
| * (encloses ApiClassInNonApiClass and AnotherApiClassInNonApiClass) -- public |
| * test.apicontainer.ApiClass -- test.nonapipackage.TestClass |
| */ |
| @Override |
| public void setUp() throws UnableToCompleteException { |
| logger.setMaxDetail(com.google.gwt.core.ext.TreeLogger.ERROR); |
| |
| apiCheck = |
| new ApiContainer("ApiContainerTest", new HashSet<Resource>(Arrays.asList(getScuArray())), |
| new HashSet<String>(), logger); |
| } |
| |
| /* |
| * Test if ApiContainer correctly creates an ApiContainer (for example, avoids |
| * an infinite loop) when a nested class extends an outer class. |
| */ |
| public void testApiContainerLoop() throws UnableToCompleteException { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("package java.lang;\n"); |
| sb.append("public class Object {\n"); |
| sb.append("\tpublic static class Foo extends Object{\n"); |
| sb.append("\t}\n"); |
| sb.append("}\n"); |
| sb.append("class Temp {\n"); |
| sb.append("}"); |
| |
| ApiContainer apiCheckLoop = |
| new ApiContainer("ApiClassTest", new HashSet<Resource>(Arrays |
| .asList(new StaticJavaResource[] {new StaticJavaResource("java.lang.Object", sb |
| .toString())})), new HashSet<String>(), logger); |
| ApiPackage javaLangPackage = apiCheckLoop.getApiPackage("java.lang"); |
| assertNotNull(javaLangPackage); |
| assertNotNull(javaLangPackage.getApiClass("java.lang.Object")); |
| assertEquals(2, javaLangPackage.getApiClassNames().size()); |
| } |
| |
| public void testEverything() { |
| checkApiClass(); |
| checkApiMembers(); |
| checkApiPackages(); |
| } |
| |
| /** |
| * Check if apiClasses are determined correctly. Check if inner classes are |
| * classified correctly as api classes. |
| */ |
| void checkApiClass() { |
| ApiPackage package1 = apiCheck.getApiPackage("java.lang"); |
| ApiPackage package2 = apiCheck.getApiPackage("test.apicontainer"); |
| assertNotNull(package1); |
| assertNotNull(package2); |
| |
| assertNull(package2.getApiClass("test.apicontainer.NonApiClass")); |
| assertNotNull(package1.getApiClass("java.lang.Object")); |
| assertNotNull(package2.getApiClass("test.apicontainer.ApiClass")); |
| assertNotNull(package2.getApiClass("test.apicontainer.NonApiClass.ApiClassInNonApiClass")); |
| assertNotNull(package2 |
| .getApiClass("test.apicontainer.NonApiClass.AnotherApiClassInNonApiClass")); |
| assertEquals(1, package1.getApiClassNames().size()); |
| assertEquals(4, package2.getApiClassNames().size()); |
| } |
| |
| /** |
| * Since constructors and methods use the same code, check methods in most |
| * cases. Also need to check apiFields. |
| * |
| * For methods, check if: (a) inherited methods are identified correctly as |
| * apiMethods, (b) method overloading is done correctly |
| * |
| */ |
| void checkApiMembers() { |
| ApiClass object = apiCheck.getApiPackage("java.lang").getApiClass("java.lang.Object"); |
| ApiClass apiClass = |
| apiCheck.getApiPackage("test.apicontainer").getApiClass("test.apicontainer.ApiClass"); |
| ApiClass innerClass = |
| apiCheck.getApiPackage("test.apicontainer").getApiClass( |
| "test.apicontainer.NonApiClass.ApiClassInNonApiClass"); |
| ApiClass oneMoreApiClass = |
| apiCheck.getApiPackage("test.apicontainer") |
| .getApiClass("test.apicontainer.OneMoreApiClass"); |
| |
| // constructors |
| assertEquals(1, innerClass.getApiMemberNames(ApiClass.MethodType.CONSTRUCTOR).size()); |
| |
| // fields |
| assertEquals(3, object.getApiFieldNames().size()); |
| assertEquals(4, apiClass.getApiFieldNames().size()); |
| assertEquals(3, oneMoreApiClass.getApiFieldNames().size()); |
| |
| // methods |
| assertEquals(4, object.getApiMemberNames(ApiClass.MethodType.METHOD).size()); |
| assertEquals(7, apiClass.getApiMemberNames(ApiClass.MethodType.METHOD).size()); |
| // the method definition lowest in the class hierarchy is kept |
| assertNotSame(getMethodByName("apiMethod0", apiClass), getMethodByName("apiMethod0", object)); |
| assertEquals(getMethodByName("protectedMethod0", apiClass), getMethodByName("protectedMethod0", |
| object)); |
| assertNotNull(getMethodByName("methodInNonApiClass1", apiClass)); |
| |
| assertEquals(5, oneMoreApiClass.getApiMemberNames(ApiClass.MethodType.METHOD).size()); |
| Set<String> methodNames = |
| new HashSet<String>(Arrays.asList(new String[] {"checkOverloadedAndOverridableDetection1"})); |
| assertEquals(1, oneMoreApiClass.getApiMembersBySet(methodNames, ApiClass.MethodType.METHOD) |
| .size()); |
| |
| // checkOverloadedMethodAccounted should appear twice. |
| methodNames = |
| new HashSet<String>(Arrays.asList(new String[] {"checkOverloadedMethodAccounted1"})); |
| assertEquals(2, oneMoreApiClass.getApiMembersBySet(methodNames, ApiClass.MethodType.METHOD) |
| .size()); |
| } |
| |
| /** |
| * Test if apiPackages are identified correctly. |
| */ |
| void checkApiPackages() { |
| assertNotNull(apiCheck.getApiPackage("java.lang")); |
| assertNotNull(apiCheck.getApiPackage("test.apicontainer")); |
| assertEquals(3, apiCheck.getApiPackageNames().size()); |
| } |
| } |