blob: 3d47cb9b8ee9b0a4d4b81ae1f0d3f38b1aafc12d [file] [log] [blame]
// Copyright 2018 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion;
import com.google.devtools.build.lib.vfs.PathFragment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests {@link AndroidAssets} */
@RunWith(JUnit4.class)
public class AndroidAssetsTest extends ResourceTestBase {
@Test
public void testParse() throws Exception {
RuleContext ruleContext = getRuleContext();
AndroidAssets assets = getLocalAssets();
ParsedAndroidAssets parsed =
assets.parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT);
// Assets should be unchanged
assertThat(parsed.getAssets()).isEqualTo(assets.getAssets());
assertThat(parsed.getAssetRoots()).isEqualTo(assets.getAssetRoots());
// Label should be correct
assertThat(parsed.getLabel()).isEqualTo(ruleContext.getLabel());
// Symbols file should be created from raw assets
assertActionArtifacts(
ruleContext,
/* inputs = */ assets.getAssets(),
/* outputs = */ ImmutableList.of(parsed.getSymbols()));
// There should be no compiled symbols
assertThat(parsed.getCompiledSymbols()).isNull();
}
@Test
public void testParseAapt2() throws Exception {
mockAndroidSdkWithAapt2();
useConfiguration("--android_sdk=//sdk:sdk");
RuleContext ruleContext = getRuleContext();
AndroidAssets assets = getLocalAssets();
ParsedAndroidAssets parsed =
assets.parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT2);
// Assets should be unchanged
assertThat(parsed.getAssets()).isEqualTo(assets.getAssets());
assertThat(parsed.getAssetRoots()).isEqualTo(assets.getAssetRoots());
// Label should be correct
assertThat(parsed.getLabel()).isEqualTo(ruleContext.getLabel());
// There should be compiled symbols
assertThat(parsed.getCompiledSymbols()).isNotNull();
// Symbols and compiled symbols files should be created from raw assets
assertActionArtifacts(
ruleContext,
/* inputs = */ assets.getAssets(),
/* outputs = */ ImmutableList.of(parsed.getSymbols()));
assertActionArtifacts(
ruleContext,
/* inputs = */ assets.getAssets(),
/* outputs = */ ImmutableList.of(parsed.getCompiledSymbols()));
}
@Test
public void testMergeNoDeps() throws Exception {
RuleContext ruleContext = getRuleContext();
ParsedAndroidAssets parsed =
getLocalAssets().parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT);
MergedAndroidAssets merged = assertMerge(ruleContext, parsed, AssetDependencies.empty());
// The assets can be correctly built into a provider
AndroidAssetsInfo info = merged.toProvider();
assertThat(info.getLabel()).isEqualTo(merged.getLabel());
// The provider just has the local values
assertThat(info.getAssets()).containsExactlyElementsIn(merged.getAssets()).inOrder();
assertThat(info.getSymbols()).containsExactly(merged.getSymbols());
assertThat(info.getDirectParsedAssets()).containsExactly(parsed);
assertThat(info.getTransitiveParsedAssets()).isEmpty();
}
@Test
public void testMergeNeverlink() throws Exception {
RuleContext ruleContext = getRuleContext();
ParsedAndroidAssets parsed =
getLocalAssets().parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT);
AssetDependencies deps = makeDeps(ruleContext, /* neverlink = */ true, AndroidAaptVersion.AAPT);
MergedAndroidAssets merged = assertMerge(ruleContext, parsed, deps);
AndroidAssetsInfo info = merged.toProvider();
assertThat(info.getLabel()).isEqualTo(merged.getLabel());
// The provider should be empty because of neverlinking
assertThat(info.getAssets()).isEmpty();
assertThat(info.getSymbols()).isEmpty();
assertThat(info.getDirectParsedAssets()).isEmpty();
assertThat(info.getTransitiveParsedAssets()).isEmpty();
assertThat(info.getCompiledSymbols()).isEmpty();
}
@Test
public void testMerge() throws Exception {
RuleContext ruleContext = getRuleContext();
ParsedAndroidAssets parsed =
getLocalAssets().parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT);
AssetDependencies deps =
makeDeps(ruleContext, /* neverlink = */ false, AndroidAaptVersion.AAPT);
MergedAndroidAssets merged = assertMerge(ruleContext, parsed, deps);
AndroidAssetsInfo info = merged.toProvider();
assertThat(info.getLabel()).isEqualTo(merged.getLabel());
// The provider should have transitive and direct deps
assertThat(info.getAssets())
.containsExactlyElementsIn(Iterables.concat(parsed.getAssets(), deps.getTransitiveAssets()))
.inOrder();
assertThat(info.getSymbols())
.containsExactlyElementsIn(
Iterables.concat(ImmutableList.of(parsed.getSymbols()), deps.getTransitiveSymbols()))
.inOrder();
assertThat(info.getDirectParsedAssets()).containsExactly(parsed).inOrder();
assertThat(info.getTransitiveParsedAssets())
.containsExactlyElementsIn(
Iterables.concat(deps.getTransitiveParsedAssets(), deps.getDirectParsedAssets()))
.inOrder();
// There should be no compiled symbols
assertThat(info.getCompiledSymbols()).isEmpty();
}
@Test
public void testMergeAapt2() throws Exception {
mockAndroidSdkWithAapt2();
useConfiguration("--android_sdk=//sdk:sdk");
RuleContext ruleContext = getRuleContext();
ParsedAndroidAssets parsed =
getLocalAssets().parse(AndroidDataContext.forNative(ruleContext), AndroidAaptVersion.AAPT2);
AssetDependencies deps =
makeDeps(ruleContext, /* neverlink = */ false, AndroidAaptVersion.AAPT2);
MergedAndroidAssets merged = assertMerge(ruleContext, parsed, deps);
AndroidAssetsInfo info = merged.toProvider();
assertThat(info.getLabel()).isEqualTo(merged.getLabel());
// The provider should have transitive and direct deps
assertThat(info.getAssets())
.containsExactlyElementsIn(Iterables.concat(parsed.getAssets(), deps.getTransitiveAssets()))
.inOrder();
assertThat(info.getSymbols())
.containsExactlyElementsIn(
Iterables.concat(ImmutableList.of(parsed.getSymbols()), deps.getTransitiveSymbols()))
.inOrder();
assertThat(info.getCompiledSymbols())
.containsExactlyElementsIn(
Iterables.concat(
ImmutableList.of(parsed.getCompiledSymbols()),
deps.getTransitiveCompiledSymbols()));
assertThat(info.getDirectParsedAssets()).containsExactly(parsed).inOrder();
assertThat(info.getTransitiveParsedAssets())
.containsExactlyElementsIn(
Iterables.concat(deps.getTransitiveParsedAssets(), deps.getDirectParsedAssets()))
.inOrder();
}
private AssetDependencies makeDeps(
RuleContext ruleContext, boolean neverlink, AndroidAaptVersion aaptVersion) {
ParsedAndroidAssets firstDirect = getDependencyAssets(ruleContext, "first_direct", aaptVersion);
ParsedAndroidAssets secondDirect =
getDependencyAssets(ruleContext, "second_direct", aaptVersion);
ParsedAndroidAssets firstTransitive =
getDependencyAssets(ruleContext, "first_transitive", aaptVersion);
ParsedAndroidAssets secondTransitive =
getDependencyAssets(ruleContext, "second_transitive", aaptVersion);
return AssetDependencies.of(
neverlink,
NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, firstDirect, secondDirect),
NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, firstTransitive, secondTransitive),
NestedSetBuilder.wrap(
Order.NAIVE_LINK_ORDER,
Iterables.concat(
firstDirect.getAssets(),
secondDirect.getAssets(),
firstTransitive.getAssets(),
secondTransitive.getAssets())),
NestedSetBuilder.wrap(
Order.NAIVE_LINK_ORDER,
ImmutableList.of(
firstDirect.getSymbols(),
secondDirect.getSymbols(),
firstTransitive.getSymbols(),
secondTransitive.getSymbols())),
aaptVersion == AndroidAaptVersion.AAPT2
? NestedSetBuilder.wrap(
Order.NAIVE_LINK_ORDER,
ImmutableList.of(
firstDirect.getCompiledSymbols(),
secondDirect.getCompiledSymbols(),
firstTransitive.getCompiledSymbols(),
secondTransitive.getCompiledSymbols()))
: NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER));
}
private MergedAndroidAssets assertMerge(
RuleContext ruleContext, ParsedAndroidAssets parsed, AssetDependencies deps)
throws InterruptedException {
MergedAndroidAssets merged =
MergedAndroidAssets.mergeFrom(AndroidDataContext.forNative(ruleContext), parsed, deps);
// Inherited values should be unchanged
assertThat(new ParsedAndroidAssets(merged)).isEqualTo(parsed);
// The raw assets should be used to merge
assertActionArtifacts(
ruleContext,
/* inputs = */ ImmutableList.<Artifact>builder()
.addAll(merged.getAssets())
.add(merged.getSymbols())
.addAll(deps.getTransitiveAssets())
.addAll(deps.getTransitiveSymbols())
.build(),
/* outputs = */ ImmutableList.of(merged.getMergedAssets()));
return merged;
}
private AndroidAssets getLocalAssets() {
return new AndroidAssets(
ImmutableList.of(getResource("asset_1"), getResource("asset_2")),
ImmutableList.of(PathFragment.create("asset_dir")),
"asset_dir");
}
private ParsedAndroidAssets getDependencyAssets(
RuleContext ruleContext, String depName, AndroidAaptVersion aaptVersion) {
return ParsedAndroidAssets.of(
new AndroidAssets(
ImmutableList.of(getResource(depName + "_asset_1"), getResource(depName + "_asset_2")),
ImmutableList.of(PathFragment.create(depName)),
depName),
getResource("symbols_for_" + depName),
aaptVersion == AndroidAaptVersion.AAPT2
? getResource("compiled_symbols_for_" + depName)
: null,
ruleContext.getLabel());
}
private RuleContext getRuleContext() throws Exception {
return getRuleContextForActionTesting(
scratchConfiguredTarget("pkg", "r", "android_library(name='r')"));
}
}