| /* |
| * 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.integration.application |
| import com.android.build.gradle.integration.common.fixture.GradleTestProject |
| import com.android.utils.FileUtils |
| import com.google.common.io.Files |
| import groovy.transform.CompileStatic |
| import org.junit.BeforeClass |
| import org.junit.Rule |
| import org.junit.Test |
| |
| import static com.android.build.gradle.integration.common.truth.TruthHelper.assertThat |
| import static com.android.build.gradle.integration.common.truth.TruthHelper.assertThatApk |
| import static com.android.build.gradle.integration.common.truth.TruthHelper.assertWithMessage |
| import static com.google.common.base.Charsets.UTF_8 |
| /** |
| * Tests for the PNG generation feature. |
| */ |
| @CompileStatic |
| class VectorDrawableTest { |
| @Rule |
| public GradleTestProject project = GradleTestProject.builder() |
| .fromTestProject("vectorDrawables") |
| .create() |
| |
| @BeforeClass |
| public static void checkBuildTools() { |
| GradleTestProject.assumeBuildToolsAtLeast(21) |
| } |
| |
| @Test |
| public void "vector file is moved and PNGs are generated"() throws Exception { |
| project.execute("clean", "assembleDebug") |
| File apk = project.getApk("debug") |
| assertThatApk(apk).containsResource("drawable/icon.png") |
| assertThatApk(apk).doesNotContainResource("drawable/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-v21/heart.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v21/heart.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v4/heart.png") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v4/heart.png") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v21/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v22/no_need.png") |
| assertThatApk(apk).containsResource("drawable-v22/no_need.xml") |
| |
| // Check HDPI. Test project contains the hdpi png, it should be used instead of the |
| // generated one. |
| File originalPng = new File( |
| project.testDir, |
| "src/main/res/drawable-hdpi/special_heart.png") |
| File generatedPng = new File( |
| project.testDir, |
| "build/generated/res/pngs/debug/drawable-hdpi/special_heart.png") |
| File pngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable-hdpi/special_heart.png") |
| |
| assertThat(generatedPng).doesNotExist() |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(originalPng)) |
| |
| // Check XHDPI. |
| generatedPng = new File( |
| project.testDir, |
| "build/generated/res/pngs/debug/drawable-xhdpi/special_heart.png") |
| pngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable-xhdpi/special_heart.png") |
| |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(generatedPng)) |
| |
| // Check interactions with other qualifiers. |
| assertThatApk(apk).containsResource("drawable-fr-hdpi-v21/french_heart.xml") |
| assertThatApk(apk).containsResource("drawable-fr-xhdpi-v21/french_heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v21/french_heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-fr/french_heart.xml") |
| assertThatApk(apk).containsResource("drawable-fr-hdpi-v4/french_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi/french_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v4/french_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-fr/french_heart.png") |
| |
| assertThatApk(apk).containsResource("drawable-hdpi-v21/modern_heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-v16/modern_heart.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v16/modern_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-v16/modern_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v21/modern_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi/modern_heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v4/modern_heart.png") |
| } |
| |
| @Test |
| public void "incremental build: add xml"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File heartXml = new File(project.testDir, "src/main/res/drawable/heart.xml") |
| File heartXmlCopy = new File(project.testDir, "src/main/res/drawable/heart_copy.xml") |
| Files.copy(heartXml, heartXmlCopy) |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| File apk = project.getApk("debug") |
| assertThatApk(apk).containsResource("drawable/icon.png") |
| assertThatApk(apk).doesNotContainResource("drawable/heart_copy.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v21/heart_copy.xml") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v21/heart_copy.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v4/heart_copy.png") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v4/heart_copy.png") |
| } |
| |
| @Test |
| public void "incremental build: delete xml"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File heartXml = new File(project.testDir, "src/main/res/drawable/heart.xml") |
| heartXml.delete() |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| File apk = project.getApk("debug") |
| assertThatApk(apk).containsResource("drawable/icon.png") |
| assertThatApk(apk).doesNotContainResource("drawable/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v21/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v4/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi-v4/heart.png") |
| } |
| |
| @Test |
| public void "incremental build: delete png"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File generatedPng = new File( |
| project.testDir, |
| "build/generated/res/pngs/debug/drawable-hdpi/special_heart.png") |
| File originalPng = new File( |
| project.testDir, |
| "src/main/res/drawable-hdpi/special_heart.png") |
| File pngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable-hdpi/special_heart.png") |
| |
| assertThat(generatedPng).doesNotExist() |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(originalPng)) |
| |
| originalPng.delete() |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(generatedPng)) |
| } |
| |
| @Test |
| public void "incremental build: add png"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File generatedPng = new File( |
| project.testDir, |
| "build/generated/res/pngs/debug/drawable-xhdpi/special_heart.png") |
| File pngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable-xhdpi/special_heart.png") |
| |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(generatedPng)) |
| |
| // Create a PNG file for XHDPI. It should be used instead of the generated one. |
| File hdpiPng = new File(project.testDir, "src/main/res/drawable-hdpi/special_heart.png") |
| File xhdpiPng = new File(project.testDir, "src/main/res/drawable-xhdpi/special_heart.png") |
| Files.createParentDirs(xhdpiPng) |
| Files.copy(hdpiPng, xhdpiPng) |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isNotEqualTo(FileUtils.sha1(generatedPng)) |
| |
| assertWithMessage("Wrong file used.") |
| .that(FileUtils.sha1(pngToUse)) |
| .isEqualTo(FileUtils.sha1(xhdpiPng)) |
| } |
| |
| @Test |
| public void "incremental build: modify xml"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File heartPngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable-hdpi/heart.png") |
| File iconPngToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable/icon.png") |
| |
| String oldHashCode = FileUtils.sha1(heartPngToUse) |
| long heartPngModified = heartPngToUse.lastModified() |
| long iconPngModified = iconPngToUse.lastModified() |
| |
| File heartXml = new File(project.testDir, "src/main/res/drawable/heart.xml") |
| String content = Files.toString(heartXml, UTF_8) |
| // Change the heart to blue. |
| Files.write(content.replace("ff0000", "0000ff"), heartXml, UTF_8) |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| assertThat(iconPngToUse.lastModified()).isEqualTo(iconPngModified) |
| assertThat(heartPngToUse.lastModified()).isNotEqualTo(heartPngModified) |
| assertWithMessage("XML file change not reflected in PNG.") |
| .that(FileUtils.sha1(heartPngToUse)) |
| .isNotEqualTo(oldHashCode) |
| } |
| |
| @Test |
| public void "incremental build: replace vector drawable with bitmap alias"() throws Exception { |
| project.execute("assembleDebug") |
| |
| File heartXml = new File(project.testDir, "src/main/res/drawable/heart.xml") |
| Files.write( |
| "<bitmap xmlns:android=\"http://schemas.android.com/apk/res/android\" " + |
| "android:src=\"@drawable/icon\" />", |
| heartXml, |
| UTF_8) |
| |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| File apk = project.getApk("debug") |
| assertThatApk(apk).containsResource("drawable/icon.png") |
| assertThatApk(apk).containsResource("drawable/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v21/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v4/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi-v4/heart.png") |
| |
| File heartXmlToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable/heart.xml") |
| |
| // They won't be equal, because of the source marker added in the XML. |
| assertThat(Files.toString(heartXmlToUse, UTF_8)).contains(Files.toString(heartXml, UTF_8)) |
| } |
| |
| @Test |
| public void "incremental build: replace bitmap alias with vector drawable"() throws Exception { |
| File heartXml = new File(project.testDir, "src/main/res/drawable/heart.xml") |
| |
| String vectorDrawable = Files.toString(heartXml, UTF_8) |
| |
| Files.write( |
| "<bitmap xmlns:android=\"http://schemas.android.com/apk/res/android\" " + |
| "android:src=\"@drawable/icon\" />", |
| heartXml, |
| UTF_8) |
| |
| project.execute("clean", "assembleDebug") |
| |
| File apk = project.getApk("debug") |
| assertThatApk(apk).containsResource("drawable/icon.png") |
| assertThatApk(apk).containsResource("drawable/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v21/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-hdpi-v4/heart.png") |
| assertThatApk(apk).doesNotContainResource("drawable-xhdpi-v4/heart.png") |
| |
| File heartXmlToUse = new File( |
| project.testDir, |
| "build/intermediates/res/merged/debug/drawable/heart.xml") |
| |
| // They won't be equal, because of the source marker added in the XML. |
| assertThat(Files.toString(heartXmlToUse, UTF_8)).contains(Files.toString(heartXml, UTF_8)) |
| |
| Files.write(vectorDrawable, heartXml, UTF_8) |
| project.execute("assembleDebug") |
| checkIncrementalBuild() |
| |
| assertThatApk(apk).doesNotContainResource("drawable/heart.xml") |
| assertThatApk(apk).doesNotContainResource("drawable-v21/heart.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v21/heart.xml") |
| assertThatApk(apk).containsResource("drawable-hdpi-v4/heart.png") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v4/heart.png") |
| assertThatApk(apk).containsResource("drawable-xhdpi-v21/heart.xml") |
| } |
| |
| private void checkIncrementalBuild() { |
| // Do nothing for now, the incremental marker was removed. |
| // TODO: remove the method or re-enable incremental markers. |
| } |
| } |