diff options
Diffstat (limited to 'src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps')
23 files changed, 1363 insertions, 0 deletions
diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/AbstractClassCacheTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/AbstractClassCacheTest.java new file mode 100644 index 0000000000..33460f6614 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/AbstractClassCacheTest.java @@ -0,0 +1,96 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.ImmutableList; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +/** Base class for {@link ClassCacheTest} and {@link DepsCheckerClassVisitorTest}. */ +public abstract class AbstractClassCacheTest { + + static final String PACKAGE_NAME = "com/google/devtools/build/importdeps/testdata/"; + + final Path bootclasspath = getPathFromSystemProperty("classcache.test.bootclasspath"); + + final Path clientJar = getPathFromSystemProperty("classcache.test.Client"); + final ImmutableList<String> clientJarPositives = + ImmutableList.of("Client", "Client$NestedAnnotation") + .stream() + .map(s -> PACKAGE_NAME + s) + .collect(ImmutableList.toImmutableList()); + + final Path libraryJar = getPathFromSystemProperty("classcache.test.Library"); + final ImmutableList<String> libraryJarPositives = + ImmutableList.<String>builder() + .add("Library") + .addAll( + IntStream.range(1, 11) + .mapToObj(i -> "Library$Class" + i) + .collect(ImmutableList.toImmutableList())) + .build() + .stream() + .map(s -> PACKAGE_NAME + s) + .collect(ImmutableList.toImmutableList()); + + final Path libraryWoMembersJar = getPathFromSystemProperty("classcache.test.Library_no_members"); + + final Path libraryAnnotationsJar = + getPathFromSystemProperty("classcache.test.LibraryAnnotations"); + final ImmutableList<String> libraryAnnotationsJarPositives = + ImmutableList.<String>builder() + .add("LibraryAnnotations") + .addAll( + Stream.of( + "ClassAnnotation", + "MethodAnnotation", + "FieldAnnotation", + "ConstructorAnnotation", + "ParameterAnnotation", + "TypeAnnotation", + "AnnotationAnnotation") + .map(name -> "LibraryAnnotations$" + name) + .collect(ImmutableList.toImmutableList())) + .build() + .stream() + .map(s -> PACKAGE_NAME + s) + .collect(ImmutableList.toImmutableList()); + + final Path libraryExceptionJar = getPathFromSystemProperty("classcache.test.LibraryException"); + final ImmutableList<String> libraryExceptionJarPositives = + ImmutableList.of(PACKAGE_NAME + "LibraryException"); + + final Path libraryInterfaceJar = getPathFromSystemProperty("classcache.test.LibraryInterface"); + final ImmutableList<String> libraryInterfacePositives = + ImmutableList.of(PACKAGE_NAME + "LibraryInterface", PACKAGE_NAME + "LibraryInterface$Func"); + + static Path getPathFromSystemProperty(String propertyName) { + String path = + checkNotNull( + System.getProperty(propertyName), "The system property %s is not set.", propertyName); + return Paths.get(path); + } + + /** Flattern a list of lists. */ + static <T> ImmutableList<T> combine(ImmutableList<T>... lists) { + return Arrays.stream(lists) + .flatMap(ImmutableList::stream) + .collect(ImmutableList.toImmutableList()); + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/BUILD b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/BUILD new file mode 100644 index 0000000000..bbf7085f1a --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/BUILD @@ -0,0 +1,160 @@ +# Description: +# Tests for the checker to check the completeness of the deps of java_import or aar_import targets. +package( + default_testonly = 1, + default_visibility = ["//src:__subpackages__"], +) + +java_test( + name = "ClassInfoTest", + srcs = ["ClassInfoTest.java"], + deps = [ + "//src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:import_deps_checker", + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "ResultCollectorTest", + srcs = ["ResultCollectorTest.java"], + deps = [ + "//src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:import_deps_checker", + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "LazyClassEntryStateTest", + srcs = ["LazyClassEntryStateTest.java"], + deps = [ + "//src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:import_deps_checker", + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "ClassCacheTest", + srcs = [ + "AbstractClassCacheTest.java", + "ClassCacheTest.java", + ], + data = [ + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_client", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryAnnotations", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryException", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryInterface", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library_no_members", + "//third_party/java/jdk:jdk8_rt_jar", + ], + jvm_flags = [ + "-Dclasscache.test.bootclasspath=$(location //third_party/java/jdk:jdk8_rt_jar)", + "-Dclasscache.test.Client=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_client)", + "-Dclasscache.test.Library=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library)", + "-Dclasscache.test.Library_no_members=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library_no_members)", + "-Dclasscache.test.LibraryAnnotations=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryAnnotations)", + "-Dclasscache.test.LibraryException=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryException)", + "-Dclasscache.test.LibraryInterface=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryInterface)", + ], + test_class = "com.google.devtools.build.importdeps.ClassCacheTest", + deps = [ + "//src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:import_deps_checker", + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "DepsCheckerClassVisitorTest", + srcs = [ + "AbstractClassCacheTest.java", + "DepsCheckerClassVisitorTest.java", + ], + data = [ + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_client", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryAnnotations", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryException", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryInterface", + "//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library_no_members", + "//third_party/java/jdk:jdk8_rt_jar", + ], + jvm_flags = [ + "-Dclasscache.test.bootclasspath=$(location //third_party/java/jdk:jdk8_rt_jar)", + "-Dclasscache.test.Client=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_client)", + "-Dclasscache.test.Library=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library)", + "-Dclasscache.test.Library_no_members=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_Library_no_members)", + "-Dclasscache.test.LibraryAnnotations=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryAnnotations)", + "-Dclasscache.test.LibraryException=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryException)", + "-Dclasscache.test.LibraryInterface=$(location //src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata:testdata_lib_LibraryInterface)", + ], + test_class = "com.google.devtools.build.importdeps.DepsCheckerClassVisitorTest", + deps = [ + "//src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:import_deps_checker", + "//third_party:asm", + "//third_party:guava", + "//third_party:junit4", + "//third_party:truth", + "//third_party/java/jdk:jdk8_rt_jar", + ], +) + +load("//src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps:tests.bzl", "create_golden_test") + +create_golden_test( + name = "bootclasspath_missing_golden_test", + golden_file = "golden_bootclasspath_missing.txt", + has_bootclasspath = False, + missing_jar = None, +) + +create_golden_test( + name = "library_exception_missing_golden_test", + golden_file = "golden_library_exception_missing.txt", + has_bootclasspath = True, + missing_jar = "testdata_lib_LibraryException", +) + +create_golden_test( + name = "library_annotation_missing_golden_test", + golden_file = "golden_library_annotation_missing.txt", + has_bootclasspath = True, + missing_jar = "testdata_lib_LibraryAnnotations", +) + +create_golden_test( + name = "library_missing_golden_test", + golden_file = "golden_library_missing.txt", + has_bootclasspath = True, + missing_jar = "testdata_lib_Library", +) + +create_golden_test( + name = "library_interface_missing_golden_test", + golden_file = "golden_library_interface_missing.txt", + has_bootclasspath = True, + missing_jar = "testdata_lib_LibraryInterface", +) + +create_golden_test( + name = "library_members_missing_golden_test", + golden_file = "golden_library_members_missing.txt", + has_bootclasspath = True, + missing_jar = "testdata_lib_Library", + replacing_jar = "testdata_lib_Library_no_members", +) + +create_golden_test( + name = "complete_classpath_golden_test", + golden_file = "golden_complete_classpath.txt", + has_bootclasspath = True, + missing_jar = None, + replacing_jar = None, +) diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassCacheTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassCacheTest.java new file mode 100644 index 0000000000..241afd98c6 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassCacheTest.java @@ -0,0 +1,142 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertThrows; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.importdeps.AbstractClassEntryState.ExistingState; +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link ClassCache}. */ +@RunWith(JUnit4.class) +public class ClassCacheTest extends AbstractClassCacheTest { + + @Test + public void testLibraryJar() throws Exception { + try (ClassCache cache = new ClassCache(bootclasspath, libraryJar)) { + assertCache( + cache, + libraryJarPositives, + combine( + libraryInterfacePositives, + libraryAnnotationsJarPositives, + libraryExceptionJarPositives)); + } + } + + @Test + public void testClientJarWithSuperClasses() throws IOException { + try (ClassCache cache = + new ClassCache(bootclasspath, clientJar, libraryJar, libraryInterfaceJar)) { + assertCache( + cache, + clientJarPositives, + combine(libraryExceptionJarPositives, libraryAnnotationsJarPositives)); + } + } + + @Test + public void testClientJarWithoutSuperClasses() throws IOException { + try (ClassCache cache = new ClassCache(bootclasspath, clientJar)) { + // Client should be incomplete, as its parent class and interfaces are not available on the + // classpath. The following is the resolution path. + { + AbstractClassEntryState state = cache.getClassState(PACKAGE_NAME + "Client"); + assertThat(state.isIncompleteState()).isTrue(); + + ImmutableList<String> failureCause = state.asIncompleteState().getResolutionFailurePath(); + assertThat(failureCause).containsExactly(PACKAGE_NAME + "Library").inOrder(); + } + assertThat(cache.getClassState(PACKAGE_NAME + "Client").isIncompleteState()).isTrue(); + assertThat(cache.getClassState(PACKAGE_NAME + "Client$NestedAnnotation")) + .isInstanceOf(ExistingState.class); + assertThat(cache.getClassState(PACKAGE_NAME + "Client$NestedAnnotation").isExistingState()) + .isTrue(); + assertThat(cache.getClassState("java/lang/Object").isExistingState()).isTrue(); + assertThat(cache.getClassState("java/util/List").isExistingState()).isTrue(); + } + } + + @Test + public void testLibraryException() throws IOException { + try (ClassCache cache = new ClassCache(bootclasspath, libraryExceptionJar)) { + assertCache( + cache, + libraryExceptionJarPositives, + combine(libraryAnnotationsJarPositives, libraryInterfacePositives, libraryJarPositives)); + } + } + + @Test + public void testLibraryAnnotations() throws IOException { + try (ClassCache cache = new ClassCache(bootclasspath, libraryAnnotationsJar)) { + assertCache( + cache, + libraryAnnotationsJarPositives, + combine(libraryExceptionJarPositives, libraryInterfacePositives, libraryJarPositives)); + } + } + + @Test + public void testCannotAccessClosedCache() throws IOException { + ClassCache cache = new ClassCache(ImmutableList.of()); + cache.close(); + cache.close(); // Can close multiple times. + assertThrows(IllegalStateException.class, () -> cache.getClassState("empty")); + } + + /** + * A regression test. First query the super class, which does not exist. Then query the subclass, + * which does not exist either. + */ + @Test + public void testSuperNotExistThenSubclassNotExist() throws IOException { + try (ClassCache cache = + new ClassCache( + libraryJar, libraryJar, libraryAnnotationsJar, libraryInterfaceJar, clientJar)) { + assertThat( + cache + .getClassState("com/google/devtools/build/importdeps/testdata/Library$Class9") + .isIncompleteState()) + .isTrue(); + assertThat( + cache + .getClassState("com/google/devtools/build/importdeps/testdata/Library$Class10") + .isIncompleteState()) + .isTrue(); + } + } + + private void assertCache( + ClassCache cache, ImmutableList<String> positives, ImmutableList<String> negatives) { + for (String positive : positives) { + AbstractClassEntryState state = cache.getClassState(positive); + assertWithMessage(positive).that(state.isExistingState()).isTrue(); + assertWithMessage(positive).that(state.asExistingState()).isInstanceOf(ExistingState.class); + assertWithMessage(positive) + .that(state.asExistingState().classInfo().get().internalName()) + .isEqualTo(positive); + } + for (String negative : negatives) { + AbstractClassEntryState state = cache.getClassState(negative); + assertWithMessage(negative).that(state.isExistingState()).isFalse(); + } + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassInfoTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassInfoTest.java new file mode 100644 index 0000000000..54d53f2f22 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassInfoTest.java @@ -0,0 +1,82 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.importdeps.ClassInfo.MemberInfo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link ClassInfo} */ +@RunWith(JUnit4.class) +public class ClassInfoTest { + + public static final String JAVA_LANG_OBJECT = "java/lang/Object"; + private final MemberInfo hashCodeMethod = MemberInfo.create(JAVA_LANG_OBJECT, "hashCode", "()I"); + private final MemberInfo sizeMethod = MemberInfo.create(JAVA_LANG_OBJECT, "clear", "()V"); + + private final ClassInfo objectClass = + ClassInfo.create(JAVA_LANG_OBJECT, ImmutableList.of(), ImmutableSet.of(hashCodeMethod)); + + private final ClassInfo listClass = + ClassInfo.create( + "java/util/List", ImmutableList.of(objectClass), ImmutableSet.of(sizeMethod)); + + @Test + public void testMemberInfo() { + MemberInfo memberInfo = MemberInfo.create(JAVA_LANG_OBJECT, "a", "I"); + assertThat(memberInfo.memberName()).isEqualTo("a"); + assertThat(memberInfo.descriptor()).isEqualTo("I"); + assertThat(memberInfo).isEqualTo(MemberInfo.create("java/lang/Object", "a", "I")); + + assertThat(hashCodeMethod).isEqualTo(MemberInfo.create("java/lang/Object", "hashCode", "()I")); + assertThat(sizeMethod).isEqualTo(MemberInfo.create("java/lang/Object", "clear", "()V")); + } + + @Test + public void testClassInfoCorrectlySet() { + assertThat(objectClass.internalName()).isEqualTo("java/lang/Object"); + assertThat(objectClass.declaredMembers()) + .containsExactly(MemberInfo.create("java/lang/Object", "hashCode", "()I")) + .inOrder(); + assertThat(objectClass.containsMember(MemberInfo.create("java/lang/Object", "hashCode", "()I"))) + .isTrue(); + + assertThat(listClass.internalName()).isEqualTo("java/util/List"); + assertThat(listClass.declaredMembers()).containsExactly(sizeMethod); + assertThat(listClass.containsMember(hashCodeMethod)).isTrue(); + } + + @Test + public void testContainsMember() { + ClassInfo parent = objectClass; + ClassInfo child = listClass; + assertThat(child.superClasses()).contains(parent); + assertThat(parent.containsMember(MemberInfo.create("java/lang/Object", "hashCode", "()I"))) + .isTrue(); + assertThat(parent.containsMember(MemberInfo.create("java/lang/Object", "size", "()I"))) + .isFalse(); + assertThat(parent.containsMember(MemberInfo.create("java/lang/Object", "clear", "()V"))) + .isFalse(); + + assertThat(child.containsMember(MemberInfo.create("java/lang/Object", "hashCode", "()I"))) + .isTrue(); + assertThat(child.containsMember(MemberInfo.create("java/lang/Object", "clear", "()V"))) + .isTrue(); + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/DepsCheckerClassVisitorTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/DepsCheckerClassVisitorTest.java new file mode 100644 index 0000000000..3d19b06638 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/DepsCheckerClassVisitorTest.java @@ -0,0 +1,128 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.importdeps.ClassInfo.MemberInfo; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.objectweb.asm.ClassReader; + +/** Test for {@link DepsCheckerClassVisitor}. */ +@RunWith(JUnit4.class) +public class DepsCheckerClassVisitorTest extends AbstractClassCacheTest { + + @Test + public void testMissingLibraryException() throws IOException { + assertThat( + getMissingClassesInClient( + bootclasspath, libraryJar, libraryInterfaceJar, libraryAnnotationsJar, clientJar)) + .containsExactlyElementsIn(libraryExceptionJarPositives); + } + + @Test + public void testMissingLibraryInterface() throws IOException { + assertThat( + getMissingClassesInClient( + bootclasspath, libraryJar, libraryAnnotationsJar, libraryExceptionJar, clientJar)) + .containsExactlyElementsIn(libraryInterfacePositives); + } + + @Test + public void testMissingLibraryAnnotations() throws IOException { + assertThat( + getMissingClassesInClient( + bootclasspath, libraryJar, libraryExceptionJar, libraryInterfaceJar, clientJar)) + .containsExactlyElementsIn(libraryAnnotationsJarPositives); + } + + @Test + public void testMissingLibraryInClient() throws IOException { + assertThat( + getMissingClassesInClient( + bootclasspath, + libraryExceptionJar, + libraryInterfaceJar, + libraryAnnotationsJar, + clientJar)) + .containsExactlyElementsIn(libraryJarPositives); + } + + @Test + public void testMissingMembersInClient() throws IOException { + ResultCollector collector = + getResultCollector( + bootclasspath, + libraryAnnotationsJar, + libraryInterfaceJar, + libraryWoMembersJar, + libraryExceptionJar, + clientJar); + assertThat(collector.getSortedMissingClassInternalNames()).isEmpty(); + assertThat(collector.getSortedMissingMembers()) + .containsExactly( + MemberInfo.create( + "com/google/devtools/build/importdeps/testdata/Library$Class1", + "I", + "Lcom/google/devtools/build/importdeps/testdata/Library$Class1;"), + MemberInfo.create( + "com/google/devtools/build/importdeps/testdata/Library$Class3", + "field", + "Lcom/google/devtools/build/importdeps/testdata/Library$Class4;"), + MemberInfo.create( + "com/google/devtools/build/importdeps/testdata/Library$Class4", + "createClass5", + "()Lcom/google/devtools/build/importdeps/testdata/Library$Class5;"), + MemberInfo.create( + "com/google/devtools/build/importdeps/testdata/Library$Class5", + "create", + "(Lcom/google/devtools/build/importdeps/testdata/Library$Class7;)" + + "Lcom/google/devtools/build/importdeps/testdata/Library$Class6;")) + .inOrder(); + } + + private ImmutableList<String> getMissingClassesInClient(Path... classpath) throws IOException { + ResultCollector resultCollector = getResultCollector(classpath); + return resultCollector.getSortedMissingClassInternalNames(); + } + + private ResultCollector getResultCollector(Path... classpath) throws IOException { + ImmutableList<String> clientClasses = + ImmutableList.of(PACKAGE_NAME + "Client", PACKAGE_NAME + "Client$NestedAnnotation"); + ResultCollector resultCollector = new ResultCollector(); + try (ClassCache cache = new ClassCache(ImmutableList.copyOf(classpath)); + ZipFile zipFile = new ZipFile(clientJar.toFile())) { + + AbstractClassEntryState state = cache.getClassState("java/lang/invoke/LambdaMetafactory"); + System.out.println(state); + for (String clientClass : clientClasses) { + ZipEntry entry = zipFile.getEntry(clientClass + ".class"); + try (InputStream classStream = zipFile.getInputStream(entry)) { + ClassReader reader = new ClassReader(classStream); + DepsCheckerClassVisitor checker = new DepsCheckerClassVisitor(cache, resultCollector); + reader.accept(checker, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + } + } + } + return resultCollector; + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/LazyClassEntryStateTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/LazyClassEntryStateTest.java new file mode 100644 index 0000000000..b2bc7f2973 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/LazyClassEntryStateTest.java @@ -0,0 +1,97 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.importdeps.AbstractClassEntryState.ExistingState; +import com.google.devtools.build.importdeps.AbstractClassEntryState.IncompleteState; +import com.google.devtools.build.importdeps.AbstractClassEntryState.MissingState; +import com.google.devtools.build.importdeps.ClassInfo.MemberInfo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link AbstractClassEntryState} */ +@RunWith(JUnit4.class) +public class LazyClassEntryStateTest { + + public static final String LIST_CLASS_NAME = "java/util/List"; + public static final ImmutableSet<MemberInfo> METHOD_LIST = + ImmutableSet.of(MemberInfo.create(LIST_CLASS_NAME, "hashCode", "()I")); + public static final ClassInfo LIST_CLASS_INFO = + ClassInfo.create(LIST_CLASS_NAME, ImmutableList.of(), METHOD_LIST); + + @Test + public void testExistingState() { + ExistingState state = ExistingState.create(LIST_CLASS_INFO); + + assertThat(state.isExistingState()).isTrue(); + assertThat(state.isIncompleteState()).isFalse(); + assertThat(state.isMissingState()).isFalse(); + + assertThat(state.asExistingState()).isSameAs(state); + assertThrows(IllegalStateException.class, () -> state.asIncompleteState()); + assertThrows(IllegalStateException.class, () -> state.asMissingState()); + + ClassInfo classInfo = state.classInfo().get(); + assertThat(classInfo.internalName()).isEqualTo("java/util/List"); + assertThat(classInfo.declaredMembers()).hasSize(1); + assertThat(classInfo.declaredMembers()) + .containsExactly(MemberInfo.create("java/util/List", "hashCode", "()I")); + } + + @Test + public void testIncompleteState() { + assertThrows( + IllegalArgumentException.class, + () -> IncompleteState.create(LIST_CLASS_INFO, ImmutableList.of())); + IncompleteState state = + IncompleteState.create(LIST_CLASS_INFO, ImmutableList.of("java/lang/Object")); + + assertThat(state.isExistingState()).isFalse(); + assertThat(state.isIncompleteState()).isTrue(); + assertThat(state.isMissingState()).isFalse(); + + assertThat(state.asIncompleteState()).isSameAs(state); + assertThrows(IllegalStateException.class, () -> state.asExistingState()); + assertThrows(IllegalStateException.class, () -> state.asMissingState()); + + ClassInfo classInfo = state.classInfo().get(); + assertThat(classInfo.internalName()).isEqualTo("java/util/List"); + assertThat(classInfo.declaredMembers()).hasSize(1); + assertThat(classInfo.declaredMembers()) + .containsExactly(MemberInfo.create("java/util/List", "hashCode", "()I")); + + ImmutableList<String> failurePath = state.getResolutionFailurePath(); + assertThat(failurePath).hasSize(1); + assertThat(failurePath).containsExactly("java/lang/Object"); + } + + @Test + public void testMissingState() { + MissingState state = MissingState.singleton(); + + assertThat(state.isMissingState()).isTrue(); + assertThat(state.isExistingState()).isFalse(); + assertThat(state.isIncompleteState()).isFalse(); + + assertThat(state.asMissingState()).isSameAs(state); + assertThrows(IllegalStateException.class, () -> state.asExistingState()); + assertThrows(IllegalStateException.class, () -> state.asIncompleteState()); + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ResultCollectorTest.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ResultCollectorTest.java new file mode 100644 index 0000000000..0d78504634 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ResultCollectorTest.java @@ -0,0 +1,81 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.importdeps.AbstractClassEntryState.IncompleteState; +import com.google.devtools.build.importdeps.AbstractClassEntryState.MissingState; +import com.google.devtools.build.importdeps.ClassInfo.MemberInfo; +import java.io.IOException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link ResultCollector}. */ +@RunWith(JUnit4.class) +public class ResultCollectorTest { + + private ResultCollector collector; + + @Before + public void setup() throws IOException { + collector = new ResultCollector(); + } + + @Test + public void testEmptyCollector() throws IOException { + assertThat(collector.getSortedMissingClassInternalNames()).isEmpty(); + assertThat(collector.getSortedMissingMembers()).isEmpty(); + assertThat(collector.getSortedIncompleteClasses()).isEmpty(); + } + + @Test + public void testOneMissingClass() throws IOException { + collector.addMissingOrIncompleteClass("java.lang.String", MissingState.singleton()); + assertThat(collector.getSortedMissingClassInternalNames()).containsExactly("java.lang.String"); + assertThat(collector.getSortedMissingMembers()).isEmpty(); + + collector.addMissingMember(MemberInfo.create("java/lang/Object", "field", "I")); + assertThat(collector.getSortedMissingMembers()) + .containsExactly(MemberInfo.create("java/lang/Object", "field", "I")); + assertThat(collector.getSortedMissingClassInternalNames()).containsExactly("java.lang.String"); + } + + @Test + public void testIncompleteClasses() throws IOException { + collector.addMissingOrIncompleteClass( + "java/lang/String", + IncompleteState.create( + ClassInfo.create("java/lang/String", ImmutableList.of(), ImmutableSet.of()), + ImmutableList.of("java/lang/Object"))); + assertThat(collector.getSortedIncompleteClasses()).hasSize(1); + assertThat(collector.getSortedIncompleteClasses().get(0).classInfo().get()) + .isEqualTo(ClassInfo.create("java/lang/String", ImmutableList.of(), ImmutableSet.of())); + } + + @Test + public void testResultsAreSorted() throws IOException { + collector.addMissingOrIncompleteClass("java.lang.String", MissingState.singleton()); + collector.addMissingOrIncompleteClass("java.lang.Integer", MissingState.singleton()); + collector.addMissingOrIncompleteClass("java.lang.Object", MissingState.singleton()); + + assertThat(collector.getSortedMissingClassInternalNames()) + .containsExactly("java.lang.String", "java.lang.Integer", "java.lang.Object"); + assertThat(collector.getSortedMissingMembers()).isEmpty(); + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_bootclasspath_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_bootclasspath_missing.txt new file mode 100644 index 0000000000..5a4e67edfe --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_bootclasspath_missing.txt @@ -0,0 +1,87 @@ +Missing java.lang.Exception +Missing java.lang.Object +Missing java.lang.String +Missing java.lang.annotation.Annotation +Missing java.lang.annotation.ElementType +Missing java.lang.annotation.Retention +Missing java.lang.annotation.RetentionPolicy +Missing java.lang.annotation.Target +Missing java.lang.invoke.CallSite +Missing java.lang.invoke.LambdaMetafactory +Missing java.lang.invoke.MethodHandle +Missing java.lang.invoke.MethodHandles$Lookup +Missing java.lang.invoke.MethodType +Missing java.util.Objects +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Client + missing ancestor: java.lang.Object + resolution failure path: com.google.devtools.build.importdeps.testdata.Library -> java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class1 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class10 + missing ancestor: java.lang.Object + resolution failure path: com.google.devtools.build.importdeps.testdata.Library$Class9 -> java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class2 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class3 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class4 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class5 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class6 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class7 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class8 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Library$Class9 + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$AnnotationAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ClassAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ConstructorAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$FieldAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$MethodAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ParameterAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryAnnotations$TypeAnnotation + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryException + missing ancestor: java.lang.Exception + resolution failure path: java.lang.Exception +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryInterface + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.LibraryInterface$Func + missing ancestor: java.lang.Object + resolution failure path: java.lang.Object +===Total=== +missing=14 +incomplete=23 +missing_members=0
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_complete_classpath.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_complete_classpath.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_complete_classpath.txt diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_annotation_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_annotation_missing.txt new file mode 100644 index 0000000000..60af5de912 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_annotation_missing.txt @@ -0,0 +1,12 @@ +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$AnnotationAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ClassAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ConstructorAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$FieldAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$MethodAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$ParameterAnnotation +Missing com.google.devtools.build.importdeps.testdata.LibraryAnnotations$TypeAnnotation +===Total=== +missing=8 +incomplete=0 +missing_members=0
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_exception_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_exception_missing.txt new file mode 100644 index 0000000000..767f4eb0b9 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_exception_missing.txt @@ -0,0 +1,5 @@ +Missing com.google.devtools.build.importdeps.testdata.LibraryException +===Total=== +missing=1 +incomplete=0 +missing_members=0
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_interface_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_interface_missing.txt new file mode 100644 index 0000000000..3c3568eb59 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_interface_missing.txt @@ -0,0 +1,9 @@ +Missing com.google.devtools.build.importdeps.testdata.LibraryInterface +Missing com.google.devtools.build.importdeps.testdata.LibraryInterface$Func +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Client + missing ancestor: com.google.devtools.build.importdeps.testdata.LibraryInterface + resolution failure path: com.google.devtools.build.importdeps.testdata.LibraryInterface +===Total=== +missing=2 +incomplete=1 +missing_members=0
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_members_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_members_missing.txt new file mode 100644 index 0000000000..73831162b3 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_members_missing.txt @@ -0,0 +1,8 @@ +Missing member 'I' in class com.google.devtools.build.importdeps.testdata.Library$Class1 : name=I, descriptor=Lcom/google/devtools/build/importdeps/testdata/Library$Class1; +Missing member 'field' in class com.google.devtools.build.importdeps.testdata.Library$Class3 : name=field, descriptor=Lcom/google/devtools/build/importdeps/testdata/Library$Class4; +Missing member 'createClass5' in class com.google.devtools.build.importdeps.testdata.Library$Class4 : name=createClass5, descriptor=()Lcom/google/devtools/build/importdeps/testdata/Library$Class5; +Missing member 'create' in class com.google.devtools.build.importdeps.testdata.Library$Class5 : name=create, descriptor=(Lcom/google/devtools/build/importdeps/testdata/Library$Class7;)Lcom/google/devtools/build/importdeps/testdata/Library$Class6; +===Total=== +missing=0 +incomplete=0 +missing_members=4
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_missing.txt b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_missing.txt new file mode 100644 index 0000000000..12447fc23a --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_missing.txt @@ -0,0 +1,18 @@ +Missing com.google.devtools.build.importdeps.testdata.Library +Missing com.google.devtools.build.importdeps.testdata.Library$Class1 +Missing com.google.devtools.build.importdeps.testdata.Library$Class10 +Missing com.google.devtools.build.importdeps.testdata.Library$Class2 +Missing com.google.devtools.build.importdeps.testdata.Library$Class3 +Missing com.google.devtools.build.importdeps.testdata.Library$Class4 +Missing com.google.devtools.build.importdeps.testdata.Library$Class5 +Missing com.google.devtools.build.importdeps.testdata.Library$Class6 +Missing com.google.devtools.build.importdeps.testdata.Library$Class7 +Missing com.google.devtools.build.importdeps.testdata.Library$Class8 +Missing com.google.devtools.build.importdeps.testdata.Library$Class9 +Incomplete ancestor classpath for com.google.devtools.build.importdeps.testdata.Client + missing ancestor: com.google.devtools.build.importdeps.testdata.Library + resolution failure path: com.google.devtools.build.importdeps.testdata.Library +===Total=== +missing=11 +incomplete=1 +missing_members=0
\ No newline at end of file diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_test.sh b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_test.sh new file mode 100755 index 0000000000..d3f090c82c --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_test.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# 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. + +gold_file=$1 +shift + +if [ -d "$TEST_TMPDIR" ]; then + # Running as part of blaze test + tmpdir="$TEST_TMPDIR" +else + # Manual run from command line + tmpdir="$(mktemp -d)" +fi + +if [ -d "$TEST_UNDECLARED_OUTPUTS_DIR" ]; then + # Running as part of blaze test: capture test output + output="$TEST_UNDECLARED_OUTPUTS_DIR" +else + # Manual run from command line: just write into temp dir + output="${tmpdir}" +fi + +actual_file="${output}/actual_result.txt" +# Run the checker command. +$@ --output "${actual_file}" &> ${output}/checker_output.txt + +checker_ret=$? +if [[ "${checker_ret}" != 0 ]] ; then + echo "Checker error!!! ${checker_ret}" + cat ${output}/checker_output.txt + exit ${checker_ret} +fi + +diff "${gold_file}" "${actual_file}" + +ret=$? +if [[ "${ret}" != 0 ]] ; then + echo "============== Actual Output ==============" + cat "${actual_file}" + echo "" # New line. + echo "===========================================" +fi +exit ${ret} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/BUILD b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/BUILD new file mode 100644 index 0000000000..ae40513a05 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/BUILD @@ -0,0 +1,43 @@ +# Description: +# Test data for testing dependency checking. +package( + default_testonly = 1, + default_visibility = ["//src:__subpackages__"], +) + +java_library( + name = "testdata_client", + srcs = ["Client.java"], + deps = [":testdata_lib_neverlink"], +) + +java_library( + name = "testdata_lib_neverlink", + srcs = glob(["Library*.java"]), + neverlink = 1, +) + +java_library( + name = "testdata_lib_Library", + srcs = ["Library.java"], +) + +java_library( + name = "testdata_lib_Library_no_members", + srcs = ["library_no_members/com/google/devtools/build/importdeps/testdata/Library.java"], +) + +java_library( + name = "testdata_lib_LibraryAnnotations", + srcs = ["LibraryAnnotations.java"], +) + +java_library( + name = "testdata_lib_LibraryException", + srcs = ["LibraryException.java"], +) + +java_library( + name = "testdata_lib_LibraryInterface", + srcs = ["LibraryInterface.java"], +) diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Client.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Client.java new file mode 100644 index 0000000000..6b833c3b61 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Client.java @@ -0,0 +1,67 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.AnnotationAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.ClassAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.ConstructorAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.FieldAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.MethodAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.ParameterAnnotation; +import com.google.devtools.build.importdeps.testdata.LibraryAnnotations.TypeAnnotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Objects; + +/** Client class that uses several libraries. */ +@ClassAnnotation +public class Client<@TypeAnnotation T> extends Library implements LibraryInterface { + + @SuppressWarnings("unused") + @FieldAnnotation + private Library.Class1 field; + + @SuppressWarnings("unused") + @FieldAnnotation + private LibraryAnnotations annotations; + + public static final Class1 I = Class1.I; + + @ConstructorAnnotation + public Client() {} + + @MethodAnnotation + public void method(@ParameterAnnotation int p, Library.Class2 p2) throws LibraryException { + Objects.nonNull(p2); // javac9 silently uses Objects. + Class3 c3 = new Class3(); + Class4 c4 = c3.field; + c3.field = c4; + Func<Class5> func = c4::createClass5; + Class5 class5 = func.get(); + @SuppressWarnings("unused") + Class6 class6 = class5.create(new Class7()); + @SuppressWarnings("unused") + Class8[][] array = new Class8[10][10]; + Class9[] array2 = new Class9[10]; + array2[0] = new Class10(); + } + + /** An inner annotation. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @AnnotationAnnotation + public @interface NestedAnnotation {} +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Library.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Library.java new file mode 100644 index 0000000000..31049ba2d5 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Library.java @@ -0,0 +1,60 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +/** A library class for testing. */ +public class Library { + + /** A library class for testing. */ + public static class Class1 { + public static final Class1 I = new Class1(); + } + + /** A library class for testing. */ + public static class Class2 {} + + /** A library class for testing. */ + public static class Class3 { + public Class4 field; + } + + /** A library class for testing. */ + public static class Class4 { + Class5 createClass5() { + return new Class5(); + } + } + + /** A library class for testing. */ + public static class Class5 { + public Class6 create(Class7 class7) { + return new Class6(); + } + } + + /** A library class for testing. */ + public static class Class6 {} + + /** A library class for testing. */ + public static class Class7 {} + + /** A library class for testing. */ + public static class Class8 {} + + /** A library class for testing. */ + public static class Class9 {} + + /** A library class for testing. */ + public static class Class10 extends Class9 {} +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryAnnotations.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryAnnotations.java new file mode 100644 index 0000000000..d0b883ae57 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryAnnotations.java @@ -0,0 +1,57 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** A library annotation for testing. */ +public class LibraryAnnotations { + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface ClassAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface MethodAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface FieldAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.CONSTRUCTOR) + public @interface ConstructorAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public @interface ParameterAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) + public @interface TypeAnnotation {} + + /** A library annotation for testing. */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.ANNOTATION_TYPE) + public @interface AnnotationAnnotation {} +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryException.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryException.java new file mode 100644 index 0000000000..ff572a005a --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryException.java @@ -0,0 +1,17 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +/** A library exception for testing. */ +public class LibraryException extends Exception {} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryInterface.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryInterface.java new file mode 100644 index 0000000000..649adc105a --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryInterface.java @@ -0,0 +1,23 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +/** A library interface for testing. */ +public interface LibraryInterface { + + /** A nested interface for testing. */ + interface Func<T> { + T get(); + } +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/library_no_members/com/google/devtools/build/importdeps/testdata/Library.java b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/library_no_members/com/google/devtools/build/importdeps/testdata/Library.java new file mode 100644 index 0000000000..991baa0cd7 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/library_no_members/com/google/devtools/build/importdeps/testdata/Library.java @@ -0,0 +1,51 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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.devtools.build.importdeps.testdata; + +/** + * A library class for testing. This library class is very similar to {@link Library}, but it does + * not have any members (fields or methods). + */ +public class Library { + + /** A library class for testing. */ + public static class Class1 {} + + /** A library class for testing. */ + public static class Class2 {} + + /** A library class for testing. */ + public static class Class3 {} + + /** A library class for testing. */ + public static class Class4 {} + + /** A library class for testing. */ + public static class Class5 {} + + /** A library class for testing. */ + public static class Class6 {} + + /** A library class for testing. */ + public static class Class7 {} + + /** A library class for testing. */ + public static class Class8 {} + + /** A library class for testing. */ + public static class Class9 {} + + /** A library class for testing. */ + public static class Class10 extends Class9 {} +} diff --git a/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/tests.bzl b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/tests.bzl new file mode 100644 index 0000000000..3edf246089 --- /dev/null +++ b/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/tests.bzl @@ -0,0 +1,64 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# 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. +'''Helpers to create golden tests, to minimize code duplication.''' + +def create_golden_test(name, golden_file, has_bootclasspath, missing_jar = None, replacing_jar = None): + '''Create a golden test for the dependency checker.''' + all_dep_jars = [ + "testdata_client", + "testdata_lib_Library", + "testdata_lib_LibraryAnnotations", + "testdata_lib_LibraryException", + "testdata_lib_LibraryInterface", + ] + testdata_pkg = "//third_party/bazel/src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata" + import_deps_checker = "//third_party/bazel/src/java_tools/import_deps_checker/java/com/google/devtools/build/importdeps:ImportDepsChecker" + client_jar = testdata_pkg + ":testdata_client" + data = [ + golden_file, + import_deps_checker, + "//third_party/java/jdk:jdk8_rt_jar" + ] + [testdata_pkg + ":" + x for x in all_dep_jars] + if (replacing_jar): + data.append(testdata_pkg + ":" + replacing_jar) + + args = [ + "$(location %s)" % golden_file, + "$(location %s)" % import_deps_checker, + ] + args.append("--bootclasspath_entry") + if has_bootclasspath: + args.append("$(location //third_party/java/jdk:jdk8_rt_jar)") + else: + args.append("$(location %s)" % client_jar) # Fake bootclasspath. + + for dep in all_dep_jars: + if dep == missing_jar: + if replacing_jar: + args.append("--classpath_entry") + args.append("$(location %s:%s)" % (testdata_pkg, replacing_jar)) + continue + args.append("--classpath_entry") + args.append("$(location %s:%s)" % (testdata_pkg, dep)) + + args = args + [ + "--input", + "$(location %s:testdata_client)" % testdata_pkg, + ] + native.sh_test( + name=name, + srcs = ["golden_test.sh"], + args = args, + data = data, + ) |