Skip to content

Commit

Permalink
[wasm][debugger] Fix step behavior (#55915)
Browse files Browse the repository at this point in the history
* Creating test to close 49143.

* Creating test to close #49141

* Adding test for #49218.

* Fix behavior of step to be the same of what we see when debugging using debugger-libs+mono or coreclr.
Fix error message of evaluate calling methods.
Adding test for #49142

* Improving test to test what @radical asked.

* Changing what was suggested by @radical.
  • Loading branch information
thaystg authored Jul 21, 2021
1 parent aaba3c2 commit f85f579
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 41 deletions.
8 changes: 7 additions & 1 deletion src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ internal enum StepFilter {
DebuggerNonUserCode = 8
}

internal enum StepSize
{
Minimal,
Line
}

internal class MonoBinaryReader : BinaryReader
{
public MonoBinaryReader(Stream stream) : base(stream) {}
Expand Down Expand Up @@ -897,7 +903,7 @@ public async Task<bool> Step(SessionId sessionId, int thread_id, StepKind kind,
commandParamsWriter.Write((byte)1);
commandParamsWriter.Write((byte)ModifierKind.Step);
commandParamsWriter.Write(thread_id);
commandParamsWriter.Write((int)0);
commandParamsWriter.Write((int)StepSize.Line);
commandParamsWriter.Write((int)kind);
commandParamsWriter.Write((int)(StepFilter.StaticCtor | StepFilter.DebuggerHidden)); //filter
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdEventRequest>(sessionId, CmdEventRequest.Set, commandParams, token);
Expand Down
17 changes: 17 additions & 0 deletions src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,23 @@ internal async Task<Result> SetBreakpointInMethod(string assembly, string type,
return res;
}

internal async Task EvaluateOnCallFrameAndCheck(string call_frame_id, params (string expression, JObject expected)[] args)
{
foreach (var arg in args)
{
var (eval_val, _) = await EvaluateOnCallFrame(call_frame_id, arg.expression);
try
{
await CheckValue(eval_val, arg.expected, arg.expression);
}
catch
{
Console.WriteLine($"CheckValue failed for {arg.expression}. Expected: {arg.expected}, vs {eval_val}");
throw;
}
}
}

internal void AssertEqual(object expected, object actual, string label)
{
if (expected?.Equals(actual) == true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,23 +476,6 @@ public async Task EvaluatePropertyThatThrows()
await EvaluateOnCallFrameAndCheck(id, ("this.PropertyThrowException", TString("System.Exception: error")));
});

async Task EvaluateOnCallFrameAndCheck(string call_frame_id, params (string expression, JObject expected)[] args)
{
foreach (var arg in args)
{
var (eval_val, _) = await EvaluateOnCallFrame(call_frame_id, arg.expression);
try
{
await CheckValue(eval_val, arg.expected, arg.expression);
}
catch
{
Console.WriteLine($"CheckValue failed for {arg.expression}. Expected: {arg.expected}, vs {eval_val}");
throw;
}
}
}

async Task EvaluateOnCallFrameFail(string call_frame_id, params (string expression, string class_name)[] args)
{
foreach (var arg in args)
Expand All @@ -513,7 +496,7 @@ public async Task EvaluateSimpleMethodCallsError() => await CheckInspectLocalsAt
var id = pause_location["callFrames"][0]["callFrameId"].Value<string>();
var (_, res) = await EvaluateOnCallFrame(id, "this.objToTest.MyMethodWrong()", expect_ok: false );
AssertEqual("Method 'MyMethodWrong' not found in type 'DebuggerTests.EvaluateMethodTestsClass.ParmToTest'", res.Error["message"]?.Value<string>(), "wrong error message");
AssertEqual("Unable to evaluate method 'MyMethodWrong'", res.Error["message"]?.Value<string>(), "wrong error message");
(_, res) = await EvaluateOnCallFrame(id, "this.objToTest.MyMethod(1)", expect_ok: false );
AssertEqual("Unable to evaluate method 'MyMethod'", res.Error["message"]?.Value<string>(), "wrong error message");
Expand All @@ -522,10 +505,10 @@ public async Task EvaluateSimpleMethodCallsError() => await CheckInspectLocalsAt
AssertEqual("Unable to evaluate method 'CallMethodWithParm'", res.Error["message"]?.Value<string>(), "wrong error message");
(_, res) = await EvaluateOnCallFrame(id, "this.ParmToTestObjNull.MyMethod()", expect_ok: false );
AssertEqual("Object reference not set to an instance of an object.", res.Error["message"]?.Value<string>(), "wrong error message");
AssertEqual("Unable to evaluate method 'MyMethod'", res.Error["message"]?.Value<string>(), "wrong error message");
(_, res) = await EvaluateOnCallFrame(id, "this.ParmToTestObjException.MyMethod()", expect_ok: false );
AssertEqual("Object reference not set to an instance of an object.", res.Error["message"]?.Value<string>(), "wrong error message");
AssertEqual("Unable to evaluate method 'MyMethod'", res.Error["message"]?.Value<string>(), "wrong error message");
});

[Fact]
Expand All @@ -540,6 +523,7 @@ await EvaluateOnCallFrameAndCheck(id,
("this.CallMethod()", TNumber(1)),
("this.CallMethod()", TNumber(1)),
("this.ParmToTestObj.MyMethod()", TString("methodOK")),
("this.ParmToTestObj.ToString()", TString("DebuggerTests.EvaluateMethodTestsClass+ParmToTest")),
("this.objToTest.MyMethod()", TString("methodOK")));
});

