/*
 * 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.rules;

import static com.facebook.buck.event.TestEventConfigerator.configureTestEvent;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.facebook.buck.event.BuckEvent;
import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.event.BuckEventBusFactory;
import com.facebook.buck.event.FakeBuckEventListener;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepFailedException;
import com.facebook.buck.step.StepRunner;
import com.facebook.buck.testutil.RuleMap;
import com.facebook.buck.util.concurrent.MoreFutures;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;

import org.easymock.Capture;
import org.easymock.EasyMockSupport;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * Ensuring that build rule caching works correctly in Buck is imperative for both its performance
 * and correctness.
 */
public class AbstractCachingBuildRuleTest extends EasyMockSupport {

  private static final BuildTarget buildTarget = BuildTargetFactory.newInstance(
      "//src/com/facebook/orca", "orca");

  /**
   * Tests what should happen when a rule is built for the first time: it should have no cached
   * RuleKey, nor should it have any artifact in the ArtifactCache. The sequence of events should be
   * as follows:
   * <ol>
   *   <li>The rule invokes the {@link BuildRule#build(BuildContext)} method of each of its deps.
   *   <li>The rule computes its own {@link RuleKey}.
   *   <li>It compares its {@link RuleKey} to the one on disk, if present.
   *   <li>Because the rule has no {@link RuleKey} on disk, the rule tries to build itself.
   *   <li>First, it checks the artifact cache, but there is a cache miss.
   *   <li>The rule generates its build steps and executes them.
   *   <li>Upon executing its steps successfully, it should write its {@link RuleKey} to disk.
   *   <li>It should persist its output to the ArtifactCache.
   * </ol>
   */
  @Test
  @SuppressWarnings({"deprecation", "PMD.UseAssertTrueInsteadOfAssertEquals"})
  public void testBuildRuleWithoutSuccessFileOrCachedArtifact()
      throws IOException, InterruptedException, ExecutionException, StepFailedException {
    // Create a dep for the build rule.
    BuildRule dep = createMock(BuildRule.class);
    expect(dep.isVisibleTo(buildTarget)).andReturn(true);

    // The EventBus should be updated with events indicating how the rule was built.
    BuckEventBus buckEventBus = BuckEventBusFactory.newInstance();

    FakeBuckEventListener listener = new FakeBuckEventListener();
    buckEventBus.register(listener);

    // Create an ArtifactCache whose expectations will be set later.
    ArtifactCache mockArtifactCache = createMock(ArtifactCache.class);

    ArtifactCache artifactCache = new LoggingArtifactCacheDecorator(buckEventBus)
        .decorate(mockArtifactCache);

    // Replay the mocks to instantiate the AbstractCachingBuildRule.
    replayAll();
    String pathToOutputFile = "some_file";
    File outputFile = new File(pathToOutputFile);
    List<Step> buildSteps = Lists.newArrayList();
    AbstractCachingBuildRule cachingRule = createRule(
        ImmutableSet.of(dep),
        ImmutableList.<InputRule>of(FakeInputRule.createWithRuleKey("/dev/null",
            new RuleKey("ae8c0f860a0ecad94ecede79b69460434eddbfbc"))),
        buildSteps,
        /* ruleKeyOnDisk */ Optional.<RuleKey>absent(),
        pathToOutputFile);
    verifyAll();
    resetAll();

    String expectedRuleKeyHash = Hashing.sha1().newHasher()
        .putBytes(RuleKey.Builder.buckVersionUID.getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)

        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("name".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes(cachingRule.getFullyQualifiedName().getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)

        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("buck.type".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("java_library".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)

        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("deps".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("19d2558a6bd3a34fb3f95412de9da27ed32fe208".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putByte(RuleKey.Builder.SEPARATOR)

        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("buck.inputs".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putBytes("ae8c0f860a0ecad94ecede79b69460434eddbfbc".getBytes())
        .putByte(RuleKey.Builder.SEPARATOR)
        .putByte(RuleKey.Builder.SEPARATOR)

        .hash()
        .toString();

    // The BuildContext that will be used by the rule's build() method.
    BuildContext context = createMock(BuildContext.class);
    expect(context.getExecutor()).andReturn(MoreExecutors.sameThreadExecutor());
    expect(context.getEventBus()).andReturn(buckEventBus).anyTimes();
    context.logBuildInfo("[BUILDING %s]", "//src/com/facebook/orca:orca");
    StepRunner stepRunner = createMock(StepRunner.class);
    expect(context.getStepRunner()).andReturn(stepRunner);
    ProjectFilesystem projectFilesystem = createMock(ProjectFilesystem.class);
    expect(context.getProjectFilesystem()).andReturn(projectFilesystem);
    String pathToSuccessFile = cachingRule.getPathToSuccessFile();
    projectFilesystem.createParentDirs(pathToSuccessFile);
    Capture<Iterable<String>> linesCapture = new Capture<Iterable<String>>();
    projectFilesystem.writeLinesToPath(capture(linesCapture), eq(pathToSuccessFile));
    expect(projectFilesystem.getFileForRelativePath(pathToOutputFile)).andReturn(outputFile).times(2);

    // There will initially be a cache miss, later followed by a cache store.
    RuleKey expectedRuleKey = new RuleKey(expectedRuleKeyHash);
    expect(mockArtifactCache.fetch(expectedRuleKey, outputFile)).andReturn(false);
    mockArtifactCache.store(expectedRuleKey, outputFile);
    expect(context.getArtifactCache()).andReturn(artifactCache).times(2);

    // The dependent rule will be built immediately with a distinct rule key.
    expect(dep.build(context)).andReturn(
        Futures.immediateFuture(new BuildRuleSuccess(dep, BuildRuleSuccess.Type.BUILT_LOCALLY)));
    expect(dep.getRuleKey()).andReturn(new RuleKey("19d2558a6bd3a34fb3f95412de9da27ed32fe208"));

    // Add a build step so we can verify that the steps are executed.
    Step buildStep = createMock(Step.class);
    buildSteps.add(buildStep);
    stepRunner.runStepForBuildTarget(buildStep, buildTarget);

    // Attempting to build the rule should force a rebuild due to a cache miss.
    replayAll();
    BuildRuleSuccess result = cachingRule.build(context).get();
    assertEquals(BuildRuleSuccess.Type.BUILT_LOCALLY, result.getType());
    verifyAll();

    // Verify that the correct value was written to the .success file.
    String firstLineInSuccessFile = Iterables.getFirst(linesCapture.getValue(),
        /* defaultValue */ null);
    assertEquals(expectedRuleKeyHash, firstLineInSuccessFile);

    List<BuckEvent> events = listener.getEvents();
    assertEquals(events.get(0),
        configureTestEvent(BuildRuleEvent.started(cachingRule), buckEventBus));
    assertEquals(events.get(1),
        configureTestEvent(ArtifactCacheEvent.started(ArtifactCacheEvent.Operation.FETCH),
            buckEventBus));
    assertEquals(events.get(2),
        configureTestEvent(ArtifactCacheEvent.finished(ArtifactCacheEvent.Operation.FETCH,
                /* success */ false),
            buckEventBus));
    assertEquals(events.get(3),
        configureTestEvent(ArtifactCacheEvent.started(ArtifactCacheEvent.Operation.STORE),
            buckEventBus));
    assertEquals(events.get(4),
        configureTestEvent(ArtifactCacheEvent.finished(ArtifactCacheEvent.Operation.STORE,
                /* success */ true),
            buckEventBus));
    assertEquals(events.get(5),
        configureTestEvent(BuildRuleEvent.finished(cachingRule,
            BuildRuleStatus.SUCCESS,
            CacheResult.MISS,
            Optional.of(BuildRuleSuccess.Type.BUILT_LOCALLY)),
            buckEventBus));
  }

  @Test
  @SuppressWarnings("deprecation")
  public void testAbiRuleCanAvoidRebuild()
      throws InterruptedException, ExecutionException, IOException {
    BuildRuleParams buildRuleParams = new BuildRuleParams(buildTarget,
        /* sortedDeps */ ImmutableSortedSet.<BuildRule>of(),
        /* visibilityPatterns */ ImmutableSet.<BuildTargetPattern>of(),
        /* pathRelativizer */ Functions.<String>identity());
    TestAbstractCachingBuildRule buildRule = new TestAbstractCachingBuildRule(buildRuleParams);

    // The EventBus should be updated with events indicating how the rule was built.
    BuckEventBus buckEventBus = BuckEventBusFactory.newInstance();

    FakeBuckEventListener listener = new FakeBuckEventListener();
    buckEventBus.register(listener);

    BuildContext buildContext = createMock(BuildContext.class);
    expect(buildContext.getExecutor()).andReturn(MoreExecutors.sameThreadExecutor());
    expect(buildContext.getEventBus()).andReturn(buckEventBus).anyTimes();
    ProjectFilesystem projectFilesystem = createMock(ProjectFilesystem.class);

    String pathToSuccessFile = buildRule.getPathToSuccessFile();
    projectFilesystem.createParentDirs(pathToSuccessFile);
    projectFilesystem.writeLinesToPath(
        ImmutableList.of("bfcd53a794e7c732019e04e08b30b32e26e19d50"),
        pathToSuccessFile);
    expect(buildContext.getProjectFilesystem())
        .andReturn(projectFilesystem)
        .anyTimes();

    replayAll();

    ListenableFuture<BuildRuleSuccess> result = buildRule.build(buildContext);
    assertTrue("We expect build() to be synchronous in this case, " +
    		       "so the future should already be resolved.",
               MoreFutures.isSuccess(result));

    BuildRuleSuccess success = result.get();
    assertEquals(BuildRuleSuccess.Type.MATCHING_DEPS_ABI_AND_RULE_KEY_NO_DEPS, success.getType());
    assertTrue(buildRule.isAbiLoadedFromDisk());

    List<BuckEvent> events = listener.getEvents();
    assertEquals(events.get(0),
        configureTestEvent(BuildRuleEvent.started(buildRule), buckEventBus));
    assertEquals(events.get(1),
        configureTestEvent(BuildRuleEvent.finished(buildRule,
            BuildRuleStatus.SUCCESS,
            CacheResult.HIT,
            Optional.of(BuildRuleSuccess.Type.MATCHING_DEPS_ABI_AND_RULE_KEY_NO_DEPS)),
            buckEventBus));

    verifyAll();
  }

  @Test
  public void testArtifactFetchedFromCache()
      throws InterruptedException, ExecutionException, IOException {
    ArtifactFetchedFromCacheScenario scenario = createArtifactFetchedFromCacheScenario(
        /* isSuccessScenario */ true);
    BuildableAbstractCachingBuildRule cachingRule = scenario.cachingRule;

    ListenableFuture<BuildRuleSuccess> result = cachingRule.build(scenario.buildContext);
    assertEquals(
        "recordOutputFileDetailsAfterFetchedFromArtifactCache() should be invoked once.",
        1,
        cachingRule.numCallsToRecordOutputFileDetailsAfterFetchedFromArtifactCache);
    ImmutableList<String> linesWrittenToSuccessFile = ImmutableList.copyOf(
        scenario.lines.getValue());
    assertEquals(
        "The RuleKey should have been written to the .success file.",
        ImmutableList.of(cachingRule.getRuleKey().toString()),
        linesWrittenToSuccessFile);

    assertTrue("We expect build() to be synchronous in this case, " +
        "so the future should already be resolved.",
        MoreFutures.isSuccess(result));
    BuildRuleSuccess success = result.get();
    assertEquals(BuildRuleSuccess.Type.FETCHED_FROM_CACHE, success.getType());

    verifyAll();
  }

  @Test
  public void testArtifactFetchedFromCacheFailsToRecordOutputFileDetails() throws IOException {
    ArtifactFetchedFromCacheScenario scenario = createArtifactFetchedFromCacheScenario(
        /* isSuccessScenario */ false);
    BuildableAbstractCachingBuildRule cachingRule = scenario.cachingRule;
    cachingRule.setRecordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException(
        /* shouldThrow */ true);

    ListenableFuture<BuildRuleSuccess> result = cachingRule.build(scenario.buildContext);
    assertEquals(
        "recordOutputFileDetailsAfterFetchedFromArtifactCache() should be invoked once.",
        1,
        cachingRule.numCallsToRecordOutputFileDetailsAfterFetchedFromArtifactCache);

    Throwable failure = MoreFutures.getFailure(result);
    assertTrue(failure instanceof IOException);
    assertEquals("Failed to record output file details!", failure.getMessage());

    verifyAll();
  }

  private ArtifactFetchedFromCacheScenario createArtifactFetchedFromCacheScenario(
      boolean isSuccessScenario)
      throws IOException {
    Step step = new AbstractExecutionStep("exploding step") {
      @Override
      public int execute(ExecutionContext context) {
        throw new UnsupportedOperationException("build step should not be executed");
      }
    };
    String pathToOutputFile = "foo/bar/baz";
    BuildableAbstractCachingBuildRule cachingRule = createRule(
        /* deps */ ImmutableSet.<BuildRule>of(),
        ImmutableList.<InputRule>of(),
        ImmutableList.of(step),
        /* ruleKeyOnDisk */ Optional.<RuleKey>absent(),
        pathToOutputFile);

    StepRunner stepRunner = createMock(StepRunner.class);
    expect(stepRunner.getListeningExecutorService()).andReturn(MoreExecutors.sameThreadExecutor());

    // Mock out all of the disk I/O.
    File initialOutputFile = createMock(File.class);
    ProjectFilesystem projectFilesystem = createMock(ProjectFilesystem.class);
    expect(projectFilesystem.getFileForRelativePath(pathToOutputFile)).andReturn(initialOutputFile);
    Capture<Iterable<String>> lines;
    if (isSuccessScenario) {
      String pathToSuccessFile = cachingRule.getPathToSuccessFile();
      projectFilesystem.createParentDirs(pathToSuccessFile);
      lines = new Capture<Iterable<String>>();
      projectFilesystem.writeLinesToPath(capture(lines), eq(pathToSuccessFile));
    } else {
      lines = null;
    }

    // Simulate successfully fetching the output file from the ArtifactCache.
    ArtifactCache artifactCache = createMock(ArtifactCache.class);
    expect(artifactCache.fetch(cachingRule.getRuleKey(), initialOutputFile)).andReturn(true);

    BuildContext buildContext = BuildContext.builder()
        .setProjectRoot(createMock(File.class))
        .setDependencyGraph(RuleMap.createGraphFromSingleRule(cachingRule))
        .setStepRunner(stepRunner)
        .setProjectFilesystem(projectFilesystem)
        .setArtifactCache(artifactCache)
        .setJavaPackageFinder(createMock(JavaPackageFinder.class))
        .setEventBus(BuckEventBusFactory.newInstance())
        .build();

    replayAll();

    ArtifactFetchedFromCacheScenario scenario = new ArtifactFetchedFromCacheScenario();
    scenario.cachingRule = cachingRule;
    scenario.buildContext = buildContext;
    scenario.lines = lines;
    return scenario;
  }

  private static class ArtifactFetchedFromCacheScenario {
    BuildableAbstractCachingBuildRule cachingRule;
    BuildContext buildContext;
    Capture<Iterable<String>> lines;
  }


  // TODO(mbolin): Test that when the success files match, nothing is built and nothing is written
  // back to the cache.

  // TODO(mbolin): Test that when the value in the success file does not agree with the current
  // value, the rule is rebuilt and the result is written back to the cache.

  // TODO(mbolin): Test that a failure when executing the build steps is propagated appropriately.

  // TODO(mbolin): Test what happens when the cache's methods throw an exception.

  private static BuildableAbstractCachingBuildRule createRule(
      ImmutableSet<BuildRule> deps,
      Iterable<InputRule> inputRules,
      List<Step> buildSteps,
      Optional<RuleKey> ruleKeyOnDisk,
      String pathToOutputFile) {
    Comparator<BuildRule> comparator = RetainOrderComparator.createComparator(deps);
    ImmutableSortedSet<BuildRule> sortedDeps = ImmutableSortedSet.copyOf(comparator, deps);

    BuildRuleParams buildRuleParams = new BuildRuleParams(buildTarget,
        sortedDeps,
        /* visibilityPatterns */ ImmutableSet.<BuildTargetPattern>of(),
        /* pathRelativizer */ Functions.<String>identity());
    return new BuildableAbstractCachingBuildRule(buildRuleParams,
        inputRules,
        pathToOutputFile,
        ruleKeyOnDisk,
        buildSteps);
  }

  private static class BuildableAbstractCachingBuildRule extends AbstractCachingBuildRule {

    private final Iterable<InputRule> inputRules;
    private final String pathToOutputFile;
    private final Optional<RuleKey> ruleKeyOnDisk;
    private final List<Step> buildSteps;
    private int numCallsToRecordOutputFileDetailsAfterFetchedFromArtifactCache;
    private boolean recordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException;

    private BuildableAbstractCachingBuildRule(BuildRuleParams params,
        Iterable<InputRule> inputRules,
        String pathToOutputFile,
        Optional<RuleKey> ruleKeyOnDisk,
        List<Step> buildSteps) {
      super(params);
      this.inputRules = inputRules;
      this.pathToOutputFile = pathToOutputFile;
      this.ruleKeyOnDisk = ruleKeyOnDisk;
      this.buildSteps = buildSteps;
      this.numCallsToRecordOutputFileDetailsAfterFetchedFromArtifactCache = 0;
      this.recordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException = false;
    }

    @Override
    public BuildRuleType getType() {
      return BuildRuleType.JAVA_LIBRARY;
    }

    @Override
    public Iterable<InputRule> getInputs() {
      return inputRules;
    }

    @Override
    public String getPathToOutputFile() {
      return pathToOutputFile;
    }

    @Override
    Optional<RuleKey> getRuleKeyOnDisk(ProjectFilesystem projectFilesystem) {
      return ruleKeyOnDisk;
    }

    @Override
    public List<Step> getBuildSteps(BuildContext context) throws IOException {
      return buildSteps;
    }

    @Override
    public Iterable<String> getInputsToCompareToOutput() {
      throw new UnsupportedOperationException();
    }

    void setRecordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException(
        boolean shouldThrow) {
      recordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException = shouldThrow;
    }

    @Override
    public void recordOutputFileDetailsAfterFetchFromArtifactCache(ArtifactCache cache,
                                                                   ProjectFilesystem projectFilesystem) throws IOException {
      numCallsToRecordOutputFileDetailsAfterFetchedFromArtifactCache++;
      if (recordOutputFileDetailsAfterFetchedFromArtifactCacheShouldThrowIOException) {
        throw new IOException("Failed to record output file details!");
      }
    }
  }

  /**
   * {@link AbstractCachingBuildRule} that implements {@link AbiRule}.
   */
  private static class TestAbstractCachingBuildRule extends AbstractCachingBuildRule
      implements AbiRule {

    private boolean isAbiLoadedFromDisk = false;

    TestAbstractCachingBuildRule(BuildRuleParams buildRuleParams) {
      super(buildRuleParams);
    }

    @Override
    public Iterable<String> getInputsToCompareToOutput() {
      throw new UnsupportedOperationException("method should not be called");
    }

    @Override
    public List<Step> getBuildSteps(BuildContext context)
        throws IOException {
      throw new UnsupportedOperationException("method should not be called");
    }

    @Override
    public BuildRuleType getType() {
      throw new UnsupportedOperationException("method should not be called");
    }

    @Override
    public RuleKey getRuleKey() {
      return new RuleKey("bfcd53a794e7c732019e04e08b30b32e26e19d50");
    }

    @Override
    public Optional<RuleKey> getRuleKeyWithoutDeps() {
      return Optional.of(new RuleKey("efd7d450d9f1c3d9e43392dec63b1f31692305b9"));
    }

    @Override
    public Optional<RuleKey> getRuleKeyWithoutDepsOnDisk(ProjectFilesystem projectFilesystem) {
      return Optional.of(new RuleKey("efd7d450d9f1c3d9e43392dec63b1f31692305b9"));
    }

    @Override
    public boolean initializeFromDisk(ProjectFilesystem projectFilesystem) {
      isAbiLoadedFromDisk = true;
      return true;
    }

    public boolean isAbiLoadedFromDisk() {
      return isAbiLoadedFromDisk;
    }

    @Override
    public Optional<Sha1HashCode> getAbiKeyForDeps() {
      return Optional.of(new Sha1HashCode("92d6de0a59080284055bcde5d2923f144b216a59"));
    }

    @Override
    public Optional<Sha1HashCode> getAbiKeyForDepsOnDisk(ProjectFilesystem projectFilesystem) {
      return Optional.of(new Sha1HashCode("92d6de0a59080284055bcde5d2923f144b216a59"));
    }
  }
}
