blob: 20fda045ffbb952110ed94488ab4ef0fcbb0d7d3 [file] [log] [blame]
// Copyright (c) 2016, 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.smali;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class JumboStringTest extends SmaliTestBase {
private static Pair<StringBuilder, StringBuilder> builders;
private final TestParameters parameters;
@BeforeClass
public static void createBuilders() {
StringBuilder builder = new StringBuilder();
StringBuilder expectedBuilder = new StringBuilder();
builder.append(" new-instance v0, Ljava/lang/StringBuilder;");
builder.append(" invoke-direct { v0 }, Ljava/lang/StringBuilder;-><init>()V");
for (int i = 0; i <= 0xffff + 2; i++) {
String prefixed = StringUtils.zeroPrefix(i, 5);
expectedBuilder.append(prefixed);
expectedBuilder.append(StringUtils.lines(""));
builder.append(" const-string v1, \"" + prefixed + "\\n\"");
builder.append(
" invoke-virtual { v0, v1 }, Ljava/lang/StringBuilder;"
+ "->append(Ljava/lang/String;)Ljava/lang/StringBuilder;");
}
builder.append(
" invoke-virtual { v0 }, Ljava/lang/StringBuilder;"
+ "->toString()Ljava/lang/String;");
builder.append(StringUtils.lines(" move-result-object v0"));
builder.append(StringUtils.lines(" return-object v0"));
builders = new Pair<>(builder, expectedBuilder);
}
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withDexRuntimes().build();
}
public JumboStringTest(TestParameters parameters) {
this.parameters = parameters;
}
@Test
public void test() throws Exception {
SmaliBuilder smaliBuilder = new SmaliBuilder(DEFAULT_CLASS_NAME);
smaliBuilder.addStaticMethod(
"java.lang.String",
DEFAULT_METHOD_NAME,
ImmutableList.of(),
2,
builders.getFirst().toString()
);
smaliBuilder.addMainMethod(
2,
" sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
" invoke-static {}, LTest;->method()Ljava/lang/String;",
" move-result-object v1",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" return-void"
);
testForR8(parameters.getBackend())
.addProgramDexFileData(smaliBuilder.compile())
.addKeepMainRule(DEFAULT_CLASS_NAME)
.setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), DEFAULT_CLASS_NAME)
.assertSuccessWithOutput(builders.getSecond().toString())
.inspect(inspector -> {
ClassSubject main = inspector.clazz(DEFAULT_CLASS_NAME);
assertThat(main, isPresent());
MethodSubject method = main.uniqueMethodWithName(DEFAULT_METHOD_NAME);
assertThat(method, isPresent());
assertTrue(method.streamInstructions().anyMatch(InstructionSubject::isJumboString));
});
}
@Test
public void test_addconfigurationdebugging() throws Exception {
SmaliBuilder smaliBuilder = new SmaliBuilder(DEFAULT_CLASS_NAME);
smaliBuilder.addStaticMethod(
"java.lang.String",
DEFAULT_METHOD_NAME,
ImmutableList.of(),
2,
builders.getFirst().toString()
);
// Intentionally dead code, but will be kept due to -addconfigurationdebugging.
smaliBuilder.addStaticMethod(
"java.lang.String",
DEFAULT_METHOD_NAME + "2",
ImmutableList.of(),
2,
builders.getFirst().toString()
);
smaliBuilder.addMainMethod(
2,
" sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
" invoke-static {}, LTest;->method()Ljava/lang/String;",
" move-result-object v1",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" return-void"
);
testForR8(parameters.getBackend())
.addProgramDexFileData(smaliBuilder.compile())
.addKeepMainRule(DEFAULT_CLASS_NAME)
.addKeepRules("-addconfigurationdebugging")
.setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), DEFAULT_CLASS_NAME)
.assertSuccessWithOutput(builders.getSecond().toString())
.inspect(inspector -> {
ClassSubject main = inspector.clazz(DEFAULT_CLASS_NAME);
assertThat(main, isPresent());
MethodSubject method = main.uniqueMethodWithName(DEFAULT_METHOD_NAME);
assertThat(method, isPresent());
assertTrue(method.streamInstructions().anyMatch(InstructionSubject::isJumboString));
MethodSubject method2 = main.uniqueMethodWithName(DEFAULT_METHOD_NAME + "2");
assertThat(method2, isPresent());
assertTrue(method2.streamInstructions().anyMatch(InstructionSubject::isJumboString));
});
}
}