blob: 6f9c7260fd275c8241cbd84dc2bae4125e70d487 [file] [log] [blame]
// Copyright (c) 2017, 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.debug;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.google.common.collect.ImmutableList;
import jasmin.ClassFile;
import java.io.File;
import java.io.OutputStream;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
// TODO(b/65474850) Should we build Jasmin at compile time or runtime ?
public class JasminDebugTest extends DebugTestBase {
public static final boolean RUN_JAVA = false;
@Rule
public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
@Test
public void testUselessCheckcast() throws Throwable {
final String className = "UselessCheckCast";
final String sourcefile = className + ".j";
final String methodName = "test";
List<Path> paths = getExtraPaths(getBuilderForUselessCheckcast(className, methodName));
runDebugTest(
getDebuggeeDexD8OrCf(RUN_JAVA),
paths,
className,
breakpoint(className, methodName),
run(),
checkLine(sourcefile, 1),
stepOver(),
checkLine(sourcefile, 2),
checkLocal("local"),
stepOver(),
checkLine(sourcefile, 3),
checkNoLocal("local"),
stepOver(),
checkLine(sourcefile, 4),
run());
}
private JasminBuilder getBuilderForUselessCheckcast(String testClassName, String testMethodName) {
JasminBuilder builder = new JasminBuilder();
JasminBuilder.ClassBuilder clazz = builder.addClass(testClassName);
clazz.addStaticMethod(testMethodName, ImmutableList.of("Ljava/lang/Object;"), "V",
".limit stack 1",
".limit locals 3",
".var 1 is local Ljava/lang/Object; from Label1 to Label2",
".line 1",
" aload 0",
" dup",
" astore 1",
" Label1:",
".line 2",
" checkcast " + testClassName,
" Label2:",
".line 3",
" checkcast " + testClassName,
".line 4",
"return");
clazz.addMainMethod(
".limit stack 2",
".limit locals 1",
"aconst_null",
"invokestatic " + testClassName + "/" + testMethodName + "(Ljava/lang/Object;)V",
"return");
return builder;
}
private List<Path> getExtraPaths(JasminBuilder builder) throws Exception {
ImmutableList<ClassBuilder> classes = builder.getClasses();
List<Path> extraPaths = new ArrayList<>(classes.size());
File out = temp.newFolder();
for (ClassBuilder clazz : classes) {
ClassFile file = new ClassFile();
file.readJasmin(new StringReader(clazz.toString()), clazz.name, false);
Path path = out.toPath().resolve(clazz.name + ".class");
Files.createDirectories(path.getParent());
try (OutputStream outputStream = Files.newOutputStream(path)) {
file.write(outputStream);
}
if (RUN_JAVA) {
extraPaths.add(path);
} else {
extraPaths.add(compileToDex(path, null));
}
}
return extraPaths;
}
}