// 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.ImmutableSet;
import com.google.devtools.build.lib.view.proto.Deps.Dependencies;
import com.google.devtools.build.lib.view.proto.Deps.Dependency;
import com.google.devtools.build.lib.view.proto.Deps.Dependency.Kind;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test for {@link ImportDepsChecker} */
@RunWith(JUnit4.class)
public class ImportDepsCheckerTest extends AbstractClassCacheTest {

  @Test
  public void testJdepsProtos() throws IOException {
    testJdepsProto(
        ImmutableSet.of(bootclasspath),
        ImmutableSet.of(libraryJar),
        ImmutableSet.of(clientJar),
        /*expectedCheckResult=*/ false,
        ImmutableSet.of(libraryJar));
    testJdepsProto(
        ImmutableSet.of(clientJar), // fake non-empty bootclasspath.
        ImmutableSet.of(libraryJar),
        ImmutableSet.of(clientJar),
        false,
        ImmutableSet.of(libraryJar));
    testJdepsProto(
        ImmutableSet.of(bootclasspath),
        ImmutableSet.of(libraryJar, libraryAnnotationsJar),
        ImmutableSet.of(clientJar),
        false,
        ImmutableSet.of(libraryJar, libraryAnnotationsJar));
    testJdepsProto(
        ImmutableSet.of(bootclasspath),
        ImmutableSet.of(libraryAnnotationsJar),
        ImmutableSet.of(libraryJar),
        false,
        ImmutableSet.of());
    testJdepsProto(
        ImmutableSet.of(bootclasspath),
        ImmutableSet.of(
            libraryJar, libraryAnnotationsJar, libraryExceptionJar, libraryInterfaceJar),
        ImmutableSet.of(clientJar),
        true,
        ImmutableSet.of(
            libraryJar, libraryAnnotationsJar, libraryExceptionJar, libraryInterfaceJar));
  }


  private static final String DUMMY_RULE_LABEL = "empty";

  private static void testJdepsProto(
      ImmutableSet<Path> bootclasspath,
      ImmutableSet<Path> regularClasspath,
      ImmutableSet<Path> inputJars,
      boolean expectedCheckResult,
      ImmutableSet<Path> expectedJdeps)
      throws IOException {
    try (ImportDepsChecker checker =
        new ImportDepsChecker(
            bootclasspath, regularClasspath, regularClasspath, inputJars, false)) {
      assertThat(checker.check()).isEqualTo(expectedCheckResult);
      Dependencies deps = checker.emitJdepsProto(DUMMY_RULE_LABEL);
      assertThat(deps.getDependencyList())
          .containsExactlyElementsIn(
              expectedJdeps
                  .stream()
                  .map(
                      path ->
                          Dependency.newBuilder()
                              .setKind(Kind.EXPLICIT)
                              .setPath(path.toString())
                              .build())
                  .collect(Collectors.toList()));
      assertPathsAreRelative(deps);
      assertThat(checker.check()).isEqualTo(expectedCheckResult);
      Dependencies deps2 = checker.emitJdepsProto(DUMMY_RULE_LABEL);
      assertThat(deps).isEqualTo(deps2);

      System.err.println(deps2);

      Dependencies depsFromMain =
          getJdepsProtoWithMainEntry(bootclasspath, regularClasspath, inputJars);
      assertThat(deps).isEqualTo(depsFromMain);
    }
  }

  private static Dependencies getJdepsProtoWithMainEntry(
      ImmutableSet<Path> bootclasspath,
      ImmutableSet<Path> regularClasspath,
      ImmutableSet<Path> inputJars)
      throws IOException {
    ArrayList<String> args = new ArrayList<>();
    bootclasspath.forEach(
        s -> {
          args.add("--bootclasspath_entry");
          args.add(s.toString());
        });
    regularClasspath.forEach(
        s -> {
          args.add("--classpath_entry");
          args.add(s.toString());
        });
    inputJars.forEach(
        s -> {
          args.add("--input");
          args.add(s.toString());
        });
    args.add("--jdeps_output");
    Path jdepsFile = Files.createTempFile("temp_importdeps", ".jdeps");
    args.add(jdepsFile.toString());
    args.add("--rule_label=" + DUMMY_RULE_LABEL);

    args.add("--output");
    args.add(Files.createTempFile("temp_output", ".txt").toString());
    args.add("--checking_mode=silence");
    Main.checkDeps(args.toArray(new String[0]));

    try (InputStream inputStream = Files.newInputStream(jdepsFile)) {
      return Dependencies.parseFrom(inputStream);
    }
  }

  private static void assertPathsAreRelative(Dependencies deps) {
    for (Dependency dep : deps.getDependencyList()) {
      assertThat(dep.getPath().startsWith("/")).isFalse();
    }
  }
}
