/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.java;

import static com.facebook.buck.java.JavaCompilationConstants.DEFAULT_JAVAC_OPTIONS;
import static com.facebook.buck.util.BuckConstant.BIN_PATH;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.facebook.buck.android.AndroidLibrary;
import com.facebook.buck.android.AndroidLibraryBuilder;
import com.facebook.buck.android.AndroidLibraryDescription;
import com.facebook.buck.android.AndroidPlatformTarget;
import com.facebook.buck.android.AndroidResourceDescription;
import com.facebook.buck.event.BuckEventBusFactory;
import com.facebook.buck.io.MorePaths;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.java.abi.AbiWriterProtocol;
import com.facebook.buck.model.BuildId;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.rules.AbiRule;
import com.facebook.buck.rules.ActionGraph;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildDependencies;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.FakeBuildRule;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.FakeBuildableContext;
import com.facebook.buck.rules.FakeRuleKeyBuilderFactory;
import com.facebook.buck.rules.ImmutableBuildContext;
import com.facebook.buck.rules.ImmutableSha1HashCode;
import com.facebook.buck.rules.NoopArtifactCache;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.RuleKeyBuilderFactory;
import com.facebook.buck.rules.Sha1HashCode;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePaths;
import com.facebook.buck.rules.TestSourcePath;
import com.facebook.buck.shell.GenruleBuilder;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepRunner;
import com.facebook.buck.step.TestExecutionContext;
import com.facebook.buck.testutil.AllExistingProjectFilesystem;
import com.facebook.buck.testutil.FakeFileHashCache;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.MoreAsserts;
import com.facebook.buck.testutil.RuleMap;
import com.facebook.buck.timing.DefaultClock;
import com.facebook.buck.util.Ansi;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.Console;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.Verbosity;
import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Suppliers;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

public class DefaultJavaLibraryTest {
  private static final String ANNOTATION_SCENARIO_TARGET =
      "//android/java/src/com/facebook:fb";
  private static final String ANNOTATION_SCENARIO_GEN_PATH_POSTIX =
      BuckConstant.ANNOTATION_DIR + "/android/java/src/com/facebook/__fb_gen__";

  @Rule
  public TemporaryFolder tmp = new TemporaryFolder();
  private String annotationScenarioGenPath;

  @Before
  public void stubOutBuildContext() {
    StepRunner stepRunner = createNiceMock(StepRunner.class);
    JavaPackageFinder packageFinder = createNiceMock(JavaPackageFinder.class);
    replay(packageFinder, stepRunner);

    annotationScenarioGenPath = new File(
        tmp.getRoot(),
        ANNOTATION_SCENARIO_GEN_PATH_POSTIX).getAbsolutePath();
  }

  /** Make sure that when isAndroidLibrary is true, that the Android bootclasspath is used. */
  @Test
  @SuppressWarnings("PMD.AvoidUsingHardCodedIP")
  public void testBuildInternalWithAndroidBootclasspath() throws IOException {
    String folder = "android/java/src/com/facebook";
    tmp.newFolder(folder.split("/"));
    BuildTarget buildTarget = BuildTargetFactory.newInstance("//" + folder + ":fb");

    Path src = Paths.get(folder, "Main.java");
    tmp.newFile(src.toString());

    BuildRuleResolver ruleResolver = new BuildRuleResolver(
        ImmutableMap.<BuildTarget, BuildRule>of());
    ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmp.getRoot().toPath());
    BuildRule libraryRule = AndroidLibraryBuilder
        .createBuilder(buildTarget)
        .addSrc(src)
        .build(ruleResolver);
    DefaultJavaLibrary javaLibrary = (DefaultJavaLibrary) libraryRule;

    String bootclasspath = "effects.jar:maps.jar:usb.jar:";
    BuildContext context = createBuildContext(libraryRule, bootclasspath, projectFilesystem);

    List<Step> steps = javaLibrary.getBuildSteps(context, new FakeBuildableContext());

