// 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 com.google.devtools.build.lib.testutil.MoreAsserts.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.ClassCache.LazyClassEntry;
import com.google.devtools.build.importdeps.ClassCache.LazyClasspath;
import com.google.devtools.build.importdeps.ClassInfo.MemberInfo;
import java.io.IOException;
import java.util.Optional;
import java.util.stream.Collectors;
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(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(),
            /*populateMembers=*/ true)) {
      assertCache(
          cache,
          libraryJarPositives,
          combine(libraryAnnotationsJarPositives, libraryExceptionJarPositives));
    }
  }

  @Test
  public void testClientJarWithSuperClasses() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {
      assertCache(
          cache,
          clientJarPositives,
          combine(libraryExceptionJarPositives, libraryAnnotationsJarPositives));
    }
  }

  @Test
  public void testClientJarWithoutSuperClasses() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(),
            ImmutableSet.of(),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {
      // 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();

        ImmutableSet<String> successPart =
            state.asIncompleteState().resolutionFailureChain().getMissingClassesWithSubclasses()
                .values().stream()
                .distinct()
                .sorted()
                .map(ClassInfo::internalName)
                .collect(ImmutableSet.toImmutableSet());
        assertThat(successPart).containsExactly(PACKAGE_NAME + "Client").inOrder();
        assertThat(state.asIncompleteState().missingAncestors())
            .containsExactly(
                PACKAGE_NAME + "Library",
                PACKAGE_NAME + "LibraryInterface",
                PACKAGE_NAME + "LibraryInterface$One",
                PACKAGE_NAME + "LibraryInterface$Two");
      }
      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(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(),
            ImmutableSet.of(),
            ImmutableSet.of(libraryExceptionJar),
            /*populateMembers=*/ true)) {
      assertCache(
          cache,
          libraryExceptionJarPositives,
          combine(libraryAnnotationsJarPositives, libraryInterfacePositives, libraryJarPositives));
    }
  }

  @Test
  public void testLibraryAnnotations() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(),
            ImmutableSet.of(),
            ImmutableSet.of(libraryAnnotationsJar),
            /*populateMembers=*/ true)) {
      assertCache(
          cache,
          libraryAnnotationsJarPositives,
          combine(libraryExceptionJarPositives, libraryInterfacePositives, libraryJarPositives));
    }
  }

  @Test
  public void testCannotAccessClosedCache() throws IOException {
    ClassCache cache =
        new ClassCache(
            ImmutableSet.of(),
            ImmutableSet.of(),
            ImmutableSet.of(),
            ImmutableSet.of(),
            /*populateMembers=*/ true);
    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(
            ImmutableSet.of(),
            ImmutableSet.of(libraryJar, libraryJar, libraryAnnotationsJar, libraryInterfaceJar),
            ImmutableSet.of(libraryJar, libraryJar, libraryAnnotationsJar, libraryInterfaceJar),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {
      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();
    }
  }

  @Test
  public void testJdepsOutput() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(),
            ImmutableSet.of(libraryJar, libraryJar, libraryAnnotationsJar, libraryInterfaceJar),
            ImmutableSet.of(libraryJar, libraryJar, libraryAnnotationsJar, libraryInterfaceJar),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {
      assertThat(
              cache
                  .getClassState("com/google/devtools/build/importdeps/testdata/Library$Class9")
                  .isIncompleteState())
          .isTrue();
      assertThat(cache.collectUsedJarsInRegularClasspath()).containsExactly(libraryJar, true);

      assertThat(
              cache
                  .getClassState("com/google/devtools/build/importdeps/testdata/LibraryAnnotations")
                  .isIncompleteState())
          .isTrue();
      assertThat(cache.collectUsedJarsInRegularClasspath())
          .containsExactly(libraryJar, true, libraryAnnotationsJar, true);

      assertThat(
              cache
                  .getClassState("com/google/devtools/build/importdeps/testdata/LibraryInterface")
                  .isIncompleteState())
          .isTrue();
      assertThat(cache.collectUsedJarsInRegularClasspath())
          .containsExactly(
              libraryJar, true, libraryAnnotationsJar, true, libraryInterfaceJar, true);
    }
  }

  @Test
  public void testJdepsOutput_withSuperclasses_hasImplicitDeps() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {

      assertThat(
              cache
                  .getClassState("com/google/devtools/build/importdeps/testdata/Client")
                  .isExistingState())
          .isTrue();
      assertThat(cache.collectUsedJarsInRegularClasspath())
          .containsExactly(libraryJar, false, libraryInterfaceJar, false);
    }
  }

  @Test
  public void testLazyClasspathLoadsBootclasspathFirst() throws IOException {
    {
      LazyClasspath classpath =
          new LazyClasspath(
              ImmutableSet.of(libraryJar),
              ImmutableSet.of(libraryWoMembersJar),
              ImmutableSet.of(libraryWoMembersJar),
              ImmutableSet.of(),
              /*populateMembers=*/ true);
      LazyClassEntry entry =
          classpath.getLazyEntry("com/google/devtools/build/importdeps/testdata/Library$Class4");
      AbstractClassEntryState state = entry.getState(classpath);
      Optional<ClassInfo> classInfo = state.classInfo();
      assertThat(classInfo.isPresent()).isTrue();
      assertThat(classInfo.get().declaredMembers()).hasSize(2);
      assertThat(
              classInfo
                  .get()
                  .declaredMembers()
                  .stream()
                  .map(MemberInfo::memberName)
                  .collect(Collectors.toSet()))
          .containsExactly("<init>", "createClass5");
    }
    {
      LazyClasspath classpath =
          new LazyClasspath(
              ImmutableSet.of(libraryWoMembersJar),
              ImmutableSet.of(libraryJar),
              ImmutableSet.of(libraryJar),
              ImmutableSet.of(),
              /*populateMembers=*/ true);
      LazyClassEntry entry =
          classpath.getLazyEntry("com/google/devtools/build/importdeps/testdata/Library$Class4");
      AbstractClassEntryState state = entry.getState(classpath);
      Optional<ClassInfo> classInfo = state.classInfo();
      assertThat(classInfo.isPresent()).isTrue();
      // The empty class has a default constructor.
      assertThat(classInfo.get().declaredMembers()).hasSize(1);
      assertThat(classInfo.get().declaredMembers().iterator().next().memberName())
          .isEqualTo("<init>");
    }
  }

  @Test
  public void testLazyClasspath_skipMembers() throws IOException {
    LazyClasspath classpath =
        new LazyClasspath(
            ImmutableSet.of(libraryJar),
            ImmutableSet.of(libraryWoMembersJar),
            ImmutableSet.of(libraryWoMembersJar),
            ImmutableSet.of(),
            /*populateMembers=*/ false);
    LazyClassEntry entry =
        classpath.getLazyEntry("com/google/devtools/build/importdeps/testdata/Library$Class4");
    AbstractClassEntryState state = entry.getState(classpath);
    Optional<ClassInfo> classInfo = state.classInfo();
    assertThat(classInfo.isPresent()).isTrue();
    assertThat(classInfo.get().declaredMembers()).isEmpty();
  }

  @Test
  public void testOriginInformation() throws IOException {
    try (ClassCache cache =
        new ClassCache(
            ImmutableSet.of(bootclasspath),
            ImmutableSet.of(libraryJar),
            ImmutableSet.of(libraryJar, libraryInterfaceJar),
            ImmutableSet.of(clientJar),
            /*populateMembers=*/ true)) {
      assertCache(
          cache,
          clientJarPositives,
          combine(libraryExceptionJarPositives, libraryAnnotationsJarPositives));

      {
        AbstractClassEntryState state = cache.getClassState(PACKAGE_NAME + "Library");
        assertThat(state.isExistingState()).isTrue();
        assertThat(state.classInfo().isPresent()).isTrue();
        assertThat(state.classInfo().get().directDep()).isTrue();
        assertThat((Object) state.classInfo().get().jarPath()).isEqualTo(libraryJar);
      }
      {
        AbstractClassEntryState state = cache.getClassState(PACKAGE_NAME + "LibraryInterface");
        assertThat(state.isExistingState()).isTrue();
        assertThat(state.classInfo().isPresent()).isTrue();
        assertThat(state.classInfo().get().directDep()).isFalse();
        assertThat((Object) state.classInfo().get().jarPath()).isEqualTo(libraryInterfaceJar);
      }
    }
  }

  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();
    }
  }
}
