/* * Copyright (C) 2015 The Android Open Source Project * * 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.android.build.gradle.internal.tasks; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.model.PackagingOptions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.io.Files; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; /** * Tests for {@link MergeJavaResourcesTaskTest} */ public class MergeJavaResourcesTaskTest { @Mock PackagingOptions packagingOptions; @Mock MergeJavaResourcesTask task; MergeJavaResourcesTask.FileFilter fileFilter; private static File sPackagedJarExpansionFolder, sMergedFolder; private static File sExpandedJar1, sExpandedJar2, sExpandedJar3; /** * Create temporary folders to simulate expanded folders with java resources embedded */ @BeforeClass public static void prepareFolders() throws IOException { sPackagedJarExpansionFolder = createTmpFolder(null /* parent */); sExpandedJar1 = createTmpFolder(sPackagedJarExpansionFolder); sExpandedJar2 = createTmpFolder(sPackagedJarExpansionFolder); sExpandedJar3 = createTmpFolder(sPackagedJarExpansionFolder); sMergedFolder = createTmpFolder(null /* parent */); } /** * After each test, all folders are cleaned. */ @After public void cleanUp() { cleanContents(sExpandedJar1); cleanContents(sExpandedJar2); cleanContents(sExpandedJar3); cleanContents(sMergedFolder); } @Before public void setUp() { MockitoAnnotations.initMocks(this); when(task.getExpandedFolders()).thenReturn(ImmutableList.of(sPackagedJarExpansionFolder)); assertTrue(listFiles(sMergedFolder).length == 0); } @Test public void testSimpleCopy() throws IOException { fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); assertFalse(new File(sMergedFolder, "foo/text.properties").exists()); File changedFile = createFile(sExpandedJar1, "foo/text.properties"); fileFilter.handleChanged(sMergedFolder, changedFile); assertTrue(new File(sMergedFolder, "foo/text.properties").exists()); } @Test public void testSimpleExclusion() throws IOException { when(packagingOptions.getExcludes()).thenReturn( ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar1, "foo/text.properties")); assertTrue(listFiles(sMergedFolder).length == 0); } @Test public void testExclusionFromMultipleFiles() throws IOException { when(packagingOptions.getExcludes()).thenReturn( ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar1, "foo/text.properties")); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar2, "foo/text.properties")); assertTrue(listFiles(sMergedFolder).length == 0); } @Test public void testMultipleExclusions() throws IOException { when(packagingOptions.getExcludes()).thenReturn( ImmutableSet.of("foo/text.properties", "bar/other.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar1, "foo/text.properties")); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar2, "bar/other.properties")); assertTrue(listFiles(sMergedFolder).length == 0); } @Test public void textNonExclusion() throws IOException { when(packagingOptions.getExcludes()).thenReturn( ImmutableSet.of("foo/text.properties", "bar/other.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar1, "foo/text.properties")); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar2, "bar/other.properties")); // this one should be copied over. fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar2, "bar/foo.properties")); assertTrue(listFiles(sMergedFolder).length == 1); assertTrue(new File(sMergedFolder, "bar/foo.properties").exists()); } @Test public void testSingleMerge() throws IOException { when(packagingOptions.getMerges()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); // one has changed... fileFilter.handleChanged(sMergedFolder, secondFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two")); } @Test public void testMultipleMerges() throws IOException { when(packagingOptions.getMerges()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); createFile(sExpandedJar3, "foo/text.properties", "three"); // one has changed... fileFilter.handleChanged(sMergedFolder, secondFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two", "three")); } @Test public void testMergeAddon() throws IOException { when(packagingOptions.getMerges()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); // simulate one has changed to create initial version fileFilter.handleChanged(sMergedFolder, secondFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two")); // add a new one. File thirdFile = createFile(sExpandedJar3, "foo/text.properties", "three"); fileFilter.handleChanged(sMergedFolder, thirdFile); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two", "three")); } @Test public void testMergeUpdate() throws IOException { when(packagingOptions.getMerges()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); createFile(sExpandedJar3, "foo/text.properties", "three"); // simulate one has changed to create initial version fileFilter.handleChanged(sMergedFolder, secondFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two", "three")); // change one... assertTrue(secondFile.delete()); secondFile = createFile(sExpandedJar2, "foo/text.properties", "deux"); fileFilter.handleChanged(sMergedFolder, secondFile); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "deux", "three")); } @Test public void testMergeRemoval() throws IOException { when(packagingOptions.getMerges()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); createFile(sExpandedJar3, "foo/text.properties", "three"); // simulate one has changed to create initial version fileFilter.handleChanged(sMergedFolder, secondFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "two", "three")); // remove one... assertTrue(secondFile.delete()); fileFilter.handleRemoved(sMergedFolder, secondFile); assertTrue(mergedFile.exists()); assertContentInAnyOrder( Files.asCharSource(mergedFile, Charset.defaultCharset()).read() , ImmutableList.of("one", "three")); } @Test public void testPickFirst() throws IOException { when(packagingOptions.getPickFirsts()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); // simulate the three elements were added. fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar1, "foo/text.properties", "one")); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar2, "foo/text.properties", "two")); fileFilter.handleChanged(sMergedFolder, createFile(sExpandedJar3, "foo/text.properties", "three")); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); String mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); assertTrue(mergedContent.equals("one") || mergedContent.equals("two") || mergedContent.equals("three")); } @Test public void testPickFirstUpdate() throws IOException { when(packagingOptions.getPickFirsts()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); File firstFile = createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); File thirdFile = createFile(sExpandedJar3, "foo/text.properties", "three"); // simulate the three elements were added. fileFilter.handleChanged(sMergedFolder, firstFile); fileFilter.handleChanged(sMergedFolder, secondFile); fileFilter.handleChanged(sMergedFolder, thirdFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); String mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); if (mergedContent.equals("one")) { assertTrue(firstFile.delete()); createFile(sExpandedJar1, "foo/text.properties", "un"); fileFilter.handleChanged(sMergedFolder, firstFile); assertEquals("un", Files.asCharSource(mergedFile, Charset.defaultCharset()).read()); } if (mergedContent.equals("two")) { assertTrue(thirdFile.delete()); createFile(sExpandedJar2, "foo/text.properties", "deux"); fileFilter.handleChanged(sMergedFolder, secondFile); assertEquals("deux", Files.asCharSource(mergedFile, Charset.defaultCharset()).read()); } if (mergedContent.equals("three")) { assertTrue(thirdFile.delete()); createFile(sExpandedJar3, "foo/text.properties", "trois"); fileFilter.handleChanged(sMergedFolder, thirdFile); assertEquals("trois", Files.asCharSource(mergedFile, Charset.defaultCharset()).read()); } } @Test public void testPickFirstRemoval() throws IOException { when(packagingOptions.getPickFirsts()).thenReturn(ImmutableSet.of("foo/text.properties")); fileFilter = new MergeJavaResourcesTask.FileFilter(task, packagingOptions); File firstFile = createFile(sExpandedJar1, "foo/text.properties", "one"); File secondFile = createFile(sExpandedJar2, "foo/text.properties", "two"); File thirdFile = createFile(sExpandedJar3, "foo/text.properties", "three"); // simulate the three elements were added. fileFilter.handleChanged(sMergedFolder, firstFile); fileFilter.handleChanged(sMergedFolder, secondFile); fileFilter.handleChanged(sMergedFolder, thirdFile); File mergedFile = new File(sMergedFolder, "foo/text.properties"); assertTrue(mergedFile.exists()); String mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); if (mergedContent.equals("one")) { assertTrue(firstFile.delete()); fileFilter.handleRemoved(sMergedFolder, firstFile); mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); assertTrue(mergedContent.equals("two") || mergedContent.equals("three")); } if (mergedContent.equals("two")) { assertTrue(thirdFile.delete()); fileFilter.handleRemoved(sMergedFolder, secondFile); mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); assertTrue(mergedContent.equals("one") || mergedContent.equals("three")); } if (mergedContent.equals("three")) { assertTrue(thirdFile.delete()); fileFilter.handleRemoved(sMergedFolder, thirdFile); mergedContent = Files.asCharSource(mergedFile, Charset.defaultCharset()).read(); assertTrue(mergedContent.equals("one") || mergedContent.equals("two")); } } private static void assertContentInAnyOrder(String content, Iterable<String> subStrings) { int length = 0; for (String subString : subStrings) { length += subString.length(); assertTrue(content.contains(subString)); } assertEquals(length, content.length()); } private static File createTmpFolder(@Nullable File parent) throws IOException { File folder = File.createTempFile("tmp", "dir"); assertTrue(folder.delete()); if (parent != null) { folder = new File(parent, folder.getName()); } assertTrue(folder.mkdirs()); return folder; } @NonNull private static File[] listFiles(@NonNull File folder) { File[] files = folder.listFiles(); if (files == null) { return new File[0]; } return files; } private static void cleanContents(File folder) { for (File f : listFiles(folder)) { if (f.isDirectory()) { cleanContents(f); } assertTrue(f.delete()); } } @NonNull private static File createFile( @NonNull File parent, @NonNull String archivePath) throws IOException { return createFile(parent, archivePath, null /* content */); } @NonNull private static File createFile( @NonNull File parent, @NonNull String archivePath, @Nullable String content) throws IOException { File newFile = new File(parent, archivePath); if (!newFile.getParentFile().exists()) { assertTrue(newFile.getParentFile().mkdirs()); } String fileContent = content == null ? "test!" : content; Files.append(fileContent, newFile, Charset.defaultCharset()); return newFile; } }