diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/android/ZipFilterActionTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/android/ZipFilterActionTest.java | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/android/ZipFilterActionTest.java b/src/test/java/com/google/devtools/build/android/ZipFilterActionTest.java new file mode 100644 index 0000000000..a59f2cb58d --- /dev/null +++ b/src/test/java/com/google/devtools/build/android/ZipFilterActionTest.java @@ -0,0 +1,296 @@ +// 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 java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimap; +import com.google.devtools.build.singlejar.ZipEntryFilter.CustomMergeStrategy; +import com.google.devtools.build.singlejar.ZipEntryFilter.StrategyCallback; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link ZipFilterAction}. */ +@RunWith(JUnit4.class) +public class ZipFilterActionTest { + + private static final class Entry { + private final String name; + private final String contents; + + public Entry(String name, String contents) { + this.name = name; + this.contents = contents; + } + + public String getName() { + return name; + } + + public String getContents() { + return contents; + } + } + + private enum FilterOperation { + SKIP, + RENAME, + CUSTOM_MERGE, + COPY + } + + private static final class TestingStrategyCallback implements StrategyCallback { + private FilterOperation operation; + + public void assertOp(FilterOperation operation) { + assertThat(this.operation).isEqualTo(operation); + } + + @Override + public void skip() throws IOException { + operation = FilterOperation.SKIP; + } + + @Override + public void rename(String filename, Date date) throws IOException { + operation = FilterOperation.RENAME; + } + + @Override + public void customMerge(Date date, CustomMergeStrategy strategy) throws IOException { + operation = FilterOperation.CUSTOM_MERGE; + } + + @Override + public void copy(Date date) throws IOException { + operation = FilterOperation.COPY; + } + } + + @Rule public ExpectedException thrown = ExpectedException.none(); + @Rule public TemporaryFolder tmp = new TemporaryFolder(); + + private int fileCount; + private TestingStrategyCallback callback; + + private Path createZip(String... filenames) throws IOException { + Entry[] entries = new Entry[filenames.length]; + int i = 0; + for (String filename : filenames) { + entries[i++] = new Entry(filename, "" + fileCount++); + } + return createZip(entries); + } + + private Path createZip(Entry... entries) throws IOException { + File zip = tmp.newFile(); + try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zip))) { + for (Entry entry : entries) { + ZipEntry e = new ZipEntry(entry.getName()); + zout.putNextEntry(e); + zout.write(entry.getContents().getBytes(UTF_8)); + zout.closeEntry(); + } + } + return zip.toPath(); + } + + @Before public void setup() { + callback = new TestingStrategyCallback(); + } + + @Test public void testCreateFilter() throws IOException { + ImmutableSet<Path> filters = ImmutableSet.of( + createZip("foo.class", "bar.java"), + createZip("foo.java", "bar.java", "baz.class")); + ImmutableSet<String> types = ImmutableSet.of(".class"); + Multimap<String, Long> filterFiles = ZipFilterAction.getEntriesToOmit(filters, types); + assertThat(filterFiles.keySet()).containsExactly("foo.class", "baz.class"); + assertThat(filterFiles).valuesForKey("foo.class").hasSize(1); + assertThat(filterFiles).valuesForKey("baz.class").hasSize(1); + } + + @Test public void testCreateFilter_NoZips() throws IOException { + ImmutableSet<Path> filters = ImmutableSet.of(); + ImmutableSet<String> types = ImmutableSet.of(".class"); + Multimap<String, Long> filterFiles = ZipFilterAction.getEntriesToOmit(filters, types); + assertThat(filterFiles).isEmpty(); + } + + @Test public void testCreateFilter_NoTypes() throws IOException { + ImmutableSet<Path> filters = ImmutableSet.of( + createZip("foo.class", "bar.java"), + createZip("foo.java", "bar.java", "baz.class")); + ImmutableSet<String> types = ImmutableSet.of(); + Multimap<String, Long> filterFiles = ZipFilterAction.getEntriesToOmit(filters, types); + assertThat(filterFiles.keySet()) + .containsExactly("foo.class", "bar.java", "foo.java", "baz.class"); + } + + @Test public void testCreateFilter_MultipleTypes() throws IOException { + ImmutableSet<Path> filters = ImmutableSet.of( + createZip("foo.class", "bar.java"), + createZip("foo.java", "bar.java", "baz.class")); + ImmutableSet<String> types = ImmutableSet.of(".class", "bar.java"); + Multimap<String, Long> filterFiles = ZipFilterAction.getEntriesToOmit(filters, types); + assertThat(filterFiles.keySet()).containsExactly("foo.class", "baz.class", "bar.java"); + assertThat(filterFiles).valuesForKey("foo.class").hasSize(1); + assertThat(filterFiles).valuesForKey("bar.java").hasSize(2); + } + + @Test public void testZipEntryFilter() throws Exception { + ZipFilterEntryFilter filter = new ZipFilterEntryFilter(".*R.class.*", + ImmutableSetMultimap.of("foo.class", 1L, "baz.class", 2L), + ImmutableMap.of("foo.class", 1L, "bar.class", 2L, "baz.class", 3L, "res/R.class", 4L), + false); + filter.accept("foo.class", callback); + callback.assertOp(FilterOperation.SKIP); + filter.accept("bar.class", callback); + callback.assertOp(FilterOperation.COPY); + filter.accept("baz.class", callback); + callback.assertOp(FilterOperation.COPY); + filter.accept("res/R.class", callback); + callback.assertOp(FilterOperation.SKIP); + } + + @Test public void testZipEntryFilter_ErrorOnMismatch() throws Exception { + ZipFilterEntryFilter filter = new ZipFilterEntryFilter(".*R.class.*", + ImmutableSetMultimap.of("foo.class", 1L, "baz.class", 2L), + ImmutableMap.of("foo.class", 1L, "bar.class", 2L, "baz.class", 3L, "res/R.class", 4L), + true); + filter.accept("foo.class", callback); + callback.assertOp(FilterOperation.SKIP); + filter.accept("bar.class", callback); + callback.assertOp(FilterOperation.COPY); + filter.accept("res/R.class", callback); + callback.assertOp(FilterOperation.SKIP); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("name matches but the hash does not."); + filter.accept("baz.class", callback); + } + + @Test public void testFlags() throws Exception { + File input = tmp.newFile("input"); + File output = tmp.newFile("output"); + output.delete(); + File filter1 = tmp.newFile("filter1"); + File filter2 = tmp.newFile("filter2"); + + ImmutableList<String> args = ImmutableList.of( + "--inputZip", input.getPath(), + "--outputZip", output.getPath(), + "--filterZips", Joiner.on(",").join(filter1.getPath(), filter2.getPath(), + filter1.getPath()), + "--filterTypes", Joiner.on(",").join(".class", ".class", ".java"), + "--explicitFilters", Joiner.on(",").join("R\\.class", "R\\$.*\\.class"), + "--outputMode", "DONT_CARE", + "--noerrorOnHashMismatch"); + thrown.expect(ZipException.class); + thrown.expectMessage("Zip file 'filter1' is malformed"); + ZipFilterAction.main(args.toArray(new String[0])); + } + + @Test public void testFullIntegration() throws IOException { + Path input = createZip(new Entry("foo.java", "foo"), new Entry("bar.class", "bar"), + new Entry("baz.class", "baz"), new Entry("1.class", "1"), new Entry("2.class", "2"), + new Entry("R.class", "r"), new Entry("Read.class", "read")); + File output = tmp.newFile(); + output.delete(); + Path filter1 = createZip(new Entry("1.class", "1"), new Entry("b.class", "b")); + Path filter2 = createZip(new Entry("1.class", "2"), new Entry("2.class", "1"), + new Entry("foo.java", "foo"), new Entry("bar.class", "bar")); + ImmutableList<String> args = ImmutableList.of( + "--inputZip", input.toFile().getPath(), + "--outputZip", output.getPath(), + "--filterZips", Joiner.on(",").join(filter1.toFile().getPath(), filter2.toFile().getPath(), + filter1.toFile().getPath()), + "--filterTypes", ".class", + "--explicitFilters", Joiner.on(",").join("R\\.class", "R\\$.*\\.class"), + "--outputMode", "DONT_CARE"); + ZipFilterAction.main(args.toArray(new String[0])); + List<String> filteredEntries = new ArrayList<>(); + try (ZipFile zip = new ZipFile(output)) { + Enumeration<? extends ZipEntry> entries = zip.entries(); + while (entries.hasMoreElements()) { + filteredEntries.add(entries.nextElement().getName()); + } + } + assertThat(filteredEntries).containsExactly("foo.java", "baz.class", "2.class", "Read.class"); + } + + @Test public void testFullIntegrationErrorsOnHash() throws IOException { + Path input = createZip("foo.java", "bar.class", "baz.class"); + File output = tmp.newFile(); + output.delete(); + Path filter = createZip("foo.java", "bar.class"); + ImmutableList<String> args = ImmutableList.of( + "--inputZip", input.toFile().getPath(), + "--outputZip", output.getPath(), + "--filterZips", filter.toFile().getPath(), + "--filterTypes", ".class", + "--outputMode", "DONT_CARE", + "--errorOnHashMismatch"); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("name matches but the hash does not"); + ZipFilterAction.main(args.toArray(new String[0])); + } + + @Test public void testFullIntegrationErrorsOnHash_WithExplicitOverride() + throws IOException { + Path input = createZip("foo.java", "bar.class", "baz.class"); + File output = tmp.newFile(); + output.delete(); + Path filter = createZip("foo.java", "bar.class"); + ImmutableList<String> args = ImmutableList.of( + "--inputZip", input.toFile().getPath(), + "--outputZip", output.getPath(), + "--filterZips", filter.toFile().getPath(), + "--filterTypes", ".class", + "--explicitFilters", "bar\\.class", + "--outputMode", "DONT_CARE", + "--errorOnHashMismatch"); + ZipFilterAction.main(args.toArray(new String[0])); + List<String> filteredEntries = new ArrayList<>(); + try (ZipFile zip = new ZipFile(output)) { + Enumeration<? extends ZipEntry> entries = zip.entries(); + while (entries.hasMoreElements()) { + filteredEntries.add(entries.nextElement().getName()); + } + } + assertThat(filteredEntries).containsExactly("foo.java", "baz.class"); + } +} |