blob: 2bcf2f7448f25c51bd7a61e8ed243d9e38a1a6ce [file] [log] [blame]
// Copyright (c) 2023, 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.b316744331;
import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.debug.DebugTestBase;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.StringUtils;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.Tag;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class Regress316744331Test extends DebugTestBase {
static final String EXPECTED = StringUtils.lines("No null fields");
static final int ENTRY_LINE = 23;
static final int IN_STREAM_CHECK_LINE = ENTRY_LINE + 1;
static final int IN_STREAM_IS_NULL_LINE = ENTRY_LINE + 2;
static final int OUT_STREAM_CHECK_LINE = ENTRY_LINE + 7;
static final int OUT_STREAM_IS_NULL_LINE = ENTRY_LINE + 8;
static final int NORMAL_EXIT_LINE = ENTRY_LINE + 11;
static final Value NULL_VALUE = Value.createObjectValue(Tag.OBJECT_TAG, 0);
private final TestParameters parameters;
private final MethodReference fooMethod;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters()
.withDefaultCfRuntime()
.withDefaultDexRuntime()
.withAllApiLevels()
.build();
}
public Regress316744331Test(TestParameters parameters) {
this.parameters = parameters;
try {
this.fooMethod = Reference.methodFromMethod(Regress316744331TestClass.class.getMethod("foo"));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
private TestBuilder<? extends SingleTestRunResult<?>, ?> getTestBuilder() {
return testForRuntime(parameters)
.addClasspathClasses(Regress316744331TestClass.class)
.addProgramClasses(Regress316744331TestClass.class);
}
@Test
public void testReference() throws Exception {
getTestBuilder()
.run(parameters.getRuntime(), Regress316744331TestClass.class)
.assertSuccessWithOutput(EXPECTED);
}
@Test
public void testModifyInStreamField() throws Throwable {
runDebugTest(
getTestBuilder().debugConfig(parameters.getRuntime()),
Regress316744331TestClass.class,
breakpoint(fooMethod, ENTRY_LINE),
run(),
checkLine(ENTRY_LINE),
inspect(t -> assertEquals(NULL_VALUE, t.getFieldOnThis("m_instream", null))),
stepOver(),
checkLine(IN_STREAM_CHECK_LINE),
inspect(t -> assertNotEquals(NULL_VALUE, t.getFieldOnThis("m_instream", null))),
inspect(t -> t.setFieldOnThis("m_instream", null, NULL_VALUE)),
// Install a break point on the possible exits.
breakpoint(fooMethod, IN_STREAM_IS_NULL_LINE),
breakpoint(fooMethod, NORMAL_EXIT_LINE),
run(),
checkLine(IN_STREAM_IS_NULL_LINE),
run());
}
@Test
public void testModifyOutStreamField() throws Throwable {
runDebugTest(
getTestBuilder().debugConfig(parameters.getRuntime()),
Regress316744331TestClass.class,
breakpoint(fooMethod, OUT_STREAM_CHECK_LINE),
run(),
checkLine(OUT_STREAM_CHECK_LINE),
inspect(t -> assertNotEquals(NULL_VALUE, t.getFieldOnThis("m_outstream", null))),
inspect(t -> t.setFieldOnThis("m_outstream", null, NULL_VALUE)),
// Install a break point on the possible exits.
breakpoint(fooMethod, OUT_STREAM_IS_NULL_LINE),
breakpoint(fooMethod, NORMAL_EXIT_LINE),
run(),
checkLine(OUT_STREAM_IS_NULL_LINE),
run());
}
}