@Test
  public void depfileBasedRuleKeyRebuildsAfterChangeToUsedHeaderUsingFileRelativeInclusion()
      throws Exception {
    CxxPlatform cxxPlatform =
        DefaultCxxPlatforms.build(new CxxBuckConfig(FakeBuckConfig.builder().build()));
    BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_used_relative_header");
    String usedHeaderName = "source_relative_header.h";
    String sourceName = "source_relative_header.cpp";
    BuildTarget preprocessTarget =
        getPreprocessTarget(cxxPlatform, target, sourceName, AbstractCxxSource.Type.CXX);

    // Run the build and verify that the C++ source was preprocessed.
    workspace.runBuckBuild("--config", "build.depfiles=true", target.toString()).assertSuccess();
    BuckBuildLog.BuildLogEntry firstRunEntry =
        workspace.getBuildLog().getLogEntry(preprocessTarget);
    assertThat(
        firstRunEntry.getSuccessType(), equalTo(Optional.of(BuildRuleSuccessType.BUILT_LOCALLY)));

    // Modify the used header.
    workspace.writeContentsToPath("static inline int newFunction() { return 20; }", usedHeaderName);

    // Run the build again and verify that we recompiled as the header caused the depfile rule key
    // to change.
    workspace.runBuckBuild("--config", "build.depfiles=true", target.toString()).assertSuccess();
    BuckBuildLog.BuildLogEntry secondRunEntry =
        workspace.getBuildLog().getLogEntry(preprocessTarget);
    assertThat(
        secondRunEntry.getSuccessType(), equalTo(Optional.of(BuildRuleSuccessType.BUILT_LOCALLY)));

    // Also, make sure all three rule keys are actually different.
    assertThat(secondRunEntry.getRuleKey(), Matchers.not(equalTo(firstRunEntry.getRuleKey())));
  }
  @Test
  public void depfileBasedRuleKeyAvoidsRecompilingAfterChangeToUnusedHeader() throws Exception {
    CxxPlatform cxxPlatform =
        DefaultCxxPlatforms.build(new CxxBuckConfig(FakeBuckConfig.builder().build()));
    BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_unused_header");
    String unusedHeaderName = "unused_header.h";
    String sourceName = "source.cpp";
    BuildTarget preprocessTarget =
        getPreprocessTarget(cxxPlatform, target, sourceName, AbstractCxxSource.Type.CXX);

    // Run the build and verify that the C++ source was preprocessed.
    workspace.runBuckBuild("--config", "build.depfiles=true", target.toString()).assertSuccess();
    BuckBuildLog.BuildLogEntry firstRunEntry =
        workspace.getBuildLog().getLogEntry(preprocessTarget);
    assertThat(
        firstRunEntry.getSuccessType(), equalTo(Optional.of(BuildRuleSuccessType.BUILT_LOCALLY)));

    // Now modify the unused header.
    workspace.writeContentsToPath(
        "static inline int newFunction() { return 20; }", unusedHeaderName);

    // Run the build again and verify that got a matching depfile rule key, and therefore
    // didn't recompile.
    workspace.runBuckBuild("--config", "build.depfiles=true", target.toString()).assertSuccess();
    BuckBuildLog.BuildLogEntry secondRunEntry =
        workspace.getBuildLog().getLogEntry(preprocessTarget);
    assertThat(
        secondRunEntry.getSuccessType(),
        equalTo(Optional.of(BuildRuleSuccessType.MATCHING_DEP_FILE_RULE_KEY)));

    // Also, make sure the original rule keys are actually different.
    assertThat(secondRunEntry.getRuleKey(), Matchers.not(equalTo(firstRunEntry.getRuleKey())));
  }
  @Test
  public void inputBasedRuleKeyAvoidsRecompilingAfterChangeToUnusedHeader() throws Exception {

    // This test is only meant to check the separate flow, as we want to avoid recompiling if only
    // unused headers have changed.
    assumeTrue("only tests \"separate\" preprocess mode", mode == CxxPreprocessMode.SEPARATE);

    CxxPlatform cxxPlatform =
        DefaultCxxPlatforms.build(new CxxBuckConfig(FakeBuckConfig.builder().build()));
    BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_unused_header");
    CxxSourceRuleFactory cxxSourceRuleFactory =
        CxxSourceRuleFactoryHelper.of(workspace.getDestPath(), target, cxxPlatform);
    String unusedHeaderName = "unused_header.h";
    String sourceName = "source.cpp";
    BuildTarget compileTarget =
        cxxSourceRuleFactory.createCompileBuildTarget(sourceName, CxxSourceRuleFactory.PicType.PDC);

    // Run the build and verify that the C++ source was compiled.
    workspace.runBuckBuild(target.toString());
    BuckBuildLog.BuildLogEntry firstRunEntry = workspace.getBuildLog().getLogEntry(compileTarget);
    assertThat(
        firstRunEntry.getSuccessType(), equalTo(Optional.of(BuildRuleSuccessType.BUILT_LOCALLY)));

    // Now modify the unused header.
    workspace.writeContentsToPath(
        "static inline int newFunction() { return 20; }", unusedHeaderName);

    // Run the build again and verify that got a matching input-based rule key, and therefore
    // didn't recompile.
    workspace.runBuckBuild(target.toString());
    BuckBuildLog.BuildLogEntry secondRunEntry = workspace.getBuildLog().getLogEntry(compileTarget);
    assertThat(
        secondRunEntry.getSuccessType(),
        equalTo(Optional.of(BuildRuleSuccessType.MATCHING_INPUT_BASED_RULE_KEY)));

    // Also, make sure the original rule keys are actually different.
    assertThat(secondRunEntry.getRuleKey(), Matchers.not(equalTo(firstRunEntry.getRuleKey())));
  }