diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java b/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java new file mode 100644 index 0000000000..71cf9c4b5d --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java @@ -0,0 +1,246 @@ +// Copyright 2015 Google Inc. 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.devtools.build.lib.actions.util.ActionsTestUtil.NULL_ACTION_OWNER; +import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.NULL_ARTIFACT_OWNER; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; +import com.google.devtools.build.lib.actions.util.ActionsTestUtil; +import com.google.devtools.build.lib.packages.PackageIdentifier; +import com.google.devtools.build.lib.vfs.Path; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.lib.vfs.util.FsApparatus; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Tests {@link ArtifactFactory}. Also see {@link ArtifactTest} for a test + * of individual artifacts. + */ +@RunWith(JUnit4.class) +public class ArtifactFactoryTest { + + private FsApparatus scratch = FsApparatus.newInMemory(); + + private Path execRoot; + private Root clientRoot; + private Root clientRoRoot; + private Root outRoot; + + private PathFragment fooPath; + private PackageIdentifier fooPackage; + private PathFragment fooRelative; + + private PathFragment barPath; + private PackageIdentifier barPackage; + private PathFragment barRelative; + + private ArtifactFactory artifactFactory; + + @Before + public void setUp() throws Exception { + execRoot = scratch.dir("/output/workspace"); + clientRoot = Root.asSourceRoot(scratch.dir("/client/workspace")); + clientRoRoot = Root.asSourceRoot(scratch.dir("/client/RO/workspace")); + outRoot = Root.asDerivedRoot(execRoot, execRoot.getRelative("out-root/x/bin")); + + fooPath = new PathFragment("foo"); + fooPackage = PackageIdentifier.createInDefaultRepo(fooPath); + fooRelative = fooPath.getRelative("foosource.txt"); + + barPath = new PathFragment("foo/bar"); + barPackage = PackageIdentifier.createInDefaultRepo(barPath); + barRelative = barPath.getRelative("barsource.txt"); + + artifactFactory = new ArtifactFactory(execRoot); + setupRoots(); + } + + private void setupRoots() { + Map<PackageIdentifier, Root> packageRootMap = new HashMap<>(); + packageRootMap.put(fooPackage, clientRoot); + packageRootMap.put(barPackage, clientRoRoot); + artifactFactory.setPackageRoots(packageRootMap); + artifactFactory.setDerivedArtifactRoots(ImmutableList.of(outRoot)); + } + + @Test + public void testGetSourceArtifactYieldsSameArtifact() throws Exception { + assertSame(artifactFactory.getSourceArtifact(fooRelative, clientRoot), + artifactFactory.getSourceArtifact(fooRelative, clientRoot)); + } + + @Test + public void testGetSourceArtifactUnnormalized() throws Exception { + assertSame(artifactFactory.getSourceArtifact(fooRelative, clientRoot), + artifactFactory.getSourceArtifact(new PathFragment("foo/./foosource.txt"), + clientRoot)); + } + + @Test + public void testResolveArtifact_noDerived_simpleSource() throws Exception { + assertSame(artifactFactory.getSourceArtifact(fooRelative, clientRoot), + artifactFactory.resolveSourceArtifact(fooRelative)); + assertSame(artifactFactory.getSourceArtifact(barRelative, clientRoRoot), + artifactFactory.resolveSourceArtifact(barRelative)); + } + + @Test + public void testResolveArtifact_noDerived_derivedRoot() throws Exception { + assertNull(artifactFactory.resolveSourceArtifact( + outRoot.getPath().getRelative(fooRelative).relativeTo(execRoot))); + assertNull(artifactFactory.resolveSourceArtifact( + outRoot.getPath().getRelative(barRelative).relativeTo(execRoot))); + } + + @Test + public void testResolveArtifact_noDerived_simpleSource_other() throws Exception { + Artifact actual = artifactFactory.resolveSourceArtifact(fooRelative); + assertSame(artifactFactory.getSourceArtifact(fooRelative, clientRoot), actual); + actual = artifactFactory.resolveSourceArtifact(barRelative); + assertSame(artifactFactory.getSourceArtifact(barRelative, clientRoRoot), actual); + } + + @Test + public void testClearResetsFactory() { + Artifact fooArtifact = artifactFactory.getSourceArtifact(fooRelative, clientRoot); + artifactFactory.clear(); + setupRoots(); + assertNotSame(fooArtifact, artifactFactory.getSourceArtifact(fooRelative, clientRoot)); + } + + @Test + public void testFindDerivedRoot() throws Exception { + assertSame(outRoot, + artifactFactory.findDerivedRoot(outRoot.getPath().getRelative(fooRelative))); + assertSame(outRoot, + artifactFactory.findDerivedRoot(outRoot.getPath().getRelative(barRelative))); + } + + @Test + public void testSetGeneratingActionIdempotenceNewActionGraph() throws Exception { + Artifact a = artifactFactory.getDerivedArtifact(fooRelative, outRoot, NULL_ARTIFACT_OWNER); + Artifact b = artifactFactory.getDerivedArtifact(barRelative, outRoot, NULL_ARTIFACT_OWNER); + MutableActionGraph actionGraph = new MapBasedActionGraph(); + Action originalAction = new ActionsTestUtil.NullAction(NULL_ACTION_OWNER, a); + actionGraph.registerAction(originalAction); + + // Creating a second Action referring to the Artifact should create a conflict. + try { + Action action = new ActionsTestUtil.NullAction(NULL_ACTION_OWNER, a, b); + actionGraph.registerAction(action); + fail(); + } catch (ActionConflictException e) { + assertSame(a, e.getArtifact()); + assertSame(originalAction, actionGraph.getGeneratingAction(a)); + } + } + + @Test + public void testGetDerivedArtifact() throws Exception { + PathFragment toolPath = new PathFragment("_bin/tool"); + Artifact artifact = artifactFactory.getDerivedArtifact(toolPath); + assertEquals(toolPath, artifact.getExecPath()); + assertEquals(Root.asDerivedRoot(execRoot), artifact.getRoot()); + assertEquals(execRoot.getRelative(toolPath), artifact.getPath()); + assertNull(artifact.getOwner()); + } + + @Test + public void testGetDerivedArtifactFailsForAbsolutePath() throws Exception { + try { + artifactFactory.getDerivedArtifact(new PathFragment("/_bin/b")); + fail(); + } catch (IllegalArgumentException e) { + // Expected exception + } + } + + private static class MockPackageRootResolver implements PackageRootResolver { + private Map<PathFragment, Root> packageRoots = Maps.newHashMap(); + + public void setPackageRoots(Map<PackageIdentifier, Root> packageRoots) { + for (Entry<PackageIdentifier, Root> packageRoot : packageRoots.entrySet()) { + this.packageRoots.put(packageRoot.getKey().getPackageFragment(), packageRoot.getValue()); + } + } + + @Override + public Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths) { + Map<PathFragment, Root> result = new HashMap<>(); + for (PathFragment execPath : execPaths) { + for (PathFragment dir = execPath.getParentDirectory(); dir != null; + dir = dir.getParentDirectory()) { + if (packageRoots.get(dir) != null) { + result.put(execPath, packageRoots.get(dir)); + } + } + if (result.get(execPath) == null) { + result.put(execPath, null); + } + } + return result; + } + } + + @Test + public void testArtifactDeserializationWithoutReusedArtifacts() throws Exception { + PathFragment derivedPath = outRoot.getExecPath().getRelative("fruit/banana"); + artifactFactory.clear(); + artifactFactory.setDerivedArtifactRoots(ImmutableList.of(outRoot)); + MockPackageRootResolver rootResolver = new MockPackageRootResolver(); + rootResolver.setPackageRoots( + ImmutableMap.of(PackageIdentifier.createInDefaultRepo(""), clientRoot)); + Artifact artifact1 = artifactFactory.deserializeArtifact(derivedPath, rootResolver); + Artifact artifact2 = artifactFactory.deserializeArtifact(derivedPath, rootResolver); + assertEquals(artifact1, artifact2); + assertNull(artifact1.getOwner()); + assertNull(artifact2.getOwner()); + assertEquals(derivedPath, artifact1.getExecPath()); + assertEquals(derivedPath, artifact2.getExecPath()); + + // Source artifacts are always reused + PathFragment sourcePath = clientRoot.getExecPath().getRelative("fruit/mango"); + artifact1 = artifactFactory.deserializeArtifact(sourcePath, rootResolver); + artifact2 = artifactFactory.deserializeArtifact(sourcePath, rootResolver); + assertSame(artifact1, artifact2); + assertEquals(sourcePath, artifact1.getExecPath()); + } + + @Test + public void testDeserializationWithInvalidPath() throws Exception { + artifactFactory.clear(); + PathFragment randomPath = new PathFragment("maracuja/lemon/kiwi"); + Artifact artifact = artifactFactory.deserializeArtifact(randomPath, + new MockPackageRootResolver()); + assertNull(artifact); + } +} |