| // Copyright (c) 2021, 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; |
| |
| import static com.android.tools.r8.SoftVerificationErrorJarGenerator.EXISTING_API_METHOD_NAME; |
| import static com.android.tools.r8.SoftVerificationErrorJarGenerator.NEW_API_CLASS_METHOD_NAME; |
| import static com.android.tools.r8.SoftVerificationErrorJarGenerator.NEW_API_CLASS_NAME; |
| import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.android.tools.r8.SoftVerificationErrorJarGenerator.ApiCallerName; |
| import com.android.tools.r8.ToolHelper.ProcessResult; |
| import com.android.tools.r8.utils.AndroidApiLevel; |
| import com.android.tools.r8.utils.ApkUtils; |
| import com.android.tools.r8.utils.BooleanBox; |
| import com.android.tools.r8.utils.ZipUtils; |
| import com.android.tools.r8.utils.codeinspector.ClassSubject; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import java.io.File; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| |
| public class SoftVerificationErrorJarRunner extends TestBase { |
| |
| public static Path DUMP_PATH = |
| Paths.get("third_party", "api-outlining", "simple-app-dump", "simple-app-dump.zip"); |
| public static Path APK_PATH = |
| Paths.get("third_party", "api-outlining", "simple-app-dump", "app-release-unsigned.apk"); |
| |
| private final int numberOfClasses; |
| private final boolean isOutlined; |
| |
| public SoftVerificationErrorJarRunner(int numberOfClasses, boolean isOutlined) { |
| this.numberOfClasses = numberOfClasses; |
| this.isOutlined = isOutlined; |
| } |
| |
| public static void main(String[] args) throws Exception { |
| new SoftVerificationErrorJarRunner(1000, false).runTest(); |
| } |
| |
| public void runTest() throws Exception { |
| |
| temp.create(); |
| |
| Path tempFolder = temp.newFolder().toPath(); |
| Path outlineJar = tempFolder.resolve("outlined.jar"); |
| |
| SoftVerificationErrorJarGenerator.createJar( |
| outlineJar, |
| numberOfClasses, |
| isOutlined, |
| ApiCallerName.CONSTRUCT_AND_CALL_UNKNOWN, |
| NEW_API_CLASS_NAME, |
| NEW_API_CLASS_METHOD_NAME, |
| EXISTING_API_METHOD_NAME); |
| |
| ZipUtils.unzip(DUMP_PATH.toString(), tempFolder.toFile()); |
| |
| File filteredProgramFolder = temp.newFolder(); |
| BooleanBox seenTestRunner = new BooleanBox(); |
| ZipUtils.unzip( |
| tempFolder.resolve("program.jar"), |
| filteredProgramFolder.toPath(), |
| zipEntry -> { |
| if (zipEntry.getName().equals("com/example/softverificationsample/TestRunner.class")) { |
| seenTestRunner.set(); |
| return false; |
| } |
| return true; |
| }); |
| |
| assertTrue(seenTestRunner.get()); |
| |
| Path filteredProgramJar = tempFolder.resolve("filtered_program.jar"); |
| ZipUtils.zip(filteredProgramJar, filteredProgramFolder.toPath()); |
| |
| // Build the app with R8. |
| Path output = |
| testForR8(Backend.DEX) |
| .addProgramFiles(outlineJar, filteredProgramJar) |
| .addClasspathFiles(tempFolder.resolve("classpath.jar")) |
| .addLibraryFiles(tempFolder.resolve("library.jar")) |
| // TODO(b/187496508): Modify keep rules to allow inlining and keep test code. |
| .addKeepRuleFiles(tempFolder.resolve("proguard.config")) |
| .addKeepRules("-keep class com.example.softverificationsample.* { *; }") |
| .setMinApi(AndroidApiLevel.M) |
| .allowUnusedProguardConfigurationRules() |
| .allowUnusedDontWarnPatterns() |
| .allowDiagnosticInfoMessages() |
| .compile() |
| .inspect(this::inspect) |
| .writeToZip(); |
| |
| Path finalApk = tempFolder.resolve("app-release-final.apk"); |
| ProcessResult processResult = ApkUtils.apkMasseur(APK_PATH, output, finalApk); |
| // TODO(mkroghj): Figure out to have this command succeed when installing the apk |
| assertEquals(0, processResult.exitCode); |
| } |
| |
| private void inspect(CodeInspector inspector) { |
| String name = |
| "com.example.softverificationsample." |
| + (isOutlined ? "ApiCallerOutlined" : "ApiCallerInlined") |
| + (numberOfClasses - 1); |
| ClassSubject clazz = inspector.clazz(name); |
| assertThat(clazz, isPresent()); |
| if (isOutlined) { |
| ClassSubject apiCallerInlined = |
| inspector.clazz("com.example.softverificationsample.ApiCallerInlined"); |
| assertThat(apiCallerInlined, isPresent()); |
| } |
| } |
| } |