Expand Down
76 changes: 71 additions & 5 deletions src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public async Task InspectLocalsInPreviousFramesDuringSteppingIn(bool use_cfo)
CheckObject(locals_m1, "nim", "Math.NestedInMath");

// step back into OuterMethod
await StepAndCheck(StepKind.Over, debugger_test_loc, 91, 8, "OuterMethod", times: 9,
await StepAndCheck(StepKind.Over, debugger_test_loc, 91, 8, "OuterMethod", times: 6,
locals_fn: (locals) =>
{
Assert.Equal(5, locals.Count());
Expand Down Expand Up @@ -236,7 +236,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs",
}
);

await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 92, 8, "OuterMethod", times: 2,
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 92, 8, "OuterMethod", times: 1,
locals_fn: (locals) =>
{
Assert.Equal(5, locals.Count());
Expand Down Expand Up @@ -284,7 +284,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs",

// Step into InnerMethod
await StepAndCheck(StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 105, 8, "InnerMethod");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 109, 12, "InnerMethod", times: 5,
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 110, 12, "InnerMethod", times: 5,
locals_fn: (locals) =>
{
Assert.Equal(4, locals.Count());
Expand All @@ -297,7 +297,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs",
);

// Step back to OuterMethod
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 88, 8, "OuterMethod", times: 6,
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 90, 8, "OuterMethod", times: 6,
locals_fn: (locals) =>
{
Assert.Equal(5, locals.Count());
Expand Down Expand Up @@ -469,7 +469,7 @@ public async Task InspectValueTypeMethodArgsWhileStepping(bool use_cfo)
// ----------- Step back to the caller ---------

pause_location = await StepAndCheck(StepKind.Over, debugger_test_loc, 30, 12, "TestStructsAsMethodArgs",
times: 2, locals_fn: (l) => { /* non-null to make sure that locals get fetched */ });
times: 1, locals_fn: (l) => { /* non-null to make sure that locals get fetched */ });
locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
await CheckProps(locals, new
{
Expand Down Expand Up @@ -862,5 +862,71 @@ public async Task BreakpointOnHiddenLineOfMethodWithNoNextVisibleLineShouldNotPa
Task t = await Task.WhenAny(pause_task, Task.Delay(2000));
Assert.True(t != pause_task, "Debugger unexpectedly paused");
}

[Fact]
public async Task SimpleStep_RegressionTest_49141()
{
await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 674, 0);

string expression = "window.setTimeout(function() { invoke_static_method ('[debugger-test] Foo:RunBart'); }, 1);";
await EvaluateAndCheck(
expression,
"dotnet://debugger-test.dll/debugger-test.cs", 674, 12,
"Bart");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 677, 8, "Bart");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 678, 4, "Bart");
}

[Fact]
public async Task StepAndEvaluateExpression()
{
await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 682, 0);

await EvaluateAndCheck(
"window.setTimeout(function() { invoke_static_method ('[debugger-test] Foo:RunBart'); }, 1);",
"dotnet://debugger-test.dll/debugger-test.cs", 682, 8,
"RunBart");
var pause_location = await StepAndCheck(StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 671, 4, "Bart");
var id = pause_location["callFrames"][0]["callFrameId"].Value<string>();
await EvaluateOnCallFrameAndCheck(id, ("this.Bar", TString("Same of something")));
pause_location = await StepAndCheck(StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 673, 8, "Bart");
id = pause_location["callFrames"][0]["callFrameId"].Value<string>();
await EvaluateOnCallFrameAndCheck(id, ("this.Bar", TString("Same of something")));
}

[Fact]
public async Task StepOverWithMoreThanOneCommandInSameLine()
{
await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 693, 0);

string expression = "window.setTimeout(function() { invoke_static_method ('[debugger-test] Foo:RunBart'); }, 1);";
await EvaluateAndCheck(
expression,
"dotnet://debugger-test.dll/debugger-test.cs", 693, 8,
"OtherBar");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 694, 8, "OtherBar");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 696, 8, "OtherBar");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 699, 8, "OtherBar");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 701, 8, "OtherBar");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 702, 4, "OtherBar");
}

[Fact]
public async Task StepOverWithMoreThanOneCommandInSameLineAsync()
{
await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 710, 0);

string expression = "window.setTimeout(function() { invoke_static_method ('[debugger-test] Foo:RunBart'); }, 1);";
await EvaluateAndCheck(
expression,
"dotnet://debugger-test.dll/debugger-test.cs", 710, 8,
"MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 711, 8, "MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 713, 8, "MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 716, 8, "MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 718, 8, "MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 719, 8, "MoveNext");
await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 720, 4, "MoveNext");
}
}
}
Loading

0 comments on commit f85f579

Please sign in to comment.