From 115ea10fe907b80ea11ad7db6f50657ecc2c18cb Mon Sep 17 00:00:00 2001 From: ajmichael Date: Wed, 29 Mar 2017 18:34:24 +0000 Subject: Move more Android tools' tests into Bazel. RELNOTES: None PiperOrigin-RevId: 151602497 --- .../java/com/google/devtools/build/android/BUILD | 74 +++++ .../DensitySpecificManifestProcessorTest.java | 255 ++++++++++++++++ .../build/android/DependencyAndroidDataTest.java | 166 +++++++++++ .../build/android/SerializedAndroidDataTest.java | 113 +++++++ .../android/SplitConfigurationFilterTest.java | 327 +++++++++++++++++++++ .../build/android/UnvalidatedAndroidDataTest.java | 104 +++++++ .../android/UnvalidatedAndroidDirectoriesTest.java | 81 +++++ 7 files changed, 1120 insertions(+) create mode 100644 src/test/java/com/google/devtools/build/android/DensitySpecificManifestProcessorTest.java create mode 100644 src/test/java/com/google/devtools/build/android/DependencyAndroidDataTest.java create mode 100644 src/test/java/com/google/devtools/build/android/SerializedAndroidDataTest.java create mode 100644 src/test/java/com/google/devtools/build/android/SplitConfigurationFilterTest.java create mode 100644 src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDataTest.java create mode 100644 src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDirectoriesTest.java (limited to 'src/test/java/com') diff --git a/src/test/java/com/google/devtools/build/android/BUILD b/src/test/java/com/google/devtools/build/android/BUILD index edc97011db..76c476f865 100644 --- a/src/test/java/com/google/devtools/build/android/BUILD +++ b/src/test/java/com/google/devtools/build/android/BUILD @@ -77,6 +77,31 @@ java_test( ], ) +java_test( + name = "DensitySpecificManifestProcessorTest", + srcs = ["DensitySpecificManifestProcessorTest.java"], + tags = ["no_windows"], # Test asserts forward slashes in android data xml files. + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:jimfs", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "DependencyAndroidDataTest", + srcs = ["DependencyAndroidDataTest.java"], + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:jimfs", + "//third_party:junit4", + "//third_party:truth", + ], +) + java_test( name = "ParsedAndroidDataTest", srcs = ["ParsedAndroidDataTest.java"], @@ -92,6 +117,55 @@ java_test( ], ) +java_test( + name = "SerializedAndroidDataTest", + srcs = ["SerializedAndroidDataTest.java"], + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:jimfs", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "SplitConfigurationFilterTest", + srcs = ["SplitConfigurationFilterTest.java"], + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:guava-testlib", + "//third_party:jsr305", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "UnvalidatedAndroidDataTest", + srcs = ["UnvalidatedAndroidDataTest.java"], + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:jimfs", + "//third_party:junit4", + "//third_party:truth", + ], +) + +java_test( + name = "UnvalidatedAndroidDirectoriesTest", + srcs = ["UnvalidatedAndroidDirectoriesTest.java"], + deps = [ + "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", + "//third_party:guava", + "//third_party:jimfs", + "//third_party:junit4", + "//third_party:truth", + ], +) + java_library( name = "test_utils", testonly = 1, diff --git a/src/test/java/com/google/devtools/build/android/DensitySpecificManifestProcessorTest.java b/src/test/java/com/google/devtools/build/android/DensitySpecificManifestProcessorTest.java new file mode 100644 index 0000000000..9d02a28ef8 --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/DensitySpecificManifestProcessorTest.java @@ -0,0 +1,255 @@ +// 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.assertThat; +import static com.google.devtools.build.android.DensitySpecificManifestProcessor.PLAY_STORE_SUPPORTED_DENSITIES; +import static com.google.devtools.build.android.DensitySpecificManifestProcessor.SCREEN_SIZES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.jimfs.Jimfs; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** Tests for {@link DensitySpecificManifestProcessor}. */ +@RunWith(JUnit4.class) +public class DensitySpecificManifestProcessorTest { + + private FileSystem fs; + private Path tmp; + + @Test public void testNoDensities() throws Exception { + Path manifest = createManifest("", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(ImmutableList.of(), + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertEquals(manifest, modified); + } + + @Test public void testSingleDensity() throws Exception { + ImmutableList densities = ImmutableList.of("xhdpi"); + Path manifest = createManifest("", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkModification(modified, densities); + } + + @Test public void test280Density() throws Exception { + ImmutableList densities = ImmutableList.of("280dpi"); + Path manifest = createManifest("", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkModification(modified, densities); + } + + @Test public void testMultipleDensities() throws Exception { + ImmutableList densities = ImmutableList.of("xhdpi", "xxhdpi", "560dpi", "xxxhdpi"); + Path manifest = createManifest("", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkModification(modified, densities); + } + + @Test public void omitCompatibleScreensIfDensityUnsupported() throws Exception { + ImmutableList densities = ImmutableList.of("xhdpi", "340dpi", "xxhdpi"); + Path manifest = createManifest("", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkCompatibleScreensOmitted(modified); + } + + @Test public void testExistingCompatibleScreens() throws Exception { + ImmutableList densities = ImmutableList.of("xhdpi"); + Path manifest = createManifest("", + "", + "", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkModification(modified, densities); + } + + @Test public void testExistingSupersetCompatibleScreens() throws Exception { + ImmutableList densities = ImmutableList.of("ldpi"); + Path manifest = createManifest("", + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "", + ""); + Path modified = new DensitySpecificManifestProcessor(densities, + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + assertNotNull(modified); + checkModification(modified, ImmutableList.of("ldpi", "xxhdpi")); + } + + @Test public void testMalformedManifest() throws Exception { + Path manifest = createManifest("", + "", + "", + "", + ""); + try { + new DensitySpecificManifestProcessor(ImmutableList.of("xhdpi"), + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + fail(); + } catch (ManifestProcessingException e) { + assertThat(e).hasMessageThat().contains("must be well-formed"); + } + } + + @Test public void testNoManifest() throws Exception { + Path manifest = createManifest(""); + try { + new DensitySpecificManifestProcessor(ImmutableList.of("xhdpi"), + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + fail(); + } catch (ManifestProcessingException e) { + assertThat(e).hasMessageThat().contains("Premature end of file."); + } + } + + @Test public void testNestedManifest() throws Exception { + Path manifest = createManifest("", + "", + " ", + " ", + ""); + try { + new DensitySpecificManifestProcessor(ImmutableList.of("xhdpi"), + tmp.resolve("manifest-filtered/AndroidManifest.xml")).process(manifest); + fail(); + } catch (ManifestProcessingException e) { + assertThat(e).hasMessageThat().contains("does not contain exactly one "); + } + } + + @Before + public void setUpEnvironment() throws Exception { + fs = Jimfs.newFileSystem(); + tmp = fs.getPath("/tmp"); + Files.createDirectory(tmp); + } + + @After + public void cleanUpEnvironment() throws Exception { + fs.close(); + } + + private Path createManifest(String... lines) throws IOException { + final Path path = tmp.resolve("AndroidManifest.xml"); + Files.createDirectories(path.getParent()); + Files.deleteIfExists(path); + BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8); + writer.write(Joiner.on("\n").join(lines)); + writer.close(); + return path; + } + + private void checkModification(Path manifest, List densities) throws Exception { + Set sizeDensities = new HashSet<>(); + for (String density : densities) { + for (String screenSize : SCREEN_SIZES) { + sizeDensities.add(screenSize + + PLAY_STORE_SUPPORTED_DENSITIES.get(density)); + } + } + + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = db.parse(Files.newInputStream(manifest)); + NodeList compatibleScreensNodes = doc.getElementsByTagName("compatible-screens"); + assertEquals(1, compatibleScreensNodes.getLength()); + Node compatibleScreens = compatibleScreensNodes.item(0); + NodeList screens = doc.getElementsByTagName("screen"); + assertEquals(densities.size() * SCREEN_SIZES.size(), + screens.getLength()); + for (int i = 0; i < screens.getLength(); i++) { + Node s = screens.item(i); + assertTrue(s.getParentNode().isSameNode(compatibleScreens)); + if (s.getNodeType() == Node.ELEMENT_NODE) { + Element screen = (Element) s; + assertTrue(sizeDensities.remove( + screen.getAttribute("android:screenSize") + + screen.getAttribute("android:screenDensity"))); + } + } + assertThat(sizeDensities).isEmpty(); + } + + private void checkCompatibleScreensOmitted(Path manifest) throws Exception { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = db.parse(Files.newInputStream(manifest)); + NodeList compatibleScreensNodes = doc.getElementsByTagName("compatible-screens"); + assertEquals(0, compatibleScreensNodes.getLength()); + NodeList screens = doc.getElementsByTagName("screen"); + assertEquals(0, screens.getLength()); + } + +} diff --git a/src/test/java/com/google/devtools/build/android/DependencyAndroidDataTest.java b/src/test/java/com/google/devtools/build/android/DependencyAndroidDataTest.java new file mode 100644 index 0000000000..2026aafb09 --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/DependencyAndroidDataTest.java @@ -0,0 +1,166 @@ +// 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 com.google.common.collect.ImmutableList; +import com.google.common.jimfs.Jimfs; +import com.google.common.truth.Truth; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for the {@link DependencyAndroidData}. + */ +@RunWith(JUnit4.class) +public class DependencyAndroidDataTest { + private FileSystem fileSystem; + private Path root; + private Path rTxt; + private Path manifest; + private Path res; + private Path otherRes; + private Path assets; + private Path otherAssets; + private Path symbols; + + @Before public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(); + root = Files.createDirectories(fileSystem.getPath("")); + rTxt = Files.createFile(root.resolve("r.txt")); + symbols = Files.createFile(root.resolve("symbols.bin")); + manifest = Files.createFile(root.resolve("AndroidManifest.xml")); + res = Files.createDirectories(root.resolve("res")); + otherRes = Files.createDirectories(root.resolve("otherres")); + assets = Files.createDirectories(root.resolve("assets")); + otherAssets = Files.createDirectories(root.resolve("otherassets")); + } + + @Test public void flagFullParse() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + "res#otherres:assets#otherassets:AndroidManifest.xml:r.txt:symbols.bin", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + manifest, + rTxt, + symbols)); + } + + @Test public void flagParseWithNoSymbolsFile() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + "res#otherres:assets#otherassets:AndroidManifest.xml:r.txt:", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + manifest, + rTxt, + null)); + } + + @Test public void flagParseOmittedSymbolsFile() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + "res#otherres:assets#otherassets:AndroidManifest.xml:r.txt", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + manifest, + rTxt, + null)); + } + + @Test public void flagParseWithEmptyResources() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + ":assets:AndroidManifest.xml:r.txt:symbols.bin", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(), + ImmutableList.of(assets), + manifest, + rTxt, + symbols)); + } + + @Test public void flagParseWithEmptyAssets() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + "res::AndroidManifest.xml:r.txt:symbols.bin", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(res), + ImmutableList.of(), + manifest, + rTxt, + symbols)); + } + + @Test public void flagParseWithEmptyResourcesAndAssets() throws Exception{ + Truth.assertThat( + DependencyAndroidData.valueOf( + "::AndroidManifest.xml:r.txt:symbols.bin", fileSystem) + ).isEqualTo( + new DependencyAndroidData(ImmutableList.of(), + ImmutableList.of(), + manifest, + rTxt, + symbols)); + } + + @Test public void flagNoManifestFails() { + try { + DependencyAndroidData.valueOf(":::r.txt", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void flagMissingManifestFails() { + try { + DependencyAndroidData.valueOf("::Manifest.xml:r.txt:symbols.bin", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void flagNoRTxtFails() { + try { + DependencyAndroidData.valueOf("::AndroidManifest.xml:", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void flagMissingRTxtFails() { + try { + DependencyAndroidData.valueOf("::Manifest.xml:missing_file", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void flagMissingSymbolsFails() { + try { + DependencyAndroidData.valueOf("::Manifest.xml:r.txt:missing_file", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } +} diff --git a/src/test/java/com/google/devtools/build/android/SerializedAndroidDataTest.java b/src/test/java/com/google/devtools/build/android/SerializedAndroidDataTest.java new file mode 100644 index 0000000000..c40f90438c --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/SerializedAndroidDataTest.java @@ -0,0 +1,113 @@ +// 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 com.google.common.collect.ImmutableList; +import com.google.common.jimfs.Jimfs; +import com.google.common.truth.Truth; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for the {@link SerializedAndroidData}. */ +@RunWith(JUnit4.class) +public class SerializedAndroidDataTest { + private FileSystem fileSystem; + private Path res; + private Path otherRes; + private Path assets; + private Path otherAssets; + private String label; + private Path symbols; + + @Before + public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(); + Path root = Files.createDirectories(fileSystem.getPath("")); + symbols = Files.createFile(root.resolve("symbols.bin")); + res = Files.createDirectories(root.resolve("res")); + otherRes = Files.createDirectories(root.resolve("otherres")); + assets = Files.createDirectories(root.resolve("assets")); + otherAssets = Files.createDirectories(root.resolve("otherassets")); + label = "//some_target/foo:foo"; + } + + @Test + public void flagFullParse() throws Exception { + Truth.assertThat( + SerializedAndroidData.valueOf( + "res#otherres;assets#otherassets;//some_target/foo:foo;symbols.bin", fileSystem)) + .isEqualTo( + new SerializedAndroidData( + ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + label, + symbols)); + } + + @Test + public void flagParseWithNoSymbolsFile() throws Exception { + Truth.assertThat( + SerializedAndroidData.valueOf( + "res#otherres;assets#otherassets;//some_target/foo:foo;", fileSystem)) + .isEqualTo( + new SerializedAndroidData( + ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + label, + null)); + } + + @Test + public void flagParseWithEmptyResources() throws Exception { + Truth.assertThat( + SerializedAndroidData.valueOf( + ";assets;//some_target/foo:foo;symbols.bin", fileSystem)) + .isEqualTo( + new SerializedAndroidData( + ImmutableList.of(), ImmutableList.of(assets), label, symbols)); + } + + @Test + public void flagParseWithEmptyAssets() throws Exception { + Truth.assertThat( + SerializedAndroidData.valueOf("res;;//some_target/foo:foo;symbols.bin", fileSystem)) + .isEqualTo( + new SerializedAndroidData( + ImmutableList.of(res), ImmutableList.of(), label, symbols)); + } + + @Test + public void flagParseWithEmptyResourcesAndAssets() throws Exception { + Truth.assertThat( + SerializedAndroidData.valueOf(";;//some_target/foo:foo;symbols.bin", fileSystem)) + .isEqualTo( + new SerializedAndroidData( + ImmutableList.of(), ImmutableList.of(), label, symbols)); + } + + @Test + public void flagNoLabelFails() { + try { + SerializedAndroidData.valueOf(";;symbols.bin", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } +} diff --git a/src/test/java/com/google/devtools/build/android/SplitConfigurationFilterTest.java b/src/test/java/com/google/devtools/build/android/SplitConfigurationFilterTest.java new file mode 100644 index 0000000000..db55ac1e68 --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/SplitConfigurationFilterTest.java @@ -0,0 +1,327 @@ +// 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.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.devtools.build.android.SplitConfigurationFilter.mapFilenamesToSplitFlags; + +import com.google.common.collect.ImmutableList; +import com.google.common.testing.EqualsTester; +import com.google.common.truth.BooleanSubject; +import com.google.devtools.build.android.SplitConfigurationFilter.ResourceConfiguration; +import com.google.devtools.build.android.SplitConfigurationFilter.UnrecognizedSplitsException; +import javax.annotation.CheckReturnValue; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link SplitConfigurationFilter}. */ +@RunWith(JUnit4.class) +public final class SplitConfigurationFilterTest { + + @Test + public void mapFilenamesToSplitFlagsShouldReturnEmptyMapForEmptyInput() + throws UnrecognizedSplitsException { + assertThat(mapFilenamesToSplitFlags(ImmutableList.of(), ImmutableList.of())) + .isEmpty(); + } + + @Test + public void mapFilenamesToSplitFlagsShouldMatchIdenticalFilenames() + throws UnrecognizedSplitsException { + assertThat(mapFilenamesToSplitFlags(ImmutableList.of("en"), ImmutableList.of("en"))) + .containsExactly("en", "en"); + assertThat(mapFilenamesToSplitFlags(ImmutableList.of("fr-v7"), ImmutableList.of("fr-v7"))) + .containsExactly("fr-v7", "fr-v7"); + assertThat(mapFilenamesToSplitFlags(ImmutableList.of("en_fr-v7"), ImmutableList.of("en,fr-v7"))) + .containsExactly("en_fr-v7", "en_fr-v7"); + assertThat( + mapFilenamesToSplitFlags( + ImmutableList.of("en", "fr-v7"), ImmutableList.of("en", "fr-v7"))) + .containsExactly("en", "en", "fr-v7", "fr-v7"); + assertThat( + mapFilenamesToSplitFlags( + ImmutableList.of("fr-v4", "fr-v7"), ImmutableList.of("fr-v4", "fr-v7"))) + .containsExactly("fr-v4", "fr-v4", "fr-v7", "fr-v7"); + } + + @Test + public void mapFilenamesToSplitFlagsShouldMatchReorderedFilenames() + throws UnrecognizedSplitsException { + assertThat(mapFilenamesToSplitFlags(ImmutableList.of("en_fr_ja"), ImmutableList.of("ja,fr,en"))) + .containsExactly("en_fr_ja", "ja_fr_en"); + assertThat( + mapFilenamesToSplitFlags( + ImmutableList.of("zu_12key", "zu"), ImmutableList.of("12key,zu", "zu"))) + .containsExactly("zu_12key", "12key_zu", "zu", "zu"); + assertThat( + mapFilenamesToSplitFlags( + ImmutableList.of("land_car", "round_port"), + ImmutableList.of("car,land", "port,round"))) + .containsExactly("land_car", "car_land", "round_port", "port_round"); + } + + @Test + public void mapFilenamesToSplitFlagsShouldMatchVersionUpgradedFilenames() + throws UnrecognizedSplitsException { + assertThat(mapFilenamesToSplitFlags(ImmutableList.of("round-v23"), ImmutableList.of("round"))) + .containsExactly("round-v23", "round"); + assertThat( + mapFilenamesToSplitFlags( + ImmutableList.of("watch-v20", "watch-v23"), ImmutableList.of("watch", "watch-v23"))) + .containsExactly("watch-v20", "watch", "watch-v23", "watch-v23"); + } + + @Test + public void equivalentFiltersShouldMatchFilterFromFilename() { + // identical inputs (barring commas -> underscores) should naturally match + assertMatchesFilterFromFilename("abc-def", "abc-def").isTrue(); + assertMatchesFilterFromFilename("abc-def-v5,ghi,jkl-lmno", "abc-def-v5_ghi_jkl-lmno").isTrue(); + // anything that results in matching sets should work, so case should be ignored + assertMatchesFilterFromFilename("abc-dEF", "aBC-def").isTrue(); + assertMatchesFilterFromFilename("aBC-def", "abc-dEF").isTrue(); + // additionally, order of elements in the set should be ignored + assertMatchesFilterFromFilename("abc,def", "def_abc").isTrue(); + assertMatchesFilterFromFilename("def,abc", "abc_def").isTrue(); + } + + @Test + public void matchingSpecifiersShouldMatchFilterFromFilenameWhenVersionsAreHigherNotWhenLower() { + // different (higher) versions, but same specifiers and same order + assertMatchesFilterFromFilename("x-v5,y-v6", "x-v7_y-v9").isTrue(); + assertMatchesFilterFromFilename("x-v7,y-v9", "x-v5_y-v6").isFalse(); + // order of sorted set changes but matching specifiers still match and filename version > flag + assertMatchesFilterFromFilename("x-v3,y-v6", "x-v23_y-v9").isTrue(); + assertMatchesFilterFromFilename("x-v23,y-v9", "x-v3_y-v6").isFalse(); + // specifier sets of multiple configs are the same + assertMatchesFilterFromFilename("x-v3,x-v17", "x-v3_x-v17").isTrue(); + assertMatchesFilterFromFilename("x-v3,x-v17", "x-v17_x-v3").isTrue(); + assertMatchesFilterFromFilename("x-v17,x-v3", "x-v17_x-v3").isTrue(); + assertMatchesFilterFromFilename("x-v17,x-v3", "x-v3_x-v17").isTrue(); + // specifier sets are the same, but one of them got a version bump + assertMatchesFilterFromFilename("x-v3,x-v17", "x-v14_x-v17").isTrue(); + assertMatchesFilterFromFilename("x-v14,x-v17", "x-v3_x-v17").isFalse(); + } + + @Test + public void nonMatchingSpecifiersShouldNotMatchFilterFromFilename() { + // completely disjoint specifier sets + assertMatchesFilterFromFilename("x,y,z", "a_b_c").isFalse(); + assertMatchesFilterFromFilename("a,b,c", "x_y_z").isFalse(); + // different number of specifier sets, which otherwise match + assertMatchesFilterFromFilename("x,y,z", "x_y").isFalse(); + assertMatchesFilterFromFilename("x,y", "x_y_z").isFalse(); + // same number of specifiers with one non-match + assertMatchesFilterFromFilename("x,y,z", "a_y_z").isFalse(); + assertMatchesFilterFromFilename("a,b,c", "a_b_z").isFalse(); + } + + @CheckReturnValue + private BooleanSubject assertMatchesFilterFromFilename(String flagFilter, String filenameFilter) { + return assertWithMessage( + "The split flag '%s' would be a match for a filename containing '%s'", + flagFilter, filenameFilter) + .that( + SplitConfigurationFilter.fromSplitFlag(flagFilter) + .matchesFilterFromFilename( + SplitConfigurationFilter.fromFilenameSuffix(filenameFilter))); + } + + @Test + public void splitConfigurationFilterShouldBeOrderedByConfigsThenFilename() { + assertThat( + ImmutableList.of( + // If all else is equal, break ties via filename (case does matter here) + SplitConfigurationFilter.fromFilenameSuffix("A"), + SplitConfigurationFilter.fromFilenameSuffix("a"), + // In filters with the same number of configs, the highest version wins + SplitConfigurationFilter.fromFilenameSuffix("d-v5_e-v5_f-v5"), + SplitConfigurationFilter.fromFilenameSuffix("a_b_c-v6"), + // It doesn't matter where in the input order that version is + SplitConfigurationFilter.fromFilenameSuffix("a-v7_b_c"), + // Specifiers break ties on number of configs + highest version + SplitConfigurationFilter.fromFilenameSuffix("d-v7_b_c"), + // Second highest version breaks ties (etc.) + SplitConfigurationFilter.fromFilenameSuffix("b-v2_d-v7_c"), + // Order doesn't matter but it does change the filename, hence sort order + SplitConfigurationFilter.fromFilenameSuffix("d-v7_b-v2_c"), + // Number of configs is the main criterion, so more sets of configs means later sort + SplitConfigurationFilter.fromFilenameSuffix("a_b_c_d_e_f_g_h_i_j_k_l_m"))) + .isStrictlyOrdered(); + + // if they are actually equal, they will compare equal + assertThat(SplitConfigurationFilter.fromFilenameSuffix("c-v13")) + .isEquivalentAccordingToCompareTo(SplitConfigurationFilter.fromFilenameSuffix("c-v13")); + + // if the only difference is split flag vs. filename suffix they will compare equal + assertThat(SplitConfigurationFilter.fromSplitFlag("split,split")) + .isEquivalentAccordingToCompareTo( + SplitConfigurationFilter.fromFilenameSuffix("split_split")); + } + + @Test + public void splitConfigurationFilterEqualsShouldPassEqualsTester() { + new EqualsTester() + .addEqualityGroup( + // base example + SplitConfigurationFilter.fromFilenameSuffix("abc-def_ghi_jkl"), + // identical clone + SplitConfigurationFilter.fromFilenameSuffix("abc-def_ghi_jkl"), + // commas are converted for split flags, the result is equal + SplitConfigurationFilter.fromSplitFlag("abc-def,ghi,jkl")) + .addEqualityGroup( + // case matters for filenames + SplitConfigurationFilter.fromFilenameSuffix("aBC-dEF_ghi_jkl")) + .addEqualityGroup( + // different filename producing equal set (elements parse the same) is still different + SplitConfigurationFilter.fromFilenameSuffix("abc-def-v0_ghi_jkl")) + .addEqualityGroup( + // different filename producing equal set (input order is different) is still different + SplitConfigurationFilter.fromFilenameSuffix("ghi_abc-def_jkl")) + .addEqualityGroup( + // totally different set is also very clearly different + SplitConfigurationFilter.fromFilenameSuffix("some-other_specifiers")) + .testEquals(); + } + + @Test + public void equalInputsShouldMatchConfigurationFromFilename() { + // identical inputs should naturally match + assertMatchesConfigurationFromFilename("abc-def", "abc-def").isTrue(); + assertMatchesConfigurationFromFilename("abc-def-v5", "abc-def-v5").isTrue(); + // case should be ignored + assertMatchesConfigurationFromFilename("abc-dEF", "aBC-def").isTrue(); + assertMatchesConfigurationFromFilename("aBC-def", "abc-dEF").isTrue(); + // wildcards should be ignored + assertMatchesConfigurationFromFilename("any-abc-def", "abc-any-def").isTrue(); + assertMatchesConfigurationFromFilename("abc-any-def", "any-abc-def").isTrue(); + // v0 should be ignored + assertMatchesConfigurationFromFilename("abc-def", "abc-def-v0").isTrue(); + assertMatchesConfigurationFromFilename("abc-def-v0", "abc-def").isTrue(); + } + + @Test + public void higherVersionSameSpecifiersShouldMatchConfigurationFromFilename() { + // any version is higher than the default v0 + assertMatchesConfigurationFromFilename("abc-def", "abc-def-v1").isTrue(); + assertMatchesConfigurationFromFilename("abc-def-v1", "abc-def").isFalse(); + // same deal for explicit v0 + assertMatchesConfigurationFromFilename("abc-def-v0", "abc-def-v1").isTrue(); + assertMatchesConfigurationFromFilename("abc-def-v1", "abc-def-v0").isFalse(); + // higher versions are better of course + assertMatchesConfigurationFromFilename("abc-def-v1", "abc-def-v999").isTrue(); + assertMatchesConfigurationFromFilename("abc-def-v999", "abc-def-v1").isFalse(); + } + + @Test + public void nonMatchingSpecifiersShouldNotMatchConfigurationFromFilename() { + // same version + assertMatchesConfigurationFromFilename("abc", "ghi").isFalse(); + assertMatchesConfigurationFromFilename("abc-v0", "ghi-v0").isFalse(); + assertMatchesConfigurationFromFilename("abc-v15", "ghi-v15").isFalse(); + // different version + assertMatchesConfigurationFromFilename("abc", "ghi-v15").isFalse(); + assertMatchesConfigurationFromFilename("abc-v0", "ghi-v15").isFalse(); + assertMatchesConfigurationFromFilename("abc-v15", "ghi-v19").isFalse(); + } + + @CheckReturnValue + private BooleanSubject assertMatchesConfigurationFromFilename( + String flagConfiguration, String fileConfiguration) { + return assertWithMessage( + "The split flag '%s' would be a match for a filename containing '%s'", + flagConfiguration, fileConfiguration) + .that( + ResourceConfiguration.fromString(flagConfiguration) + .matchesConfigurationFromFilename( + ResourceConfiguration.fromString(fileConfiguration))); + } + + @Test + public void resourceConfigurationShouldBeOrderedByApiVersionThenSpecifiers() { + assertThat( + ImmutableList.of( + // -v0 and no -v0 sort equal given the same specifiers, so it's a tie + ResourceConfiguration.fromString("a"), + // version ties are broken based on lexicographic string ordering + ResourceConfiguration.fromString("b-v0"), + // string ordering ignores case of the specifiers + ResourceConfiguration.fromString("Z"), + // higher API versions sort later regardless of the specifiers + ResourceConfiguration.fromString("z-v6"), + ResourceConfiguration.fromString("b-v13"), + // wildcards ("any") are ignored when considering specifier order + ResourceConfiguration.fromString("any-c-v13"))) + .isStrictlyOrdered(); + + // if they are actually equal, they will compare equal + assertThat(ResourceConfiguration.fromString("c-v13")) + .isEquivalentAccordingToCompareTo(ResourceConfiguration.fromString("c-v13")); + + // if the only difference is wildcards they will compare equal + assertThat(ResourceConfiguration.fromString("any-c-v13")) + .isEquivalentAccordingToCompareTo(ResourceConfiguration.fromString("c-v13")); + + // if the only difference is specifying (or not specifying) -v0 they will compare equal + assertThat(ResourceConfiguration.fromString("a-v0")) + .isEquivalentAccordingToCompareTo(ResourceConfiguration.fromString("a")); + + // if the only difference is case they will compare equal + assertThat(ResourceConfiguration.fromString("z")) + .isEquivalentAccordingToCompareTo(ResourceConfiguration.fromString("Z")); + } + + @Test + public void resourceConfigurationShouldPassEqualsTester() { + new EqualsTester() + .addEqualityGroup( + // base example + ResourceConfiguration.fromString("abc-def"), + // identical clone + ResourceConfiguration.fromString("abc-def"), + // case doesn't matter + ResourceConfiguration.fromString("aBC-dEF"), + // absent version code is equivalent to -v0 + ResourceConfiguration.fromString("abc-def-v0"), + // skip "any" + ResourceConfiguration.fromString("any-abc-any-def-any")) + .addEqualityGroup( + // order matters + ResourceConfiguration.fromString("def-abc")) + .addEqualityGroup( + // empty segments are not collapsed + ResourceConfiguration.fromString("abc---def")) + .addEqualityGroup( + // different version codes are parsed but result in a non-equal instance + ResourceConfiguration.fromString("abc-def-v15")) + .addEqualityGroup( + // two configurations with version codes must also have EQUAL version codes + ResourceConfiguration.fromString("abc-def-v12")) + .addEqualityGroup( + // empty strings are equal + ResourceConfiguration.fromString(""), + // yes, even if they have a v0 + ResourceConfiguration.fromString("v0"), + // or if there are some wildcards which will collapse to nothing + ResourceConfiguration.fromString("any"), + ResourceConfiguration.fromString("any-v0"), + ResourceConfiguration.fromString("any-any-any"), + ResourceConfiguration.fromString("any-any-any-v0")) + .addEqualityGroup( + // not if the version is nonzero though + ResourceConfiguration.fromString("v15"), ResourceConfiguration.fromString("any-v15")) + .testEquals(); + } +} diff --git a/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDataTest.java b/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDataTest.java new file mode 100644 index 0000000000..0ee7b25b4f --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDataTest.java @@ -0,0 +1,104 @@ +// 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 com.google.common.collect.ImmutableList; +import com.google.common.jimfs.Jimfs; +import com.google.common.truth.Truth; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link UnvalidatedAndroidData}. */ +@RunWith(JUnit4.class) +public class UnvalidatedAndroidDataTest { + private FileSystem fileSystem; + private Path root; + private Path manifest; + private Path res; + private Path otherRes; + private Path assets; + private Path otherAssets; + + @Before public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(); + root = fileSystem.getPath(""); + manifest = Files.createFile(root.resolve("AndroidManifest.xml")); + res = Files.createDirectories(root.resolve("res")); + otherRes = Files.createDirectories(root.resolve("otherres")); + assets = Files.createDirectories(root.resolve("assets")); + otherAssets = Files.createDirectories(root.resolve("otherassets")); + } + + @Test public void flagFullParse() throws Exception { + Truth.assertThat( + UnvalidatedAndroidData.valueOf( + "res#otherres:assets#otherassets:AndroidManifest.xml", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidData(ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets), + manifest)); + } + + @Test public void flagParseWithEmptyResources() throws Exception { + Truth.assertThat( + UnvalidatedAndroidData.valueOf( + ":assets:AndroidManifest.xml", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidData(ImmutableList.of(), + ImmutableList.of(assets), + manifest)); + } + + @Test public void flagParseWithEmptyAssets() throws Exception { + Truth.assertThat( + UnvalidatedAndroidData.valueOf( + "res::AndroidManifest.xml", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidData(ImmutableList.of(res), + ImmutableList.of(), + manifest)); + } + + @Test public void flagParseWithEmptyResourcesAndAssets() throws Exception { + Truth.assertThat( + UnvalidatedAndroidData.valueOf( + "::AndroidManifest.xml", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidData(ImmutableList.of(), + ImmutableList.of(), + manifest)); + } + + @Test public void flagNoManifestFails() { + try { + UnvalidatedAndroidData.valueOf("::", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void flagMissingManifestFails() { + try { + UnvalidatedAndroidData.valueOf("::Manifest.xml", fileSystem); + Assert.fail("expected exception for bad flag format"); + } catch (IllegalArgumentException expected) { + } + } +} diff --git a/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDirectoriesTest.java b/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDirectoriesTest.java new file mode 100644 index 0000000000..1d70d81915 --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/UnvalidatedAndroidDirectoriesTest.java @@ -0,0 +1,81 @@ +// 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 com.google.common.collect.ImmutableList; +import com.google.common.jimfs.Jimfs; +import com.google.common.truth.Truth; +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 {@link UnvalidatedAndroidDirectories}. */ +@RunWith(JUnit4.class) +public class UnvalidatedAndroidDirectoriesTest { + private FileSystem fileSystem; + private Path res; + private Path otherRes; + private Path assets; + private Path otherAssets; + + @Before public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(); + Path root = fileSystem.getPath(""); + res = Files.createDirectories(root.resolve("res")); + otherRes = Files.createDirectories(root.resolve("otherres")); + assets = Files.createDirectories(root.resolve("assets")); + otherAssets = Files.createDirectories(root.resolve("otherassets")); + } + + @Test public void flagFullParse() throws Exception { + Truth.assertThat( + UnvalidatedAndroidDirectories.valueOf( + "res#otherres:assets#otherassets", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidDirectories(ImmutableList.of(res, otherRes), + ImmutableList.of(assets, otherAssets))); + } + + @Test public void flagParseWithEmptyAssets() throws Exception { + Truth.assertThat( + UnvalidatedAndroidDirectories.valueOf( + "res:", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidDirectories(ImmutableList.of(res), + ImmutableList.of())); + } + + @Test public void flagParseWithEmptyResources() throws Exception { + Truth.assertThat( + UnvalidatedAndroidDirectories.valueOf( + ":assets", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidDirectories(ImmutableList.of(), + ImmutableList.of(assets))); + } + + @Test public void flagParseWithEmptyResourcesAndAssets() throws Exception { + Truth.assertThat( + UnvalidatedAndroidDirectories.valueOf( + ":", fileSystem) + ).isEqualTo( + new UnvalidatedAndroidDirectories(ImmutableList.of(), + ImmutableList.of())); + } + +} -- cgit v1.2.3