diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java | 174 |
1 files changed, 171 insertions, 3 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java index 056970f322..1f81b1300c 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java @@ -19,10 +19,20 @@ import static com.google.common.truth.Truth.assertWithMessage; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.common.collect.Streams; +import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; +import com.google.devtools.build.lib.events.ExtendedEventHandler; +import com.google.devtools.build.lib.events.StoredEventHandler; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; +import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.Optional; +import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,6 +45,8 @@ public class AndroidResourcesTest extends ResourceTestBase { private static final ImmutableList<PathFragment> RESOURCES_ROOTS = ImmutableList.of(DEFAULT_RESOURCE_ROOT); + private static final ImmutableSet<String> TOOL_FILENAMES = ImmutableSet.of("aapt2", "empty.sh"); + @Before @Test public void testGetResourceRootsNoResources() throws Exception { @@ -91,7 +103,7 @@ public class AndroidResourcesTest extends ResourceTestBase { @Test public void testFilterEmpty() throws Exception { - assertFilter(ImmutableList.<Artifact>of(), ImmutableList.<Artifact>of()); + assertFilter(ImmutableList.of(), ImmutableList.of()); } @Test @@ -102,8 +114,7 @@ public class AndroidResourcesTest extends ResourceTestBase { @Test public void testFilterToEmpty() throws Exception { - assertFilter( - getResources("values-en/foo.xml", "values-es/bar.xml"), ImmutableList.<Artifact>of()); + assertFilter(getResources("values-en/foo.xml", "values-es/bar.xml"), ImmutableList.of()); } @Test @@ -168,4 +179,161 @@ public class AndroidResourcesTest extends ResourceTestBase { Iterables.concat(filteredDepsBuilder.build(), filteredResources)); } } + + @Test + public void testParseNoCompile() throws Exception { + useConfiguration("--android_aapt=aapt"); + + RuleContext ruleContext = getRuleContext(/* useDataBinding = */ true); + ParsedAndroidResources parsed = assertParse(ruleContext); + + // Since we are not using aapt2, there should be no compiled symbols + assertThat(parsed.getCompiledSymbols()).isNull(); + + // The parse action should take resources in and output symbols + assertActionArtifacts( + ruleContext, + /* inputs = */ parsed.getResources(), + /* outputs = */ ImmutableList.of(parsed.getSymbols())); + } + + @Test + public void testParseAndCompile() throws Exception { + mockAndroidSdkWithAapt2(); + useConfiguration("--android_sdk=//sdk:sdk", "--android_aapt=aapt2"); + + RuleContext ruleContext = getRuleContext(/* useDataBinding = */ false); + ParsedAndroidResources parsed = assertParse(ruleContext); + + assertThat(parsed.getCompiledSymbols()).isNotNull(); + + // The parse action should take resources in and output symbols + assertActionArtifacts( + ruleContext, + /* inputs = */ parsed.getResources(), + /* outputs = */ ImmutableList.of(parsed.getSymbols())); + + // Since there was no data binding, the compile action should just take in resources and output + // compiled symbols. + assertActionArtifacts( + ruleContext, + /* inputs = */ parsed.getResources(), + /* outputs = */ ImmutableList.of(parsed.getCompiledSymbols())); + } + + @Test + public void testParseWithDataBinding() throws Exception { + mockAndroidSdkWithAapt2(); + useConfiguration("--android_sdk=//sdk:sdk", "--android_aapt=aapt2"); + + RuleContext ruleContext = getRuleContext(/* useDataBinding = */ true); + + ParsedAndroidResources parsed = assertParse(ruleContext); + + // The parse action should take resources and busybox artifacts in and output symbols + assertActionArtifacts( + ruleContext, + /* inputs = */ parsed.getResources(), + /* outputs = */ ImmutableList.of(parsed.getSymbols())); + + // The compile action should take in resources and manifest in and output compiled symbols and + // an unused data binding zip. + assertActionArtifacts( + ruleContext, + /* inputs = */ ImmutableList.<Artifact>builder() + .addAll(parsed.getResources()) + .add(getManifest()) + .build(), + /* outputs = */ ImmutableList.of( + parsed.getCompiledSymbols(), + DataBinding.getSuffixedInfoFile(ruleContext, "_unused"))); + } + + /** + * Assets that the action used to generate the given outputs has the expected inputs and outputs. + */ + private void assertActionArtifacts( + RuleContext ruleContext, ImmutableList<Artifact> inputs, ImmutableList<Artifact> outputs) { + // Actions must have at least one output + assertThat(outputs).isNotEmpty(); + + // Get the action from one of the outputs + ActionAnalysisMetadata action = + ruleContext.getAnalysisEnvironment().getLocalGeneratingAction(outputs.get(0)); + assertThat(action).isNotNull(); + + assertThat(removeToolingArtifacts(action.getInputs())).containsExactlyElementsIn(inputs); + + assertThat(action.getOutputs()).containsExactlyElementsIn(outputs); + } + + /** Remove busybox and aapt2 tooling artifacts from a list of action inputs */ + private Iterable<Artifact> removeToolingArtifacts(Iterable<Artifact> inputArtifacts) { + return Streams.stream(inputArtifacts) + .filter( + artifact -> + // Not a known tool + !TOOL_FILENAMES.contains(artifact.getFilename()) + // Not one of the various busybox tools (we get different ones on different OSs) + && !artifact.getFilename().contains("busybox") + // Not a params file + && !artifact.getFilename().endsWith(".params")) + .collect(Collectors.toList()); + } + + /** + * Validates that a parse action was invoked correctly. Returns the {@link ParsedAndroidResources} + * for further validation. + */ + private ParsedAndroidResources assertParse(RuleContext ruleContext) throws Exception { + ImmutableList<Artifact> resources = getResources("values-en/foo.xml", "drawable-hdpi/bar.png"); + AndroidResources raw = + new AndroidResources( + resources, AndroidResources.getResourceRoots(ruleContext, resources, "resource_files")); + StampedAndroidManifest manifest = + new StampedAndroidManifest(ruleContext, getManifest(), "some.java.pkg", false); + + ParsedAndroidResources parsed = raw.parse(ruleContext, manifest); + + // Inherited values should be equal + assertThat(raw).isEqualTo(parsed); + + // Label should be set from RuleContext + assertThat(parsed.getLabel()).isEqualTo(ruleContext.getLabel()); + + return parsed; + } + + private Artifact getManifest() { + return getResource("some/path/AndroidManifest.xml"); + } + + /** Gets a dummy rule context object by creating a dummy target. */ + private RuleContext getRuleContext(boolean useDataBinding) throws Exception { + ConfiguredTarget target = + scratchConfiguredTarget( + "java/foo", + "target", + "android_library(name = 'target',", + useDataBinding ? " enable_data_binding = True" : "", + ")"); + RuleContext dummy = getRuleContext(target); + + ExtendedEventHandler eventHandler = new StoredEventHandler(); + assertThat(targetConfig.isActionsEnabled()).isTrue(); + return view.getRuleContextForTesting( + eventHandler, + target, + new CachingAnalysisEnvironment( + view.getArtifactFactory(), + skyframeExecutor.getActionKeyContext(), + ConfiguredTargetKey.of(target.getLabel(), targetConfig), + /*isSystemEnv=*/ false, + targetConfig.extendedSanityChecks(), + eventHandler, + /*env=*/ null, + targetConfig.isActionsEnabled()), + new BuildConfigurationCollection( + ImmutableList.of(dummy.getConfiguration()), dummy.getHostConfiguration())); + } } |