| // Copyright 2021 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 org.mockito.Mockito.inOrder; | |
| import static org.mockito.Mockito.mock; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| 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.CompletionContext.ArtifactReceiver; | |
| import com.google.devtools.build.lib.actions.util.ActionsTestUtil; | |
| import com.google.devtools.build.lib.skyframe.TreeArtifactValue; | |
| import com.google.devtools.build.lib.vfs.DigestHashFunction; | |
| import com.google.devtools.build.lib.vfs.PathFragment; | |
| import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| import org.mockito.InOrder; | |
| /** Tests for {@link CompletionContext}. */ | |
| @RunWith(JUnit4.class) | |
| public final class CompletionContextTest { | |
| private static final FileArtifactValue DUMMY_METADATA = | |
| FileArtifactValue.createForRemoteFile( | |
| /* digest= */ new byte[0], /* size= */ 0, /* locationIndex= */ 0); | |
| private final ActionInputMap inputMap = new ActionInputMap(0); | |
| private final ArtifactRoot outputRoot = | |
| ArtifactRoot.asDerivedRoot( | |
| new InMemoryFileSystem(DigestHashFunction.SHA256).getPath("/execroot"), | |
| RootType.OUTPUT, | |
| "out"); | |
| @Test | |
| public void regularArtifact() { | |
| Artifact file = ActionsTestUtil.createArtifact(outputRoot, "file"); | |
| inputMap.put(file, DUMMY_METADATA); | |
| CompletionContext ctx = createCompletionContext(); | |
| assertThat(visit(ctx, file)).containsExactly(file); | |
| } | |
| @Test | |
| public void treeArtifact_present() { | |
| SpecialArtifact tree = createTreeArtifact("tree"); | |
| TreeFileArtifact treeFile1 = TreeFileArtifact.createTreeOutput(tree, "file1"); | |
| TreeFileArtifact treeFile2 = TreeFileArtifact.createTreeOutput(tree, "file2"); | |
| TreeArtifactValue treeValue = | |
| TreeArtifactValue.newBuilder(tree) | |
| .putChild(treeFile1, DUMMY_METADATA) | |
| .putChild(treeFile2, DUMMY_METADATA) | |
| .build(); | |
| inputMap.putTreeArtifact(tree, treeValue); | |
| CompletionContext ctx = createCompletionContext(); | |
| assertThat(visit(ctx, tree)).containsExactly(treeFile1, treeFile2).inOrder(); | |
| } | |
| @Test | |
| public void fileset() { | |
| SpecialArtifact fileset = createFileset("fs"); | |
| Artifact b1 = ActionsTestUtil.createArtifact(outputRoot, "b1"); | |
| Artifact b2 = ActionsTestUtil.createArtifact(outputRoot, "b2"); | |
| ImmutableList<FilesetOutputSymlink> links = | |
| ImmutableList.of(filesetLink("a1", b1), filesetLink("a2", b2)); | |
| inputMap.putFileset( | |
| fileset, FilesetOutputTree.create(links, /* treeArtifacts= */ ImmutableMap.of())); | |
| CompletionContext ctx = createCompletionContext(); | |
| ArtifactReceiver receiver = mock(ArtifactReceiver.class); | |
| ctx.visitArtifacts(ImmutableList.of(fileset), receiver); | |
| InOrder inOrder = inOrder(receiver); | |
| inOrder | |
| .verify(receiver) | |
| .acceptFilesetMapping( | |
| fileset, new FilesetOutputSymlink(PathFragment.create("a1"), b1, DUMMY_METADATA)); | |
| inOrder | |
| .verify(receiver) | |
| .acceptFilesetMapping( | |
| fileset, new FilesetOutputSymlink(PathFragment.create("a2"), b2, DUMMY_METADATA)); | |
| } | |
| private static List<Artifact> visit(CompletionContext ctx, Artifact artifact) { | |
| List<Artifact> visited = new ArrayList<>(); | |
| ctx.visitArtifacts( | |
| ImmutableList.of(artifact), | |
| new ArtifactReceiver() { | |
| @Override | |
| public void accept(Artifact artifact, FileArtifactValue metadata) { | |
| visited.add(artifact); | |
| } | |
| @Override | |
| public void acceptFilesetMapping(Artifact fileset, FilesetOutputSymlink link) { | |
| throw new AssertionError(fileset); | |
| } | |
| }); | |
| return visited; | |
| } | |
| private SpecialArtifact createTreeArtifact(String rootRelativePath) { | |
| return ActionsTestUtil.createTreeArtifactWithGeneratingAction( | |
| outputRoot, outputRoot.getExecPath().getRelative(rootRelativePath)); | |
| } | |
| private SpecialArtifact createFileset(String rootRelativePath) { | |
| return SpecialArtifact.create( | |
| outputRoot, | |
| outputRoot.getExecPath().getRelative(rootRelativePath), | |
| ActionsTestUtil.NULL_ARTIFACT_OWNER, | |
| SpecialArtifactType.FILESET); | |
| } | |
| private static FilesetOutputSymlink filesetLink(String from, Artifact target) { | |
| return new FilesetOutputSymlink(PathFragment.create(from), target, DUMMY_METADATA); | |
| } | |
| private CompletionContext createCompletionContext() { | |
| return new CompletionContext(ArtifactPathResolver.IDENTITY, inputMap); | |
| } | |
| } |