aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-06-30 15:37:34 +0200
committerGravatar Marcel Hlopko <hlopko@google.com>2017-07-03 09:05:07 +0200
commit3e2cee83eddb340d9a0d96cc545ccbda76b489ac (patch)
tree2533fdc53f091386e633c162a476c83fb61c9a10 /src/test
parent469079377a9561a7c2cc7a46492c44e012b9fb33 (diff)
Add methods for filtering LocalResourceContainer
Dynamically Configured Resource Filtering change 1/6 To enable dynamically configured resource filtering, we'll need to be able to pass filtered resources into resource processing code used by android_library targets. The resource parsing action, used only in android_library targets, takes the LocalResourceContainer as an input, unlike android_binary processing code which never used it directly. Abstract the code for actually building the collection of resource roots out of the withResources method, and create an additional method for calling it from resource filtering. Also, split some common test code out of ResourceFilterTestBase to make a ResourceTestBase class for testing changes to this (and eventually, other) resource-oriented classes, and create LocalResourceContainerTest for this class in particular. RELNOTES: none PiperOrigin-RevId: 160640192
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/BUILD42
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/LocalResourceContainerTest.java172
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/ResourceFilterTest.java79
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/ResourceTestBase.java164
6 files changed, 394 insertions, 71 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
index 888047d871..35f940f6b5 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
@@ -2410,7 +2410,7 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
checkError("java/android/resources", "r",
"'java/android/resources/res/somefile.xml' is not in the expected resource directory "
+ "structure of <resource directory>/{"
- + Joiner.on(',').join(LocalResourceContainer.Builder.RESOURCE_DIRECTORY_TYPES) + "}",
+ + Joiner.on(',').join(LocalResourceContainer.RESOURCE_DIRECTORY_TYPES) + "}",
"android_binary(name = 'r',",
" manifest = 'AndroidManifest.xml',",
" resource_files = ['res/somefile.xml', 'r/t/f/m/raw/fold']",
@@ -2424,7 +2424,7 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
"r",
"'java/android/resources/res/other/somefile.xml' is not in the expected resource directory "
+ "structure of <resource directory>/{"
- + Joiner.on(',').join(LocalResourceContainer.Builder.RESOURCE_DIRECTORY_TYPES) + "}",
+ + Joiner.on(',').join(LocalResourceContainer.RESOURCE_DIRECTORY_TYPES) + "}",
"android_binary(name = 'r',",
" manifest = 'AndroidManifest.xml',",
" resource_files = ['res/other/somefile.xml', 'r/t/f/m/raw/fold']",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
index ab4a1c1eac..b8298e2ea9 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
@@ -822,7 +822,7 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
checkError("java/android", "r",
"'java/android/res/somefile.xml' is not in the expected resource directory structure of"
+ " <resource directory>/{"
- + Joiner.on(',').join(LocalResourceContainer.Builder.RESOURCE_DIRECTORY_TYPES) + "}",
+ + Joiner.on(',').join(LocalResourceContainer.RESOURCE_DIRECTORY_TYPES) + "}",
"android_library(name = 'r',",
" manifest = 'AndroidManifest.xml',",
" resource_files = ['res/somefile.xml', 'r/t/f/m/raw/fold']",
@@ -834,7 +834,7 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
checkError("java/android", "r",
"'java/android/res/other/somefile.xml' is not in the expected resource directory structure"
+ " of <resource directory>/{"
- + Joiner.on(',').join(LocalResourceContainer.Builder.RESOURCE_DIRECTORY_TYPES) + "}",
+ + Joiner.on(',').join(LocalResourceContainer.RESOURCE_DIRECTORY_TYPES) + "}",
"android_library(name = 'r',",
" manifest = 'AndroidManifest.xml',",
" resource_files = ['res/other/somefile.xml', 'r/t/f/m/raw/fold']",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
index 96e6b301fe..c011cde25e 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
@@ -77,6 +77,48 @@ java_test(
)
java_test(
+ name = "ResourceFilterTest",
+ srcs = ["ResourceFilterTest.java"],
+ deps = [
+ ":ResourceTestBase",
+ "//src/main/java/com/google/devtools/build/lib:android-rules",
+ "//src/main/java/com/google/devtools/build/lib/actions",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+java_test(
+ name = "LocalResourceContainerTest",
+ srcs = ["LocalResourceContainerTest.java"],
+ deps = [
+ ":ResourceTestBase",
+ "//src/main/java/com/google/devtools/build/lib:android-rules",
+ "//src/main/java/com/google/devtools/build/lib:packages-internal",
+ "//src/main/java/com/google/devtools/build/lib:vfs",
+ "//src/main/java/com/google/devtools/build/lib/actions",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+java_library(
+ name = "ResourceTestBase",
+ srcs = ["ResourceTestBase.java"],
+ deps = [
+ "//src/main/java/com/google/devtools/build/lib:inmemoryfs",
+ "//src/main/java/com/google/devtools/build/lib:packages-internal",
+ "//src/main/java/com/google/devtools/build/lib:vfs",
+ "//src/main/java/com/google/devtools/build/lib/actions",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+java_test(
name = "AndroidDeviceScriptFixtureTest",
srcs = ["AndroidDeviceScriptFixtureTest.java"],
deps = [
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/LocalResourceContainerTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/LocalResourceContainerTest.java
new file mode 100644
index 0000000000..6f397bf5fb
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/LocalResourceContainerTest.java
@@ -0,0 +1,172 @@
+// Copyright 2017 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.rules.android;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
+import com.google.devtools.build.lib.packages.RuleErrorConsumer;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests {@link LocalResourceContainer} */
+@RunWith(JUnit4.class)
+public class LocalResourceContainerTest extends ResourceTestBase {
+ private static final PathFragment DEFAULT_RESOURCE_ROOT = PathFragment.create(RESOURCE_ROOT);
+ private static final ImmutableList<PathFragment> RESOURCES_ROOTS =
+ ImmutableList.of(DEFAULT_RESOURCE_ROOT);
+
+ @Before
+ @Test
+ public void testGetResourceRootsNoResources() throws Exception {
+ assertThat(getResourceRoots()).isEmpty();
+ }
+
+ @Test
+ public void testGetResourceRootsInvalidResourceDirectory() throws Exception {
+ try {
+ getResourceRoots("is-this-drawable-or-values/foo.xml");
+ assertWithMessage("Expected exception not thrown!").fail();
+ } catch (RuleErrorException e) {
+ // expected
+ }
+
+ errorConsumer.assertAttributeError(
+ "resources", "is not in the expected resource directory structure");
+ }
+
+ @Test
+ public void testGetResourceRootsMultipleRoots() throws Exception {
+ try {
+ getResourceRoots("subdir/values/foo.xml", "otherdir/values/bar.xml");
+ assertWithMessage("Expected exception not thrown!").fail();
+ } catch (RuleErrorException e) {
+ // expected
+ }
+
+ errorConsumer.assertAttributeError(
+ "resources", "All resources must share a common directory");
+ }
+
+ @Test
+ public void testGetResourceRoots() throws Exception {
+ assertThat(getResourceRoots("values-hdpi/foo.xml", "values-mdpi/bar.xml"))
+ .isEqualTo(RESOURCES_ROOTS);
+ }
+
+ @Test
+ public void testGetResourceRootsCommonSubdirectory() throws Exception {
+ assertThat(getResourceRoots("subdir/values-hdpi/foo.xml", "subdir/values-mdpi/bar.xml"))
+ .containsExactly(DEFAULT_RESOURCE_ROOT.getRelative("subdir"));
+ }
+
+ private ImmutableList<PathFragment> getResourceRoots(String... pathResourceStrings)
+ throws Exception {
+ return getResourceRoots(getResources(pathResourceStrings));
+ }
+
+ private ImmutableList<PathFragment> getResourceRoots(ImmutableList<Artifact> artifacts)
+ throws Exception {
+ return LocalResourceContainer.getResourceRoots(errorConsumer, artifacts);
+ }
+
+ @Test
+ public void testFilterEmpty() throws Exception {
+ assertFilter(ImmutableList.<Artifact>of(), ImmutableList.<Artifact>of());
+ }
+
+ @Test
+ public void testFilterNoop() throws Exception {
+ ImmutableList<Artifact> resources = getResources("values-en/foo.xml", "values-es/bar.xml");
+ assertFilter(resources, resources);
+ }
+
+ @Test
+ public void testFilterToEmpty() throws Exception {
+ assertFilter(
+ getResources("values-en/foo.xml", "values-es/bar.xml"), ImmutableList.<Artifact>of());
+ }
+
+ @Test
+ public void testPartiallyFilter() throws Exception {
+ Artifact keptResource = getResource("values-en/foo.xml");
+ assertFilter(
+ ImmutableList.of(keptResource, getResource("values-es/bar.xml")),
+ ImmutableList.of(keptResource));
+ }
+
+ private void assertFilter(
+ ImmutableList<Artifact> unfilteredResources, ImmutableList<Artifact> filteredResources)
+ throws Exception {
+ ResourceFilter filter =
+ new FakeResourceFilter(ImmutableMap.of(unfilteredResources, filteredResources));
+ ImmutableList<PathFragment> unfilteredResourcesRoots = getResourceRoots(unfilteredResources);
+ LocalResourceContainer unfiltered =
+ new LocalResourceContainer(
+ unfilteredResources,
+ unfilteredResourcesRoots,
+ unfilteredResources,
+ unfilteredResourcesRoots);
+
+ LocalResourceContainer filtered = unfiltered.filter(errorConsumer, filter);
+
+ if (unfilteredResources.equals(filteredResources)) {
+ // The filtering was a no-op; the original object, not a copy, should be returned
+ assertThat(filtered).isSameAs(unfiltered);
+ } else {
+ // The resources and their roots should be filtered
+ assertThat(filtered.getResources()).containsExactlyElementsIn(filteredResources).inOrder();
+ assertThat(filtered.getResourceRoots())
+ .containsExactlyElementsIn(getResourceRoots(filteredResources))
+ .inOrder();
+
+ // The assets and their roots should not be filtered; the original objects, not a copy, should
+ // be returned.
+ assertThat(filtered.getAssets()).isSameAs(unfiltered.getAssets());
+ assertThat(filtered.getAssetRoots()).isSameAs(unfiltered.getAssetRoots());
+ }
+ }
+
+ private static class FakeResourceFilter extends ResourceFilter {
+ private final Map<ImmutableList<Artifact>, ImmutableList<Artifact>> filterInputToOutputMap;
+
+ FakeResourceFilter(
+ Map<ImmutableList<Artifact>, ImmutableList<Artifact>> filterInputToOutputMap) {
+ super(
+ ImmutableList.<String>of(),
+ ImmutableList.<String>of(),
+ FilterBehavior.FILTER_IN_ANALYSIS);
+ this.filterInputToOutputMap = filterInputToOutputMap;
+ }
+
+ @Override
+ public ImmutableList<Artifact> filter(
+ RuleErrorConsumer errorConsumer, ImmutableList<Artifact> artifacts) {
+ if (filterInputToOutputMap.containsKey(artifacts)) {
+ return filterInputToOutputMap.get(artifacts);
+ }
+
+ assertWithMessage("Called with unexpected input: " + artifacts).fail();
+ return artifacts;
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/ResourceFilterTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/ResourceFilterTest.java
index 8dbb18df72..b7aaf7d1d0 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/ResourceFilterTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/ResourceFilterTest.java
@@ -14,22 +14,13 @@
package com.google.devtools.build.lib.rules.android;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
-import com.google.devtools.build.lib.packages.RuleErrorConsumer;
import com.google.devtools.build.lib.rules.android.ResourceFilter.FilterBehavior;
-import com.google.devtools.build.lib.vfs.FileSystem;
-import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -38,53 +29,7 @@ import org.junit.runners.JUnit4;
// TODO(asteinb): Test behavior not already covered in this test, and, when practical, move unit
// tests currently located in {@link AndroidBinaryTest} to this class instead.
@RunWith(JUnit4.class)
-public class ResourceFilterTest {
- private FakeRuleErrorConsumer errorConsumer;
-
- @Before
- public void setup() {
- errorConsumer = new FakeRuleErrorConsumer();
- }
-
- private static final class FakeRuleErrorConsumer implements RuleErrorConsumer {
- // Use an ArrayListMultimap since it allows duplicates - we'll want to know if a warning is
- // reported twice.
- private final Multimap<String, String> attributeWarnings = ArrayListMultimap.create();
-
- @Override
- public void ruleWarning(String message) {}
-
- @Override
- public void ruleError(String message) {
- assertWithMessage(message).fail();
- }
-
- @Override
- public void attributeWarning(String attrName, String message) {
- attributeWarnings.put(attrName, message);
- }
-
- @Override
- public void attributeError(String attrName, String message) {
- assertWithMessage(message + " (attribute: " + attrName + ")").fail();
- }
-
- public Collection<String> getAndClearAttributeWarnings(String attrName) {
- if (!attributeWarnings.containsKey(attrName)) {
- return ImmutableList.of();
- }
-
- return attributeWarnings.removeAll(attrName);
- }
-
- public void assertNoAttributeWarnings(String attrName) {
- assertThat(attributeWarnings).doesNotContainKey(attrName);
- }
- };
-
- private static final FileSystem FILE_SYSTEM = new InMemoryFileSystem();
- private static final Root ROOT = Root.asSourceRoot(FILE_SYSTEM.getRootDirectory());
-
+public class ResourceFilterTest extends ResourceTestBase {
@Test
public void testFilterInExecution() {
testNoopFilter(
@@ -98,10 +43,10 @@ public class ResourceFilterTest {
@Test
public void testFilterEmpty() {
testNoopFilter(
- ImmutableList.of(),
- ImmutableList.of(),
+ ImmutableList.<String>of(),
+ ImmutableList.<String>of(),
FilterBehavior.FILTER_IN_ANALYSIS,
- ImmutableList.of());
+ ImmutableList.<String>of());
}
@Test
@@ -128,7 +73,7 @@ public class ResourceFilterTest {
@Test
public void testFilterByDensityPersistsOrdering() {
testFilter(
- ImmutableList.of(),
+ ImmutableList.<String>of(),
ImmutableList.of("hdpi", "ldpi"),
FilterBehavior.FILTER_IN_ANALYSIS,
// If we add resources to the output list in density order, these resources will be
@@ -306,7 +251,11 @@ public class ResourceFilterTest {
FilterBehavior filterBehavior,
List<String> resources) {
testFilter(
- resourceConfigurationFilters, densities, filterBehavior, resources, ImmutableList.of());
+ resourceConfigurationFilters,
+ densities,
+ filterBehavior,
+ resources,
+ ImmutableList.<String>of());
}
private void testFilter(
@@ -317,12 +266,12 @@ public class ResourceFilterTest {
List<String> resourcesToDiscard) {
List<Artifact> unexpectedResources = new ArrayList<>();
for (String resource : resourcesToDiscard) {
- unexpectedResources.add(getArtifact(resource));
+ unexpectedResources.add(getResource(resource));
}
List<Artifact> expectedResources = new ArrayList<>();
for (String resource : resourcesToKeep) {
- expectedResources.add(getArtifact(resource));
+ expectedResources.add(getResource(resource));
}
ImmutableList<Artifact> allArtifacts =
@@ -333,8 +282,4 @@ public class ResourceFilterTest {
assertThat(filtered).containsExactlyElementsIn(expectedResources).inOrder();
}
-
- private static Artifact getArtifact(String pathString) {
- return new Artifact(FILE_SYSTEM.getPath("/java/android/res/" + pathString), ROOT);
- }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/ResourceTestBase.java b/src/test/java/com/google/devtools/build/lib/rules/android/ResourceTestBase.java
new file mode 100644
index 0000000000..cada5518d9
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/ResourceTestBase.java
@@ -0,0 +1,164 @@
+// Copyright 2017 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.rules.android;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.packages.RuleErrorConsumer;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+import java.util.Collection;
+import org.junit.After;
+import org.junit.Before;
+
+/** Base class for tests that work with resource artifacts. */
+public abstract class ResourceTestBase {
+ public static final String RESOURCE_ROOT = "java/android/res";
+
+ private static final ArtifactOwner OWNER = () -> {
+ try {
+ return Label.create("java", "all");
+ } catch (LabelSyntaxException e) {
+ assertWithMessage(e.getMessage()).fail();
+ return null;
+ }
+ };
+
+ /** A faked {@link RuleErrorConsumer} that validates that only expected errors were reported. */
+ public static final class FakeRuleErrorConsumer implements RuleErrorConsumer {
+ private String ruleErrorMessage = null;
+ private String attributeErrorAttribute = null;
+ private String attributeErrorMessage = null;
+
+ // Use an ArrayListMultimap since it allows duplicates - we'll want to know if a warning is
+ // reported twice.
+ private final Multimap<String, String> attributeWarnings = ArrayListMultimap.create();
+
+ @Override
+ public void ruleWarning(String message) {}
+
+ @Override
+ public void ruleError(String message) {
+ ruleErrorMessage = message;
+ }
+
+ @Override
+ public void attributeWarning(String attrName, String message) {
+ attributeWarnings.put(attrName, message);
+ }
+
+ @Override
+ public void attributeError(String attrName, String message) {
+ attributeErrorAttribute = attrName;
+ attributeErrorMessage = message;
+ }
+
+ public Collection<String> getAndClearAttributeWarnings(String attrName) {
+ if (!attributeWarnings.containsKey(attrName)) {
+ return ImmutableList.of();
+ }
+
+ return attributeWarnings.removeAll(attrName);
+ }
+
+ public void assertNoAttributeWarnings(String attrName) {
+ assertThat(attributeWarnings).doesNotContainKey(attrName);
+ }
+
+ /**
+ * Called at the end of a test to assert that that test produced a rule error
+ *
+ * @param expectedMessage a substring of the expected message
+ */
+ public void assertRuleError(String expectedMessage) {
+ // Clear the message before asserting so that if we fail here the error is not masked by the
+ // @After call to assertNoUnexpectedErrors.
+
+ String message = ruleErrorMessage;
+ ruleErrorMessage = null;
+
+ assertThat(message).contains(expectedMessage);
+ }
+
+ /**
+ * Called at the end of a test to assert that that test produced an attribute error
+ *
+ * @param expectedAttribute the attribute that caused the error
+ * @param expectedMessage a substring of the expected message
+ */
+ public void assertAttributeError(String expectedAttribute, String expectedMessage) {
+ // Clear the message before asserting so that if we fail here the error is not masked by the
+ // @After call to assertNoUnexpectedErrors.
+ String attr = attributeErrorAttribute;
+ String message = attributeErrorMessage;
+ attributeErrorAttribute = null;
+ attributeErrorMessage = null;
+
+ assertThat(message).contains(expectedMessage);
+ assertThat(attr).isEqualTo(expectedAttribute);
+ }
+
+ /**
+ * Asserts this {@link RuleErrorConsumer} encountered no unexpected errors. To consume an
+ * expected error, call {@link #assertRuleError(String)} or {@link #assertAttributeError(String,
+ * String)} in your test after the error is produced.
+ */
+ private void assertNoUnexpectedErrors() {
+ assertThat(ruleErrorMessage).isNull();
+ assertThat(attributeErrorMessage).isNull();
+ assertThat(attributeErrorAttribute).isNull();
+ }
+ };
+
+ public FakeRuleErrorConsumer errorConsumer;
+ public FileSystem fileSystem;
+ public Root root;
+
+ @Before
+ public void setup() {
+ errorConsumer = new FakeRuleErrorConsumer();
+ fileSystem = new InMemoryFileSystem();
+ root = Root.asDerivedRoot(fileSystem.getRootDirectory());
+ }
+
+ @After
+ public void assertNoErrors() {
+ errorConsumer.assertNoUnexpectedErrors();
+ }
+
+ public ImmutableList<Artifact> getResources(String... pathStrings) {
+ ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
+ for (String pathString : pathStrings) {
+ builder.add(getResource(pathString));
+ }
+
+ return builder.build();
+ }
+
+ public Artifact getResource(String pathString) {
+ Path path = fileSystem.getPath("/" + RESOURCE_ROOT + "/" + pathString);
+ return new Artifact(
+ path, root, root.getExecPath().getRelative(path.relativeTo(root.getPath())), OWNER);
+ }
+}