// Copyright 2015 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.actions;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.mock;

import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.collect.Lists;
import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.actions.Artifact.ArchivedTreeArtifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactSerializationContext;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
import com.google.devtools.build.lib.actions.Artifact.OwnerlessArtifactWrapper;
import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
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.RootType;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.LabelArtifactOwner;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationDepsUtils;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.Root.RootCodecDependencies;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/** Tests for {@link Artifact}. */
@RunWith(TestParameterInjector.class)
public final class ArtifactTest {

  private final Scratch scratch = new Scratch();
  private Path execDir;
  private ArtifactRoot rootDir;

  @Before
  public void setRootDir() throws Exception {
    execDir = scratch.dir("/base/exec");
    rootDir = ArtifactRoot.asDerivedRoot(execDir, RootType.Output, "root");
  }

  @Test
  public void testConstruction_badRootDir() throws IOException {
    Path f1 = scratch.file("/exec/dir/file.ext");
    assertThrows(
        IllegalArgumentException.class,
        () ->
            ActionsTestUtil.createArtifactWithExecPath(
                    ArtifactRoot.asDerivedRoot(execDir, RootType.Output, "bogus"),
                    f1.relativeTo(execDir))
                .getRootRelativePath());
  }

  private static long getUsedMemory() {
    System.gc();
    System.gc();
    System.runFinalization();
    System.gc();
    System.gc();
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
  }

  @Test
  public void testMemoryUsage() throws IOException {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    PathFragment aPath = PathFragment.create("src/a");
    int arrSize = 1 << 20;
    Object[] arr = new Object[arrSize];
    long usedMemory = getUsedMemory();
    for (int i = 0; i < arrSize; i++) {
      arr[i] = ActionsTestUtil.createArtifactWithExecPath(root, aPath);
    }
    assertThat((getUsedMemory() - usedMemory) / arrSize).isAtMost(34L);
  }

