// 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.ResultCollector.MissingMember;
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(
            /*checkMissingMembers=*/ true,
            bootclasspath,
            libraryAnnotationsJar,
            libraryInterfaceJar,
            libraryWoMembersJar,
            libraryExceptionJar,
            clientJar);
    assertThat(collector.getSortedMissingClassInternalNames()).isEmpty();
    assertThat(
            collector
                .getSortedMissingMembers()
                .stream()
                .map(DepsCheckerClassVisitorTest::constructFullQualifiedMemberName)
                .collect(ImmutableList.toImmutableList()))
        .containsExactly(
            constructFullyQualifiedMemberName(
                "com/google/devtools/build/importdeps/testdata/Library$Class1",
                "I",
                "Lcom/google/devtools/build/importdeps/testdata/Library$Class1;"),
            constructFullyQualifiedMemberName(
                "com/google/devtools/build/importdeps/testdata/Library$Class3",
                "field",
                "Lcom/google/devtools/build/importdeps/testdata/Library$Class4;"),
            constructFullyQualifiedMemberName(
                "com/google/devtools/build/importdeps/testdata/Library$Class4",
                "createClass5",
                "()Lcom/google/devtools/build/importdeps/testdata/Library$Class5;"),
            constructFullyQualifiedMemberName(
                "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();
  }

  @Test
  public void testMissingMembersIgnoredWhenUnchecked() throws IOException {
    ResultCollector collector =
        getResultCollector(
            /*checkMissingMembers=*/ false,
            bootclasspath,
            libraryAnnotationsJar,
            libraryInterfaceJar,
            libraryWoMembersJar,
            libraryExceptionJar,
            clientJar);
    assertThat(collector.isEmpty()).isTrue();
  }

  private static String constructFullQualifiedMemberName(MissingMember member) {
    return constructFullyQualifiedMemberName(
        member.owner().internalName(), member.memberName(), member.descriptor());
  }

  private static String constructFullyQualifiedMemberName(
      String owner, String memberName, String descriptor) {
    return owner + memberName + descriptor;
  }

  private ImmutableList<String> getMissingClassesInClient(Path... classpath) throws IOException {
    ResultCollector resultCollector = getResultCollector(/*checkMissingMembers=*/ false, classpath);
    return resultCollector.getSortedMissingClassInternalNames();
  }

  private ResultCollector getResultCollector(boolean checkMissingMembers, Path... classpath)
      throws IOException {
    ImmutableList<String> clientClasses =
        ImmutableList.of(
            PACKAGE_NAME + "Client",
            PACKAGE_NAME + "Client$NestedAnnotation",
            PACKAGE_NAME + "Client$InnerClassWithSyntheticConstructorParam");
    ResultCollector resultCollector = new ResultCollector(checkMissingMembers);
    try (ClassCache cache =
            new ClassCache(
                ImmutableList.copyOf(classpath),
                ImmutableList.of(),
                ImmutableList.of(),
                ImmutableList.of());
        ZipFile zipFile = new ZipFile(clientJar.toFile())) {
      assertThat(cache.getClassState("java/lang/invoke/LambdaMetafactory").isExistingState())
          .isTrue();
      AbstractClassEntryState state = cache.getClassState("java/lang/Enum");
      assertThat(state.isExistingState()).isTrue();
      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;
  }
}
