blob: 036c18a11eca6a5d8992e0ea7480f9d3c3cbe051 [file]
// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.androidresources;
import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
import com.android.tools.r8.dump.CompilerDump;
import com.android.tools.r8.utils.DumpInputFlags;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class AndroidResourcesDumpTest extends TestBase {
@Parameter(0)
public TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection parameters() {
return getTestParameters().withDefaultDexRuntime().withMinimumApiLevel().build();
}
public static AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
return new AndroidTestResourceBuilder()
.withSimpleManifestAndAppNameString()
.setPackageName("example")
.addStringValue("foo", "the foobar string")
.addXmlWithStringReference("file.xml", "foo")
.build(temp);
}
public static AndroidTestResource getFeatureTestResources(TemporaryFolder temp)
throws IOException {
return new AndroidTestResourceBuilder()
.withSimpleManifestAndAppNameString()
.setPackageName("feature_foo")
.addStringValue("feature_foo", "the feature string")
.addXmlWithStringReference("feature.xml", "feature_foo")
.build(temp);
}
@Test
public void testR8WithDumpToFile() throws Exception {
Path dump = temp.newFile("with_resources.zip").toPath();
AndroidTestResource testResources = getTestResources(temp);
TemporaryFolder featureSplitTemp = ToolHelper.getTemporaryFolderForTest();
featureSplitTemp.create();
AndroidTestResource featureTestResources = getFeatureTestResources(featureSplitTemp);
testForR8(parameters.getBackend())
.addProgramClasses(Main.class)
.addKeepMainRule(Main.class)
.addAndroidResources(testResources)
.addFeatureSplitAndroidResources(featureTestResources, "thefeature")
.addOptionsModification(
options -> options.setDumpInputFlags(DumpInputFlags.dumpToFile(dump)))
.setMinApi(parameters)
.allowDiagnosticInfoMessages()
.compileWithExpectedDiagnostics(
diagnostics ->
diagnostics
.assertInfosMatch(
diagnosticMessage(startsWith("Dumped compilation inputs to:")))
.assertNoWarnings()
.assertNoErrors());
CompilerDump compilerDump = CompilerDump.fromArchive(dump, temp.newFolder().toPath());
validateResourceEquality(
testResources,
ImmutableList.of("res/xml/file.xml", "AndroidManifest.xml", "resources.pb"),
compilerDump.getAndroidResources());
validateResourceEquality(
featureTestResources,
ImmutableList.of("res/xml/feature.xml", "AndroidManifest.xml", "resources.pb"),
compilerDump.getAndroidResourcesForFeature(1));
}
@Test
public void testR8WithDumpToDirectory() throws Exception {
Path dump = temp.newFolder("with_resources").toPath();
AndroidTestResource testResources = getTestResources(temp);
TemporaryFolder featureSplitTemp = ToolHelper.getTemporaryFolderForTest();
featureSplitTemp.create();
AndroidTestResource featureTestResources = getFeatureTestResources(featureSplitTemp);
testForR8(parameters.getBackend())
.addProgramClasses(Main.class)
.addKeepMainRule(Main.class)
.addAndroidResources(testResources)
.addFeatureSplitAndroidResources(featureTestResources, "thefeature")
.addOptionsModification(
options -> options.setDumpInputFlags(DumpInputFlags.dumpToDirectory(dump)))
.setMinApi(parameters)
.allowDiagnosticInfoMessages()
.compileWithExpectedDiagnostics(
diagnostics ->
diagnostics
.assertInfosMatch(
diagnosticMessage(startsWith("Dumped compilation inputs to:")))
.assertNoWarnings()
.assertNoErrors());
// Verify that only one archive was dumped.
List<Path> dumpArchives = Files.list(dump).collect(Collectors.toList());
assertEquals(1, dumpArchives.size());
Path dumpArchive = dumpArchives.iterator().next();
CompilerDump compilerDump = CompilerDump.fromArchive(dumpArchive);
validateResourceEquality(
testResources,
ImmutableList.of("res/xml/file.xml", "AndroidManifest.xml", "resources.pb"),
compilerDump.getAndroidResources());
validateResourceEquality(
featureTestResources,
ImmutableList.of("res/xml/feature.xml", "AndroidManifest.xml", "resources.pb"),
compilerDump.getAndroidResourcesForFeature(1));
}
private static void validateResourceEquality(
AndroidTestResource testResources, List<String> fileEntries, Path dumpInput)
throws IOException {
int resourceFileCount = 0;
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(dumpInput))) {
ZipEntry nextEntry = zipInputStream.getNextEntry();
Path resourceZip = testResources.getResourceZip();
while (nextEntry != null) {
resourceFileCount++;
String name = nextEntry.getName();
assertTrue(fileEntries.contains(name));
// We allow xml files to have been rewritten.
if (!name.endsWith(".xml")) {
byte[] original = ZipUtils.readSingleEntry(resourceZip, name);
assertArrayEquals(original, ByteStreams.toByteArray(zipInputStream));
}
nextEntry = zipInputStream.getNextEntry();
}
}
assertEquals(resourceFileCount, fileEntries.size());
}
static class Main {
public static void main(String[] args) {}
}
}