blob: af13cb9b134f2041b0076bc5de8904ba8ba08955 [file] [log] [blame]
// Copyright (c) 2019, 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.ir.optimize.string;
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.Assume.assumeTrue;
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.Streams;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class StringConcatenationTest extends TestBase {
private static final Class<?> MAIN = StringConcatenationTestClass.class;
private static final String JAVA_OUTPUT = StringUtils.lines(
"xyz",
"42",
"0.14 0 false null",
"Hello,R8",
"Hello,R8",
"Hello,",
"Hello,D8",
"na;na;na;na;na;na;na;na;Batman!",
"na;na;na;na;na;na;na;na;Batman!"
);
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimes().build();
}
private final TestParameters parameters;
public StringConcatenationTest(TestParameters parameters) {
this.parameters = parameters;
}
@Test
public void testJVMOutput() throws Exception {
assumeTrue("Only run JVM reference once (for CF backend)", parameters.isCfRuntime());
testForJvm()
.addTestClasspath()
.run(parameters.getRuntime(), MAIN)
.assertSuccessWithOutput(JAVA_OUTPUT);
}
private void test(
TestRunResult result, int expectedStringCount1, int expectedStringCount2)
throws Exception {
CodeInspector codeInspector = result.inspector();
ClassSubject mainClass = codeInspector.clazz(MAIN);
MethodSubject method = mainClass.uniqueMethodWithName("trivialSequence");
assertThat(method, isPresent());
long count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(expectedStringCount1, count);
method = mainClass.uniqueMethodWithName("nonStringArgs");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(0, count);
method = mainClass.uniqueMethodWithName("typeConversion");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(0, count);
method = mainClass.uniqueMethodWithName("nestedBuilders_appendBuilderItself");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(expectedStringCount2, count);
method = mainClass.uniqueMethodWithName("nestedBuilders_appendBuilderResult");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(expectedStringCount2, count);
method = mainClass.uniqueMethodWithName("simplePhi");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(5, count);
method = mainClass.uniqueMethodWithName("loop");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(3, count);
method = mainClass.uniqueMethodWithName("loopWithBuilder");
assertThat(method, isPresent());
count = Streams.stream(method.iterateInstructions(
i -> i.isConstString(JumboStringMode.ALLOW))).count();
assertEquals(2, count);
}
@Test
public void testD8() throws Exception {
assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());
D8TestRunResult result =
testForD8()
.debug()
.addProgramClasses(MAIN)
.setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), MAIN)
.assertSuccessWithOutput(JAVA_OUTPUT);
test(result, 3, 4);
result =
testForD8()
.release()
.addProgramClasses(MAIN)
.setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), MAIN)
.assertSuccessWithOutput(JAVA_OUTPUT);
// TODO(b/114002137): could be 1 and 3.
test(result, 3, 4);
}
@Test
public void testR8() throws Exception {
R8TestRunResult result =
testForR8(parameters.getBackend())
.addProgramClasses(MAIN)
.enableInliningAnnotations()
.addKeepMainRule(MAIN)
.setMinApi(parameters.getRuntime())
.noMinification()
.run(parameters.getRuntime(), MAIN)
.assertSuccessWithOutput(JAVA_OUTPUT);
// TODO(b/114002137): could be 1 and 3.
test(result, 3, 4);
}
}