aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/import_deps_checker/javatests/com/google
diff options
context:
space:
mode:
authorGravatar cnsun <cnsun@google.com>2018-02-06 10:57:49 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-06 10:59:37 -0800
commit33c419bb0952721f056f01a0374f9f2d238e98bd (patch)
tree2d85645b03699f85231cd28c8d9865058c9e3925 /src/java_tools/import_deps_checker/javatests/com/google
parent11c59283ec83db0c62ad67e7f0ffbfb8a5183b06 (diff)
Add a new tool to check the deps of aar_import. This is the first cl of a
series. The following CLs will integrate this into bazel. RELNOTES:n/a. PiperOrigin-RevId: 184706507
Diffstat (limited to 'src/java_tools/import_deps_checker/javatests/com/google')
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/AbstractClassCacheTest.java96
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/BUILD160
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassCacheTest.java142
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ClassInfoTest.java82
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/DepsCheckerClassVisitorTest.java128
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/LazyClassEntryStateTest.java97
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/ResultCollectorTest.java81
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_bootclasspath_missing.txt87
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_complete_classpath.txt0
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_annotation_missing.txt12
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_exception_missing.txt5
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_interface_missing.txt9
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_members_missing.txt8
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_library_missing.txt18
-rwxr-xr-xsrc/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/golden_test.sh56
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/BUILD43
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Client.java67
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/Library.java60
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryAnnotations.java57
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryException.java17
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/LibraryInterface.java23
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/testdata/library_no_members/com/google/devtools/build/importdeps/testdata/Library.java51
-rw-r--r--src/java_tools/import_deps_checker/javatests/com/google/devtools/build/importdeps/tests.bzl64
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,
+ )