// 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 org.junit.Assert.assertArrayEquals; import static org.junit.Assert.fail; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.devtools.build.android.AndroidResourceMerger.MergingException; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Tests for {@link DensitySpecificResourceFilter}. */ @RunWith(JUnit4.class) public class DensitySpecificResourceFilterTest { private Path tmp; @Test public void testNoDensityResources() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/layout/derp.xml", "test/res/layout-ldrtl/derp.png", "test/res/layout-ldrtl-xhdpi/derp.png", "test/res/drawable-en/test.png"), ImmutableList.of( "test/res/layout/derp.xml", "test/res/layout-ldrtl/derp.png", "test/res/layout-ldrtl-xhdpi/derp.png", "test/res/drawable-en/test.png"), ImmutableList.of("xxhdpi")); } @Test public void testDontFilterXml() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-xxhdpi/derp.xml", "test/res/drawable-ldpi/derp.xml", "test/res/drawable-en/test.png"), ImmutableList.of( "test/res/drawable-xxhdpi/derp.xml", "test/res/drawable-ldpi/derp.xml", "test/res/drawable-en/test.png"), ImmutableList.of("xxhdpi")); } @Test public void testNoDpiNoFilter() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-nodpi/test.png", "test/res/drawable-xxhdpi/test.png", "test/res/drawable-ldpi/test.png"), ImmutableList.of( "test/res/drawable-nodpi/test.png", "test/res/drawable-xxhdpi/test.png"), ImmutableList.of("xxhdpi")); } @Test public void testChoosesExactDensity() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-nodpi/test.png", "test/res/drawable/test.png", "test/res/drawable-mdpi/derp.png", "test/res/drawable-xxhdpi/test.png", "test/res/drawable-mdpi/test.png", "test/res/drawable-xxxhdpi/test.png"), ImmutableList.of( "test/res/drawable-nodpi/test.png", "test/res/drawable/test.png", "test/res/drawable-mdpi/derp.png", "test/res/drawable-xxhdpi/test.png"), ImmutableList.of("xxhdpi")); } @Test public void testMultipleDensities() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-mdpi/test.png", "test/res/drawable-xxhdpi/test.png", "test/res/drawable-xxxhdpi/test.png"), ImmutableList.of( "test/res/drawable-xxhdpi/test.png", "test/res/drawable-xxxhdpi/test.png"), ImmutableList.of("xxhdpi", "xxxhdpi")); } @Test public void testNonStandardDensity() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-mdpi/test.png", "test/res/drawable-hdpi/test.png", "test/res/drawable-280dpi/test.png", "test/res/drawable-xhdpi/test.png", "test/res/drawable-340dpi/test.png", "test/res/drawable-xxhdpi/test.png"), ImmutableList.of( "test/res/drawable-280dpi/test.png", "test/res/drawable-340dpi/test.png"), ImmutableList.of("280dpi", "340dpi")); } @Test public void testUnknownDensityFails() { try { checkTransformedResources( ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.of("xxhdpi", "322dpi")); fail("expected MergingException"); } catch (MergingException expected) { } } @Test public void testPrefersHigherQualityWhenAffinityExact() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-xxxhdpi/test.png", "test/res/drawable-mdpi/test.png"), ImmutableList.of( "test/res/drawable-xxxhdpi/test.png"), ImmutableList.of("xhdpi")); } @Test public void testPrefersExactlyDoubleDensity() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-hdpi/test.png", "test/res/drawable-mdpi/test.png"), ImmutableList.of( "test/res/drawable-hdpi/test.png"), ImmutableList.of("ldpi")); } @Test public void testGroupsByQualifiers() throws Exception { checkTransformedResources( ImmutableList.of( "test/res/drawable-en-ldrtl-hdpi/test.png", "test/res/drawable-mdpi/test.png"), ImmutableList.of( "test/res/drawable-en-ldrtl-hdpi/test.png", "test/res/drawable-mdpi/test.png"), ImmutableList.of("ldpi")); } @Test public void testQualifiers() throws Exception { // This list checks that we correctly grab a -xhdpi-v19 version of the drawable when it is not // present at our requested density. checkTransformedResources( ImmutableList.of( "res/drawable-mdpi-v11/btn_edit_pressed.png", "res/drawable-mdpi/btn_edit_pressed.png", "res/drawable-xhdpi-v19/btn_edit_pressed.png", "res/drawable-tvdpi-v11/btn_edit_pressed.png", "res/drawable-hdpi-v11/btn_edit_pressed.png", "res/drawable-xhdpi-v11/btn_edit_pressed.png", "res/drawable-xxhdpi-v19/btn_edit_pressed.png", "res/drawable-hdpi/btn_edit_pressed.png", "res/drawable-tvdpi/btn_edit_pressed.png", "res/drawable-xxhdpi/btn_edit_pressed.png", "res/drawable-xhdpi/btn_edit_pressed.png", "res/drawable-tvdpi-v19/btn_edit_pressed.png", "res/drawable-hdpi-v19/btn_edit_pressed.png", "res/drawable-xxhdpi-v11/btn_edit_pressed.png"), ImmutableList.of( "res/drawable-mdpi-v11/btn_edit_pressed.png", "res/drawable-mdpi/btn_edit_pressed.png", "res/drawable-xhdpi-v19/btn_edit_pressed.png"), ImmutableList.of("mdpi")); } @Test public void fullIntegration() throws Exception { createFiles( "res/drawable-mdpi-v11/btn_edit_pressed.png", "res/drawable-mdpi/btn_edit_pressed.png", "res/drawable-xhdpi-v19/btn_edit_pressed.png", "res/drawable-tvdpi-v11/btn_edit_pressed.png", "res/drawable-hdpi-v11/btn_edit_pressed.png", "res/drawable-xhdpi-v11/btn_edit_pressed.png", "res/drawable-xxhdpi-v19/btn_edit_pressed.png", "res/drawable-hdpi/btn_edit_pressed.png", "res/drawable-tvdpi/btn_edit_pressed.png", "res/drawable-xxhdpi/btn_edit_pressed.png", "res/drawable-xhdpi/btn_edit_pressed.png", "res/drawable-tvdpi-v19/btn_edit_pressed.png", "res/drawable-hdpi-v19/btn_edit_pressed.png", "res/drawable-xxhdpi-v11/btn_edit_pressed.png"); Path out = Files.createTempDirectory(this.toString()); Path working = Files.createTempDirectory(this.toString()); ImmutableList<String> densities = ImmutableList.of("xxhdpi"); DensitySpecificResourceFilter filter = new DensitySpecificResourceFilter(densities, out, working); final Path filteredResourceDir = filter.filter(tmp); final ImmutableList.Builder<String> filteredResources = ImmutableList.<String>builder(); try { Files.walkFileTree(filteredResourceDir, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { filteredResources.add(filteredResourceDir.relativize(path).toString()); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { throw new RuntimeException(e); } String[] expected = new String[] { "res/drawable-xxhdpi/btn_edit_pressed.png", "res/drawable-xxhdpi-v11/btn_edit_pressed.png", "res/drawable-xxhdpi-v19/btn_edit_pressed.png" }; String[] actual = filteredResources.build().toArray(new String[0]); Arrays.sort(expected); Arrays.sort(actual); assertArrayEquals(expected, actual); } @Before public void setUpEnvironment() throws Exception { tmp = Files.createTempDirectory(this.toString()); } private ImmutableList <Path> createFiles(String... pathStrings) throws IOException { Builder<Path> paths = ImmutableList.builder(); for (String pathString : pathStrings) { final Path path = tmp.resolve(pathString); Files.createDirectories(path.getParent()); Files.createFile(path); paths.add(path); } return paths.build(); } private void checkTransformedResources(List<String> resourcePaths, List<String> expectedResourcePaths, List<String> densities) throws MergingException { List<Path> resources = new ArrayList<>(); for (String resourcePath : resourcePaths) { resources.add(FileSystems.getDefault().getPath(resourcePath)); } DensitySpecificResourceFilter transformer = new DensitySpecificResourceFilter(densities, null, null); List<Path> resourcesToRemove = transformer.getResourceToRemove(resources); List<String> actualResourcePaths = new ArrayList<>(resourcePaths); for (Path path : resourcesToRemove) { actualResourcePaths.remove(path.toString()); } String[] expected = expectedResourcePaths.toArray(new String[0]); String[] actual = actualResourcePaths.toArray(new String[0]); Arrays.sort(expected); Arrays.sort(actual); assertArrayEquals(expected, actual); } }