blob: 4adf9efe4a6da99d335577e31ed0922e11dd71b9 [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.classinliner;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ClassInlinerBuilderWithControlFlowTest extends ClassInlinerTestBase {
private static final String EXPECTED =
StringUtils.lines(
"flow = >0>0>-1>1234>1236>7>3>1240>1266>6>1248>3798>8>1254>10>1264>8885>12>1273>19063>14>"
+ "16>1288>39449>18>1301>80229>20>1315>161806>23>1335>324994>25>1353>651383>27>1372>1"
+ "304183>29>1392>2609806>32>1418>5221092>34>1442>10443683>36>1467>20888893>38>1493>4"
+ "1779342>40>1520>42>1551>83560313>44>1581>167122280>46>1612>334246248>48>1644>66849"
+ "4219>50>1677>1336990197>52>54>1716>-1620985089>56>1753>1052998963>58>1791>21059998"
+ "12>60>1830>-82965744>62>1870>-165929517>64>1911>-331857019>");
private final TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public ClassInlinerBuilderWithControlFlowTest(TestParameters parameters) {
this.parameters = parameters;
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
.addInnerClasses(ClassInlinerBuilderWithControlFlowTest.class)
.addKeepMainRule(TestClass.class)
.addDontObfuscate()
.setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::inspect)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
}
@Test
public void testExpectedBehavior() throws Exception {
testForRuntime(parameters)
.addInnerClasses(ClassInlinerBuilderWithControlFlowTest.class)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
}
private void inspect(CodeInspector inspector) {
ClassSubject clazz = inspector.clazz(TestClass.class);
assertEquals(
Collections.singleton(StringBuilder.class.getTypeName()), collectTypes(clazz.mainMethod()));
assertThat(inspector.clazz(ControlFlow.class), not(isPresent()));
}
static class TestClass {
public static void main(String[] args) {
ControlFlow flow = new ControlFlow(-1, 2, 7);
for (int k = 0; k < 25; k++) {
if (k % 3 == 0) {
flow.foo(k);
} else if (k % 3 == 1) {
flow.bar(1, 2, 3, 4);
}
}
System.out.println("flow = " + flow.toString());
}
}
static class ControlFlow {
int a;
int b;
int c = 1234;
int d;
String s = ">";
ControlFlow(int b, int c, int d) {
this.s += this.a++ + ">";
this.s += this.b + ">";
this.b = b;
this.s += this.b + ">";
this.s += this.c + ">";
this.c += c;
this.s += this.c + ">";
this.s += (this.d = d) + ">";
}
void foo(int count) {
for (int i = 0; i < count; i++) {
switch (i % 4) {
case 0:
this.s += ++this.a + ">";
break;
case 1:
this.c += this.b;
this.s += this.c + ">";
break;
case 2:
this.d += this.d++ + this.c++ + this.b++ + this.a++;
this.s += this.d + ">";
break;
}
}
}
void bar(int a, int b, int c, int d) {
this.a += a;
this.b += b;
this.c += c;
this.d += d;
}
@Override
public String toString() {
return s;
}
}
}