blob: 59cfbe8aae08977f5eb03e31aebfff892fd66e55 [file] [log] [blame]
// Copyright (c) 2018, 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.regress;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldAccessInstructionSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Iterator;
import java.util.function.Function;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class B76025099 extends TestBase {
private Backend backend;
@Parameterized.Parameters(name = "Backend: {0}")
public static Backend[] data() {
return ToolHelper.getBackends();
}
public B76025099(Backend backend) {
this.backend = backend;
}
private static final String PRG =
ToolHelper.EXAMPLES_BUILD_DIR + "regress_76025099" + FileUtils.JAR_EXTENSION;
private AndroidApp runR8(AndroidApp app) throws Exception {
R8Command command =
ToolHelper.addProguardConfigurationConsumer(
ToolHelper.prepareR8CommandBuilder(app, emptyConsumer(backend)),
pgConfig -> {
pgConfig.setPrintMapping(true);
pgConfig.setPrintMappingFile(map);
})
.addLibraryFiles(runtimeJar(backend))
.addProguardConfigurationFiles(pgConfig)
.setDisableMinification(true)
.setOutput(tempRoot.toPath(), outputMode(backend))
.build();
return ToolHelper.runR8(command);
}
private File tempRoot;
private Path jarPath;
private AndroidApp originalApp;
private String mainName;
private Path pgConfig;
private Path map;
@Before
public void setUp() throws Exception {
tempRoot = temp.getRoot();
jarPath = Paths.get(PRG);
originalApp = readJar(jarPath);
mainName = "regress_76025099.Main";
pgConfig = File.createTempFile("keep-rules", ".config", tempRoot).toPath();
String config = keepMainProguardConfiguration(mainName);
config += System.lineSeparator() + "-dontobfuscate";
Files.write(pgConfig, config.getBytes());
map = File.createTempFile("proguard", ".map", tempRoot).toPath();
}
@Test
public void testProguardAndD8() throws Exception {
Assume.assumeTrue(backend == Backend.DEX);
if (!isRunProguard()) {
return;
}
ProcessResult jvmOutput = ToolHelper.runJava(ImmutableList.of(jarPath), mainName);
assertEquals(0, jvmOutput.exitCode);
Path proguarded =
File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, tempRoot).toPath();
ProcessResult proguardResult = ToolHelper.runProguardRaw(jarPath, proguarded, pgConfig, map);
assertEquals(0, proguardResult.exitCode);
AndroidApp processedApp = ToolHelper.runD8(readJar(proguarded));
verifyFieldAccess(processedApp, jvmOutput);
}
@Test
public void testR8() throws Exception {
ProcessResult jvmOutput = ToolHelper.runJava(ImmutableList.of(jarPath), mainName);
assertEquals(0, jvmOutput.exitCode);
AndroidApp processedApp = runR8(originalApp);
verifyFieldAccess(processedApp, jvmOutput);
}
private static InstructionSubject findInstructionOrNull(
Iterator<InstructionSubject> iterator, Function<InstructionSubject, Boolean> predicate) {
while (iterator.hasNext()) {
InstructionSubject instruction = iterator.next();
if (predicate.apply(instruction)) {
return instruction;
}
}
return null;
}
private void verifyFieldAccess(AndroidApp processedApp, ProcessResult jvmOutput)
throws Exception {
CodeInspector inspector = new CodeInspector(processedApp);
ClassSubject impl = inspector.clazz("regress_76025099.impl.Impl");
assertThat(impl, isPresent());
MethodSubject init = impl.init("java.lang.String");
assertThat(init, isPresent());
Iterator<InstructionSubject> iterator = init.iterateInstructions();
assertNotNull(findInstructionOrNull(iterator, InstructionSubject::isInvoke));
InstructionSubject instruction =
findInstructionOrNull(iterator, InstructionSubject::isInstancePut);
assertNotNull(instruction);
FieldAccessInstructionSubject fieldAccessInstruction =
(FieldAccessInstructionSubject) instruction;
assertEquals("name", fieldAccessInstruction.name());
assertTrue(fieldAccessInstruction.holder().is(impl.getDexProgramClass().type.toString()));
assertNotNull(findInstructionOrNull(iterator, InstructionSubject::isReturnVoid));
ProcessResult output;
if (backend == Backend.DEX) {
output = runOnArtRaw(processedApp, mainName);
} else {
assert backend == Backend.CF;
output = runOnJavaRaw(processedApp, mainName, Collections.emptyList());
}
assertEquals(0, output.exitCode);
assertEquals(jvmOutput.stdout, output.stdout);
}
}