From 3ed13c847ec4953442f8ff36461196c1b978d1ef Mon Sep 17 00:00:00 2001 From: Googler Date: Mon, 7 Mar 2016 21:53:29 +0000 Subject: Detect and warn about runfiles conflicts. A runfile conflict is when two different artifacts have been added to a Runfiles object under the same relative path. Conflict resolution is unchanged (last artifact wins). -- MOS_MIGRATED_REVID=116584195 --- .../devtools/build/lib/analysis/RunfilesTest.java | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) (limited to 'src/test/java/com') diff --git a/src/test/java/com/google/devtools/build/lib/analysis/RunfilesTest.java b/src/test/java/com/google/devtools/build/lib/analysis/RunfilesTest.java index dec63d4805..223357e7db 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/RunfilesTest.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/RunfilesTest.java @@ -29,6 +29,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -120,4 +121,171 @@ public class RunfilesTest extends FoundationTestCase { Maps.immutableEntry(pathBC, artifactBC)); assertNoEvents(); } + + private void checkConflictWarning() { + assertContainsEvent("overwrote runfile"); + assertEquals("ConflictChecker.put should have warned once", 1, eventCollector.count()); + assertEquals(EventKind.WARNING, Iterables.getOnlyElement(eventCollector).getKind()); + } + + private void checkConflictError() { + assertContainsEvent("overwrote runfile"); + assertEquals("ConflictChecker.put should have errored once", 1, eventCollector.count()); + assertEquals(EventKind.ERROR, Iterables.getOnlyElement(eventCollector).getKind()); + } + + @Test + public void testPutCatchesConflict() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Artifact artifactC = new Artifact(new PathFragment("c"), root); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, artifactB); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactB)); + checker.put(map, pathA, artifactC); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactC)); + checkConflictWarning(); + } + + @Test + public void testPutReportsError() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Artifact artifactC = new Artifact(new PathFragment("c"), root); + Map map = new LinkedHashMap<>(); + + // Same as above but with ERROR not WARNING + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.ERROR, reporter, null); + checker.put(map, pathA, artifactB); + reporter.removeHandler(failFastHandler); // So it doesn't throw AssertionError + checker.put(map, pathA, artifactC); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactC)); + checkConflictError(); + } + + @Test + public void testPutCatchesConflictBetweenNullAndNotNull() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, null); + checker.put(map, pathA, artifactB); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactB)); + checkConflictWarning(); + } + + @Test + public void testPutCatchesConflictBetweenNotNullAndNull() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Map map = new LinkedHashMap<>(); + + // Same as above but opposite order + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, artifactB); + checker.put(map, pathA, null); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, null)); + checkConflictWarning(); + } + + @Test + public void testPutIgnoresConflict() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Artifact artifactC = new Artifact(new PathFragment("c"), root); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.IGNORE, reporter, null); + checker.put(map, pathA, artifactB); + checker.put(map, pathA, artifactC); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactC)); + assertNoEvents(); + } + + @Test + public void testPutIgnoresConflictNoListener() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Artifact artifactC = new Artifact(new PathFragment("c"), root); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, null, null); + checker.put(map, pathA, artifactB); + checker.put(map, pathA, artifactC); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactC)); + assertNoEvents(); + } + + @Test + public void testPutIgnoresSameArtifact() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Artifact artifactB2 = new Artifact(new PathFragment("b"), root); + assertEquals(artifactB, artifactB2); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, artifactB); + checker.put(map, pathA, artifactB2); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, artifactB2)); + assertNoEvents(); + } + + @Test + public void testPutIgnoresNullAndNull() { + PathFragment pathA = new PathFragment("a"); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, null); + // Add it again + checker.put(map, pathA, null); + assertThat(map.entrySet()).containsExactly(Maps.immutableEntry(pathA, null)); + assertNoEvents(); + } + + @Test + public void testPutNoConflicts() { + Root root = Root.asSourceRoot(scratch.resolve("/workspace")); + PathFragment pathA = new PathFragment("a"); + PathFragment pathB = new PathFragment("b"); + PathFragment pathC = new PathFragment("c"); + Artifact artifactA = new Artifact(new PathFragment("a"), root); + Artifact artifactB = new Artifact(new PathFragment("b"), root); + Map map = new LinkedHashMap<>(); + + Runfiles.ConflictChecker checker = + new Runfiles.ConflictChecker(Runfiles.ConflictPolicy.WARN, reporter, null); + checker.put(map, pathA, artifactA); + // Add different artifact under different path + checker.put(map, pathB, artifactB); + // Add artifact again under different path + checker.put(map, pathC, artifactA); + assertThat(map.entrySet()) + .containsExactly( + Maps.immutableEntry(pathA, artifactA), + Maps.immutableEntry(pathB, artifactB), + Maps.immutableEntry(pathC, artifactA)) + .inOrder(); + assertNoEvents(); + } } -- cgit v1.2.3