  @Test
  public void testEquivalenceRelation() throws Exception {
    PathFragment aPath = PathFragment.create("src/a");
    PathFragment bPath = PathFragment.create("src/b");
    assertThat(ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, aPath))
        .isEqualTo(ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, aPath));
    assertThat(ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, bPath))
        .isEqualTo(ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, bPath));
    assertThat(
            ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, aPath)
                .equals(ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, bPath)))
        .isFalse();
  }

  @Test
  public void testComparison() {
    PathFragment aPath = PathFragment.create("src/a");
    PathFragment bPath = PathFragment.create("src/b");
    Artifact aArtifact = ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, aPath);
    Artifact bArtifact = ActionsTestUtil.createArtifactWithRootRelativePath(rootDir, bPath);
    assertThat(Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, bArtifact)).isEqualTo(-1);
    assertThat(Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, aArtifact)).isEqualTo(0);
    assertThat(Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, bArtifact)).isEqualTo(0);
    assertThat(Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, aArtifact)).isEqualTo(1);
  }

  @Test
  public void testGetFilename() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact javaFile = ActionsTestUtil.createArtifact(root, scratch.file("/foo/Bar.java"));
    Artifact generatedHeader =
        ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar.proto.h"));
    Artifact generatedCc = ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar.proto.cc"));
    Artifact aCPlusPlusFile = ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar.cc"));
    assertThat(JavaSemantics.JAVA_SOURCE.matches(javaFile.getFilename())).isTrue();
    assertThat(CppFileTypes.CPP_HEADER.matches(generatedHeader.getFilename())).isTrue();
    assertThat(CppFileTypes.CPP_SOURCE.matches(generatedCc.getFilename())).isTrue();
    assertThat(CppFileTypes.CPP_SOURCE.matches(aCPlusPlusFile.getFilename())).isTrue();
  }

  @Test
  public void testGetExtension() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact javaFile = ActionsTestUtil.createArtifact(root, scratch.file("/foo/Bar.java"));
    assertThat(javaFile.getExtension()).isEqualTo("java");
  }

  @Test
  public void testIsFileType() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact javaFile = ActionsTestUtil.createArtifact(root, scratch.file("/foo/Bar.java"));
    assertThat(javaFile.isFileType(FileType.of("java"))).isTrue();
    assertThat(javaFile.isFileType(FileType.of("cc"))).isFalse();
  }

  @Test
  public void testIsFileTypeSet() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact javaFile = ActionsTestUtil.createArtifact(root, scratch.file("/foo/Bar.java"));
    assertThat(javaFile.isFileType(FileTypeSet.of(FileType.of("cc"), FileType.of("java"))))
        .isTrue();
    assertThat(javaFile.isFileType(FileTypeSet.of(FileType.of("py"), FileType.of("js")))).isFalse();
    assertThat(javaFile.isFileType(FileTypeSet.of())).isFalse();
  }

  @Test
  public void testMangledPath() {
    String path = "dir/sub_dir/name:end";
    assertThat(Actions.escapedPath(path)).isEqualTo("dir_Ssub_Udir_Sname_Cend");
  }

  private List<Artifact> getFooBarArtifacts() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact aHeader1 = ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar1.h"));
    Artifact aHeader2 = ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar2.h"));
    return Lists.newArrayList(aHeader1, aHeader2);
  }

  @Test
  public void testAddExecPaths() throws Exception {
    List<String> paths = new ArrayList<>();
    Artifact.addExecPaths(getFooBarArtifacts(), paths);
    assertThat(paths).containsExactly("bar1.h", "bar2.h");
  }

  @Test
  public void testAddExecPathsNewActionGraph() throws Exception {
    List<String> paths = new ArrayList<>();
    Artifact.addExecPaths(getFooBarArtifacts(), paths);
    assertThat(paths).containsExactly("bar1.h", "bar2.h");
  }

  @Test
  public void testRootRelativePathIsSameAsExecPath() throws Exception {
    ArtifactRoot root = ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo")));
    Artifact a = ActionsTestUtil.createArtifact(root, scratch.file("/foo/bar1.h"));
    assertThat(a.getRootRelativePath()).isSameInstanceAs(a.getExecPath());
  }

  @Test
  public void testToDetailString() throws Exception {
    Path execRoot = scratch.getFileSystem().getPath("/execroot/workspace");
    Artifact a =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "b"), "c");
    assertThat(a.toDetailString()).isEqualTo("[[<execution_root>]b]c");
  }

  @Test
  public void testWeirdArtifact() {
    Path execRoot = scratch.getFileSystem().getPath("/");
    assertThrows(
        IllegalArgumentException.class,
        () ->
            ActionsTestUtil.createArtifactWithExecPath(
                    ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "a"),
                    PathFragment.create("c"))
                .getRootRelativePath());
  }

  @Test
  public void derivedArtifactCodecs(@TestParameter boolean includeGeneratingActionKey)
      throws Exception {
    ArtifactSerializationContext artifactContext =
        new ArtifactSerializationContext() {
          @Override
          public SourceArtifact getSourceArtifact(
              PathFragment execPath, Root root, ArtifactOwner owner) {
            throw new UnsupportedOperationException();
          }

          @Override
          public boolean includeGeneratingActionKey(DerivedArtifact artifact) {
            return includeGeneratingActionKey;
          }
        };

    DerivedArtifact artifact =
        (DerivedArtifact) ActionsTestUtil.createArtifact(rootDir, "dir/out.txt");
    artifact.setGeneratingActionKey(ActionsTestUtil.NULL_ACTION_LOOKUP_DATA);

    ArtifactRoot anotherRoot =
        ArtifactRoot.asDerivedRoot(scratch.getFileSystem().getPath("/"), RootType.Output, "other");
    DerivedArtifact anotherArtifact =
        DerivedArtifact.create(
            anotherRoot,
            anotherRoot.getExecPath().getRelative("dir/out.txt"),
            ActionsTestUtil.NULL_ARTIFACT_OWNER);
    anotherArtifact.setGeneratingActionKey(ActionsTestUtil.NULL_ACTION_LOOKUP_DATA);

    SpecialArtifact tree =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(
            rootDir, rootDir.getExecPath().getRelative("tree"));
    TreeFileArtifact treeChild = TreeFileArtifact.createTreeOutput(tree, "child");
    ArchivedTreeArtifact archivedTree = ArchivedTreeArtifact.createForTree(tree);
    ArchivedTreeArtifact customArchivedTree =
        ArchivedTreeArtifact.createWithCustomDerivedTreeRoot(
            tree, PathFragment.create("custom"), PathFragment.create("archived.zip"));

    SpecialArtifact templateExpansionTree =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(
            rootDir, rootDir.getExecPath().getRelative("template"));
    TreeFileArtifact expansionOutput =
        TreeFileArtifact.createTemplateExpansionOutput(
            templateExpansionTree,
            "output",
            ActionsTestUtil.NULL_TEMPLATE_EXPANSION_ARTIFACT_OWNER);
    expansionOutput.setGeneratingActionKey(
        ActionLookupData.create(ActionsTestUtil.NULL_TEMPLATE_EXPANSION_ARTIFACT_OWNER, 0));

    SerializationTester tester =
        new SerializationTester(
                artifact,
                anotherArtifact,
                tree,
                treeChild,
                archivedTree,
                customArchivedTree,
                expansionOutput)
            .addDependency(FileSystem.class, scratch.getFileSystem())
            .addDependency(
                RootCodecDependencies.class, new RootCodecDependencies(anotherRoot.getRoot()))
            .addDependency(ArtifactSerializationContext.class, artifactContext);

    if (!includeGeneratingActionKey) {
      tester.<DerivedArtifact>setVerificationFunction(
          (original, deserialized) -> {
            String debug =
                String.format(
                    "original=%s\ndeseriaized=%s",
                    original.toDebugString(), deserialized.toDebugString());
            assertWithMessage(debug).that(deserialized.hasGeneratingActionKey()).isFalse();
            assertWithMessage(debug).that(deserialized.equalsWithoutOwner(original)).isTrue();
            assertThat(new OwnerlessArtifactWrapper(deserialized))
                .isEqualTo(new OwnerlessArtifactWrapper(original));

            assertThrows(debug, RuntimeException.class, deserialized::getArtifactOwner);
            assertThrows(debug, RuntimeException.class, deserialized::getGeneratingActionKey);
            assertThrows(debug, RuntimeException.class, deserialized::getOwner);
            assertThrows(debug, RuntimeException.class, deserialized::getOwnerLabel);
            assertThrows(debug, RuntimeException.class, () -> deserialized.equals(original));
            assertThrows(
                debug,
                RuntimeException.class,
                () -> deserialized.setGeneratingActionKey(original.getGeneratingActionKey()));
          });
    }

    tester.runTests();
  }

  @Test
  public void sourceArtifactCodecRecyclesSourceArtifactInstances() throws Exception {
    Root root = Root.fromPath(scratch.dir("/"));
    ArtifactRoot artifactRoot = ArtifactRoot.asSourceRoot(root);
    ArtifactFactory artifactFactory =
        new ArtifactFactory(execDir.getParentDirectory(), "blaze-out");

    ObjectCodecs objectCodecs =
        new ObjectCodecs(
            AutoRegistry.get()
                .getBuilder()
                .addReferenceConstant(scratch.getFileSystem())
                .setAllowDefaultCodec(true)
                .build(),
            ImmutableClassToInstanceMap.builder()
                .put(FileSystem.class, scratch.getFileSystem())
                .put(ArtifactSerializationContext.class, artifactFactory::getSourceArtifact)
                .put(RootCodecDependencies.class, new RootCodecDependencies(artifactRoot.getRoot()))
                .build());

    PathFragment pathFragment = PathFragment.create("src/foo.cc");
    ArtifactOwner owner = new LabelArtifactOwner(Label.parseAbsoluteUnchecked("//foo:bar"));
    SourceArtifact sourceArtifact = new SourceArtifact(artifactRoot, pathFragment, owner);
    SourceArtifact deserialized1 =
        (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
    SourceArtifact deserialized2 =
        (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
    assertThat(deserialized1).isSameInstanceAs(deserialized2);

    Artifact sourceArtifactFromFactory =
        artifactFactory.getSourceArtifact(pathFragment, root, owner);
    Artifact deserialized =
        (Artifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifactFromFactory));
    assertThat(sourceArtifactFromFactory).isSameInstanceAs(deserialized);
  }

  @Test
  public void testLongDirname() throws Exception {
    String dirName = createDirNameArtifact().getDirname();

    assertThat(dirName).isEqualTo("aaa/bbb/ccc");
  }

  @Test
  public void testDirnameInExecutionDir() throws Exception {
    Artifact artifact =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/foo"))),
            scratch.file("/foo/bar.txt"));

    assertThat(artifact.getDirname()).isEqualTo(".");
  }

  @Test
  public void testCanConstructPathFromDirAndFilename() throws Exception {
    Artifact artifact = createDirNameArtifact();
    String constructed = String.format("%s/%s", artifact.getDirname(), artifact.getFilename());

    assertThat(constructed).isEqualTo("aaa/bbb/ccc/ddd");
  }

  @Test
  public void testIsSourceArtifact() throws Exception {
    assertThat(
            new Artifact.SourceArtifact(
                    ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/"))),
                    PathFragment.create("src/foo.cc"),
                    ArtifactOwner.NULL_OWNER)
                .isSourceArtifact())
        .isTrue();
    assertThat(
            ActionsTestUtil.createArtifact(
                    ArtifactRoot.asDerivedRoot(scratch.dir("/genfiles"), RootType.Output, "aaa"),
                    scratch.file("/genfiles/aaa/bar.out"))
                .isSourceArtifact())
        .isFalse();
  }

  @Test
  public void testGetRoot() throws Exception {
    Path execRoot = scratch.getFileSystem().getPath("/");
    ArtifactRoot root = ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "newRoot");
    assertThat(ActionsTestUtil.createArtifact(root, scratch.file("/newRoot/foo")).getRoot())
        .isEqualTo(root);
  }

  @Test
  public void hashCodeAndEquals() {
    Path execRoot = scratch.getFileSystem().getPath("/");
    ArtifactRoot root = ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "newRoot");
    ActionLookupKey firstOwner =
        new ActionLookupKey() {
          @Override
          public Label getLabel() {
            return null;
          }

          @Override
          public BuildConfigurationKey getConfigurationKey() {
            return null;
          }

          @Override
          public SkyFunctionName functionName() {
            return null;
          }
        };
    ActionLookupKey secondOwner =
        new ActionLookupKey() {
          @Override
          public Label getLabel() {
            return null;
          }

          @Override
          public BuildConfigurationKey getConfigurationKey() {
            return null;
          }

          @Override
          public SkyFunctionName functionName() {
            return null;
          }
        };
    DerivedArtifact derived1 =
        DerivedArtifact.create(root, PathFragment.create("newRoot/shared"), firstOwner);
    derived1.setGeneratingActionKey(ActionLookupData.create(firstOwner, 0));
    DerivedArtifact derived2 =
        DerivedArtifact.create(root, PathFragment.create("newRoot/shared"), secondOwner);
    derived2.setGeneratingActionKey(ActionLookupData.create(secondOwner, 0));
    ArtifactRoot sourceRoot = ArtifactRoot.asSourceRoot(Root.fromPath(root.getRoot().asPath()));
    Artifact source1 = new SourceArtifact(sourceRoot, PathFragment.create("shared"), firstOwner);
    Artifact source2 = new SourceArtifact(sourceRoot, PathFragment.create("shared"), secondOwner);
    new EqualsTester()
        .addEqualityGroup(derived1)
        .addEqualityGroup(derived2)
        .addEqualityGroup(source1, source2)
        .testEquals();
    assertThat(derived1.hashCode()).isEqualTo(derived2.hashCode());
    assertThat(derived1.hashCode()).isNotEqualTo(source1.hashCode());
    assertThat(source1.hashCode()).isEqualTo(source2.hashCode());
    Artifact.OwnerlessArtifactWrapper wrapper1 = new Artifact.OwnerlessArtifactWrapper(derived1);
    Artifact.OwnerlessArtifactWrapper wrapper2 = new Artifact.OwnerlessArtifactWrapper(derived2);
    Artifact.OwnerlessArtifactWrapper wrapper3 = new Artifact.OwnerlessArtifactWrapper(source1);
    Artifact.OwnerlessArtifactWrapper wrapper4 = new Artifact.OwnerlessArtifactWrapper(source2);
    new EqualsTester()
        .addEqualityGroup(wrapper1, wrapper2)
        .addEqualityGroup(wrapper3, wrapper4)
        .testEquals();
    Path path1 = derived1.getPath();
    Path path2 = derived2.getPath();
    Path path3 = source1.getPath();
    Path path4 = source2.getPath();
    new EqualsTester().addEqualityGroup(path1, path2, path3, path4).testEquals();
  }

  private Artifact createDirNameArtifact() throws Exception {
    return ActionsTestUtil.createArtifact(
        ArtifactRoot.asSourceRoot(Root.fromPath(scratch.dir("/"))),
        scratch.file("/aaa/bbb/ccc/ddd"));
  }

  @Test
  public void canDeclareContentBasedOutput() {
    Path execRoot = scratch.getFileSystem().getPath("/");
    ArtifactRoot root = ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "newRoot");
    assertThat(
            DerivedArtifact.create(
                    root,
                    PathFragment.create("newRoot/my.output"),
                    ActionsTestUtil.NULL_ARTIFACT_OWNER,
                    /*contentBasedPath=*/ true)
                .contentBasedPath())
        .isTrue();
  }

  @Test
  public void testGetRepositoryRelativePathExternalSourceArtifacts() throws IOException {
    ArtifactRoot externalRoot =
        ArtifactRoot.asExternalSourceRoot(
            Root.fromPath(
                scratch
                    .dir("/output_base")
                    .getRelative(LabelConstants.EXTERNAL_REPOSITORY_LOCATION)
                    .getRelative("foo")));

    // --experimental_sibling_repository_layout not set
    assertThat(
            new Artifact.SourceArtifact(
                    externalRoot,
                    LabelConstants.EXTERNAL_PATH_PREFIX.getRelative("foo/bar/baz.cc"),
                    ArtifactOwner.NULL_OWNER)
                .getRepositoryRelativePath())
        .isEqualTo(PathFragment.create("bar/baz.cc"));

    // --experimental_sibling_repository_layout set
    assertThat(
            new Artifact.SourceArtifact(
                    externalRoot,
                    LabelConstants.EXPERIMENTAL_EXTERNAL_PATH_PREFIX.getRelative("foo/bar/baz.cc"),
                    ArtifactOwner.NULL_OWNER)
                .getRepositoryRelativePath())
        .isEqualTo(PathFragment.create("bar/baz.cc"));
  }

  @Test
  public void archivedTreeArtifact_create_returnsArtifactInArchivedRoot() {
    ArtifactRoot root =
        ArtifactRoot.asDerivedRoot(execDir, RootType.Output, "blaze-out", "fastbuild");
    SpecialArtifact tree = createTreeArtifact(root, "tree");

    ArchivedTreeArtifact archivedTreeArtifact = ArchivedTreeArtifact.createForTree(tree);

    assertThat(archivedTreeArtifact.getParent()).isSameInstanceAs(tree);
    assertThat(archivedTreeArtifact.getArtifactOwner())
        .isSameInstanceAs(ActionsTestUtil.NULL_ARTIFACT_OWNER);
    assertThat(archivedTreeArtifact.getExecPathString())
        .isEqualTo("blaze-out/:archived_tree_artifacts/fastbuild/tree.zip");
    assertThat(archivedTreeArtifact.getRoot().getExecPathString())
        .isEqualTo("blaze-out/:archived_tree_artifacts/fastbuild");
  }

  @Test
  public void archivedTreeArtifact_create_returnsArtifactWithGeneratingActionFromParent() {
    ActionLookupKey actionLookupKey = mock(ActionLookupKey.class);
    ActionLookupData actionLookupData = ActionLookupData.create(actionLookupKey, 0);
    SpecialArtifact tree = createTreeArtifact(rootDir, "tree", actionLookupData);

    ArchivedTreeArtifact archivedTreeArtifact = ArchivedTreeArtifact.createForTree(tree);

    assertThat(archivedTreeArtifact.getExecPathString())
        .isEqualTo("root/:archived_tree_artifacts/tree.zip");
    assertThat(archivedTreeArtifact.getArtifactOwner()).isSameInstanceAs(actionLookupKey);
    assertThat(archivedTreeArtifact.getGeneratingActionKey()).isSameInstanceAs(actionLookupData);
  }

  @Test
  public void archivedTreeArtifact_createWithCustomDerivedTreeRoot_returnsArtifactWithCustomRoot() {
    ArtifactRoot root =
        ArtifactRoot.asDerivedRoot(execDir, RootType.Output, "blaze-out", "fastbuild");
    SpecialArtifact tree = createTreeArtifact(root, "dir/tree");

    ArchivedTreeArtifact archivedTreeArtifact =
        ArchivedTreeArtifact.createWithCustomDerivedTreeRoot(
            tree, PathFragment.create("custom/custom2"), PathFragment.create("treePath/file.xyz"));

    assertThat(archivedTreeArtifact.getParent()).isSameInstanceAs(tree);
    assertThat(archivedTreeArtifact.getExecPathString())
        .isEqualTo("blaze-out/custom/custom2/fastbuild/treePath/file.xyz");
    assertThat(archivedTreeArtifact.getRoot().getExecPathString())
        .isEqualTo("blaze-out/custom/custom2/fastbuild");
  }

  @Test
  public void archivedTreeArtifact_codec_roundTripsArchivedArtifact() throws Exception {
    ArchivedTreeArtifact artifact1 = createArchivedTreeArtifact(rootDir, "tree1");
    ArtifactRoot anotherRoot =
        ArtifactRoot.asDerivedRoot(scratch.getFileSystem().getPath("/"), RootType.Output, "src");
    ArchivedTreeArtifact artifact2 = createArchivedTreeArtifact(anotherRoot, "tree2");
    new SerializationTester(artifact1, artifact2)
        .addDependency(FileSystem.class, scratch.getFileSystem())
        .addDependency(
            RootCodecDependencies.class, new RootCodecDependencies(anotherRoot.getRoot()))
        .addDependencies(SerializationDepsUtils.SERIALIZATION_DEPS_FOR_TEST)
        .<ArchivedTreeArtifact>setVerificationFunction(
            (original, deserialized) -> {
              assertThat(original).isEqualTo(deserialized);
              assertThat(original.getGeneratingActionKey())
                  .isEqualTo(deserialized.getGeneratingActionKey());
            })
        .runTests();
  }

  @Test
  public void archivedTreeArtifact_getExecPathWithinArchivedArtifactsTree_returnsCorrectPath() {
    assertThat(
            ArchivedTreeArtifact.getExecPathWithinArchivedArtifactsTree(
                PathFragment.create("bazel-out/k8-fastbuild/bin/dir/subdir")))
        .isEqualTo(
            PathFragment.create("bazel-out/:archived_tree_artifacts/k8-fastbuild/bin/dir/subdir"));
  }

  private static SpecialArtifact createTreeArtifact(ArtifactRoot root, String relativePath) {
    return createTreeArtifact(root, relativePath, ActionsTestUtil.NULL_ACTION_LOOKUP_DATA);
  }

  private static SpecialArtifact createTreeArtifact(
      ArtifactRoot root, String relativePath, ActionLookupData actionLookupData) {
    SpecialArtifact treeArtifact =
        SpecialArtifact.create(
            root,
            root.getExecPath().getRelative(relativePath),
            actionLookupData.getActionLookupKey(),
            SpecialArtifactType.TREE);
    treeArtifact.setGeneratingActionKey(actionLookupData);
    return treeArtifact;
  }

  private static ArchivedTreeArtifact createArchivedTreeArtifact(
      ArtifactRoot root, String treeRelativePath) {
    return ArchivedTreeArtifact.createForTree(createTreeArtifact(root, treeRelativePath));
  }
}
