// 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.android; import static com.google.common.truth.Truth.assertAbout; import static com.google.common.truth.Truth.assertThat; import com.android.ide.common.internal.PngCruncher; import com.android.ide.common.internal.PngException; import com.google.common.collect.ImmutableMap; import com.google.common.jimfs.Jimfs; import com.google.common.truth.Subject; import com.google.common.util.concurrent.MoreExecutors; import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Tests for the AndroidDataWriter. */ @RunWith(JUnit4.class) public class AndroidDataWriterTest { private static final String START_RESOURCES = new String(AndroidDataWriter.PRELUDE) + "", "") .addResource( "values/stubs.xml", AndroidDataBuilder.ResourceType.VALUE, "") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("values/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + ">", "", "", "", "", "", END_RESOURCES); } @Test public void writeResourceXmlWithQualfiers() throws Exception { Path target = fs.getPath("target"); Path source = fs.getPath("source"); AndroidDataWriter mergedDataWriter = AndroidDataWriter.createWithDefaults(target); ParsedAndroidData direct = AndroidDataBuilder.of(source) .addResource( "values/ids.xml", AndroidDataBuilder.ResourceType.VALUE, "") .addResource( "values-en/ids.xml", AndroidDataBuilder.ResourceType.VALUE, "") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("values/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + ">", "", END_RESOURCES); assertAbout(paths).that(actual.getResourceDir().resolve("values-en/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values-en/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + ">", "", END_RESOURCES); } @Test public void writePublicResourceSameNameDifferentType() throws Exception { Path target = fs.getPath("target"); Path source = fs.getPath("source"); AndroidDataWriter mergedDataWriter = AndroidDataWriter.createWithDefaults(target); ParsedAndroidData direct = AndroidDataBuilder.of(source) .addResource( "values/integers.xml", AndroidDataBuilder.ResourceType.VALUE, "12345", "", "54321", "") .addResource( "values/strings.xml", AndroidDataBuilder.ResourceType.VALUE, "meow", "") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("values/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + ">", "", "12345", "54321", "", "meow", "", "", "", "", END_RESOURCES); } @Test public void writeWithIDDuplicates() throws Exception { // We parse IDs from layout, etc. XML. We can include it in the merged values.xml redundantly // (redundant because we also give aapt the original layout xml, which it can parse for IDs // too), but make sure we don't accidentally put multiple copies in the merged values.xml file. // Otherwise, aapt will throw an error if there are duplicates in the same values.xml file. Path target = fs.getPath("target"); Path source = fs.getPath("source"); AndroidDataWriter mergedDataWriter = AndroidDataWriter.createWithDefaults(target); ParsedAndroidData direct = AndroidDataBuilder.of(source) .addResource( "layout/some_layout.xml", AndroidDataBuilder.ResourceType.LAYOUT, "", // Test redundantly having a "+id/MyTextView" in a different attribute. "") // Test what happens if a user accidentally uses the same ID in multiple layouts too. .addResource( "layout/another_layout.xml", AndroidDataBuilder.ResourceType.LAYOUT, "") // Also check what happens if a value XML file also contains the same ID. .addResource( "values/ids.xml", AndroidDataBuilder.ResourceType.VALUE, "", "") .addResource( "values/strings.xml", AndroidDataBuilder.ResourceType.VALUE, "I has a bucket") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("layout/some_layout.xml")).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("values/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + ">", "", "", "", "", "I has a bucket", END_RESOURCES); } @Test public void writeResourceXmlWithAttributes() throws Exception { Path target = fs.getPath("target"); Path source = fs.getPath("source"); AndroidDataWriter mergedDataWriter = AndroidDataWriter.createWithDefaults(target); ParsedAndroidData direct = AndroidDataBuilder.of(source) .addValuesWithAttributes( "values/ids.xml", ImmutableMap.of("foo", "fooVal", "bar", "barVal"), "", "") .addValuesWithAttributes( "values/stubs.xml", ImmutableMap.of("baz", "bazVal"), "") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getResourceDir().resolve("values/values.xml")).exists(); assertAbout(paths) .that(actual.getResourceDir().resolve("values/values.xml")) .xmlContentsIsEqualTo( START_RESOURCES + " foo=\"fooVal\" bar=\"barVal\" baz=\"bazVal\">", "", "", "", "", "", END_RESOURCES); } @Test public void writeAssetFile() throws Exception { Path target = fs.getPath("target"); Path source = fs.getPath("source"); AndroidDataWriter mergedDataWriter = AndroidDataWriter.createWithDefaults(target); String asset = "hunting/of/the/boojum"; ParsedAndroidData direct = AndroidDataBuilder.of(source) .addAsset(asset, "not a snark!") .createManifest("AndroidManifest.xml", "com.carroll.lewis", "") .buildParsed(); MergedAndroidData actual = UnwrittenMergedAndroidData.of( source.resolve("AndroidManifest.xml"), direct, ParsedAndroidDataBuilder.empty()) .write(mergedDataWriter); assertAbout(paths).that(actual.getManifest()).exists(); assertAbout(paths).that(actual.getAssetDir().resolve(asset)).exists(); } private static final Subject.Factory paths = PathsSubject::new; }