blob: 7eeed7dabd932b14a167d1ba4f6e5513505e0fff [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.debug.DebugTestBase.JUnit3Wrapper.Command;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.FrameInspector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.Tag;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/** Tests local variable information. */
@RunWith(Parameterized.class)
public class LocalsTest extends DebugTestBase {
public static final String SOURCE_FILE = "Locals.java";
@Parameters(name = "{0}")
public static Collection<Object[]> configs() {
DelayedDebugTestConfig d8 = D8DebugTestResourcesConfig::new;
DelayedDebugTestConfig r8Cf = R8CfDebugTestResourcesConfig::new;
return Arrays.asList(new Object[] {"D8", d8}, new Object[] {"R8/CF", r8Cf});
}
private final DebugTestConfig config;
public LocalsTest(String name, DelayedDebugTestConfig config) {
this.config = config.getConfig(temp);
}
@Test
public void testNoLocal() throws Throwable {
final String className = "Locals";
final String methodName = "noLocals";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 8),
checkNoLocal(),
stepOver(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 9),
checkNoLocal(),
run());
}
@Test
public void testUnusedLocal() throws Throwable {
final String className = "Locals";
final String methodName = "unusedLocals";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 12),
checkNoLocal(),
stepOver(),
checkLine(SOURCE_FILE, 13),
checkLocal("i", Value.createInt(Integer.MAX_VALUE)),
run());
}
@Test
public void testConstantLocal() throws Throwable {
final String className = "Locals";
final String methodName = "constantLocals";
Value pValue = Value.createInt(10);
Value cValue = Value.createInt(5);
Value vValue = Value.createInt(pValue.getIntValue() + cValue.getIntValue());
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 17),
checkLocal("p", pValue),
stepOver(),
checkLine(SOURCE_FILE, 18),
checkLocal("p", pValue),
checkLocal("c", cValue),
stepOver(),
checkLine(SOURCE_FILE, 19),
checkLocal("p", pValue),
checkLocal("c", cValue),
checkLocal("v", vValue),
run());
}
@Test
public void testConstantLocalWithUpdate() throws Throwable {
final String className = "Locals";
final String methodName = "constantLocals";
Value pValue = Value.createInt(10);
Value cValue = Value.createInt(5);
Value newValue = Value.createInt(5);
Value vValue = Value.createInt(pValue.getIntValue() + newValue.getIntValue());
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 17),
checkLocal("p", pValue),
stepOver(),
checkLine(SOURCE_FILE, 18),
checkLocal("p", pValue),
checkLocal("c", cValue),
setLocal("c", newValue),
checkLocal("c", newValue), // we should see the updated value
stepOver(),
checkLine(SOURCE_FILE, 19),
checkLocal("p", pValue),
checkLocal("c", newValue),
checkLocal("v", vValue),
run());
}
@Test
public void testZeroLocals() throws Throwable {
final String className = "Locals";
final String methodName = "zeroLocals";
final Value newValueForI = Value.createInt(10);
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 23),
checkNoLocal(),
stepOver(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 24),
checkLocal("i", Value.createInt(0)),
setLocal("i", newValueForI),
stepOver(),
checkLine(SOURCE_FILE, 25),
checkLocal("i", newValueForI),
checkLocal("f", Value.createFloat(0)),
run());
}
@Test
public void testNoFlowOptimization() throws Throwable {
final String className = "Locals";
final String methodName = "noFlowOptimization";
final Value oldValueForI = Value.createInt(0);
final Value newValueForI = Value.createInt(10);
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 29),
checkNoLocal(),
stepOver(),
checkMethod(className, methodName),
checkLine(SOURCE_FILE, 30),
checkLocal("i", oldValueForI),
setLocal("i", newValueForI),
stepOver(),
checkLine(SOURCE_FILE, 33),
checkLocal("i", newValueForI),
run());
}
@Test
public void testInvokeRange() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "invokeRange"),
run(),
inspect(state -> {
// 1st breakpoint
Assert.assertEquals("invokeRange", state.getMethodName());
Assert.assertEquals(58, state.getLineNumber());
state.checkLocal("a", Value.createInt(12));
state.checkLocal("b", Value.createInt(11));
state.checkLocal("c", Value.createInt(10));
state.checkLocal("d", Value.createInt(9));
state.checkLocal("e", Value.createInt(8));
state.checkLocal("f", Value.createInt(7));
state.checkLocal("g", Value.createInt(0));
FrameInspector outerFrame = state.getFrame(1);
for (int i = 1; i < 12; ++i) {
outerFrame.checkLocal("i" + i, Value.createInt(i));
}
}),
run(),
inspect(state -> {
// 2nd breakpoint
Assert.assertEquals("invokeRange", state.getMethodName());
Assert.assertEquals(58, state.getLineNumber());
state.checkLocal("a", Value.createInt(6));
state.checkLocal("b", Value.createInt(5));
state.checkLocal("c", Value.createInt(4));
state.checkLocal("d", Value.createInt(3));
state.checkLocal("e", Value.createInt(2));
state.checkLocal("f", Value.createInt(1));
state.checkLocal("g", Value.createInt(57));
FrameInspector outerFrame = state.getFrame(1);
for (int i = 1; i < 12; ++i) {
outerFrame.checkLocal("i" + i, Value.createInt(i));
}
}),
run(),
// TODO(shertz) maybe we should duplicate invokeRange to avoid this extra 'skip'.
// Skip last breakpoint
run());
}
@Test
public void testInvokeRange2() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "reverseRange"),
run(),
inspect(state -> {
Assert.assertEquals("reverseRange", state.getMethodName());
Assert.assertEquals(54, state.getLineNumber());
state.checkLocal("a", Value.createInt(1));
state.checkLocal("b", Value.createInt(2));
state.checkLocal("c", Value.createInt(3));
state.checkLocal("d", Value.createInt(4));
state.checkLocal("e", Value.createInt(5));
state.checkLocal("f", Value.createInt(6));
state.checkLocal("g", Value.createInt(7));
}),
stepInto(),
inspect(state -> {
Assert.assertEquals("invokeRange", state.getMethodName());
Assert.assertEquals(58, state.getLineNumber());
state.checkLocal("a", Value.createInt(7));
state.checkLocal("b", Value.createInt(6));
state.checkLocal("c", Value.createInt(5));
state.checkLocal("d", Value.createInt(4));
state.checkLocal("e", Value.createInt(3));
state.checkLocal("f", Value.createInt(2));
state.checkLocal("g", Value.createInt(1));
}),
inspect(state -> {
FrameInspector outerFrame = state.getFrame(1);
outerFrame.checkLocal("a", Value.createInt(1));
outerFrame.checkLocal("b", Value.createInt(2));
outerFrame.checkLocal("c", Value.createInt(3));
outerFrame.checkLocal("d", Value.createInt(4));
outerFrame.checkLocal("e", Value.createInt(5));
outerFrame.checkLocal("f", Value.createInt(6));
outerFrame.checkLocal("g", Value.createInt(7));
}),
run());
}
@Test
public void testLocals_MoreThan16() throws Throwable {
final int minIndex = 1;
final int maxIndex = 16;
Map<String, Value> arrayLocals = new HashMap<>();
runDebugTest(
config,
"Locals",
breakpoint("Locals", "breakpoint"),
run(),
inspect(state -> {
// 1st breakpoint: all lengthOfArray[N] are set to 0
FrameInspector outerFrame = state.getFrame(1);
Map<String, Value> localValues = outerFrame.getLocalValues();
for (int i = minIndex; i <= maxIndex; ++i) {
String varName = "lengthOfArray" + i;
Assert.assertTrue(localValues.containsKey(varName));
Assert.assertEquals(Value.createInt(0), localValues.get(varName));
}
// Capture IDs of arrays.
for (int i = minIndex; i <= maxIndex; ++i) {
String varName = "array" + i;
Assert.assertTrue(localValues.containsKey(varName));
arrayLocals.put(varName, localValues.get(varName));
}
}),
// Step out to reach next instructions in the tested method
stepOut(),
inspect(state -> {
Assert.assertEquals("Locals.java", state.getSourceFile());
Assert.assertEquals(107, state.getLineNumber());
// Verify that all arrays have the same value.
arrayLocals.forEach((name, value) -> state.checkLocal(name, value));
}),
// Step instruction by instruction to ensure all locals previously declared are safe.
stepUntil(StepKind.OVER, StepLevel.INSTRUCTION, state -> {
final String sourceFile = state.getSourceFile();
final int lineNumber = state.getLineNumber();
arrayLocals.forEach((name, value) -> state.checkLocal(name, value));
// Stop when we reach the expected line.
return lineNumber == 125 && sourceFile.equals("Locals.java");
}),
run());
}
@Test
public void testInvokeRangeLong() throws Throwable {
final int initialValueOfX = 21;
final long expectedValueOfL = (long) initialValueOfX * 2;
final int expectedValueOfX = (int) expectedValueOfL / initialValueOfX;
runDebugTest(
config,
"Locals",
breakpoint("Locals", "invokerangeLong"),
run(),
inspect(state -> {
FrameInspector outerFrame = state.getFrame(1);
Map<String, Value> values = outerFrame.getLocalValues();
Assert.assertTrue("No variable 'x'", values.containsKey("x"));
Assert.assertTrue("No variable 'obj'", values.containsKey("obj"));
Assert.assertTrue("No variable 'l'", values.containsKey("l"));
// 'x' is an int
Value valueOfX = values.get("x");
Assert.assertEquals(Tag.INT_TAG, valueOfX.getTag());
Assert.assertEquals(Value.createInt(expectedValueOfX), valueOfX);
// 'obj' is an Object (Integer).
Value valueOfObj = values.get("obj");
Assert.assertEquals(Tag.OBJECT_TAG, valueOfObj.getTag());
// 'l' is a long.
Value valueOfL = values.get("l");
Assert.assertEquals(Tag.LONG_TAG, valueOfL.getTag());
Assert.assertEquals(Value.createLong(expectedValueOfL), valueOfL);
}),
run());
}
@Test
public void testInvokeRangeLongThrowOnDiv() throws Throwable {
final int initialValueOfX = 21;
final long expectedValueOfL = (long) initialValueOfX * 2;
runDebugTest(
config,
"Locals",
breakpoint("Locals", "foo"),
run(),
// Initialize obj to 42 using original value of x.
stepOver(),
// Set value of x to zero which will cause a div-by-zero arithmetic exception below.
checkLocal("x", Value.createInt(initialValueOfX)),
setLocal("x", Value.createInt(0)),
// Single step until the catch handler triggers.
checkLine(SOURCE_FILE, 166),
stepOver(),
checkLine(SOURCE_FILE, 168),
stepOver(),
checkLine(SOURCE_FILE, 169),
stepOver(),
// At the catch handler, inspect the initial state of locals.
checkLine(SOURCE_FILE, 172),
checkLocal("x", Value.createInt(0)),
getLocal("obj", value -> Assert.assertEquals(Tag.OBJECT_TAG, value.getTag())),
checkLocal("l", Value.createLong(expectedValueOfL)),
// Step onto first line of catch handler and inspect again, including the exception local.
stepOver(),
checkLine(SOURCE_FILE, 173),
getLocal("e", value -> Assert.assertEquals(Tag.OBJECT_TAG, value.getTag())),
checkLocal("x", Value.createInt(0)),
getLocal("obj", value -> Assert.assertEquals(Tag.OBJECT_TAG, value.getTag())),
checkLocal("l", Value.createLong(expectedValueOfL)),
run());
}
@Test
public void testStepEmptyForLoopBody1() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "stepEmptyForLoopBody1"),
run(),
checkLocal("n", Value.createInt(3)),
checkNoLocal("i"),
stepOver(),
checkLocal("n", Value.createInt(3)),
checkLocal("i", Value.createInt(3)),
run());
}
@Test
public void testStepEmptyForLoopBody2() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "stepEmptyForLoopBody2"),
run(),
checkLocal("n", Value.createInt(3)),
checkNoLocal("i"),
stepOver(),
checkLocal("n", Value.createInt(3)),
checkLocal("i", Value.createInt(3)),
run());
}
@Test
public void testStepNonEmptyForLoopBody() throws Throwable {
final int LOOP_HEADER_LINE = 207;
final int LOOP_BODY_LINE = 208;
final int RETURN_LINE = 209;
final Value N = Value.createInt(3);
final Value I0 = Value.createInt(0);
final Value I1 = Value.createInt(1);
final Value I2 = Value.createInt(2);
final Value I3 = Value.createInt(3);
runDebugTest(
config,
"Locals",
breakpoint("Locals", "stepNonEmptyForLoopBody"),
run(),
checkLine(SOURCE_FILE, LOOP_HEADER_LINE),
checkLocal("n", N),
checkNoLocal("i"),
stepOver(),
checkLine(SOURCE_FILE, LOOP_BODY_LINE),
checkLocal("n", N),
checkLocal("i", I0),
stepOver(),
checkLine(SOURCE_FILE, LOOP_HEADER_LINE),
checkLocal("n", N),
checkLocal("i", I0),
stepOver(),
checkLine(SOURCE_FILE, LOOP_BODY_LINE),
checkLocal("n", N),
checkLocal("i", I1),
stepOver(),
checkLine(SOURCE_FILE, LOOP_HEADER_LINE),
checkLocal("n", N),
checkLocal("i", I1),
stepOver(),
checkLine(SOURCE_FILE, LOOP_BODY_LINE),
checkLocal("n", N),
checkLocal("i", I2),
stepOver(),
checkLine(SOURCE_FILE, LOOP_HEADER_LINE),
checkLocal("n", N),
checkLocal("i", I2),
stepOver(),
checkLine(SOURCE_FILE, RETURN_LINE),
checkLocal("n", N),
checkLocal("i", I3),
run());
}
@Test
public void tempInCase() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "tempInCase"),
run(),
checkLine(SOURCE_FILE, 215),
checkLocal("x", Value.createInt(42)),
stepOver(),
checkLine(SOURCE_FILE, 216),
checkLocal("res", Value.createInt(0)),
checkNoLocal("i"),
stepOver(),
checkLine(SOURCE_FILE, 217),
stepOver(),
checkLine(SOURCE_FILE, 218),
checkLocal("rem", Value.createInt(42)),
setLocal("rem", Value.createInt(1)),
stepOver(),
checkLine(SOURCE_FILE, 220),
checkLocal("res", Value.createInt(0)),
run());
}
@Test
public void localSwap() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "localSwap"),
run(),
checkLine(SOURCE_FILE, 238),
stepOver(),
checkLine(SOURCE_FILE, 240),
stepOver(),
checkLine(SOURCE_FILE, 241),
checkLocal("x", Value.createInt(1)),
checkLocal("y", Value.createInt(2)),
checkLocal("t", Value.createInt(1)),
stepOver(),
stepOver(),
checkLine(SOURCE_FILE, 244),
checkLocal("x", Value.createInt(2)),
checkLocal("y", Value.createInt(1)),
checkNoLocal("t"),
run());
}
@Test
public void argumentLiveAtReturn() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "argumentLiveAtReturn"),
run(),
checkLine(SOURCE_FILE, 248),
stepOver(),
checkLine(SOURCE_FILE, 262),
checkLocal("x", Value.createInt(-1)),
checkNoLocal("t"),
run());
}
@Test
public void switchRewriteToIfs() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "switchRewriteToIfs"),
run(),
checkLine(SOURCE_FILE, 267),
stepOver(),
checkLine(SOURCE_FILE, 268),
checkLocal("x", Value.createInt(1)),
checkLocal("t", Value.createInt(2)),
stepOver(),
checkLine(SOURCE_FILE, 269),
checkLocal("x", Value.createInt(2)),
checkLocal("t", Value.createInt(2)),
stepOver(),
checkLine(SOURCE_FILE, 271),
checkLocal("x", Value.createInt(4)),
checkNoLocal("t"),
run());
}
@Test
public void switchRewriteToSwitches() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "switchRewriteToSwitches"),
run(),
checkLine(SOURCE_FILE, 282),
stepOver(),
checkLine(SOURCE_FILE, 283),
checkLocal("x", Value.createInt(1)),
checkLocal("t", Value.createInt(2)),
stepOver(),
checkLine(SOURCE_FILE, 284),
checkLocal("x", Value.createInt(2)),
checkLocal("t", Value.createInt(2)),
stepOver(),
checkLine(SOURCE_FILE, 286),
checkLocal("x", Value.createInt(4)),
checkNoLocal("t"),
run());
}
@Test
public void regression65039701() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "regression65039701"),
run(),
checkLine(SOURCE_FILE, 304),
checkLocal("createIntNotLong", Value.createBoolean(true)),
stepOver(),
checkLine(SOURCE_FILE, 305),
checkLocal("a"),
stepOver(),
checkLine(SOURCE_FILE, 306),
stepOver(),
checkLine(SOURCE_FILE, 308),
run());
}
@Test
public void regression65066975() throws Throwable {
runDebugTest(
config,
"Locals",
breakpoint("Locals", "regression65066975"),
run(),
checkLine(SOURCE_FILE, 312),
checkLocal("bit", Value.createBoolean(false)),
stepOver(),
checkLine(SOURCE_FILE, 313),
stepOver(),
checkLine(SOURCE_FILE, 316),
stepOver(),
checkLine(SOURCE_FILE, 318),
stepOver(),
checkLine(SOURCE_FILE, 319),
run());
}
@Test
public void testLocalConstantBis() throws Throwable {
final String className = "Locals";
final String methodName = "localConstantBis";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkLine(SOURCE_FILE, 332),
checkNoLocal("result"),
stepOver(),
checkLine(SOURCE_FILE, 333),
checkLocal("result", Value.createInt(0)),
stepOver(),
checkLine(SOURCE_FILE, 334),
checkLocal("result", Value.createInt(0)),
stepOver(),
checkLine(SOURCE_FILE, 338),
checkLocal("result", Value.createInt(1)),
run());
}
@Test
public void testLocalConstant() throws Throwable {
final String className = "Locals";
final String methodName = "localConstant";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkLine(SOURCE_FILE, 322),
checkNoLocal("result1"),
checkNoLocal("result2"),
stepOver(),
checkLine(SOURCE_FILE, 323),
checkNoLocal("result1"),
checkNoLocal("result2"),
stepOver(),
checkLine(SOURCE_FILE, 324),
checkLocal("result1"),
checkNoLocal("result2"),
run());
}
@Test
public void testLocalTriggeringCSE() throws Throwable {
final String className = "Locals";
final String methodName = "localTriggeringCSE";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkLine(SOURCE_FILE, 342),
checkNoLocal("a"),
checkNoLocal("b"),
checkNoLocal("c"),
checkNoLocal("d"),
stepOver(),
checkLine(SOURCE_FILE, 343),
checkLocal("a", Value.createInt(1)),
checkNoLocal("b"),
checkNoLocal("c"),
checkNoLocal("d"),
stepOver(),
checkLine(SOURCE_FILE, 344),
checkLocal("a", Value.createInt(1)),
checkLocal("b", Value.createInt(3)),
checkNoLocal("c"),
checkNoLocal("d"),
stepOver(),
checkLine(SOURCE_FILE, 345),
checkLocal("a", Value.createInt(1)),
checkLocal("b", Value.createInt(3)),
checkLocal("c", Value.createInt(4)),
checkNoLocal("d"),
setLocal("a", Value.createInt(2)),
stepOver(),
checkLine(SOURCE_FILE, 346),
checkLocal("a", Value.createInt(2)),
checkLocal("b", Value.createInt(3)),
checkLocal("c", Value.createInt(4)),
checkLocal("d", Value.createInt(5)),
run());
}
/**
* Companion test with dex inspection
* {@link com.android.tools.r8.debuginfo.CodeGeneratorTestRunner#test2AddrInstruction}
*/
@Test
public void testLocalUsedBy2AddrInstruction() throws Throwable {
final String className = "Locals";
final String methodName = "intAddition";
runDebugTest(
config,
className,
breakpoint(className, methodName),
run(),
checkLine(SOURCE_FILE, 350),
checkLocal("a", Value.createInt(1)),
checkLocal("b", Value.createInt(2)),
checkLocal("c", Value.createInt(6)),
stepOver(),
checkLine(SOURCE_FILE, 351),
checkLocal("a", Value.createInt(3)),
checkLocal("b", Value.createInt(2)),
checkLocal("c", Value.createInt(6)),
stepOver(),
checkLine(SOURCE_FILE, 352),
checkLocal("a", Value.createInt(3)),
checkLocal("b", Value.createInt(8)),
checkLocal("c", Value.createInt(6)),
stepOver(),
checkLine(SOURCE_FILE, 353),
checkLocal("a", Value.createInt(3)),
checkLocal("b", Value.createInt(8)),
checkLocal("c", Value.createInt(11)),
run());
}
@Test
public void testLocalVisibilityIntoLoop() throws Throwable {
final String className = "Locals";
final String methodName = "localVisibilityIntoLoop";
List<Command> commands = new ArrayList<>();
commands.add(breakpoint(className, methodName, 358));
commands.add(run());
commands.add(checkMethod(className, methodName));
commands.add(checkLine(SOURCE_FILE, 358));
commands.add(stepOver());
commands.add(checkLine(SOURCE_FILE, 359));
commands.add(checkNoLocal("Ai"));
commands.add(checkNoLocal("Bi"));
commands.add(checkNoLocal("i"));
commands.add(stepOver());
commands.add(checkMethod(className, methodName));
commands.add(checkLine(SOURCE_FILE, 360));
commands.add(checkNoLocal("Ai"));
commands.add(checkNoLocal("Bi"));
commands.add(checkLocal("i", Value.createInt(0)));
commands.add(stepOver());
commands.add(checkMethod(className, methodName));
commands.add(checkLine(SOURCE_FILE, 361));
commands.add(checkNoLocal("Ai"));
commands.add(checkLocal("Bi"));
commands.add(checkLocal("i", Value.createInt(0)));
commands.add(stepOver());
commands.add(checkMethod(className, methodName));
commands.add(checkLine(SOURCE_FILE, 362));
commands.add(checkLocal("Ai"));
commands.add(checkLocal("Bi"));
commands.add(checkLocal("i", Value.createInt(0)));
commands.add(stepOver());
commands.add(stepOver());
commands.add(stepOver());
commands.add(checkMethod(className, methodName));
commands.add(checkLine(SOURCE_FILE, 359));
commands.add(checkNoLocal("Ai"));
commands.add(checkNoLocal("Bi"));
commands.add(checkLocal("i", Value.createInt(0)));
commands.add(run());
runDebugTest(config, className, commands);
}
}