// Copyright 2016 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.java.turbine.javac;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toSet;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.java.turbine.javac.JavacTurbine.Result;
import com.google.devtools.build.lib.view.proto.Deps;
import com.google.devtools.build.lib.view.proto.Deps.Dependency;
import com.google.turbine.options.TurbineOptions;
import com.google.turbine.options.TurbineOptions.ReducedClasspathMode;
import com.sun.source.tree.LiteralTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskEvent.Kind;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;

/** Unit tests for {@link JavacTurbine}. */
@RunWith(JUnit4.class)
public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest {

  private static final ImmutableList<String> HOST_CLASSPATH =
      ImmutableList.copyOf(
          Splitter.on(File.pathSeparatorChar).split(System.getProperty("java.class.path")));

  @Test
  public void hello() throws Exception {
    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static void main(String[] args) {",
        "    System.err.println(\"Hello World\");",
        "  }",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello {",
      "",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "",
      "  // access flags 0x9",
      "  public static main([Ljava/lang/String;)V",
      "    // parameter  args",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  // verify that FLOW is disabled, as if we had passed -relax
  // if it isn't we'd get an error about the missing return in f().
  @Test
  public void relax() throws Exception {
    addSourceLines("Hello.java", "class Hello {", "  int f() {}", "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello {",
      "",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "",
      "  // access flags 0x0",
      "  f()I",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  public @interface MyAnnotation {}

  /**
   * A sample annotation processor for testing.
   *
   * <p>Writes two output files (one source, one data) the very first round it's called. Used to
   * verify that annotation processor output is collected into the output jar.
   */
  @SupportedAnnotationTypes("MyAnnotation")
  public static class MyProcessor extends AbstractProcessor {

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
    }

    boolean first = true;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      if (!first) {
        // Write the output files exactly once to ensure we don't try to write the same file
        // twice or do work on the final round.
        return false;
      }
      if (roundEnv.getRootElements().isEmpty()) {
        return false;
      }
      first = false;
      Element element = roundEnv.getRootElements().iterator().next();
      try {
        JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile("Generated", element);
        try (OutputStream os = sourceFile.openOutputStream()) {
          os.write("public class Generated {}".getBytes(UTF_8));
        }
      } catch (IOException e) {
        throw new IOError(e);
      }
      try {
        FileObject file =
            processingEnv
                .getFiler()
                .createResource(StandardLocation.CLASS_OUTPUT, "com.foo", "hello.txt", element);
        try (OutputStream os = file.openOutputStream()) {
          os.write("hello".getBytes(UTF_8));
        }
      } catch (IOException e) {
        throw new IOError(e);
      }
      return false;
    }
  }

  @Test
  public void processing() throws Exception {
    addSourceLines("MyAnnotation.java", "public @interface MyAnnotation {}");
    addSourceLines(
        "Hello.java",
        "@MyAnnotation",
        "class Hello {",
        "  public static void main(String[] args) {",
        "    System.err.println(\"Hello World\");",
        "  }",
        "}");

    Path gensrc = temp.newFile("gensrc.jar").toPath();

    optionsBuilder.addProcessors(ImmutableList.of(MyProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(HOST_CLASSPATH);
    optionsBuilder.addClassPathEntries(HOST_CLASSPATH);
    optionsBuilder.setGensrcOutput(gensrc.toString());

    compile();

    Map<String, byte[]> outputs = collectOutputs();
    assertThat(filterManifestEntries(outputs.keySet()))
        .containsExactly(
            "Generated.class", "MyAnnotation.class", "Hello.class", "com/foo/hello.txt");

    {
      String text = textify(outputs.get("Generated.class"));
      String[] expected = {
        "// class version 52.0 (52)",
        "// access flags 0x21",
        "public class Generated {",
        "",
        "",
        "  // access flags 0x1",
        "  public <init>()V",
        "}",
        ""
      };
      assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
    }

    // sanity-check that annotation processing doesn't interfere with stripping
    {
      String text = textify(outputs.get("Hello.class"));
      String[] expected = {
        "// class version 52.0 (52)",
        "// access flags 0x20",
        "class Hello {",
        "",
        "",
        "  @LMyAnnotation;() // invisible",
        "",
        "  // access flags 0x0",
        "  <init>()V",
        "",
        "  // access flags 0x9",
        "  public static main([Ljava/lang/String;)V",
        "    // parameter  args",
        "}",
        ""
      };
      assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
    }

    Map<String, byte[]> gensrcFiles = collectFiles(gensrc);
    assertThat(gensrcFiles.keySet()).containsExactly("Generated.java");
    assertThat(new String(gensrcFiles.get("Generated.java"), UTF_8))
        .isEqualTo("public class Generated {}");
  }

  /**
   * A sample annotation processor for testing.
   *
   * <p>Writes an output file containing a SJD violation.
   */
  @SupportedAnnotationTypes("MyAnnotation")
  public static class SjdProcessor extends AbstractProcessor {

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
    }

    boolean first = true;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      if (!first) {
        return false;
      }
      if (roundEnv.getRootElements().isEmpty()) {
        return false;
      }
      first = false;
      Element element = roundEnv.getRootElements().iterator().next();
      try {
        JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile("Generated", element);
        try (OutputStream os = sourceFile.openOutputStream()) {
          os.write(
              ("public class Generated {\n"
                      + "  public static final int CONST = A.CONST;"
                      + "  public static B b;"
                      + "}")
                  .getBytes(UTF_8));
        }
      } catch (IOException e) {
        throw new IOError(e);
      }
      return false;
    }
  }

  @Test
  public void processingStrict() throws Exception {

    Path libD = temp.newFile("libd.jar").toPath();
    compileLib(
        libD,
        ImmutableList.<Path>of(),
        ImmutableList.of(
            new StringJavaFileObject("D.java", "public class D { static final int CONST = 42; }")));

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        Collections.singleton(libD),
        ImmutableList.of(new StringJavaFileObject("C.java", "class C extends D {}")));

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.of(libC, libD),
        ImmutableList.of(new StringJavaFileObject("B.java", "class B extends C {}")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        ImmutableList.of(libB, libC, libD),
        ImmutableList.of(new StringJavaFileObject("A.java", "class A extends B {}")));
    Path depsA =
        writedeps(
            "liba.jdeps",
            Deps.Dependencies.newBuilder()
                .setSuccess(true)
                .setRuleLabel("//lib:a")
                .addDependency(
                    Deps.Dependency.newBuilder()
                        .setPath(libB.toString())
                        .setKind(Deps.Dependency.Kind.EXPLICIT))
                .build());

    addSourceLines(
        "MyAnnotation.java", //
        "public @interface MyAnnotation {}");
    addSourceLines(
        "Hello.java", //
        "@MyAnnotation",
        "class Hello {}");

    optionsBuilder.addSources(sources.stream().map(p -> p.toString()).collect(toImmutableList()));
    optionsBuilder.addProcessors(ImmutableList.of(SjdProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(HOST_CLASSPATH);
    optionsBuilder.addClassPathEntries(
        ImmutableList.of(libA.toString(), libB.toString(), libC.toString(), libD.toString()));
    optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
    optionsBuilder.addDirectJars(ImmutableList.of(libA.toString()));
    optionsBuilder.setTargetLabel("//my:target");

    StringWriter errOutput = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      result = turbine.compile();
    }
    assertThat(result).isEqualTo(Result.OK_WITH_FULL_CLASSPATH);
  }

  static Map<String, byte[]> collectFiles(Path jar) throws IOException {
    Map<String, byte[]> files = new LinkedHashMap<>();
    try (JarFile jf = new JarFile(jar.toFile())) {
      Enumeration<JarEntry> entries = jf.entries();
      while (entries.hasMoreElements()) {
        JarEntry entry = entries.nextElement();
        files.put(entry.getName(), ByteStreams.toByteArray(jf.getInputStream(entry)));
      }
    }
    return files;
  }

  static String textify(byte[] bytes) {
    StringWriter sw = new StringWriter();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(sw, true)), 0);
    return sw.toString();
  }

  private static final Function<Object, String> TO_STRING =
      new Function<Object, String>() {
        @Override
        public String apply(Object input) {
          return String.valueOf(input);
        }
      };

  @Test
  public void jdeps() throws Exception {

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        ImmutableList.<Path>of(),
        ImmutableList.of(
            new StringJavaFileObject("C.java", "interface C { String getString(); }")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        Collections.singleton(libC),
        ImmutableList.of(new StringJavaFileObject("A.java", "interface A { C getC(); }")));

    Path depsA =
        writedeps(
            "liba.jdeps",
            Deps.Dependencies.newBuilder()
                .setSuccess(true)
                .setRuleLabel("//lib:a")
                .addDependency(
                    Deps.Dependency.newBuilder()
                        .setPath(libC.toString())
                        .setKind(Deps.Dependency.Kind.EXPLICIT))
                .build());

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.<Path>of(),
        ImmutableList.of(new StringJavaFileObject("B.java", "interface B {}")));

    optionsBuilder.addClassPathEntries(
        ImmutableList.of(libA.toString(), libB.toString(), libC.toString()));
    optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
    optionsBuilder.addDirectJars(ImmutableList.of(libA.toString(), libB.toString()));
    optionsBuilder.setTargetLabel("//my:target");

    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static A a = null;",
        "  public static String s = a.getC().getString();",
        "  public static void main(String[] args) {",
        "    B b = null;",
        "  }",
        "}");

    compile();

    Deps.Dependencies depsProto = getDeps();

    assertThat(depsProto.getSuccess()).isTrue();
    assertThat(depsProto.getRequiresReducedClasspathFallback()).isFalse();
    assertThat(depsProto.getRuleLabel()).isEqualTo("//my:target");
    assertThat(getEntries(depsProto))
        .containsExactly(
            libA.toString(), Deps.Dependency.Kind.EXPLICIT,
            libB.toString(), Deps.Dependency.Kind.INCOMPLETE,
            libC.toString(), Deps.Dependency.Kind.INCOMPLETE);
  }

  private Map<String, Deps.Dependency.Kind> getEntries(Deps.Dependencies deps) {
    Map<String, Deps.Dependency.Kind> result = new LinkedHashMap<>();
    for (Dependency dep : deps.getDependencyList()) {
      result.put(dep.getPath(), dep.getKind());
    }
    return result;
  }

  private Deps.Dependencies getDeps() throws IOError {
    Deps.Dependencies depsProto;
    try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(outputDeps))) {
      Deps.Dependencies.Builder builder = Deps.Dependencies.newBuilder();
      builder.mergeFrom(in);
      depsProto = builder.build();
    } catch (IOException e) {
      throw new IOError(e);
    }
    return depsProto;
  }

  private void compileLib(
      Path jar, Collection<Path> classpath, Iterable<? extends JavaFileObject> units)
      throws IOException {
    final Path outdir = temp.newFolder().toPath();
    JavacFileManager fm = new JavacFileManager(new Context(), false, UTF_8);
    fm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singleton(outdir));
    fm.setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
    List<String> options = ImmutableList.of("-d", outdir.toString());
    JavacTool tool = JavacTool.create();

    JavacTask task =
        tool.getTask(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8)), true),
            fm,
            null,
            options,
            null,
            units);
    assertThat(task.call()).isTrue();

    try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(jar))) {
      Files.walkFileTree(
          outdir,
          new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)
                throws IOException {
              JarEntry je = new JarEntry(outdir.relativize(path).toString());
              jos.putNextEntry(je);
              Files.copy(path, jos);
              return FileVisitResult.CONTINUE;
            }
          });
    }
  }

  @Trusted
  static class StringJavaFileObject extends SimpleJavaFileObject {
    private final String content;

    StringJavaFileObject(String name, String... lines) {
      super(URI.create(name), JavaFileObject.Kind.SOURCE);
      this.content = Joiner.on('\n').join(lines);
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
      return content;
    }
  }

  @Test
  public void reducedClasspath() throws Exception {

    Path libD = temp.newFile("libd.jar").toPath();
    compileLib(
        libD,
        ImmutableList.<Path>of(),
        ImmutableList.of(new StringJavaFileObject("D.java", "public class D {}")));

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        Collections.singleton(libD),
        ImmutableList.of(new StringJavaFileObject("C.java", "class C { static D d; }")));

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.of(libC, libD),
        ImmutableList.of(new StringJavaFileObject("B.java", "class B { static C c; }")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        ImmutableList.of(libB, libC, libD),
        ImmutableList.of(new StringJavaFileObject("A.java", "class A { static B b; }")));
    Path depsA =
        writedeps(
            "liba.jdeps",
            Deps.Dependencies.newBuilder()
                .setSuccess(true)
                .setRuleLabel("//lib:a")
                .addDependency(
                    Deps.Dependency.newBuilder()
                        .setPath(libB.toString())
                        .setKind(Deps.Dependency.Kind.EXPLICIT))
                .build());

    optionsBuilder.addClassPathEntries(
        ImmutableList.of(libA.toString(), libB.toString(), libC.toString(), libD.toString()));
    optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
    optionsBuilder.addDirectJars(ImmutableList.of(libA.toString()));
    optionsBuilder.setTargetLabel("//my:target");

    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static A a = new A();",
        "  public static void main(String[] args) {",
        "    A a = null;",
        "    B b = null;",
        "    C c = null;",
        "    D d = null;",
        "  }",
        "}");

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    try (JavacTurbine turbine =
        new JavacTurbine(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
            optionsBuilder.build())) {
      assertThat(turbine.compile())
          .isAnyOf(Result.OK_WITH_FULL_CLASSPATH, Result.OK_WITH_REDUCED_CLASSPATH);

      Context context = turbine.context;

      JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
      assertThat(fm.getLocationAsPaths(StandardLocation.CLASS_PATH)).containsAtLeast(libA, libB);

      Deps.Dependencies depsProto = getDeps();

      assertThat(depsProto.getSuccess()).isTrue();
      assertThat(depsProto.getRequiresReducedClasspathFallback()).isFalse();
      assertThat(depsProto.getRuleLabel()).isEqualTo("//my:target");
      assertThat(getEntries(depsProto))
          .containsAtLeast(
              libA.toString(),
              Deps.Dependency.Kind.EXPLICIT,
              libB.toString(),
              Deps.Dependency.Kind.INCOMPLETE);
    }
  }

  Path writedeps(String name, Deps.Dependencies deps) throws IOException {
    Path path = temp.newFile(name).toPath();
    try (OutputStream os = Files.newOutputStream(path)) {
      deps.writeTo(os);
    }
    return path;
  }

  @Test
  public void reducedClasspathFallback() throws Exception {

    Path libD = temp.newFile("libd.jar").toPath();
    compileLib(
        libD,
        ImmutableList.<Path>of(),
        ImmutableList.of(
            new StringJavaFileObject("D.java", "public class D { static final int CONST = 42; }")));

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        Collections.singleton(libD),
        ImmutableList.of(new StringJavaFileObject("C.java", "class C extends D {}")));

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.of(libC, libD),
        ImmutableList.of(new StringJavaFileObject("B.java", "class B extends C {}")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        ImmutableList.of(libB, libC, libD),
        ImmutableList.of(new StringJavaFileObject("A.java", "class A extends B {}")));
    Path depsA =
        writedeps(
            "liba.jdeps",
            Deps.Dependencies.newBuilder()
                .setSuccess(true)
                .setRuleLabel("//lib:a")
                .addDependency(
                    Deps.Dependency.newBuilder()
                        .setPath(libB.toString())
                        .setKind(Deps.Dependency.Kind.EXPLICIT))
                .build());

    optionsBuilder.addClassPathEntries(
        ImmutableList.of(libA.toString(), libB.toString(), libC.toString(), libD.toString()));
    optionsBuilder.addAllDepsArtifacts(ImmutableList.of(depsA.toString()));
    optionsBuilder.addDirectJars(ImmutableList.of(libA.toString()));
    optionsBuilder.setTargetLabel("//my:target");

    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static final int CONST = A.CONST;",
        "  public static void main(String[] args) {}",
        "}");

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    try (JavacTurbine turbine =
        new JavacTurbine(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
            optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.OK_WITH_FULL_CLASSPATH);
      Context context = turbine.context;

      JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
      assertThat(fm.getLocationAsPaths(StandardLocation.CLASS_PATH))
          .containsExactly(libA, libB, libC, libD);

      Deps.Dependencies depsProto = getDeps();

      assertThat(depsProto.getSuccess()).isTrue();
      assertThat(depsProto.getRequiresReducedClasspathFallback()).isFalse();
      assertThat(depsProto.getRuleLabel()).isEqualTo("//my:target");
      assertThat(getEntries(depsProto))
          .containsExactly(
              libA.toString(), Deps.Dependency.Kind.EXPLICIT,
              libB.toString(), Deps.Dependency.Kind.IMPLICIT,
              libC.toString(), Deps.Dependency.Kind.IMPLICIT,
              libD.toString(), Deps.Dependency.Kind.IMPLICIT);
    }
  }

  @Test
  public void constants() throws Exception {
    addSourceLines(
        "Const.java",
        "class Const {",
        "  public static final int A = 42;",
        "  public static final int B = 42 + 42;",
        "  public static final int C = new Integer(42);",
        "  public static final int D = 42 + new Integer(42);",
        "  public static final Integer E = 42;",
        "  public static final String F = \"42\";",
        "  public static final java.lang.String G = \"42\";",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Const.class");

    String text = textify(outputs.get("Const.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Const {",
      "",
      "",
      "  // access flags 0x19",
      "  public final static I A = 42",
      "",
      "  // access flags 0x19",
      "  public final static I B = 84",
      "",
      "  // access flags 0x19",
      "  public final static I C",
      "",
      "  // access flags 0x19",
      "  public final static I D",
      "",
      "  // access flags 0x19",
      "  public final static Ljava/lang/Integer; E",
      "",
      "  // access flags 0x19",
      "  public final static Ljava/lang/String; F = \"42\"",
      "",
      "  // access flags 0x19",
      "  public final static Ljava/lang/String; G = \"42\"",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "}",
      "",
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void constantsEnum() throws Exception {
    addSourceLines(
        "TheEnum.java", //
        "public enum TheEnum {",
        "  ONE, TWO, THREE;",
        "}");

    compile();
    Map<String, byte[]> outputs = collectOutputs();
    // just don't crash; enum constants need to be preserved
    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("TheEnum.class");

    String text = textify(outputs.get("TheEnum.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x4031",
      "// signature Ljava/lang/Enum<LTheEnum;>;",
      "// declaration: TheEnum extends java.lang.Enum<TheEnum>",
      "public final enum TheEnum extends java/lang/Enum {",
      "",
      "",
      "  // access flags 0x4019",
      "  public final static enum LTheEnum; ONE",
      "",
      "  // access flags 0x4019",
      "  public final static enum LTheEnum; TWO",
      "",
      "  // access flags 0x4019",
      "  public final static enum LTheEnum; THREE",
      "",
      "  // access flags 0x9",
      "  public static values()[LTheEnum;",
      "",
      "  // access flags 0x9",
      "  public static valueOf(Ljava/lang/String;)LTheEnum;",
      "    // parameter mandated  name",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  /**
   * A sample annotation processor for testing.
   *
   * <p>Writes an output file that isn't valid UTF-8 to test handling of encoding errors.
   */
  @SupportedAnnotationTypes("MyAnnotation")
  public static class MyBadEncodingProcessor extends AbstractProcessor {

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
    }

    boolean first = true;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      if (!first) {
        return false;
      }
      if (roundEnv.getRootElements().isEmpty()) {
        return false;
      }
      first = false;
      Element element = roundEnv.getRootElements().iterator().next();
      try {
        JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile("Generated", element);
        try (OutputStream os = sourceFile.openOutputStream()) {
          os.write("class Generated { public static String x = \"".getBytes(UTF_8));
          os.write(0xc2); // write an unpaired surrogate
          os.write("\";}}".getBytes(UTF_8));
        }
      } catch (IOException e) {
        throw new IOError(e);
      }
      return false;
    }
  }

  @Test
  public void badEncoding() throws Exception {
    addSourceLines("MyAnnotation.java", "public @interface MyAnnotation {}");
    addSourceLines(
        "Hello.java",
        "@MyAnnotation",
        "class Hello {",
        "  public static void main(String[] args) {",
        "    System.err.println(\"Hello World\");",
        "  }",
        "}");

    optionsBuilder.addProcessors(ImmutableList.of(MyBadEncodingProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(HOST_CLASSPATH);
    optionsBuilder.addClassPathEntries(HOST_CLASSPATH);

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));
    try (StringWriter sw = new StringWriter();
        JavacTurbine turbine =
            new JavacTurbine(new PrintWriter(sw, true), optionsBuilder.build())) {
      Result result = turbine.compile();
      assertThat(result).isEqualTo(Result.ERROR);
      assertThat(sw.toString()).contains("unmappable character");
    }
  }

  @Test
  public void requiredConstructor() throws Exception {
    addSourceLines(
        "Super.java", //
        "class Super {",
        "  public Super(int x) {}",
        "}");
    addSourceLines(
        "Hello.java",
        "class Hello extends Super {",
        "  public Hello() {",
        "    super(42);",
        "  }",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet()))
        .containsExactly("Super.class", "Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello extends Super {",
      "",
      "",
      "  // access flags 0x1",
      "  public <init>()V",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void annotationDeclaration() throws Exception {
    addSourceLines(
        "Anno.java",
        "import java.lang.annotation.Retention;",
        "import java.lang.annotation.RetentionPolicy;",
        "@Retention(RetentionPolicy.RUNTIME)",
        "@interface Anno {",
        "  public int value() default CONST;",
        "  int CONST = 42;",
        "  int NONCONST = new Integer(42);",
        "}");
    addSourceLines("Hello.java", "@Anno(value=Anno.CONST)", "class Hello {", "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet()))
        .containsExactly("Anno.class", "Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello {",
      "",
      "",
      "  @LAnno;(value=42)",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void overlappingSourceJars() throws Exception {
    Path sourceJar1 = temp.newFile("srcs1.jar").toPath();
    try (OutputStream os = Files.newOutputStream(sourceJar1);
        JarOutputStream jos = new JarOutputStream(os)) {
      jos.putNextEntry(new JarEntry("Hello.java"));
      jos.write("public class Hello {}".getBytes(UTF_8));
    }

    Path sourceJar2 = temp.newFile("srcs2.jar").toPath();
    try (OutputStream os = Files.newOutputStream(sourceJar2);
        JarOutputStream jos = new JarOutputStream(os)) {
      jos.putNextEntry(new JarEntry("Hello.java"));
      jos.write("public class Hello {}".getBytes(UTF_8));
    }

    optionsBuilder.setSourceJars(ImmutableList.of(sourceJar2.toString(), sourceJar1.toString()));

    StringWriter errOutput = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      result = turbine.compile();
    }
    assertThat(result).isEqualTo(Result.ERROR);
    assertThat(errOutput.toString()).contains("duplicate class: Hello");
  }

  @Test
  public void privateMembers() throws Exception {
    addSourceLines("Hello.java", "class Hello {", "  private void f() {}", "  private int x;", "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello {",
      "",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void invalidJavacopts() throws Exception {
    addSourceLines("Hello.java", "class Hello {}");
    optionsBuilder.addAllJavacOpts(ImmutableList.of("-NOT_AN_OPTION"));
    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));
    StringWriter errOutput = new StringWriter();
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.ERROR);
    }
    assertThat(errOutput.toString()).contains("invalid flag: -NOT_AN_OPTION");
  }

  /** An annotation processor that reads a file that doesn't exist. */
  @SupportedAnnotationTypes("*")
  public static class NoSuchFileProcessor extends AbstractProcessor {

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      try {
        processingEnv
            .getFiler()
            .getResource(StandardLocation.CLASS_OUTPUT, "", "NO_SUCH_FILE")
            .openInputStream();
      } catch (IOException e) {
        throw new IOError(e);
      }
      return false;
    }
  }

  @Test
  public void processorReadsNonexistentFile() throws Exception {
    addSourceLines("Hello.java", "@Deprecated class Hello {}");
    optionsBuilder.addProcessors(ImmutableList.of(NoSuchFileProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(HOST_CLASSPATH);
    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter errOutput = new StringWriter();
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.ERROR);
    }
    assertThat(errOutput.toString()).contains("classes/NO_SUCH_FILE");
  }

  @Test
  public void emptySources() throws Exception {
    // don't set up any source files
    compile();
    Map<String, byte[]> outputs = collectOutputs();
    assertThat(filterManifestEntries(outputs.keySet())).isEmpty();
  }

  /** An annotation processor that violates the contract. */
  @SupportedAnnotationTypes("*")
  public static class MisguidedAnnotationProcessor extends AbstractProcessor {

    public final class Scanner extends TreeScanner<Void, Void> {
      @Override
      public Void visitLiteral(LiteralTree tree, Void unused) {
        values.add(tree.getValue());
        return null;
      }
    }

    public final class Listener implements TaskListener {

      public final ProcessingEnvironment processingEnv;

      Listener(ProcessingEnvironment processingEnv) {
        this.processingEnv = processingEnv;
      }

      @Override
      public void started(TaskEvent e) {}

      @Override
      public void finished(TaskEvent e) {
        if (e.getKind() == Kind.ANALYZE) {
          e.getCompilationUnit().accept(new Scanner(), null);
        } else if (e.getKind() == Kind.GENERATE) {
          try {
            FileObject file =
                processingEnv
                    .getFiler()
                    .createResource(
                        StandardLocation.CLASS_OUTPUT, "", "output.txt", e.getTypeElement());
            try (OutputStream os = file.openOutputStream()) {
              os.write(values.toString().getBytes(UTF_8));
            }
          } catch (IOException exception) {
            throw new IOError(exception);
          }
        }
      }
    }

    public final Set<Object> values = new LinkedHashSet<>();

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
    }

    @Override
    public synchronized void init(final ProcessingEnvironment processingEnv) {
      JavacTask.instance(processingEnv).addTaskListener(new Listener(processingEnv));
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      return false;
    }
  }

  void setupMisguidedProcessor() throws Exception {
    addSourceLines(
        "Hello.java",
        "@Deprecated class Hello {",
        "  int x = 42;",
        "  String s = \"hello\";",
        "  double y = 42.1;",
        "}");

    Path processorJar =
        createClassJar(
            "libprocessor.jar",
            MisguidedAnnotationProcessor.class,
            MisguidedAnnotationProcessor.Listener.class,
            MisguidedAnnotationProcessor.Scanner.class);

    optionsBuilder.addProcessors(ImmutableList.of(MisguidedAnnotationProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(ImmutableList.of(processorJar.toString()));
  }

  public static class TransitiveDep {}

  public static class DirectDep extends TransitiveDep {}

  @Test
  public void noNativeHeaderOutput() throws Exception {

    // deliberately exclude TransitiveDep
    Path deps =
        createClassJar(
            "libdeps.jar",
            AbstractJavacTurbineCompilationTest.class,
            JavacTurbineTest.class,
            DirectDep.class);

    // compilation will complete supertypes of DirectDep iff NATIVE_HEADER_OUTPUT is set
    addSourceLines(
        "Hello.java",
        "import " + DirectDep.class.getCanonicalName() + ";",
        "class Hello {",
        "  public native DirectDep foo() /*-{",
        "  }-*/;",
        "}");

    optionsBuilder.addClassPathEntries(Collections.singleton(deps.toString()));
    optionsBuilder.addDirectJars(ImmutableList.of(deps.toString()));

    compile();
    Map<String, byte[]> outputs = collectOutputs();
    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class");
  }

  public static class Lib {}

  @Test
  public void ignoreStrictDepsErrors() throws Exception {

    Path lib =
        createClassJar(
            "deps.jar",
            AbstractJavacTurbineCompilationTest.class,
            JavacTurbineTest.class,
            Lib.class);

    addSourceLines(
        "Hello.java", "import " + Lib.class.getCanonicalName() + ";", "class Hello extends Lib {}");

    optionsBuilder.addClassPathEntries(ImmutableList.of(lib.toString()));

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter errOutput = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      result = turbine.compile();
    }
    assertThat(result).isNotEqualTo(Result.OK_WITH_REDUCED_CLASSPATH);
  }

  @Test
  public void ignoreStrictDepsErrorsForFailingCompilations() throws Exception {

    Path lib =
        createClassJar(
            "deps.jar",
            AbstractJavacTurbineCompilationTest.class,
            JavacTurbineTest.class,
            Lib.class);

    addSourceLines(
        "Hello.java",
        "import " + Lib.class.getCanonicalName() + ";",
        "class Hello extends Lib {",
        "  no.such.Class f;",
        "}");

    optionsBuilder.addClassPathEntries(ImmutableList.of(lib.toString()));

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter errOutput = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(errOutput, true), optionsBuilder.build())) {
      result = turbine.compile();
    }
    assertThat(errOutput.toString()).doesNotContain("[strict]");
    assertThat(errOutput.toString()).doesNotContain("** Please add the following dependencies:");
    assertThat(result).isEqualTo(Result.ERROR);
  }

  @Test
  public void clinit() throws Exception {
    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static int x;",
        "  static {",
        "    x = 42;",
        "  }",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class");

    String text = textify(outputs.get("Hello.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "class Hello {",
      "",
      "",
      "  // access flags 0x9",
      "  public static I x",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void bridge() throws Exception {
    addSourceLines(
        "Bridge.java",
        "import java.util.concurrent.Callable;",
        "class Bridge implements Callable<String> {",
        "  public String call() { return \"\"; }",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Bridge.class");

    String text = textify(outputs.get("Bridge.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x20",
      "// signature Ljava/lang/Object;Ljava/util/concurrent/Callable<Ljava/lang/String;>;",
      "// declaration: Bridge implements java.util.concurrent.Callable<java.lang.String>",
      "class Bridge implements java/util/concurrent/Callable {",
      "",
      "",
      "  // access flags 0x0",
      "  <init>()V",
      "",
      "  // access flags 0x1",
      "  public call()Ljava/lang/String;",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void enumDecl() throws Exception {
    addSourceLines(
        "P.java",
        "import java.util.function.Predicate;",
        "enum P implements Predicate<String> {",
        "  INSTANCE {",
        "    @Override",
        "    public boolean test(String s) {",
        "      return NoSuch.method();",
        "    }",
        "  }",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    String text = textify(outputs.get("P.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x4420",
      "// signature Ljava/lang/Enum<LP;>;Ljava/util/function/Predicate<Ljava/lang/String;>;",
      "// declaration: P extends java.lang.Enum<P>"
          + " implements java.util.function.Predicate<java.lang.String>",
      "abstract enum P extends java/lang/Enum implements java/util/function/Predicate {",
      "",
      "  // access flags 0x4010",
      "  final enum INNERCLASS P$1 null null",
      "",
      "  // access flags 0x4019",
      "  public final static enum LP; INSTANCE",
      "",
      "  // access flags 0x9",
      "  public static values()[LP;",
      "",
      "  // access flags 0x9",
      "  public static valueOf(Ljava/lang/String;)LP;",
      "    // parameter mandated  name",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @Test
  public void lambdaBody() throws Exception {
    addSourceLines(
        "P.java",
        "import java.util.function.Predicate;",
        "enum P {",
        "  INSTANCE(x -> {",
        "    return false;",
        "  });",
        "  P(Predicate<String> p) {}",
        "}");

    compile();

    Map<String, byte[]> outputs = collectOutputs();

    String text = textify(outputs.get("P.class"));
    String[] expected = {
      "// class version 52.0 (52)",
      "// access flags 0x4030",
      "// signature Ljava/lang/Enum<LP;>;",
      "// declaration: P extends java.lang.Enum<P>",
      "final enum P extends java/lang/Enum {",
      "",
      "  // access flags 0x19",
      "  public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup"
          + " java/lang/invoke/MethodHandles Lookup",
      "",
      "  // access flags 0x4019",
      "  public final static enum LP; INSTANCE",
      "",
      "  // access flags 0x9",
      "  public static values()[LP;",
      "",
      "  // access flags 0x9",
      "  public static valueOf(Ljava/lang/String;)LP;",
      "    // parameter mandated  name",
      "}",
      ""
    };
    assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
  }

  @SupportedAnnotationTypes("*")
  public static class SimpleProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      return false;
    }
  }

  @Test
  public void noWarningDiagnostics() throws Exception {
    addSourceLines(
        "A.java", //
        "@Deprecated public class A {",
        "}");
    addSourceLines(
        "B.java", //
        "public class B {",
        "  public static final A a;",
        "}");

    optionsBuilder.addProcessors(ImmutableList.of(SimpleProcessor.class.getName()));
    optionsBuilder.addProcessorPathEntries(HOST_CLASSPATH);
    optionsBuilder.addAllJavacOpts(ImmutableList.of("-Xlint:deprecation"));
    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter output = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(output, true), optionsBuilder.build())) {
      result = turbine.compile();
    }

    assertThat(output.toString()).isEmpty();
    assertThat(result).isAnyOf(Result.OK_WITH_FULL_CLASSPATH, Result.OK_WITH_REDUCED_CLASSPATH);
  }

  @Test
  public void noDoclint() throws Exception {
    addSourceLines(
        "A.java", //
        "/** {@link Invalid} **/",
        "public class A {",
        "}");

    optionsBuilder.addAllJavacOpts(
        ImmutableList.of("-source", "8", "-target", "8", "-Xdoclint:reference"));
    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter output = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(output, true), optionsBuilder.build())) {
      result = turbine.compile();
    }

    assertThat(output.toString()).isEmpty();
    assertThat(result).isAnyOf(Result.OK_WITH_FULL_CLASSPATH, Result.OK_WITH_REDUCED_CLASSPATH);
  }

  @Test
  public void processJavacopts_useSourceByDefault() {
    TurbineOptions options = TurbineOptions.builder().setOutput("/out").build();
    ImmutableList<String> javacopts = JavacTurbine.processJavacopts(options);
    assertThat(javacopts).contains("-source");
    assertThat(javacopts).doesNotContain("--release");
  }

  @Test
  public void processJavacopts_releaseDefault() {
    TurbineOptions options =
        TurbineOptions.builder()
            .setOutput("/out")
            .addAllJavacOpts(ImmutableList.of("--release", "9"))
            .build();
    ImmutableList<String> javacopts = JavacTurbine.processJavacopts(options);
    assertThat(javacopts).doesNotContain("-source");
  }

  @Test
  public void processJavacopts_normalizeRelease() {
    TurbineOptions options =
        TurbineOptions.builder()
            .setOutput("/out")
            .addAllJavacOpts(ImmutableList.of("-source", "8", "-target", "8", "--release", "9"))
            .build();
    ImmutableList<String> javacopts = JavacTurbine.processJavacopts(options);
    assertThat(javacopts).contains("--release");
    assertThat(javacopts).containsNoneOf("-source", "-target");
  }

  @Test
  public void processJavacopts_filtersDoclint() {
    TurbineOptions options =
        TurbineOptions.builder()
            .setOutput("/out")
            .addAllJavacOpts(ImmutableList.of("-Xmyopt", "-Xdoclint:reference"))
            .build();
    ImmutableList<String> javacopts = JavacTurbine.processJavacopts(options);
    assertThat(javacopts).contains("-Xmyopt");
    assertThat(javacopts).doesNotContain("-Xdoclint:reference");
  }

  @Test
  public void testManifestEntries() throws Exception {
    optionsBuilder.setTargetLabel("//foo:foo");
    optionsBuilder.setInjectingRuleKind("foo_library");
    compile();
    try (JarFile jarFile = new JarFile(output.toFile())) {
      Manifest manifest = jarFile.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertThat(attributes.getValue("Injecting-Rule-Kind")).isEqualTo("foo_library");
      assertThat(jarFile.getEntry(JarFile.MANIFEST_NAME).getLastModifiedTime().toInstant())
          .isEqualTo(
              LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant());
    }
  }

  private static Set<String> filterManifestEntries(Set<String> entries) {
    return entries.stream()
        .filter(
            name ->
                !(name.startsWith(JavacTurbine.MANIFEST_DIR)
                    || name.equals(JavacTurbine.MANIFEST_NAME)))
        .collect(toSet());
  }

  @Test
  public void diagnosticFormattingTest() throws Exception {
    addSourceLines(
        "A.java", //
        "class A {",
        "}}");

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    StringWriter output = new StringWriter();
    Result result;
    try (JavacTurbine turbine =
        new JavacTurbine(new PrintWriter(output, true), optionsBuilder.build())) {
      result = turbine.compile();
    }

    assertThat(result).isEqualTo(Result.ERROR);
    assertThat(output.toString()).contains("A.java:2: error: class, interface, or enum expected");
  }

  @Test
  public void bazelReducedSuccess() throws Exception {

    Path libD = temp.newFile("libd.jar").toPath();
    compileLib(
        libD,
        ImmutableList.<Path>of(),
        ImmutableList.of(new StringJavaFileObject("D.java", "public class D {}")));

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        Collections.singleton(libD),
        ImmutableList.of(new StringJavaFileObject("C.java", "class C { static D d; }")));

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.of(libC, libD),
        ImmutableList.of(new StringJavaFileObject("B.java", "class B { static C c; }")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        ImmutableList.of(libB, libC, libD),
        ImmutableList.of(new StringJavaFileObject("A.java", "class A { static B b; }")));

    optionsBuilder.addClassPathEntries(ImmutableList.of(libA.toString(), libB.toString()));
    optionsBuilder.setReducedClasspathMode(ReducedClasspathMode.BAZEL_REDUCED);
    optionsBuilder.setTargetLabel("//my:target");

    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static A a = new A();",
        "  public static void main(String[] args) {",
        "    A a = null;",
        "    B b = null;",
        "    C c = null;",
        "    D d = null;",
        "  }",
        "}");

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    try (JavacTurbine turbine =
        new JavacTurbine(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8)), true),
            optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.OK_WITH_REDUCED_CLASSPATH);
      Context context = turbine.context;

      JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
      assertThat(fm.getLocationAsPaths(StandardLocation.CLASS_PATH)).containsExactly(libA, libB);

      Deps.Dependencies depsProto = getDeps();

      assertThat(depsProto.getSuccess()).isTrue();
      assertThat(depsProto.getRequiresReducedClasspathFallback()).isFalse();
      assertThat(depsProto.getRuleLabel()).isEqualTo("//my:target");
      assertThat(getEntries(depsProto))
          .containsExactly(
              libA.toString(),
              Deps.Dependency.Kind.EXPLICIT,
              libB.toString(),
              Deps.Dependency.Kind.INCOMPLETE);
    }
  }

  @Test
  public void bazelReducedClasspath() throws Exception {

    Path libD = temp.newFile("libd.jar").toPath();
    compileLib(
        libD,
        ImmutableList.<Path>of(),
        ImmutableList.of(
            new StringJavaFileObject("D.java", "public class D { static final int CONST = 42; }")));

    Path libC = temp.newFile("libc.jar").toPath();
    compileLib(
        libC,
        Collections.singleton(libD),
        ImmutableList.of(new StringJavaFileObject("C.java", "class C extends D {}")));

    Path libB = temp.newFile("libb.jar").toPath();
    compileLib(
        libB,
        ImmutableList.of(libC, libD),
        ImmutableList.of(new StringJavaFileObject("B.java", "class B extends C {}")));

    Path libA = temp.newFile("liba.jar").toPath();
    compileLib(
        libA,
        ImmutableList.of(libB, libC, libD),
        ImmutableList.of(new StringJavaFileObject("A.java", "class A extends B {}")));

    optionsBuilder.addClassPathEntries(ImmutableList.of(libA.toString()));
    optionsBuilder.setTargetLabel("//my:target");
    optionsBuilder.setReducedClasspathMode(ReducedClasspathMode.BAZEL_REDUCED);

    addSourceLines(
        "Hello.java",
        "class Hello {",
        "  public static final int CONST = A.CONST;",
        "  public static void main(String[] args) {}",
        "}");

    optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));

    try (JavacTurbine turbine =
        new JavacTurbine(
            new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
            optionsBuilder.build())) {
      assertThat(turbine.compile()).isEqualTo(Result.REQUIRES_FALLBACK);

      Deps.Dependencies depsProto = getDeps();

      assertThat(depsProto.getSuccess()).isFalse();
      assertThat(depsProto.getRequiresReducedClasspathFallback()).isTrue();
      assertThat(depsProto.getRuleLabel()).isEqualTo("//my:target");
    }
  }
}