    // Find the JavacStep and verify its bootclasspath.
    Step step = Iterables.find(steps, new Predicate<Step>() {
      @Override
      public boolean apply(Step command) {
        return command instanceof JavacStep;
      }
    });
    assertNotNull("Expected a JavacStep in the steplist.", step);
    JavacStep javac = (JavacStep) step;
    assertEquals("Should compile Main.java rather than generated R.java.",
        ImmutableSet.of(src),
        javac.getSrcs());
  }

  @Test
  public void testGetInputsToCompareToOutputWhenAResourceAsSourcePathExists() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget genruleBuildTarget = BuildTargetFactory.newInstance("//generated:stuff");
    BuildRule genrule = GenruleBuilder
        .newGenruleBuilder(genruleBuildTarget)
        .setBash("echo 'aha' > $OUT")
        .setOut("stuff.txt")
        .build(ruleResolver);

    ProjectFilesystem filesystem = new AllExistingProjectFilesystem() {
      @Override
      public boolean isDirectory(Path path, LinkOption... linkOptionsk) {
        return false;
      }
    };

    DefaultJavaLibrary javaRule = (DefaultJavaLibrary) JavaLibraryBuilder
        .createBuilder(BuildTargetFactory.newInstance("//library:code"))
        .addResource(new BuildTargetSourcePath(filesystem, genrule.getBuildTarget()))
        .addResource(new TestSourcePath("library/data.txt"))
        .build(ruleResolver, filesystem);

    assertEquals(
        "Generated files should not be included in getInputsToCompareToOutput() because they " +
            "should not be part of the RuleKey computation.",
        ImmutableList.of(Paths.get("library/data.txt")),
        javaRule.getInputsToCompareToOutput());
  }

  @Test
  public void testJavaLibaryThrowsIfResourceIsDirectory() {
    ProjectFilesystem filesystem = new AllExistingProjectFilesystem() {
      @Override
      public boolean isDirectory(Path path, LinkOption... linkOptionsk) {
        return true;
      }
    };

    try {
      JavaLibraryBuilder
          .createBuilder(BuildTargetFactory.newInstance("//library:code"))
          .addResource(new TestSourcePath("library"))
          .build(new BuildRuleResolver(), filesystem);
      fail("An exception should have been thrown because a directory was passed as a resource.");
    } catch (HumanReadableException e) {
      assertTrue(e.getHumanReadableErrorMessage().contains("a directory is not a valid input"));
    }
  }

  /**
   * Verify adding an annotation processor java binary.
   */
  @Test
  public void testAddAnnotationProcessorJavaBinary() throws IOException {
    AnnotationProcessingScenario scenario = new AnnotationProcessingScenario();
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_JAVA_BINARY);

    scenario.getAnnotationProcessingParamsBuilder()
        .addAllProcessors(ImmutableList.of("MyProcessor"));

    ImmutableList<String> parameters = scenario.buildAndGetCompileParameters();

    MoreAsserts.assertContainsOne(parameters, "-processorpath");
    MoreAsserts.assertContainsOne(parameters, "-processor");
    assertHasProcessor(parameters, "MyProcessor");
    MoreAsserts.assertContainsOne(parameters, "-s");
    MoreAsserts.assertContainsOne(parameters, annotationScenarioGenPath);

    assertEquals(
        "Expected '-processor MyProcessor' parameters",
        parameters.indexOf("-processor") + 1,
        parameters.indexOf("MyProcessor"));
    assertEquals(
        "Expected '-s " + annotationScenarioGenPath + "' parameters",
        parameters.indexOf("-s") + 1,
        parameters.indexOf(annotationScenarioGenPath));

    for (String parameter : parameters) {
      assertTrue("Expected no custom annotation options.", !parameter.startsWith("-A") ||
          parameter.startsWith("-A" + AbiWriterProtocol.PARAM_ABI_OUTPUT_FILE));
    }
  }

  /**
   * Verify adding an annotation processor prebuilt jar.
   */
  @Test
  public void testAddAnnotationProcessorPrebuiltJar() throws IOException {
    AnnotationProcessingScenario scenario = new AnnotationProcessingScenario();
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_PREBUILT_JAR);

    scenario.getAnnotationProcessingParamsBuilder()
        .addAllProcessors(ImmutableList.of("MyProcessor"));

    ImmutableList<String> parameters = scenario.buildAndGetCompileParameters();

    MoreAsserts.assertContainsOne(parameters, "-processorpath");
    MoreAsserts.assertContainsOne(parameters, "-processor");
    assertHasProcessor(parameters, "MyProcessor");
    MoreAsserts.assertContainsOne(parameters, "-s");
    MoreAsserts.assertContainsOne(parameters, annotationScenarioGenPath);
  }

  /**
   * Verify adding an annotation processor java library.
   */
  @Test
  public void testAddAnnotationProcessorJavaLibrary() throws IOException {
    AnnotationProcessingScenario scenario = new AnnotationProcessingScenario();
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_PREBUILT_JAR);

    scenario.getAnnotationProcessingParamsBuilder()
        .addAllProcessors(ImmutableList.of("MyProcessor"));

    ImmutableList<String> parameters = scenario.buildAndGetCompileParameters();

    MoreAsserts.assertContainsOne(parameters, "-processorpath");
    MoreAsserts.assertContainsOne(parameters, "-processor");
    assertHasProcessor(parameters, "MyProcessor");
    MoreAsserts.assertContainsOne(parameters, "-s");
    MoreAsserts.assertContainsOne(parameters, annotationScenarioGenPath);
  }

  /**
   * Verify adding multiple annotation processors.
   */
  @Test
  public void testAddAnnotationProcessorJar() throws IOException {
    AnnotationProcessingScenario scenario = new AnnotationProcessingScenario();
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_PREBUILT_JAR);
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_JAVA_BINARY);
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_JAVA_LIBRARY);

    scenario.getAnnotationProcessingParamsBuilder()
        .addAllProcessors(ImmutableList.of("MyProcessor"));

    ImmutableList<String> parameters = scenario.buildAndGetCompileParameters();

    MoreAsserts.assertContainsOne(parameters, "-processorpath");
    MoreAsserts.assertContainsOne(parameters, "-processor");
    assertHasProcessor(parameters, "MyProcessor");
    MoreAsserts.assertContainsOne(parameters, "-s");
    MoreAsserts.assertContainsOne(parameters, annotationScenarioGenPath);
  }

  @Test
  public void testGetClasspathEntriesMap() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    BuildRule libraryOne = JavaLibraryBuilder.createBuilder(libraryOneTarget)
        .addSrc(Paths.get("java/src/com/libone/Bar.java"))
        .build(ruleResolver);

    BuildTarget libraryTwoTarget = BuildTargetFactory.newInstance("//:libtwo");
    BuildRule libraryTwo = JavaLibraryBuilder
        .createBuilder(libraryTwoTarget)
        .addSrc(Paths.get("java/src/com/libtwo/Foo.java"))
        .addDep(libraryOne.getBuildTarget())
        .build(ruleResolver);

    BuildTarget parentTarget = BuildTargetFactory.newInstance("//:parent");
    BuildRule parent = JavaLibraryBuilder
        .createBuilder(parentTarget)
        .addSrc(Paths.get("java/src/com/parent/Meh.java"))
        .addDep(libraryTwo.getBuildTarget())
        .build(ruleResolver);

    assertEquals(
        ImmutableSetMultimap.of(
            getJavaLibrary(libraryOne),
            Paths.get("buck-out/gen/lib__libone__output/libone.jar"),
            getJavaLibrary(libraryTwo),
            Paths.get("buck-out/gen/lib__libtwo__output/libtwo.jar"),
            getJavaLibrary(parent),
            Paths.get("buck-out/gen/lib__parent__output/parent.jar")),
        ((HasClasspathEntries) parent).getTransitiveClasspathEntries());
  }

  @Test
  public void testClasspathForJavacCommand() throws IOException {
    // libraryOne responds like an ordinary prebuilt_jar with no dependencies. We have to use a
    // FakeJavaLibraryRule so that we can override the behavior of getAbiKey().
    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    FakeJavaLibrary libraryOne = new FakeJavaLibrary(
        libraryOneTarget,
        new SourcePathResolver(new BuildRuleResolver())) {
      @Override
      public Sha1HashCode getAbiKey() {
        return ImmutableSha1HashCode.of(Strings.repeat("cafebabe", 5));
      }

      @Override
      public ImmutableSetMultimap<JavaLibrary, Path> getDeclaredClasspathEntries() {
        return ImmutableSetMultimap.of(
            (JavaLibrary) this,
            Paths.get("java/src/com/libone/bar.jar"));
      }

      @Override
      public ImmutableSetMultimap<JavaLibrary, Path> getOutputClasspathEntries() {
        return ImmutableSetMultimap.of(
            (JavaLibrary) this,
            Paths.get("java/src/com/libone/bar.jar"));
      }

      @Override
      public ImmutableSetMultimap<JavaLibrary, Path> getTransitiveClasspathEntries() {
        return ImmutableSetMultimap.of();
      }
    };

    Map<BuildTarget, BuildRule> buildRuleIndex = Maps.newHashMap();
    buildRuleIndex.put(libraryOneTarget, libraryOne);
    BuildRuleResolver ruleResolver = new BuildRuleResolver(buildRuleIndex);

    BuildTarget libraryTwoTarget = BuildTargetFactory.newInstance("//:libtwo");
    BuildRule libraryTwo = JavaLibraryBuilder
        .createBuilder(libraryTwoTarget)
        .addSrc(Paths.get("java/src/com/libtwo/Foo.java"))
        .addDep(libraryOne.getBuildTarget())
        .build(ruleResolver);

    BuildContext buildContext = EasyMock.createMock(BuildContext.class);
    expect(buildContext.getBuildDependencies()).andReturn(BuildDependencies.FIRST_ORDER_ONLY)
        .times(2);
    JavaPackageFinder javaPackageFinder = EasyMock.createMock(JavaPackageFinder.class);
    expect(buildContext.getJavaPackageFinder()).andReturn(javaPackageFinder);

    replay(buildContext, javaPackageFinder);

    List<Step> steps = libraryTwo.getBuildSteps(buildContext, new FakeBuildableContext());

    EasyMock.verify(buildContext, javaPackageFinder);

    ImmutableList<JavacStep> javacSteps = FluentIterable
        .from(steps)
        .filter(JavacStep.class)
        .toList();
    assertEquals("There should be only one javac step.", 1, javacSteps.size());
    JavacStep javacStep = javacSteps.get(0);
    assertEquals(
        "The classpath to use when compiling //:libtwo according to getDeclaredClasspathEntries()" +
            " should contain only bar.jar.",
        ImmutableSet.of(Paths.get("java/src/com/libone/bar.jar")),
        ImmutableSet.copyOf(
            ((JavaLibrary) libraryTwo).getDeclaredClasspathEntries().values()));
    assertEquals(
        "The classpath for the javac step to compile //:libtwo should contain only bar.jar.",
        ImmutableSet.of(Paths.get("java/src/com/libone/bar.jar")),
        javacStep.getClasspathEntries());
  }

  /**
   * Verify adding an annotation processor java binary with options.
   */
  @Test
  public void testAddAnnotationProcessorWithOptions() throws IOException {
    AnnotationProcessingScenario scenario = new AnnotationProcessingScenario();
    scenario.addAnnotationProcessorTarget(AnnotationProcessorTarget.VALID_JAVA_BINARY);

    scenario.getAnnotationProcessingParamsBuilder().addAllProcessors(
        ImmutableList.of("MyProcessor"));
    scenario.getAnnotationProcessingParamsBuilder().addParameter("MyParameter");
    scenario.getAnnotationProcessingParamsBuilder().addParameter("MyKey=MyValue");
    scenario.getAnnotationProcessingParamsBuilder().setProcessOnly(true);

    ImmutableList<String> parameters = scenario.buildAndGetCompileParameters();

    MoreAsserts.assertContainsOne(parameters, "-processorpath");
    MoreAsserts.assertContainsOne(parameters, "-processor");
    assertHasProcessor(parameters, "MyProcessor");
    MoreAsserts.assertContainsOne(parameters, "-s");
    MoreAsserts.assertContainsOne(parameters, annotationScenarioGenPath);
    MoreAsserts.assertContainsOne(parameters, "-proc:only");

    assertEquals(
        "Expected '-processor MyProcessor' parameters",
        parameters.indexOf("-processor") + 1,
        parameters.indexOf("MyProcessor"));
    assertEquals(
        "Expected '-s " + annotationScenarioGenPath + "' parameters",
        parameters.indexOf("-s") + 1,
        parameters.indexOf(annotationScenarioGenPath));

    MoreAsserts.assertContainsOne(parameters, "-AMyParameter");
    MoreAsserts.assertContainsOne(parameters, "-AMyKey=MyValue");
  }

  private void assertHasProcessor(List<String> params, String processor) {
    int index = params.indexOf("-processor");
    if (index >= params.size()) {
      fail(String.format("No processor argument found in %s.", params));
    }

    Set<String> processors = ImmutableSet.copyOf(Splitter.on(',').split(params.get(index + 1)));
    if (!processors.contains(processor)) {
      fail(String.format("Annotation processor %s not found in %s.", processor, params));
    }
  }

  @Test
  public void testExportedDeps() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget nonIncludedTarget = BuildTargetFactory.newInstance("//:not_included");
    BuildRule notIncluded = JavaLibraryBuilder
        .createBuilder(nonIncludedTarget)
        .addSrc(Paths.get("java/src/com/not_included/Raz.java"))
        .build(ruleResolver);

    BuildTarget includedTarget = BuildTargetFactory.newInstance("//:included");
    BuildRule included = JavaLibraryBuilder
        .createBuilder(includedTarget)
        .addSrc(Paths.get("java/src/com/included/Rofl.java"))
        .build(ruleResolver);

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    BuildRule libraryOne = JavaLibraryBuilder
        .createBuilder(libraryOneTarget)
        .addDep(notIncluded.getBuildTarget())
        .addDep(included.getBuildTarget())
        .addExportedDep(included.getBuildTarget())
        .addSrc(Paths.get("java/src/com/libone/Bar.java"))
        .build(ruleResolver);

    BuildTarget libraryTwoTarget = BuildTargetFactory.newInstance("//:libtwo");
    BuildRule libraryTwo = JavaLibraryBuilder
        .createBuilder(libraryTwoTarget)
        .addSrc(Paths.get("java/src/com/libtwo/Foo.java"))
        .addDep(libraryOne.getBuildTarget())
        .addExportedDep(libraryOne.getBuildTarget())
        .build(ruleResolver);

    BuildTarget parentTarget = BuildTargetFactory.newInstance("//:parent");
    BuildRule parent = JavaLibraryBuilder
        .createBuilder(parentTarget)
        .addSrc(Paths.get("java/src/com/parent/Meh.java"))
        .addDep(libraryTwo.getBuildTarget())
        .build(ruleResolver);

    assertEquals(
        "A java_library that depends on //:libone should include only libone.jar in its " +
            "classpath when compiling itself.",
        ImmutableSetMultimap.of(
            getJavaLibrary(notIncluded),
            Paths.get("buck-out/gen/lib__not_included__output/not_included.jar")),
        getJavaLibrary(notIncluded).getOutputClasspathEntries());

    assertEquals(
        ImmutableSetMultimap.of(
            getJavaLibrary(included),
            Paths.get("buck-out/gen/lib__included__output/included.jar")),
        getJavaLibrary(included).getOutputClasspathEntries());

    assertEquals(
        ImmutableSetMultimap.of(
            getJavaLibrary(included),
            Paths.get("buck-out/gen/lib__included__output/included.jar"),
            getJavaLibrary(libraryOne),
            Paths.get("buck-out/gen/lib__libone__output/libone.jar"),
            getJavaLibrary(libraryOne),
            Paths.get("buck-out/gen/lib__included__output/included.jar")),
        getJavaLibrary(libraryOne).getOutputClasspathEntries());

    assertEquals(
        "//:libtwo exports its deps, so a java_library that depends on //:libtwo should include " +
            "both libone.jar and libtwo.jar in its classpath when compiling itself.",
        ImmutableSetMultimap.of(
            getJavaLibrary(libraryOne),
            Paths.get("buck-out/gen/lib__libone__output/libone.jar"),
            getJavaLibrary(libraryOne),
            Paths.get("buck-out/gen/lib__included__output/included.jar"),
            getJavaLibrary(libraryTwo),
            Paths.get("buck-out/gen/lib__libone__output/libone.jar"),
            getJavaLibrary(libraryTwo),
            Paths.get("buck-out/gen/lib__libtwo__output/libtwo.jar"),
            getJavaLibrary(libraryTwo),
            Paths.get("buck-out/gen/lib__included__output/included.jar")),
        getJavaLibrary(libraryTwo).getOutputClasspathEntries());

    assertEquals(
        "A java_binary that depends on //:parent should include libone.jar, libtwo.jar and " +
            "parent.jar.",
        ImmutableSetMultimap.<JavaLibrary, Path>builder()
            .put(
                getJavaLibrary(included),
                Paths.get("buck-out/gen/lib__included__output/included.jar"))
            .put(
                getJavaLibrary(notIncluded),
                Paths.get("buck-out/gen/lib__not_included__output/not_included.jar"))
            .putAll(
                getJavaLibrary(libraryOne),
                Paths.get("buck-out/gen/lib__included__output/included.jar"),
                Paths.get("buck-out/gen/lib__libone__output/libone.jar"))
            .putAll(
                getJavaLibrary(libraryTwo),
                Paths.get("buck-out/gen/lib__included__output/included.jar"),
                Paths.get("buck-out/gen/lib__not_included__output/not_included.jar"),
                Paths.get("buck-out/gen/lib__libone__output/libone.jar"),
                Paths.get("buck-out/gen/lib__libtwo__output/libtwo.jar"))
            .put(getJavaLibrary(parent), Paths.get("buck-out/gen/lib__parent__output/parent.jar"))
            .build(),
        getJavaLibrary(parent).getTransitiveClasspathEntries());

    assertEquals(
        "A java_library that depends on //:parent should include only parent.jar in its " +
            "-classpath when compiling itself.",
        ImmutableSetMultimap.of(
            getJavaLibrary(parent),
            Paths.get("buck-out/gen/lib__parent__output/parent.jar")),
        getJavaLibrary(parent).getOutputClasspathEntries());
  }

  /**
   * Tests that an error is thrown when non-java library rules are listed in the exported deps
   * parameter.
   */
  @Test
  public void testExportedDepsShouldOnlyContainJavaLibraryRules() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget genruleBuildTarget = BuildTargetFactory.newInstance("//generated:stuff");
    BuildRule genrule = GenruleBuilder
        .newGenruleBuilder(genruleBuildTarget)
        .setBash("echo 'aha' > $OUT")
        .setOut("stuff.txt")
        .build(ruleResolver);

    String commonLibAbiKeyHash = Strings.repeat("a", 40);
    BuildTarget buildTarget = BuildTargetFactory.newInstance("//:lib");

    try {
      createDefaultJavaLibaryRuleWithAbiKey(
          commonLibAbiKeyHash,
          buildTarget,
          // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
          /* srcs */ ImmutableSortedSet.of("foo/Bar.java"),
          /* deps */ ImmutableSortedSet.<BuildRule>of(),
          /* exportedDeps */ ImmutableSortedSet.of(genrule));
      fail("A non-java library listed as exported dep should have thrown.");
    } catch (HumanReadableException e) {
      String expected =
          buildTarget + ": exported dep " +
          genruleBuildTarget + " (" + genrule.getType() + ") " +
          "must be a type of java library.";
      assertEquals(expected, e.getMessage());
    }

  }

  /**
   * Tests DefaultJavaLibraryRule#getAbiKeyForDeps() when the dependencies contain a JavaAbiRule
   * that is not a JavaLibraryRule.
   */
  @Test
  public void testGetAbiKeyForDepsWithMixedDeps() throws IOException {
    String tinyLibAbiKeyHash = Strings.repeat("a", 40);
    BuildRule tinyLibrary = createDefaultJavaLibaryRuleWithAbiKey(
        tinyLibAbiKeyHash,
        BuildTargetFactory.newInstance("//:tinylib"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.<BuildRule>of(),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    String javaAbiRuleKeyHash = Strings.repeat("b", 40);
    FakeJavaAbiRule fakeJavaAbiRule = new FakeJavaAbiRule(
        AndroidResourceDescription.TYPE,
        BuildTargetFactory.newInstance("//:tinylibfakejavaabi"),
        javaAbiRuleKeyHash);

    BuildRule defaultJavaLibary = createDefaultJavaLibaryRuleWithAbiKey(
        Strings.repeat("c", 40),
        BuildTargetFactory.newInstance("//:javalib"),
        /* srcs */ ImmutableSet.<String>of(),
        /* deps */ ImmutableSortedSet.of(tinyLibrary, fakeJavaAbiRule),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    Hasher hasher = Hashing.sha1().newHasher();
    hasher.putUnencodedChars(tinyLibAbiKeyHash);
    hasher.putUnencodedChars(javaAbiRuleKeyHash);

    assertEquals(
        ImmutableSha1HashCode.of(hasher.hash().toString()),
        ((AbiRule) defaultJavaLibary).getAbiKeyForDeps());
  }

  /**
   * @see com.facebook.buck.rules.AbiRule#getAbiKeyForDeps()
   */
  @Test
  public void testGetAbiKeyForDepsInThePresenceOfExportedDeps() throws IOException {
    // Create a java_library named //:tinylib with a hardcoded ABI key.
    String tinyLibAbiKeyHash = Strings.repeat("a", 40);
    BuildRule tinyLibrary = createDefaultJavaLibaryRuleWithAbiKey(
        tinyLibAbiKeyHash,
        BuildTargetFactory.newInstance("//:tinylib"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.<BuildRule>of(),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    // Create two java_library rules, each of which depends on //:tinylib, but only one of which
    // exports its deps.
    String commonWithExportAbiKeyHash = Strings.repeat("b", 40);
    BuildRule commonWithExport = createDefaultJavaLibaryRuleWithAbiKey(
        commonWithExportAbiKeyHash,
        BuildTargetFactory.newInstance("//:common_with_export"),
        /* srcs */ ImmutableSet.<String>of(),
        /* deps */ ImmutableSortedSet.of(tinyLibrary),
        /* exportedDeps */ ImmutableSortedSet.of(tinyLibrary));
    BuildRule commonNoExport = createDefaultJavaLibaryRuleWithAbiKey(
        /* abiHash */ null,
        BuildTargetFactory.newInstance("//:common_no_export"),
        /* srcs */ ImmutableSet.<String>of(),
        /* deps */ ImmutableSortedSet.of(tinyLibrary),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    // Verify getAbiKeyForDeps() for the two //:common_XXX rules.
    assertEquals(
        "getAbiKeyForDeps() should be the same for both rules because they have the same deps.",
        ((AbiRule) commonNoExport).getAbiKeyForDeps(),
        ((AbiRule) commonWithExport).getAbiKeyForDeps());
    String expectedAbiKeyForDepsHash = Hashing.sha1().newHasher()
        .putUnencodedChars(tinyLibAbiKeyHash).hash().toString();
    String observedAbiKeyForDepsHash =
        ((AbiRule) commonNoExport).getAbiKeyForDeps().getHash();
    assertEquals(expectedAbiKeyForDepsHash, observedAbiKeyForDepsHash);

    // Create a BuildRuleResolver populated with the three build rules we created thus far.
    Map<BuildTarget, BuildRule> buildRuleIndex = Maps.newHashMap();
    buildRuleIndex.put(tinyLibrary.getBuildTarget(), tinyLibrary);
    buildRuleIndex.put(commonWithExport.getBuildTarget(), commonWithExport);
    buildRuleIndex.put(commonNoExport.getBuildTarget(), commonNoExport);
    BuildRuleResolver ruleResolver = new BuildRuleResolver(buildRuleIndex);

    // Create two rules, each of which depends on one of the //:common_XXX rules.
    BuildRule consumerNoExport = JavaLibraryBuilder
        .createBuilder(BuildTargetFactory.newInstance("//:consumer_no_export"))
        .addDep(commonNoExport.getBuildTarget())
        .build(ruleResolver);
    BuildRule consumerWithExport = JavaLibraryBuilder
        .createBuilder(BuildTargetFactory.newInstance("//:consumer_with_export"))
        .addDep(commonWithExport.getBuildTarget())
        .build(ruleResolver);

    // Verify getAbiKeyForDeps() for the two //:consumer_XXX rules.

    // This differs from the EMPTY_ABI_KEY in that the value of that comes from the SHA1 of an empty
    // jar file, whereas this is constructed from the empty set of values.
    Sha1HashCode noAbiDeps = ImmutableSha1HashCode.of(Hashing.sha1().newHasher().hash().toString());
    assertEquals(
        "The ABI of the deps of //:consumer_no_export should be the empty ABI.",
        noAbiDeps,
        ((AbiRule) consumerNoExport).getAbiKeyForDeps());
    assertThat(
        "Although //:consumer_no_export and //:consumer_with_export have the same deps, " +
        "the ABIs of their deps will differ because of the use of exported_deps is non-empty",
        ((AbiRule) consumerNoExport).getAbiKeyForDeps(),
        not(equalTo(((AbiRule) consumerWithExport).getAbiKeyForDeps())));
    String expectedAbiKeyNoDepsHashForConsumerWithExport = Hashing.sha1().newHasher()
        .putUnencodedChars(((HasJavaAbi) commonWithExport).getAbiKey().getHash())
        .putUnencodedChars(tinyLibAbiKeyHash)
        .hash()
        .toString();
    String observedAbiKeyNoDepsHashForConsumerWithExport =
        ((AbiRule) consumerWithExport).getAbiKeyForDeps()
        .getHash();
    assertEquals(
        "By hardcoding the ABI keys for the deps, we made getAbiKeyForDeps() a predictable value.",
        expectedAbiKeyNoDepsHashForConsumerWithExport,
        observedAbiKeyNoDepsHashForConsumerWithExport);
  }

  /**
   * @see DefaultJavaLibrary#getAbiKey()
   */
  @Test
  public void testGetAbiKeyInThePresenceOfExportedDeps() throws IOException {
    // Create a java_library named //:commonlib with a hardcoded ABI key.
    String commonLibAbiKeyHash = Strings.repeat("a", 40);
    BuildRule commonLibrary = createDefaultJavaLibaryRuleWithAbiKey(
        commonLibAbiKeyHash,
        BuildTargetFactory.newInstance("//:commonlib"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSortedSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.<BuildRule>of(),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    // Create two java_library rules, each of which depends on //:commonlib, but only one of which
    // exports its deps.
    String libWithExportAbiKeyHash = Strings.repeat("b", 40);
    BuildRule libWithExport = createDefaultJavaLibaryRuleWithAbiKey(
        libWithExportAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_with_export"),
        /* srcs */ ImmutableSet.<String>of(),
        /* deps */ ImmutableSortedSet.of(commonLibrary),
        /* exportedDeps */ ImmutableSortedSet.of(commonLibrary));
    String libNoExportAbiKeyHash = Strings.repeat("c", 40);
    BuildRule libNoExport = createDefaultJavaLibaryRuleWithAbiKey(
        /* abiHash */ libNoExportAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_no_export"),
        /* srcs */ ImmutableSet.<String>of(),
        /* deps */ ImmutableSortedSet.of(commonLibrary),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());

    // Verify getAbiKey() for the two //:lib_XXX rules.
    String expectedLibWithExportAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(commonLibAbiKeyHash)
        .putUnencodedChars(libWithExportAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "getAbiKey() should include the dependencies' ABI keys for the rule with export_deps=true.",
        expectedLibWithExportAbiKeyHash,
        ((HasJavaAbi) libWithExport).getAbiKey().getHash());

    assertEquals(
        "getAbiKey() should not include the dependencies' ABI keys for the rule with " +
            "export_deps=false.",
        libNoExportAbiKeyHash,
        ((HasJavaAbi) libNoExport).getAbiKey().getHash());
  }

  /**
   * @see DefaultJavaLibrary#getAbiKey()
   */
  @Test
  public void testGetAbiKeyRecursiveExportedDeps() throws IOException {
    String libAAbiKeyHash = Strings.repeat("a", 40);
    String libBAbiKeyHash = Strings.repeat("b", 40);
    String libCAbiKeyHash = Strings.repeat("c", 40);
    String libDAbiKeyHash = Strings.repeat("d", 40);

    // Test the following dependency graph:
    // a(export_deps=true) -> b(export_deps=true) -> c(export_deps=true) -> d(export_deps=true)
    BuildRule libD = createDefaultJavaLibaryRuleWithAbiKey(
        libDAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_d"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.<BuildRule>of(),
        /* exporedtDeps */ ImmutableSortedSet.<BuildRule>of());
    BuildRule libC = createDefaultJavaLibaryRuleWithAbiKey(
        libCAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_c"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libD),
        /* exporedtDeps */ ImmutableSortedSet.of(libD));
    BuildRule libB = createDefaultJavaLibaryRuleWithAbiKey(
        libBAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_b"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libC),
        /* exportedDeps */ ImmutableSortedSet.of(libC));
    BuildRule libA = createDefaultJavaLibaryRuleWithAbiKey(
        libAAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_a"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libB),
        /* exportedDeps */ ImmutableSortedSet.of(libB));

    assertEquals(
        "If a rule has no dependencies its final ABI key should be the rule's own ABI key.",
        libDAbiKeyHash,
        ((HasJavaAbi) libD).getAbiKey().getHash());

    String expectedLibCAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(libDAbiKeyHash)
        .putUnencodedChars(libCAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "The ABI key for lib_c should contain lib_d's ABI key.",
        expectedLibCAbiKeyHash,
        ((HasJavaAbi) libC).getAbiKey().getHash());

    String expectedLibBAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(expectedLibCAbiKeyHash)
        .putUnencodedChars(libDAbiKeyHash)
        .putUnencodedChars(libBAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "The ABI key for lib_b should contain lib_c's and lib_d's ABI keys.",
        expectedLibBAbiKeyHash,
        ((HasJavaAbi) libB).getAbiKey().getHash());

    String expectedLibAAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(expectedLibBAbiKeyHash)
        .putUnencodedChars(expectedLibCAbiKeyHash)
        .putUnencodedChars(libAAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "The ABI key for lib_a should contain lib_b's, lib_c's and lib_d's ABI keys.",
        expectedLibAAbiKeyHash,
        ((HasJavaAbi) libA).getAbiKey().getHash());

    // Test the following dependency graph:
    // a(export_deps=true) -> b(export_deps=true) -> c(export_deps=false) -> d(export_deps=false)
    libD = createDefaultJavaLibaryRuleWithAbiKey(
        libDAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_d2"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.<BuildRule>of(),
        /* exportedDeps */ ImmutableSortedSet.<BuildRule>of());
    libC = createDefaultJavaLibaryRuleWithAbiKey(
        libCAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_c2"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libD),
        /* exportDeps */ ImmutableSortedSet.<BuildRule>of());
    libB = createDefaultJavaLibaryRuleWithAbiKey(
        libBAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_b2"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libC),
        /* exportedDeps */ ImmutableSortedSet.of(libC));
    libA = createDefaultJavaLibaryRuleWithAbiKey(
        libAAbiKeyHash,
        BuildTargetFactory.newInstance("//:lib_a2"),
        // Must have a source file or else its ABI will be AbiWriterProtocol.EMPTY_ABI_KEY.
        /* srcs */ ImmutableSet.of("foo/Bar.java"),
        /* deps */ ImmutableSortedSet.of(libB),
        /* exportedDeps */ ImmutableSortedSet.of(libB));

    assertEquals(
        "If export_deps is false, the final ABI key should be the rule's own ABI key.",
        libDAbiKeyHash,
        ((HasJavaAbi) libD).getAbiKey().getHash());

    assertEquals(
        "If export_deps is false, the final ABI key should be the rule's own ABI key.",
        libCAbiKeyHash,
        ((HasJavaAbi) libC).getAbiKey().getHash());

    expectedLibBAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(libCAbiKeyHash)
        .putUnencodedChars(libBAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "The ABI key for lib_b should contain lib_c's ABI key.",
        expectedLibBAbiKeyHash,
        ((HasJavaAbi) libB).getAbiKey().getHash());

    expectedLibAAbiKeyHash = Hashing.sha1().newHasher()
        .putUnencodedChars(expectedLibBAbiKeyHash)
        .putUnencodedChars(libCAbiKeyHash)
        .putUnencodedChars(libAAbiKeyHash)
        .hash()
        .toString();
    assertEquals(
        "The ABI key for lib_a should contain lib_b's, lib_c's and lib_d's ABI keys.",
        expectedLibAAbiKeyHash,
        ((HasJavaAbi) libA).getAbiKey().getHash());

  }

  private static BuildRule createDefaultJavaLibaryRuleWithAbiKey(
      @Nullable final String partialAbiHash,
      BuildTarget buildTarget,
      ImmutableSet<String> srcs,
      ImmutableSortedSet<BuildRule> deps,
      ImmutableSortedSet<BuildRule> exportedDeps) {
    ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
    ImmutableSortedSet<SourcePath> srcsAsPaths = FluentIterable.from(srcs)
        .transform(MorePaths.TO_PATH)
        .transform(SourcePaths.toSourcePath(projectFilesystem))
        .toSortedSet(Ordering.natural());

    BuildRuleParams buildRuleParams = new FakeBuildRuleParamsBuilder(buildTarget)
        .setDeps(ImmutableSortedSet.copyOf(deps))
        .setType(JavaLibraryDescription.TYPE)
        .build();

    return new DefaultJavaLibrary(
        buildRuleParams,
        new SourcePathResolver(new BuildRuleResolver()),
        srcsAsPaths,
        /* resources */ ImmutableSet.<SourcePath>of(),
        /* proguardConfig */ Optional.<Path>absent(),
        /* postprocessClassesCommands */ ImmutableList.<String>of(),
        exportedDeps,
        /* providedDeps */ ImmutableSortedSet.<BuildRule>of(),
        /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
        DEFAULT_JAVAC_OPTIONS,
        /* resourcesRoot */ Optional.<Path>absent()) {
      @Override
      public Sha1HashCode getAbiKey() {
        if (partialAbiHash == null) {
          return super.getAbiKey();
        } else {
          return createTotalAbiKey(ImmutableSha1HashCode.of(partialAbiHash));
        }
      }
    };
  }

  @Test
  public void testEmptySuggestBuildFunction() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    JavaLibrary libraryOne = (JavaLibrary) JavaLibraryBuilder
        .createBuilder(libraryOneTarget)
        .addSrc(Paths.get("java/src/com/libone/bar.java"))
        .build(ruleResolver);

    BuildContext context = createSuggestContext(ruleResolver,
        BuildDependencies.FIRST_ORDER_ONLY);

    ImmutableSetMultimap<JavaLibrary, Path> classpathEntries =
        libraryOne.getTransitiveClasspathEntries();

    assertEquals(
        Optional.<JavacStep.SuggestBuildRules>absent(),
        ((DefaultJavaLibrary) libraryOne).createSuggestBuildFunction(
            context,
            classpathEntries,
            classpathEntries,
            createJarResolver(/* classToSymbols */ImmutableMap.<Path, String>of())));

    EasyMock.verify(context);
  }

  @Test
  public void testSuggsetDepsReverseTopoSortRespected() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();
    ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmp.getRoot().toPath());

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    BuildRule libraryOne = JavaLibraryBuilder
        .createBuilder(libraryOneTarget)
        .addSrc(Paths.get("java/src/com/libone/Bar.java"))
        .build(ruleResolver);

    BuildTarget libraryTwoTarget = BuildTargetFactory.newInstance("//:libtwo");
    BuildRule libraryTwo = JavaLibraryBuilder
        .createBuilder(libraryTwoTarget)
        .addSrc(Paths.get("java/src/com/libtwo/Foo.java"))
        .addDep(libraryOne.getBuildTarget())
        .build(ruleResolver);

    BuildTarget parentTarget = BuildTargetFactory.newInstance("//:parent");
    BuildRule parent = JavaLibraryBuilder
        .createBuilder(parentTarget)
        .addSrc(Paths.get("java/src/com/parent/Meh.java"))
        .addDep(libraryTwo.getBuildTarget())
        .build(ruleResolver);

    BuildTarget grandparentTarget = BuildTargetFactory.newInstance("//:grandparent");
    BuildRule grandparent = JavaLibraryBuilder
        .createBuilder(grandparentTarget)
        .addSrc(Paths.get("java/src/com/parent/OldManRiver.java"))
        .addDep(parent.getBuildTarget())
        .build(ruleResolver);

    BuildContext context = createSuggestContext(ruleResolver,
        BuildDependencies.WARN_ON_TRANSITIVE);

    ImmutableSetMultimap<JavaLibrary, Path> transitive =
        ((HasClasspathEntries) parent).getTransitiveClasspathEntries();

    ImmutableMap<Path, String> classToSymbols = ImmutableMap.of(
        Iterables.getFirst(transitive.get((JavaLibrary) parent), null),
        "com.facebook.Foo",
        Iterables.getFirst(transitive.get((JavaLibrary) libraryOne), null),
        "com.facebook.Bar",
        Iterables.getFirst(transitive.get((JavaLibrary) libraryTwo), null),
        "com.facebook.Foo");

    Optional<JavacStep.SuggestBuildRules> suggestFn =
        ((DefaultJavaLibrary) grandparent).createSuggestBuildFunction(
            context,
            transitive,
            /* declaredClasspathEntries */ ImmutableSetMultimap.<JavaLibrary, Path>of(),
            createJarResolver(classToSymbols));

    assertTrue(suggestFn.isPresent());
    assertEquals(ImmutableSet.of("//:parent", "//:libone"),
                 suggestFn.get().suggest(
                     projectFilesystem,
                     ImmutableSet.of("com.facebook.Foo", "com.facebook.Bar")));

    EasyMock.verify(context);
  }

  @Test
  public void testRuleKeyIsOrderInsensitiveForSourcesAndResources() throws IOException {
    // Note that these filenames were deliberately chosen to have identical hashes to maximize
    // the chance of order-sensitivity when being inserted into a HashMap.  Just using
    // {foo,bar}.{java,txt} resulted in a passing test even for the old broken code.

    ProjectFilesystem filesystem = new AllExistingProjectFilesystem() {
      @Override
      public boolean isDirectory(Path path, LinkOption... linkOptionsk) {
        return false;
      }
    };
    BuildRuleResolver resolver1 = new BuildRuleResolver();
    SourcePathResolver pathResolver1 = new SourcePathResolver(resolver1);
    DefaultJavaLibrary rule1 = (DefaultJavaLibrary) JavaLibraryBuilder
        .createBuilder(BuildTargetFactory.newInstance("//lib:lib"))
        .addSrc(Paths.get("agifhbkjdec.java"))
        .addSrc(Paths.get("bdeafhkgcji.java"))
        .addSrc(Paths.get("bdehgaifjkc.java"))
        .addSrc(Paths.get("cfiabkjehgd.java"))
        .addResource(new TestSourcePath("becgkaifhjd.txt"))
        .addResource(new TestSourcePath("bkhajdifcge.txt"))
        .addResource(new TestSourcePath("cabfghjekid.txt"))
        .addResource(new TestSourcePath("chkdbafijge.txt"))
        .build(resolver1, filesystem);

    BuildRuleResolver resolver2 = new BuildRuleResolver();
    SourcePathResolver pathResolver2 = new SourcePathResolver(resolver2);
    DefaultJavaLibrary rule2 = (DefaultJavaLibrary) JavaLibraryBuilder
        .createBuilder(BuildTargetFactory.newInstance("//lib:lib"))
        .addSrc(Paths.get("cfiabkjehgd.java"))
        .addSrc(Paths.get("bdehgaifjkc.java"))
        .addSrc(Paths.get("bdeafhkgcji.java"))
        .addSrc(Paths.get("agifhbkjdec.java"))
        .addResource(new TestSourcePath("chkdbafijge.txt"))
        .addResource(new TestSourcePath("cabfghjekid.txt"))
        .addResource(new TestSourcePath("bkhajdifcge.txt"))
        .addResource(new TestSourcePath("becgkaifhjd.txt"))
        .build(resolver2, filesystem);

    Iterable<Path> inputs1 = rule1.getInputsToCompareToOutput();
    Iterable<Path> inputs2 = rule2.getInputsToCompareToOutput();
    assertEquals(ImmutableList.copyOf(inputs1), ImmutableList.copyOf(inputs2));

    ImmutableMap.Builder<String, String> fileHashes = ImmutableMap.builder();
    for (String filename : ImmutableList.of(
        "agifhbkjdec.java", "bdeafhkgcji.java", "bdehgaifjkc.java", "cfiabkjehgd.java",
        "becgkaifhjd.txt", "bkhajdifcge.txt", "cabfghjekid.txt", "chkdbafijge.txt")) {
      fileHashes.put(filename, Hashing.sha1().hashString(filename, Charsets.UTF_8).toString());
    }
    RuleKeyBuilderFactory ruleKeyBuilderFactory =
        new FakeRuleKeyBuilderFactory(FakeFileHashCache.createFromStrings(fileHashes.build()));

    RuleKey.Builder builder1 = ruleKeyBuilderFactory.newInstance(rule1, pathResolver1);
    RuleKey.Builder builder2 = ruleKeyBuilderFactory.newInstance(rule2, pathResolver2);
    rule1.appendToRuleKey(builder1);
    rule2.appendToRuleKey(builder2);
    RuleKey.Builder.RuleKeyPair pair1 = builder1.build();
    RuleKey.Builder.RuleKeyPair pair2 = builder2.build();
    assertEquals(pair1.getTotalRuleKey(), pair2.getTotalRuleKey());
    assertEquals(pair1.getRuleKeyWithoutDeps(), pair2.getRuleKeyWithoutDeps());
  }

  @Test
  public void testWhenNoJavacIsProvidedAJavacInMemoryStepIsAdded() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    BuildRule rule = JavaLibraryBuilder
        .createBuilder(libraryOneTarget)
        .addSrc(Paths.get("java/src/com/libone/Bar.java"))
        .build(ruleResolver);
    DefaultJavaLibrary buildable = (DefaultJavaLibrary) rule;

    ImmutableList.Builder<Step> stepsBuilder = ImmutableList.builder();
    buildable.createCommandsForJavac(
        buildable.getPathToOutputFile(),
        ImmutableSet.copyOf(buildable.getTransitiveClasspathEntries().values()),
        ImmutableSet.copyOf(buildable.getDeclaredClasspathEntries().values()),
        DEFAULT_JAVAC_OPTIONS,
        BuildDependencies.FIRST_ORDER_ONLY,
        Optional.<JavacStep.SuggestBuildRules>absent(),
        stepsBuilder,
        libraryOneTarget);

    List<Step> steps = stepsBuilder.build();
    assertEquals(steps.size(), 3);
    assertTrue(((JavacStep) steps.get(2)).getJavac() instanceof Jsr199Javac);
  }

  @Test
  public void testWhenJavacJarIsProvidedAJavacInMemoryStepIsAdded() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget libraryOneTarget = BuildTargetFactory.newInstance("//:libone");
    Path javacJarPath = Paths.get("java/src/com/libone/JavacJar.jar");
    BuildRule rule = JavaLibraryBuilder
        .createBuilder(libraryOneTarget)
        .addSrc(Paths.get("java/src/com/libone/Bar.java"))
        .setJavacJar(javacJarPath)
        .build(ruleResolver);
    DefaultJavaLibrary buildable = (DefaultJavaLibrary) rule;

    ImmutableList.Builder<Step> stepsBuilder = ImmutableList.builder();
    buildable.createCommandsForJavac(
        buildable.getPathToOutputFile(),
        ImmutableSet.copyOf(buildable.getTransitiveClasspathEntries().values()),
        ImmutableSet.copyOf(buildable.getDeclaredClasspathEntries().values()),
        buildable.getJavacOptions(),
        BuildDependencies.FIRST_ORDER_ONLY,
        Optional.<JavacStep.SuggestBuildRules>absent(),
        stepsBuilder,
        libraryOneTarget);

    List<Step> steps = stepsBuilder.build();
    assertEquals(steps.size(), 3);
    assertTrue(((JavacStep) steps.get(2)).getJavac() instanceof Jsr199Javac);
    Jsr199Javac jsrJavac = ((Jsr199Javac) (((JavacStep) steps.get(2)).getJavac()));
    assertTrue(jsrJavac.getJavacJar().isPresent());
    assertEquals(jsrJavac.getJavacJar().get(), javacJarPath);
  }

  @Test
  public void testAddPostprocessClassesCommands() {
    ImmutableList<String> postprocessClassesCommands = ImmutableList.of("tool arg1", "tool2");
    Path outputDirectory = BIN_PATH.resolve("android/java/lib__java__classes");
    ExecutionContext executionContext = EasyMock.createMock(ExecutionContext.class);
    ImmutableList.Builder<Step> commands = ImmutableList.builder();
    DefaultJavaLibrary.addPostprocessClassesCommands(
        commands,
        postprocessClassesCommands,
        outputDirectory);

    ImmutableList<Step> steps = commands.build();
    assertEquals(2, steps.size());

    assertTrue(steps.get(0) instanceof ShellStep);
    ShellStep step0 = (ShellStep) steps.get(0);
    assertEquals(
        ImmutableList.of("bash", "-c", "tool arg1 " + outputDirectory),
        step0.getShellCommand(executionContext));

    assertTrue(steps.get(1) instanceof ShellStep);
    ShellStep step1 = (ShellStep) steps.get(1);
    assertEquals(
        ImmutableList.of("bash", "-c", "tool2 " + outputDirectory),
        step1.getShellCommand(executionContext));
  }

  // Utilities
  private JavaLibrary getJavaLibrary(BuildRule rule) {
    return (JavaLibrary) rule;
  }

  private DefaultJavaLibrary.JarResolver createJarResolver(
      final ImmutableMap<Path, String> classToSymbols) {

    ImmutableSetMultimap.Builder<Path, String> resolveMapBuilder =
        ImmutableSetMultimap.builder();

    for (Map.Entry<Path, String> entry : classToSymbols.entrySet()) {
      String fullyQualified = entry.getValue();
      String packageName = fullyQualified.substring(0, fullyQualified.lastIndexOf('.'));
      String className = fullyQualified.substring(fullyQualified.lastIndexOf('.'));
      resolveMapBuilder.putAll(entry.getKey(), fullyQualified, packageName, className);
    }

    final ImmutableSetMultimap<Path, String> resolveMap = resolveMapBuilder.build();

    return new DefaultJavaLibrary.JarResolver() {
      @Override
      public ImmutableSet<String> resolve(ProjectFilesystem filesystem, Path relativeClassPath) {
        if (resolveMap.containsKey(relativeClassPath)) {
          return resolveMap.get(relativeClassPath);
        } else {
          return ImmutableSet.of();
        }
      }
    };
  }

  private BuildContext createSuggestContext(BuildRuleResolver ruleResolver,
                                            BuildDependencies buildDependencies) {
    ActionGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);

    BuildContext context = EasyMock.createMock(BuildContext.class);
    expect(context.getActionGraph()).andReturn(graph).anyTimes();

    expect(context.getBuildDependencies()).andReturn(buildDependencies).anyTimes();

    replay(context);

    return context;
  }

  // TODO(mbolin): Eliminate the bootclasspath parameter, as it is completely misused in this test.
  private BuildContext createBuildContext(BuildRule javaLibrary,
                                          @Nullable String bootclasspath,
                                          @Nullable ProjectFilesystem projectFilesystem) {
    AndroidPlatformTarget platformTarget = EasyMock.createMock(AndroidPlatformTarget.class);
    ImmutableList<Path> bootclasspathEntries = (bootclasspath == null)
        ? ImmutableList.of(Paths.get("I am not used"))
        : ImmutableList.of(Paths.get(bootclasspath));
    expect(platformTarget.getBootclasspathEntries()).andReturn(bootclasspathEntries)
        .anyTimes();
    replay(platformTarget);

    if (projectFilesystem == null) {
      projectFilesystem = EasyMock.createMock(ProjectFilesystem.class);
    }

    // TODO(mbolin): Create a utility that populates a BuildContext.Builder with fakes.
    return ImmutableBuildContext.builder()
        .setActionGraph(RuleMap.createGraphFromSingleRule(javaLibrary))
        .setStepRunner(EasyMock.createMock(StepRunner.class))
        .setProjectFilesystem(projectFilesystem)
        .setClock(new DefaultClock())
        .setBuildId(new BuildId())
        .setArtifactCache(new NoopArtifactCache())
        .setBuildDependencies(BuildDependencies.TRANSITIVE)
        .setJavaPackageFinder(EasyMock.createMock(JavaPackageFinder.class))
        .setAndroidBootclasspathSupplier(
            BuildContext.createBootclasspathSupplier(Suppliers.ofInstance(platformTarget)))
        .setEventBus(BuckEventBusFactory.newInstance())
        .build();
  }

  private enum AnnotationProcessorTarget {
    VALID_PREBUILT_JAR("//tools/java/src/com/facebook/library:prebuilt-processors") {
      @Override
      public BuildRule createRule(BuildTarget target) {
        return PrebuiltJarBuilder.createBuilder(target)
            .setBinaryJar(Paths.get("MyJar"))
            .build(new BuildRuleResolver());
      }
    },
    VALID_JAVA_BINARY("//tools/java/src/com/facebook/annotations:custom-processors") {
      @Override
      public BuildRule createRule(BuildTarget target) {
       return new JavaBinaryRuleBuilder(target)
            .setMainClass("com.facebook.Main")
            .build(new BuildRuleResolver());
      }
    },
    VALID_JAVA_LIBRARY("//tools/java/src/com/facebook/somejava:library") {
      @Override
      public BuildRule createRule(BuildTarget target) {
        return JavaLibraryBuilder.createBuilder(target)
            .addSrc(Paths.get("MyClass.java"))
            .setProguardConfig(Paths.get("MyProguardConfig"))
            .build(new BuildRuleResolver());
      }
    };

    private final String targetName;

    private AnnotationProcessorTarget(String targetName) {
      this.targetName = targetName;
    }

    public BuildTarget createTarget() {
      return BuildTargetFactory.newInstance(targetName);
    }

    public abstract BuildRule createRule(BuildTarget target);
  }

  // Captures all the common code between the different annotation processing test scenarios.
  private class AnnotationProcessingScenario {
    private final AnnotationProcessingParams.Builder annotationProcessingParamsBuilder;
    private final Map<BuildTarget, BuildRule> buildRuleIndex;
    private ExecutionContext executionContext;
    private BuildContext buildContext;

    public AnnotationProcessingScenario() throws IOException {
      annotationProcessingParamsBuilder = new AnnotationProcessingParams.Builder();
      buildRuleIndex = Maps.newHashMap();
    }

    public AnnotationProcessingParams.Builder getAnnotationProcessingParamsBuilder() {
      return annotationProcessingParamsBuilder;
    }

    public void addAnnotationProcessorTarget(AnnotationProcessorTarget processor) {
      BuildTarget target = processor.createTarget();
      BuildRule rule = processor.createRule(target);

      annotationProcessingParamsBuilder.addProcessorBuildTarget(rule);
      buildRuleIndex.put(target, rule);
    }

    public ImmutableList<String> buildAndGetCompileParameters() throws IOException {
      ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmp.getRoot().toPath());
      BuildRule javaLibrary = createJavaLibraryRule(projectFilesystem);
      buildContext = createBuildContext(javaLibrary, /* bootclasspath */ null, projectFilesystem);
      List<Step> steps = javaLibrary.getBuildSteps(
          buildContext, new FakeBuildableContext());
      JavacStep javacCommand = lastJavacCommand(steps);

      executionContext = TestExecutionContext.newBuilder()
          .setProjectFilesystem(projectFilesystem)
          .setConsole(new Console(Verbosity.SILENT, System.out, System.err, Ansi.withoutTty()))
          .setDebugEnabled(true)
          .build();

      ImmutableList<String> options = javacCommand.getOptions(executionContext,
          /* buildClasspathEntries */ ImmutableSet.<Path>of());

      return options;
    }

    // TODO(simons): Actually generate a java library rule, rather than an android one.
    private BuildRule createJavaLibraryRule(ProjectFilesystem projectFilesystem)
        throws IOException {
      BuildTarget buildTarget = BuildTargetFactory.newInstance(ANNOTATION_SCENARIO_TARGET);
      annotationProcessingParamsBuilder.setOwnerTarget(buildTarget);
      annotationProcessingParamsBuilder.setProjectFilesystem(projectFilesystem);

      tmp.newFolder("android", "java", "src", "com", "facebook");
      String src = "android/java/src/com/facebook/Main.java";
      tmp.newFile(src);

      AnnotationProcessingParams params = annotationProcessingParamsBuilder.build();
      ImmutableJavacOptions.Builder options = JavacOptions.builder(DEFAULT_JAVAC_OPTIONS)
          .setAnnotationProcessingParams(params);

      BuildRuleParams buildRuleParams = new FakeBuildRuleParamsBuilder(buildTarget)
          .setProjectFilesystem(projectFilesystem)
          .setType(AndroidLibraryDescription.TYPE)
          .build();

      return new AndroidLibrary(
          buildRuleParams,
          new SourcePathResolver(new BuildRuleResolver()),
          ImmutableSet.of(new TestSourcePath(src)),
          /* resources */ ImmutableSet.<SourcePath>of(),
          /* proguardConfig */ Optional.<Path>absent(),
          /* postprocessClassesCommands */ ImmutableList.<String>of(),
          /* exportedDeps */ ImmutableSortedSet.<BuildRule>of(),
          /* providedDeps */ ImmutableSortedSet.<BuildRule>of(),
          /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
          options.build(),
          /* resourcesRoot */ Optional.<Path>absent(),
          /* manifestFile */ Optional.<SourcePath>absent(),
          /* isPrebuiltAar */ false);
    }

    private JavacStep lastJavacCommand(Iterable<Step> commands) {
      Step javac = null;
      for (Step step : commands) {
        if (step instanceof JavacStep) {
          javac = step;
          // Intentionally no break here, since we want the last one.
        }
      }
      assertNotNull("Expected a JavacStep in step list", javac);
      return (JavacStep) javac;
    }
  }

  private static class FakeJavaAbiRule extends FakeBuildRule implements HasJavaAbi {
    private final String abiKeyHash;

    public FakeJavaAbiRule(BuildRuleType type, BuildTarget buildTarget, String abiKeyHash) {
      super(type, buildTarget, new SourcePathResolver(new BuildRuleResolver()));
      this.abiKeyHash = abiKeyHash;
    }

    @Override
    public Sha1HashCode getAbiKey() {
      return ImmutableSha1HashCode.of(abiKeyHash);
    }
  }
}
