// 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.lib.skyframe;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.actions.ActionInputHelper.treeFileArtifact;
import static org.junit.Assert.fail;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.Runnables;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionResult;
import com.google.devtools.build.lib.actions.Actions;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.actions.MetadataProvider;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.cache.MetadataHandler;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.TestAction;
import com.google.devtools.build.lib.actions.util.TestAction.DummyAction;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Timestamp builder tests for TreeArtifacts. */
@RunWith(JUnit4.class)
public class TreeArtifactBuildTest extends TimestampBuilderTestCase {

  private static final Predicate<Event> IS_ERROR_EVENT = new Predicate<Event>() {
    @Override
    public boolean apply(Event event) {
      return event.getKind().equals(EventKind.ERROR);
    }
  };

  // Common Artifacts, TreeFileArtifact, and Buttons. These aren't all used in all tests, but
  // they're used often enough that we can save ourselves a lot of copy-pasted code by creating them
  // in setUp().

  Artifact in;

  SpecialArtifact outOne;
  TreeFileArtifact outOneFileOne;
  TreeFileArtifact outOneFileTwo;
  Button buttonOne = new Button();

  SpecialArtifact outTwo;
  TreeFileArtifact outTwoFileOne;
  TreeFileArtifact outTwoFileTwo;
  Button buttonTwo = new Button();
  @Before
  public void setUp() throws Exception {
    in = createSourceArtifact("input");
    writeFile(in, "input_content");

    outOne = createTreeArtifact("outputOne");
    outOneFileOne = treeFileArtifact(outOne, "out_one_file_one");
    outOneFileTwo = treeFileArtifact(outOne, "out_one_file_two");

    outTwo = createTreeArtifact("outputTwo");
    outTwoFileOne = treeFileArtifact(outTwo, "out_one_file_one");
    outTwoFileTwo = treeFileArtifact(outTwo, "out_one_file_two");
  }

  @Test
  public void testCodec() throws Exception {
    new SerializationTester(outOne, outOneFileOne)
        .addDependency(FileSystem.class, scratch.getFileSystem())
        .runTests();
  }

  /** Simple smoke test. If this isn't passing, something is very wrong... */
  @Test
  public void testTreeArtifactSimpleCase() throws Exception {
    TouchingTestAction action = new TouchingTestAction(outOneFileOne, outOneFileTwo);
    registerAction(action);
    buildArtifact(action.getSoleOutput());

    assertThat(outOneFileOne.getPath().exists()).isTrue();
    assertThat(outOneFileTwo.getPath().exists()).isTrue();
  }

