| // 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 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.internal.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 com.android.tools.r8.utils.codeinspector.Matchers; | |
| import java.io.File; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import org.hamcrest.MatcherAssert; | |
| 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); | |
| MatcherAssert.assertThat(clazz, Matchers.isPresent()); | |
| if (isOutlined) { | |
| ClassSubject apiCallerInlined = | |
| inspector.clazz("com.example.softverificationsample.ApiCallerInlined"); | |
| MatcherAssert.assertThat(apiCallerInlined, Matchers.isPresent()); | |
| } | |
| } | |
| } |