  /** Simple test for the case with dependencies. */
  @Test
  public void testDependentTreeArtifacts() throws Exception {
    TouchingTestAction actionOne = new TouchingTestAction(outOneFileOne, outOneFileTwo);
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo));
    registerAction(actionTwo);

    buildArtifact(outTwo);

    assertThat(outOneFileOne.getPath().exists()).isTrue();
    assertThat(outOneFileTwo.getPath().exists()).isTrue();
    assertThat(outTwoFileOne.getPath().exists()).isTrue();
    assertThat(outTwoFileTwo.getPath().exists()).isTrue();
  }

  @Test
  public void testInputTreeArtifactMetadataProvider() throws Exception {
    TouchingTestAction actionOne = new TouchingTestAction(outOneFileOne, outOneFileTwo);
    registerAction(actionOne);

    final Artifact normalOutput = createDerivedArtifact("normal/out");
    Action testAction =
        new TestAction(
            TestAction.NO_EFFECT, ImmutableList.of(outOne), ImmutableList.of(normalOutput)) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              // Check the metadata provider for input TreeFileArtifacts.
              MetadataProvider metadataProvider = actionExecutionContext.getMetadataProvider();
              assertThat(metadataProvider.getMetadata(outOneFileOne).getType().isFile()).isTrue();
              assertThat(metadataProvider.getMetadata(outOneFileTwo).getType().isFile()).isTrue();

              // Touch the action output.
              touchFile(normalOutput);
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(testAction);
    buildArtifact(normalOutput);
  }

  /** Unchanged TreeArtifact outputs should not cause reexecution. */
  @Test
  public void testCacheCheckingForTreeArtifactsDoesNotCauseReexecution() throws Exception {
    SpecialArtifact outOne = createTreeArtifact("outputOne");
    Button buttonOne = new Button();

    SpecialArtifact outTwo = createTreeArtifact("outputTwo");
    Button buttonTwo = new Button();

    TouchingTestAction actionOne = new TouchingTestAction(
        buttonOne, outOne, "file_one", "file_two");
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        buttonTwo, outOne, outTwo, "file_one", "file_two");
    registerAction(actionTwo);

    buttonOne.pressed = buttonTwo.pressed = false;
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isTrue(); // built
    assertThat(buttonTwo.pressed).isTrue(); // built

    buttonOne.pressed = buttonTwo.pressed = false;
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isFalse(); // not built
    assertThat(buttonTwo.pressed).isFalse(); // not built
  }

  /**
   * Test rebuilding TreeArtifacts for inputs, outputs, and dependents.
   * Also a test for caching.
   */
  @Test
  public void testTransitiveReexecutionForTreeArtifacts() throws Exception {
    WriteInputToFilesAction actionOne = new WriteInputToFilesAction(
        buttonOne,
        in,
        outOneFileOne, outOneFileTwo);
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        buttonTwo,
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo));
    registerAction(actionTwo);

    buttonOne.pressed = buttonTwo.pressed = false;
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isTrue(); // built
    assertThat(buttonTwo.pressed).isTrue(); // built

    buttonOne.pressed = buttonTwo.pressed = false;
    writeFile(in, "modified_input");
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isTrue(); // built
    assertThat(buttonTwo.pressed).isTrue(); // not built

    buttonOne.pressed = buttonTwo.pressed = false;
    writeFile(outOneFileOne, "modified_output");
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isTrue(); // built
    assertThat(buttonTwo.pressed).isFalse(); // should have been cached

    buttonOne.pressed = buttonTwo.pressed = false;
    writeFile(outTwoFileOne, "more_modified_output");
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isFalse(); // not built
    assertThat(buttonTwo.pressed).isTrue(); // built
  }

  /** Tests that changing a TreeArtifact directory should cause reexeuction. */
  @Test
  public void testDirectoryContentsCachingForTreeArtifacts() throws Exception {
    WriteInputToFilesAction actionOne = new WriteInputToFilesAction(
        buttonOne,
        in,
        outOneFileOne, outOneFileTwo);
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        buttonTwo,
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo));
    registerAction(actionTwo);

    buttonOne.pressed = buttonTwo.pressed = false;
    buildArtifact(outTwo);
    // just a smoke test--if these aren't built we have bigger problems!
    assertThat(buttonOne.pressed).isTrue();
    assertThat(buttonTwo.pressed).isTrue();

    // Adding a file to a directory should cause reexecution.
    buttonOne.pressed = buttonTwo.pressed = false;
    Path spuriousOutputOne = outOne.getPath().getRelative("spuriousOutput");
    touchFile(spuriousOutputOne);
    buildArtifact(outTwo);
    // Should re-execute, and delete spurious output
    assertThat(spuriousOutputOne.exists()).isFalse();
    assertThat(buttonOne.pressed).isTrue();
    assertThat(buttonTwo.pressed).isFalse(); // should have been cached

    buttonOne.pressed = buttonTwo.pressed = false;
    Path spuriousOutputTwo = outTwo.getPath().getRelative("anotherSpuriousOutput");
    touchFile(spuriousOutputTwo);
    buildArtifact(outTwo);
    assertThat(spuriousOutputTwo.exists()).isFalse();
    assertThat(buttonOne.pressed).isFalse();
    assertThat(buttonTwo.pressed).isTrue();

    // Deleting should cause reexecution.
    buttonOne.pressed = buttonTwo.pressed = false;
    deleteFile(outOneFileOne);
    buildArtifact(outTwo);
    assertThat(outOneFileOne.getPath().exists()).isTrue();
    assertThat(buttonOne.pressed).isTrue();
    assertThat(buttonTwo.pressed).isFalse(); // should have been cached

    buttonOne.pressed = buttonTwo.pressed = false;
    deleteFile(outTwoFileOne);
    buildArtifact(outTwo);
    assertThat(outTwoFileOne.getPath().exists()).isTrue();
    assertThat(buttonOne.pressed).isFalse();
    assertThat(buttonTwo.pressed).isTrue();
  }

  /** TreeArtifacts don't care about mtime, even when the file is empty. */
  @Test
  public void testMTimeForTreeArtifactsDoesNotMatter() throws Exception {
    // For this test, we only touch the input file.
    Artifact in = createSourceArtifact("touchable_input");
    touchFile(in);

    WriteInputToFilesAction actionOne = new WriteInputToFilesAction(
        buttonOne,
        in,
        outOneFileOne, outOneFileTwo);
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        buttonTwo,
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo));
    registerAction(actionTwo);

    buttonOne.pressed = buttonTwo.pressed = false;
    buildArtifact(outTwo);
    assertThat(buttonOne.pressed).isTrue(); // built
    assertThat(buttonTwo.pressed).isTrue(); // built

    buttonOne.pressed = buttonTwo.pressed = false;
    touchFile(in);
    buildArtifact(outTwo);
    // mtime does not matter.
    assertThat(buttonOne.pressed).isFalse();
    assertThat(buttonTwo.pressed).isFalse();

    // None of the below following should result in anything being built.
    buttonOne.pressed = buttonTwo.pressed = false;
    touchFile(outOneFileOne);
    buildArtifact(outTwo);
    // Nothing should be built.
    assertThat(buttonOne.pressed).isFalse();
    assertThat(buttonTwo.pressed).isFalse();

    buttonOne.pressed = buttonTwo.pressed = false;
    touchFile(outOneFileTwo);
    buildArtifact(outTwo);
    // Nothing should be built.
    assertThat(buttonOne.pressed).isFalse();
    assertThat(buttonTwo.pressed).isFalse();
  }

  /** Tests that the declared order of TreeArtifact contents does not matter. */
  @Test
  public void testOrderIndependenceOfTreeArtifactContents() throws Exception {
    WriteInputToFilesAction actionOne = new WriteInputToFilesAction(
        in,
        // The design of WritingTestAction is s.t.
        // these files will be registered in the given order.
        outOneFileTwo, outOneFileOne);
    registerAction(actionOne);

    CopyTreeAction actionTwo = new CopyTreeAction(
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo));
    registerAction(actionTwo);

    buildArtifact(outTwo);
  }

  @Test
  public void testActionExpansion() throws Exception {
    WriteInputToFilesAction action = new WriteInputToFilesAction(in, outOneFileOne, outOneFileTwo);

    CopyTreeAction actionTwo = new CopyTreeAction(
        ImmutableList.of(outOneFileOne, outOneFileTwo),
        ImmutableList.of(outTwoFileOne, outTwoFileTwo)) {
      @Override
      public void executeTestBehavior(ActionExecutionContext actionExecutionContext)
          throws ActionExecutionException {
        super.executeTestBehavior(actionExecutionContext);

        Collection<ActionInput> expanded =
            ActionInputHelper.expandArtifacts(ImmutableList.of(outOne),
                actionExecutionContext.getArtifactExpander());
        // Only files registered should show up here.
        assertThat(expanded).containsExactly(outOneFileOne, outOneFileTwo);
      }
    };

    registerAction(action);
    registerAction(actionTwo);

    buildArtifact(outTwo); // should not fail
  }

  @Test
  public void testInvalidOutputRegistrations() throws Exception {
    // Failure expected
    StoredEventHandler storingEventHandler = new StoredEventHandler();
    reporter.removeHandler(failFastHandler);
    reporter.addHandler(storingEventHandler);

    TreeArtifactTestAction failureOne = new TreeArtifactTestAction(
        Runnables.doNothing(), outOneFileOne, outOneFileTwo) {
      @Override
      public void executeTestBehavior(ActionExecutionContext actionExecutionContext) {
        try {
          writeFile(outOneFileOne, "one");
          writeFile(outOneFileTwo, "two");
          // In this test case, we only register one output. This will fail.
          registerOutput(actionExecutionContext, "one");
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };

    registerAction(failureOne);
    try {
      buildArtifact(outOne);
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      //not all outputs were created
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains("not present on disk");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }

    TreeArtifactTestAction failureTwo = new TreeArtifactTestAction(
        Runnables.doNothing(), outTwoFileOne, outTwoFileTwo) {
      @Override
      public void executeTestBehavior(ActionExecutionContext actionExecutionContext) {
        try {
          writeFile(outTwoFileOne, "one");
          writeFile(outTwoFileTwo, "two");
          // In this test case, register too many outputs. This will fail.
          registerOutput(actionExecutionContext, "one");
          registerOutput(actionExecutionContext, "two");
          registerOutput(actionExecutionContext, "three");
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };

    registerAction(failureTwo);
    storingEventHandler.clear();
    try {
      buildArtifact(outTwo);
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains("not present on disk");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }
  }

  private static void checkDirectoryPermissions(Path path) throws IOException {
    assertThat(path.isDirectory()).isTrue();
    assertThat(path.isExecutable()).isTrue();
    assertThat(path.isReadable()).isTrue();
    assertThat(path.isWritable()).isFalse();
  }

  private static void checkFilePermissions(Path path) throws IOException {
    assertThat(path.isDirectory()).isFalse();
    assertThat(path.isExecutable()).isTrue();
    assertThat(path.isReadable()).isTrue();
    assertThat(path.isWritable()).isFalse();
  }

  @Test
  public void testOutputsAreReadOnlyAndExecutable() throws Exception {
    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              writeFile(out.getPath().getChild("three").getChild("four"), "three/four");
              registerOutput(actionExecutionContext, "one");
              registerOutput(actionExecutionContext, "two");
              registerOutput(actionExecutionContext, "three/four");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    buildArtifact(action.getSoleOutput());

    checkDirectoryPermissions(out.getPath());
    checkFilePermissions(out.getPath().getChild("one"));
    checkFilePermissions(out.getPath().getChild("two"));
    checkDirectoryPermissions(out.getPath().getChild("three"));
    checkFilePermissions(out.getPath().getChild("three").getChild("four"));
  }

  @Test
  public void testValidRelativeSymlinkAccepted() throws Exception {
    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "../one");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    buildArtifact(action.getSoleOutput());
  }

  @Test
  public void testInvalidSymlinkRejected() throws Exception {
    // Failure expected
    StoredEventHandler storingEventHandler = new StoredEventHandler();
    reporter.removeHandler(failFastHandler);
    reporter.addHandler(storingEventHandler);

    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "../invalid");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    try {
      buildArtifact(action.getSoleOutput());
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains(
          "Failed to resolve relative path links/link");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }
  }

  @Test
  public void testAbsoluteSymlinkBadTargetRejected() throws Exception {
    // Failure expected
    StoredEventHandler storingEventHandler = new StoredEventHandler();
    reporter.removeHandler(failFastHandler);
    reporter.addHandler(storingEventHandler);

    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "/random/pointer");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    try {
      buildArtifact(action.getSoleOutput());
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains("Failed to resolve relative path links/link");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }
  }

  @Test
  public void testAbsoluteSymlinkAccepted() throws Exception {
    scratch.overwriteFile("/random/pointer");

    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "/random/pointer");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    buildArtifact(action.getSoleOutput());
  }

  @Test
  public void testRelativeSymlinkTraversingOutsideOfTreeArtifactRejected() throws Exception {
    // Failure expected
    StoredEventHandler storingEventHandler = new StoredEventHandler();
    reporter.removeHandler(failFastHandler);
    reporter.addHandler(storingEventHandler);

    final SpecialArtifact out = createTreeArtifact("output");

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "../../output/random/pointer");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    try {
      buildArtifact(action.getSoleOutput());
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains(
          "A TreeArtifact may not contain relative symlinks whose target paths traverse "
          + "outside of the TreeArtifact");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }
  }

  @Test
  public void testRelativeSymlinkTraversingToDirOutsideOfTreeArtifactRejected() throws Exception {
    // Failure expected
    StoredEventHandler storingEventHandler = new StoredEventHandler();
    reporter.removeHandler(failFastHandler);
    reporter.addHandler(storingEventHandler);

    final SpecialArtifact out = createTreeArtifact("output");

    // Create a valid directory that can be referenced
    scratch.dir(out.getRoot().getRoot().getRelative("some/dir").getPathString());

    TreeArtifactTestAction action =
        new TreeArtifactTestAction(out) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext) {
            try {
              writeFile(out.getPath().getChild("one"), "one");
              writeFile(out.getPath().getChild("two"), "two");
              FileSystemUtils.ensureSymbolicLink(
                  out.getPath().getChild("links").getChild("link"), "../../some/dir");
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);

    try {
      buildArtifact(action.getSoleOutput());
      fail(); // Should have thrown
    } catch (BuildFailedException e) {
      List<Event> errors = ImmutableList.copyOf(
          Iterables.filter(storingEventHandler.getEvents(), IS_ERROR_EVENT));
      assertThat(errors).hasSize(2);
      assertThat(errors.get(0).getMessage()).contains(
          "A TreeArtifact may not contain relative symlinks whose target paths traverse "
              + "outside of the TreeArtifact");
      assertThat(errors.get(1).getMessage()).contains("not all outputs were created or valid");
    }
  }

  // This is more a smoke test than anything, because it turns out that:
  // 1) there is no easy way to turn fast digests on/off for these test cases, and
  // 2) injectDigest() doesn't really complain if you inject bad digests or digests
  // for nonexistent files. Instead some weird error shows up down the line.
  // In fact, there are no tests for injectDigest anywhere in the codebase.
  // So all we're really testing here is that injectDigest() doesn't throw a weird exception.
  // TODO(bazel-team): write real tests for injectDigest, here and elsewhere.
  @Test
  public void testDigestInjection() throws Exception {
    TreeArtifactTestAction action =
        new TreeArtifactTestAction(outOne) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext)
              throws ActionExecutionException {
            try {
              writeFile(outOneFileOne, "one");
              writeFile(outOneFileTwo, "two");

              MetadataHandler md = actionExecutionContext.getMetadataHandler();
              FileStatus stat = outOneFileOne.getPath().stat(Symlinks.NOFOLLOW);
              md.injectDigest(
                  outOneFileOne,
                  stat,
                  Hashing.md5().hashString("one", Charset.forName("UTF-8")).asBytes());

              stat = outOneFileTwo.getPath().stat(Symlinks.NOFOLLOW);
              md.injectDigest(
                  outOneFileTwo,
                  stat,
                  Hashing.md5().hashString("two", Charset.forName("UTF-8")).asBytes());
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            return ActionResult.EMPTY;
          }
        };

    registerAction(action);
    buildArtifact(action.getSoleOutput());
  }

  @Test
  public void testExpandedActionsBuildInActionTemplate() throws Throwable {
    // artifact1 is a tree artifact generated by a TouchingTestAction.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    TreeFileArtifact treeFileArtifactA = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child1"));
    TreeFileArtifact treeFileArtifactB = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child2"));
    registerAction(new TouchingTestAction(treeFileArtifactA, treeFileArtifactB));

    // artifact2 is a tree artifact generated by an action template.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    // We mock out the action template function to expand into two actions that just touch the
    // output files.
    TreeFileArtifact expectedOutputTreeFileArtifact1 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child1"));
    TreeFileArtifact expectedOutputTreeFileArtifact2 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child2"));
    Action generateOutputAction = new DummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactA), expectedOutputTreeFileArtifact1);
    Action noGenerateOutputAction = new DummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactB), expectedOutputTreeFileArtifact2);

    actionTemplateExpansionFunction =
        new DummyActionTemplateExpansionFunction(
            actionKeyContext, ImmutableList.of(generateOutputAction, noGenerateOutputAction));

    buildArtifact(artifact2);
  }

  @Test
  public void testExpandedActionDoesNotGenerateOutputInActionTemplate() throws Throwable {
    // expect errors
    reporter.removeHandler(failFastHandler);

    // artifact1 is a tree artifact generated by a TouchingTestAction.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    TreeFileArtifact treeFileArtifactA = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child1"));
    TreeFileArtifact treeFileArtifactB = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child2"));
    registerAction(new TouchingTestAction(treeFileArtifactA, treeFileArtifactB));

    // artifact2 is a tree artifact generated by an action template.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    // We mock out the action template function to expand into two actions:
    // One Action that touches the output file.
    // The other action that does not generate the output file.
    TreeFileArtifact expectedOutputTreeFileArtifact1 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child1"));
    TreeFileArtifact expectedOutputTreeFileArtifact2 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child2"));
    Action generateOutputAction = new DummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactA), expectedOutputTreeFileArtifact1);
    Action noGenerateOutputAction = new NoOpDummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactB),
        ImmutableList.<Artifact>of(expectedOutputTreeFileArtifact2));

    actionTemplateExpansionFunction =
        new DummyActionTemplateExpansionFunction(
            actionKeyContext, ImmutableList.of(generateOutputAction, noGenerateOutputAction));

    try {
      buildArtifact(artifact2);
      fail("Expected BuildFailedException");
    } catch (BuildFailedException e) {
      assertThat(e).hasMessageThat().contains("not all outputs were created or valid");
    }
  }

  @Test
  public void testOneExpandedActionThrowsInActionTemplate() throws Throwable {
    // expect errors
    reporter.removeHandler(failFastHandler);

    // artifact1 is a tree artifact generated by a TouchingTestAction.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    TreeFileArtifact treeFileArtifactA = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child1"));
    TreeFileArtifact treeFileArtifactB = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child2"));
    registerAction(new TouchingTestAction(treeFileArtifactA, treeFileArtifactB));

    // artifact2 is a tree artifact generated by an action template.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    // We mock out the action template function to expand into two actions:
    // One Action that touches the output file.
    // The other action that just throws when executed.
    TreeFileArtifact expectedOutputTreeFileArtifact1 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child1"));
    TreeFileArtifact expectedOutputTreeFileArtifact2 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child2"));
    Action generateOutputAction = new DummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactA), expectedOutputTreeFileArtifact1);
    Action throwingAction = new ThrowingDummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactB),
        ImmutableList.<Artifact>of(expectedOutputTreeFileArtifact2));

    actionTemplateExpansionFunction =
        new DummyActionTemplateExpansionFunction(
            actionKeyContext, ImmutableList.of(generateOutputAction, throwingAction));

    try {
      buildArtifact(artifact2);
      fail("Expected BuildFailedException");
    } catch (BuildFailedException e) {
      assertThat(e).hasMessageThat().contains("Throwing dummy action");
    }
  }

  @Test
  public void testAllExpandedActionsThrowInActionTemplate() throws Throwable {
    // expect errors
    reporter.removeHandler(failFastHandler);

    // artifact1 is a tree artifact generated by a TouchingTestAction.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    TreeFileArtifact treeFileArtifactA = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child1"));
    TreeFileArtifact treeFileArtifactB = ActionInputHelper.treeFileArtifact(
        artifact1, PathFragment.create("child2"));
    registerAction(new TouchingTestAction(treeFileArtifactA, treeFileArtifactB));

    // artifact2 is a tree artifact generated by an action template.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    // We mock out the action template function to expand into two actions that throw when executed.
    TreeFileArtifact expectedOutputTreeFileArtifact1 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child1"));
    TreeFileArtifact expectedOutputTreeFileArtifact2 = ActionInputHelper.treeFileArtifact(
        artifact2, PathFragment.create("child2"));
    Action throwingAction = new ThrowingDummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactA),
        ImmutableList.<Artifact>of(expectedOutputTreeFileArtifact1));
    Action anotherThrowingAction = new ThrowingDummyAction(
        ImmutableList.<Artifact>of(treeFileArtifactB),
        ImmutableList.<Artifact>of(expectedOutputTreeFileArtifact2));

    actionTemplateExpansionFunction =
        new DummyActionTemplateExpansionFunction(
            actionKeyContext, ImmutableList.of(throwingAction, anotherThrowingAction));

    try {
      buildArtifact(artifact2);
      fail("Expected BuildFailedException");
    } catch (BuildFailedException e) {
      assertThat(e).hasMessageThat().contains("Throwing dummy action");
    }
  }

  @Test
  public void testInputTreeArtifactCreationFailedInActionTemplate() throws Throwable {
    // expect errors
    reporter.removeHandler(failFastHandler);

    // artifact1 is created by a action that throws.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    registerAction(
        new ThrowingDummyAction(ImmutableList.<Artifact>of(), ImmutableList.of(artifact1)));

    // artifact2 is a tree artifact generated by an action template.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    try {
      buildArtifact(artifact2);
      fail("Expected BuildFailedException");
    } catch (BuildFailedException e) {
      assertThat(e).hasMessageThat().contains("Throwing dummy action");
    }
  }

  @Test
  public void testEmptyInputAndOutputTreeArtifactInActionTemplate() throws Throwable {
    // artifact1 is an empty tree artifact which is generated by a single no-op dummy action.
    SpecialArtifact artifact1 = createTreeArtifact("treeArtifact1");
    registerAction(new NoOpDummyAction(ImmutableList.<Artifact>of(), ImmutableList.of(artifact1)));

    // artifact2 is a tree artifact generated by an action template that takes artifact1 as input.
    SpecialArtifact artifact2 = createTreeArtifact("treeArtifact2");
    SpawnActionTemplate actionTemplate = ActionsTestUtil.createDummySpawnActionTemplate(
        artifact1, artifact2);
    registerAction(actionTemplate);

    buildArtifact(artifact2);

    assertThat(artifact1.getPath().exists()).isTrue();
    assertThat(artifact1.getPath().getDirectoryEntries()).isEmpty();
    assertThat(artifact2.getPath().exists()).isTrue();
    assertThat(artifact2.getPath().getDirectoryEntries()).isEmpty();
  }

  /**
   * A generic test action that takes at most one input TreeArtifact,
   * exactly one output TreeArtifact, and some path fragment inputs/outputs.
   */
  private abstract static class TreeArtifactTestAction extends TestAction {
    final Iterable<TreeFileArtifact> inputFiles;
    final Iterable<TreeFileArtifact> outputFiles;

    TreeArtifactTestAction(final SpecialArtifact output, final String... subOutputs) {
      this(Runnables.doNothing(),
          null,
          ImmutableList.<TreeFileArtifact>of(),
          output,
          Collections2.transform(
              Arrays.asList(subOutputs),
              new Function<String, TreeFileArtifact>() {
                @Nullable
                @Override
                public TreeFileArtifact apply(String s) {
                  return ActionInputHelper.treeFileArtifact(output, s);
                }
              }));
    }

    TreeArtifactTestAction(Runnable effect, TreeFileArtifact... outputFiles) {
      this(effect, Arrays.asList(outputFiles));
    }

    TreeArtifactTestAction(Runnable effect, Collection<TreeFileArtifact> outputFiles) {
      this(effect, null, ImmutableList.<TreeFileArtifact>of(),
          outputFiles.iterator().next().getParent(), outputFiles);
    }

    TreeArtifactTestAction(Runnable effect, Artifact inputFile,
        Collection<TreeFileArtifact> outputFiles) {
      this(effect, inputFile, ImmutableList.<TreeFileArtifact>of(),
          outputFiles.iterator().next().getParent(), outputFiles);
    }

    TreeArtifactTestAction(Runnable effect, Collection<TreeFileArtifact> inputFiles,
        Collection<TreeFileArtifact> outputFiles) {
      this(effect, inputFiles.iterator().next().getParent(), inputFiles,
          outputFiles.iterator().next().getParent(), outputFiles);
    }

    TreeArtifactTestAction(
        Runnable effect,
        @Nullable Artifact input,
        Collection<TreeFileArtifact> inputFiles,
        Artifact output,
        Collection<TreeFileArtifact> outputFiles) {
      super(effect,
          input == null ? ImmutableList.<Artifact>of() : ImmutableList.of(input),
          ImmutableList.of(output));
      Preconditions.checkArgument(
          inputFiles.isEmpty() || (input != null && input.isTreeArtifact()));
      Preconditions.checkArgument(output == null || output.isTreeArtifact());
      this.inputFiles = ImmutableList.copyOf(inputFiles);
      this.outputFiles = ImmutableList.copyOf(outputFiles);
      for (TreeFileArtifact inputFile : inputFiles) {
        Preconditions.checkState(inputFile.getParent().equals(input));
      }
      for (TreeFileArtifact outputFile : outputFiles) {
        Preconditions.checkState(outputFile.getParent().equals(output));
      }
    }

    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      if (getInputs().iterator().hasNext()) {
        // Sanity check--verify all inputs exist.
        Artifact input = getSoleInput();
        if (!input.getPath().exists()) {
          throw new IllegalStateException("action's input Artifact does not exist: "
              + input.getPath());
        }
        for (Artifact inputFile : inputFiles) {
          if (!inputFile.getPath().exists()) {
            throw new IllegalStateException("action's input does not exist: " + inputFile);
          }
        }
      }

      Artifact output = getSoleOutput();
      assertThat(output.getPath().exists()).isTrue();
      try {
        effect.call();
        executeTestBehavior(actionExecutionContext);
        for (TreeFileArtifact outputFile : outputFiles) {
          actionExecutionContext.getMetadataHandler().addExpandedTreeOutput(outputFile);
        }
      } catch (RuntimeException e) {
        throw new RuntimeException(e);
      } catch (Exception e) {
        throw new ActionExecutionException("TestAction failed due to exception",
            e, this, false);
      }
      return ActionResult.EMPTY;
    }

    void executeTestBehavior(ActionExecutionContext c) throws ActionExecutionException {
      // Default: do nothing
    }

    /** Checks there's exactly one input, and returns it. */
    // This prevents us from making testing mistakes, like
    // assuming there's only one input when this isn't actually true.
    Artifact getSoleInput() {
      Iterator<Artifact> it = getInputs().iterator();
      Artifact r = it.next();
      Preconditions.checkNotNull(r);
      Preconditions.checkState(!it.hasNext());
      return r;
    }

    /** Checks there's exactly one output, and returns it. */
    SpecialArtifact getSoleOutput() {
      Iterator<Artifact> it = getOutputs().iterator();
      SpecialArtifact r = (SpecialArtifact) it.next();
      Preconditions.checkNotNull(r);
      Preconditions.checkState(!it.hasNext());
      Preconditions.checkState(r.equals(getPrimaryOutput()));
      return r;
    }

    void registerOutput(ActionExecutionContext context, String outputName) throws IOException {
      context.getMetadataHandler().addExpandedTreeOutput(
          treeFileArtifact(getSoleOutput(), PathFragment.create(outputName)));
    }

    static List<TreeFileArtifact> asTreeFileArtifacts(
        final SpecialArtifact parent, String... files) {
      return Lists.transform(
          Arrays.asList(files),
          new Function<String, TreeFileArtifact>() {
            @Nullable
            @Override
            public TreeFileArtifact apply(String s) {
              return ActionInputHelper.treeFileArtifact(parent, s);
            }
          });
    }
  }

  /** An action that touches some output TreeFileArtifacts. Takes no inputs. */
  private static class TouchingTestAction extends TreeArtifactTestAction {
    TouchingTestAction(TreeFileArtifact... outputPaths) {
      super(Runnables.doNothing(), outputPaths);
    }

    TouchingTestAction(Runnable effect, SpecialArtifact output, String... outputPaths) {
      super(effect, asTreeFileArtifacts(output, outputPaths));
    }

    @Override
    public void executeTestBehavior(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      try {
        for (Artifact file : outputFiles) {
          touchFile(file);
        }
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /** Takes an input file and populates several copies inside a TreeArtifact. */
  private static class WriteInputToFilesAction extends TreeArtifactTestAction {
    WriteInputToFilesAction(Artifact input, TreeFileArtifact... outputs) {
      this(Runnables.doNothing(), input, outputs);
    }

    WriteInputToFilesAction(
        Runnable effect,
        Artifact input,
        TreeFileArtifact... outputs) {
      super(effect, input, Arrays.asList(outputs));
      Preconditions.checkArgument(!input.isTreeArtifact());
    }

    @Override
    public void executeTestBehavior(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      try {
        for (Artifact file : outputFiles) {
          FileSystemUtils.createDirectoryAndParents(file.getPath().getParentDirectory());
          FileSystemUtils.copyFile(getSoleInput().getPath(), file.getPath());
        }
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /** Copies the given TreeFileArtifact inputs to the given outputs, in respective order. */
  private static class CopyTreeAction extends TreeArtifactTestAction {

    CopyTreeAction(
        Runnable effect, SpecialArtifact input, SpecialArtifact output, String... sourcesAndDests) {
      super(effect, input, asTreeFileArtifacts(input, sourcesAndDests), output,
          asTreeFileArtifacts(output, sourcesAndDests));
    }

    CopyTreeAction(
        Collection<TreeFileArtifact> inputPaths,
        Collection<TreeFileArtifact> outputPaths) {
      super(Runnables.doNothing(), inputPaths, outputPaths);
    }

    CopyTreeAction(
        Runnable effect,
        Collection<TreeFileArtifact> inputPaths,
        Collection<TreeFileArtifact> outputPaths) {
      super(effect, inputPaths, outputPaths);
    }

    @Override
    public void executeTestBehavior(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      Iterator<TreeFileArtifact> inputIterator = inputFiles.iterator();
      Iterator<TreeFileArtifact> outputIterator = outputFiles.iterator();

      try {
        while (inputIterator.hasNext() || outputIterator.hasNext()) {
          Artifact input = inputIterator.next();
          Artifact output = outputIterator.next();
          FileSystemUtils.createDirectoryAndParents(output.getPath().getParentDirectory());
          FileSystemUtils.copyFile(input.getPath(), output.getPath());
        }
      } catch (IOException e) {
        throw new RuntimeException(e);
      }

      // both iterators must be of the same size
      assertThat(inputIterator.hasNext()).isFalse();
      assertThat(inputIterator.hasNext()).isFalse();
    }
  }

  private SpecialArtifact createTreeArtifact(String name) {
    FileSystem fs = scratch.getFileSystem();
    Path execRoot =
        fs.getPath(TestUtils.tmpDir()).getRelative("execroot").getRelative("default-exec-root");
    PathFragment execPath = PathFragment.create("out").getRelative(name);
    return new SpecialArtifact(
        ArtifactRoot.asDerivedRoot(execRoot, execRoot.getRelative("out")),
        execPath,
        ACTION_LOOKUP_KEY,
        SpecialArtifactType.TREE);
  }

  private void buildArtifact(Artifact artifact) throws Exception {
    buildArtifacts(cachingBuilder(), artifact);
  }

  private static void writeFile(Path path, String contents) throws IOException {
    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
    // sometimes we write read-only files
    if (path.exists()) {
      path.setWritable(true);
    }
    FileSystemUtils.writeContentAsLatin1(path, contents);
  }

  private static void writeFile(Artifact file, String contents) throws IOException {
    writeFile(file.getPath(), contents);
  }

  private static void touchFile(Path path) throws IOException {
    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
    path.getParentDirectory().setWritable(true);
    FileSystemUtils.touchFile(path);
  }

  private static void touchFile(Artifact file) throws IOException {
    touchFile(file.getPath());
  }

  private static void deleteFile(Artifact file) throws IOException {
    Path path = file.getPath();
    // sometimes we write read-only files
    if (path.exists()) {
      path.setWritable(true);
      // work around the sticky bit (this might depend on the behavior of the OS?)
      path.getParentDirectory().setWritable(true);
      path.delete();
    }
  }

  /** A dummy action template expansion function that just returns the injected actions */
  private static class DummyActionTemplateExpansionFunction implements SkyFunction {
    private final ActionKeyContext actionKeyContext;
    private final ImmutableList<ActionAnalysisMetadata> actions;

    DummyActionTemplateExpansionFunction(
        ActionKeyContext actionKeyContext, ImmutableList<ActionAnalysisMetadata> actions) {
      this.actionKeyContext = actionKeyContext;
      this.actions = actions;
    }

    @Override
    public SkyValue compute(SkyKey skyKey, Environment env) {
      try {
        return new ActionTemplateExpansionValue(
            Actions.filterSharedActionsAndThrowActionConflict(actionKeyContext, actions));
      } catch (ActionConflictException e) {
        throw new IllegalStateException(e);
      }
    }

    @Override
    public String extractTag(SkyKey skyKey) {
      return null;
    }
  }

  /** No-op action that does not generate the action outputs. */
  private static class NoOpDummyAction extends TestAction {
    public NoOpDummyAction(Collection<Artifact> inputs, Collection<Artifact> outputs) {
      super(NO_EFFECT, inputs, outputs);
    }

    /** Do nothing */
    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      return ActionResult.EMPTY;
    }
  }

  /** No-op action that throws when executed */
  private static class ThrowingDummyAction extends TestAction {
    public ThrowingDummyAction(Collection<Artifact> inputs, Collection<Artifact> outputs) {
      super(NO_EFFECT, inputs, outputs);
    }

    /** Throws */
    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException {
      throw new ActionExecutionException("Throwing dummy action", this, true);
    }
  }
}
