Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sdks/wasm/DebuggerTestSuite/Tests.cs')
-rw-r--r--sdks/wasm/DebuggerTestSuite/Tests.cs2840
1 files changed, 1495 insertions, 1345 deletions
diff --git a/sdks/wasm/DebuggerTestSuite/Tests.cs b/sdks/wasm/DebuggerTestSuite/Tests.cs
index af0ed721916..34dc5ef605d 100644
--- a/sdks/wasm/DebuggerTestSuite/Tests.cs
+++ b/sdks/wasm/DebuggerTestSuite/Tests.cs
@@ -1,1378 +1,1528 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
using System;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.WebAssembly.Diagnostics;
using Newtonsoft.Json.Linq;
using Xunit;
-using WebAssembly.Net.Debugging;
-[assembly: CollectionBehavior (CollectionBehavior.CollectionPerAssembly)]
+[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
namespace DebuggerTests
{
- public class SourceList : DebuggerTestBase {
-
- [Fact]
- public async Task CheckThatAllSourcesAreSent () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- //all sources are sent before runtime ready is sent, nothing to check
- await insp.Ready ();
- Assert.Contains ("dotnet://debugger-test.dll/debugger-test.cs", scripts.Values);
- Assert.Contains ("dotnet://debugger-test.dll/debugger-test2.cs", scripts.Values);
- Assert.Contains ("dotnet://Simple.Dependency.dll/dependency.cs", scripts.Values);
- }
-
- [Fact]
- public async Task CreateGoodBreakpoint () {
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var bp1_res = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 5, 2);
-
- Assert.EndsWith ("debugger-test.cs", bp1_res.Value ["breakpointId"].ToString());
- Assert.Equal (1, bp1_res.Value ["locations"]?.Value<JArray> ()?.Count);
-
- var loc = bp1_res.Value ["locations"]?.Value<JArray> ()[0];
-
- Assert.NotNull (loc ["scriptId"]);
- Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts [loc["scriptId"]?.Value<string> ()]);
- Assert.Equal (5, loc ["lineNumber"]);
- Assert.Equal (2, loc ["columnNumber"]);
- });
- }
-
- [Fact]
- public async Task CreateJSBreakpoint () {
- // Test that js breakpoints get set correctly
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- // 13 24
- // 13 31
- var bp1_res = await SetBreakpoint ("/debugger-driver.html", 13, 24);
-
- Assert.EndsWith ("debugger-driver.html", bp1_res.Value ["breakpointId"].ToString());
- Assert.Equal (1, bp1_res.Value ["locations"]?.Value<JArray> ()?.Count);
-
- var loc = bp1_res.Value ["locations"]?.Value<JArray> ()[0];
-
- Assert.NotNull (loc ["scriptId"]);
- Assert.Equal (13, loc ["lineNumber"]);
- Assert.Equal (24, loc ["columnNumber"]);
-
- var bp2_res = await SetBreakpoint ("/debugger-driver.html", 13, 31);
-
- Assert.EndsWith ("debugger-driver.html", bp2_res.Value ["breakpointId"].ToString());
- Assert.Equal (1, bp2_res.Value ["locations"]?.Value<JArray> ()?.Count);
-
- var loc2 = bp2_res.Value ["locations"]?.Value<JArray> ()[0];
-
- Assert.NotNull (loc2 ["scriptId"]);
- Assert.Equal (13, loc2 ["lineNumber"]);
- Assert.Equal (31, loc2 ["columnNumber"]);
- });
- }
-
- [Fact]
- public async Task CreateJS0Breakpoint () {
- // Test that js column 0 does as expected
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- // 13 24
- // 13 31
- var bp1_res = await SetBreakpoint ("/debugger-driver.html", 13, 0);
-
- Assert.EndsWith ("debugger-driver.html", bp1_res.Value ["breakpointId"].ToString());
- Assert.Equal (1, bp1_res.Value ["locations"]?.Value<JArray> ()?.Count);
-
- var loc = bp1_res.Value ["locations"]?.Value<JArray> ()[0];
-
- Assert.NotNull (loc ["scriptId"]);
- Assert.Equal (13, loc ["lineNumber"]);
- Assert.Equal (24, loc ["columnNumber"]);
+ public class SourceList : DebuggerTestBase
+ {
+
+ [Fact]
+ public async Task CheckThatAllSourcesAreSent()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
- var bp2_res = await SetBreakpoint ("/debugger-driver.html", 13, 31);
+ await Ready();
+ //all sources are sent before runtime ready is sent, nothing to check
+ await insp.Ready();
+ Assert.Contains("dotnet://debugger-test.dll/debugger-test.cs", scripts.Values);
+ Assert.Contains("dotnet://debugger-test.dll/debugger-test2.cs", scripts.Values);
+ Assert.Contains("dotnet://debugger-test.dll/dependency.cs", scripts.Values);
+ }
- Assert.EndsWith ("debugger-driver.html", bp2_res.Value ["breakpointId"].ToString());
- Assert.Equal (1, bp2_res.Value ["locations"]?.Value<JArray> ()?.Count);
+ [Fact]
+ public async Task CreateGoodBreakpoint()
+ {
+ var insp = new Inspector();
- var loc2 = bp2_res.Value ["locations"]?.Value<JArray> ()[0];
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
- Assert.NotNull (loc2 ["scriptId"]);
- Assert.Equal (13, loc2 ["lineNumber"]);
- Assert.Equal (31, loc2 ["columnNumber"]);
- });
- }
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp1_res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8);
- [Theory]
- [InlineData (0)]
- [InlineData (44)]
- public async Task CheckMultipleBreakpointsOnSameLine (int col) {
- var insp = new Inspector ();
+ Assert.EndsWith("debugger-test.cs", bp1_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp1_res.Value["locations"]?.Value<JArray>()?.Count);
+
+ var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
- var scripts = SubscribeToScripts(insp);
+ Assert.NotNull(loc["scriptId"]);
+ Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts[loc["scriptId"]?.Value<string>()]);
+ Assert.Equal(10, loc["lineNumber"]);
+ Assert.Equal(8, loc["columnNumber"]);
+ });
+ }
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
+ [Fact]
+ public async Task CreateJSBreakpoint()
+ {
+ // Test that js breakpoints get set correctly
+ var insp = new Inspector();
- var bp1_res = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-array-test.cs", 197, col);
- Assert.EndsWith ("debugger-array-test.cs", bp1_res.Value["breakpointId"].ToString());
- Assert.Equal (1, bp1_res.Value ["locations"]?.Value<JArray> ()?.Count);
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
- var loc = bp1_res.Value ["locations"]?.Value<JArray> ()[0];
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ // 13 24
+ // 13 31
+ var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 24);
- CheckLocation ("dotnet://debugger-test.dll/debugger-array-test.cs", 197, 44, scripts, loc);
+ Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp1_res.Value["locations"]?.Value<JArray>()?.Count);
- var bp2_res = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-array-test.cs", 197, 49);
- Assert.EndsWith ("debugger-array-test.cs", bp2_res.Value["breakpointId"].ToString());
- Assert.Equal (1, bp2_res.Value ["locations"]?.Value<JArray> ()?.Count);
+ var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
- var loc2 = bp2_res.Value ["locations"]?.Value<JArray> ()[0];
+ Assert.NotNull(loc["scriptId"]);
+ Assert.Equal(13, loc["lineNumber"]);
+ Assert.Equal(24, loc["columnNumber"]);
+
+ var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31);
- CheckLocation ("dotnet://debugger-test.dll/debugger-array-test.cs", 197, 49, scripts, loc2);
- });
- }
+ Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp2_res.Value["locations"]?.Value<JArray>()?.Count);
- [Fact]
- public async Task CreateBadBreakpoint () {
- var insp = new Inspector ();
+ var loc2 = bp2_res.Value["locations"]?.Value<JArray>()[0];
- //Collect events
- var scripts = SubscribeToScripts(insp);
+ Assert.NotNull(loc2["scriptId"]);
+ Assert.Equal(13, loc2["lineNumber"]);
+ Assert.Equal(31, loc2["columnNumber"]);
+ });
+ }
+
+ [Fact]
+ public async Task CreateJS0Breakpoint()
+ {
+ // Test that js column 0 does as expected
+ var insp = new Inspector();
- await Ready ();
- await insp.Ready (async (cli, token) => {
- var bp1_req = JObject.FromObject(new {
- lineNumber = 5,
- columnNumber = 2,
- url = "dotnet://debugger-test.dll/this-file-doesnt-exist.cs",
- });
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ // 13 24
+ // 13 31
+ var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 0);
+
+ Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp1_res.Value["locations"]?.Value<JArray>()?.Count);
+
+ var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
+
+ Assert.NotNull(loc["scriptId"]);
+ Assert.Equal(13, loc["lineNumber"]);
+ Assert.Equal(24, loc["columnNumber"]);
+
+ var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31);
+
+ Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp2_res.Value["locations"]?.Value<JArray>()?.Count);
+
+ var loc2 = bp2_res.Value["locations"]?.Value<JArray>()[0];
- var bp1_res = await cli.SendCommand ("Debugger.setBreakpointByUrl", bp1_req, token);
+ Assert.NotNull(loc2["scriptId"]);
+ Assert.Equal(13, loc2["lineNumber"]);
+ Assert.Equal(31, loc2["columnNumber"]);
+ });
+ }
- Assert.True (bp1_res.IsOk);
- Assert.Empty (bp1_res.Value["locations"].Values<object>());
- //Assert.Equal ((int)MonoErrorCodes.BpNotFound, bp1_res.Error ["code"]?.Value<int> ());
- });
- }
+ [Theory]
+ [InlineData(0)]
+ [InlineData(50)]
+ public async Task CheckMultipleBreakpointsOnSameLine(int col)
+ {
+ var insp = new Inspector();
+
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp1_res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-array-test.cs", 219, col);
+ Assert.EndsWith("debugger-array-test.cs", bp1_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp1_res.Value["locations"]?.Value<JArray>()?.Count);
+
+ var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
+
+ CheckLocation("dotnet://debugger-test.dll/debugger-array-test.cs", 219, 50, scripts, loc);
+
+ var bp2_res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-array-test.cs", 219, 55);
+ Assert.EndsWith("debugger-array-test.cs", bp2_res.Value["breakpointId"].ToString());
+ Assert.Equal(1, bp2_res.Value["locations"]?.Value<JArray>()?.Count);
+
+ var loc2 = bp2_res.Value["locations"]?.Value<JArray>()[0];
+
+ CheckLocation("dotnet://debugger-test.dll/debugger-array-test.cs", 219, 55, scripts, loc2);
+ });
+ }
+
+ [Fact]
+ public async Task CreateBadBreakpoint()
+ {
+ var insp = new Inspector();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ var bp1_req = JObject.FromObject(new
+ {
+ lineNumber = 8,
+ columnNumber = 2,
+ url = "dotnet://debugger-test.dll/this-file-doesnt-exist.cs",
+ });
+
+ var bp1_res = await cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, token);
+
+ Assert.True(bp1_res.IsOk);
+ Assert.Empty(bp1_res.Value["locations"].Values<object>());
+ //Assert.Equal ((int)MonoErrorCodes.BpNotFound, bp1_res.Error ["code"]?.Value<int> ());
+ });
+ }
+
+ [Fact]
+ public async Task CreateGoodBreakpointAndHit()
+ {
+ var insp = new Inspector();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8);
+
+ var eval_req = JObject.FromObject(new
+ {
+ expression = "window.setTimeout(function() { invoke_add(); }, 1);",
+ });
+
+ await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_add(); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 10, 8,
+ "IntAdd",
+ wait_for_event_fn: (pause_location) =>
+ {
+ Assert.Equal("other", pause_location["reason"]?.Value<string>());
+ Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());
+
+ var top_frame = pause_location["callFrames"][0];
+ Assert.Equal("IntAdd", top_frame["functionName"].Value<string>());
+ Assert.Contains("debugger-test.cs", top_frame["url"].Value<string>());
+
+ CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]);
+
+ //now check the scope
+ var scope = top_frame["scopeChain"][0];
+ Assert.Equal("local", scope["type"]);
+ Assert.Equal("IntAdd", scope["name"]);
+
+ Assert.Equal("object", scope["object"]["type"]);
+ Assert.Equal("dotnet:scope:0", scope["object"]["objectId"]);
+ CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]);
+ CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]);
+ return Task.CompletedTask;
+ }
+ );
+
+ });
+ }
+
+ [Fact]
+ public async Task ExceptionThrownInJS()
+ {
+ var insp = new Inspector();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ var eval_req = JObject.FromObject(new
+ {
+ expression = "invoke_bad_js_test();"
+ });
+
+ var eval_res = await cli.SendCommand("Runtime.evaluate", eval_req, token);
+ Assert.True(eval_res.IsErr);
+ Assert.Equal("Uncaught", eval_res.Error["exceptionDetails"]?["text"]?.Value<string>());
+ });
+ }
+
+ [Fact]
+ public async Task ExceptionThrownInJSOutOfBand()
+ {
+ var insp = new Inspector();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ await SetBreakpoint("/debugger-driver.html", 27, 2);
+
+ var eval_req = JObject.FromObject(new
+ {
+ expression = "window.setTimeout(function() { invoke_bad_js_test(); }, 1);",
+ });
+
+ var eval_res = await cli.SendCommand("Runtime.evaluate", eval_req, token);
+ // Response here will be the id for the timer from JS!
+ Assert.True(eval_res.IsOk);
+
+ var ex = await Assert.ThrowsAsync<ArgumentException>(async () => await insp.WaitFor("Runtime.exceptionThrown"));
+ var ex_json = JObject.Parse(ex.Message);
+ Assert.Equal(dicFileToUrl["/debugger-driver.html"], ex_json["exceptionDetails"]?["url"]?.Value<string>());
+ });
+
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsAtBreakpointSite(bool use_cfo) =>
+ await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, "IntAdd",
+ "window.setTimeout(function() { invoke_add(); }, 1);",
+ use_cfo: use_cfo,
+ test_fn: (locals) =>
+ {
+ CheckNumber(locals, "a", 10);
+ CheckNumber(locals, "b", 20);
+ CheckNumber(locals, "c", 30);
+ CheckNumber(locals, "d", 0);
+ CheckNumber(locals, "e", 0);
+ }
+ );
+
+ [Fact]
+ public async Task InspectPrimitiveTypeLocalsAtBreakpointSite() =>
+ await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-test.cs", 154, 8, "PrimitiveTypesTest",
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:PrimitiveTypesTest'); }, 1);",
+ test_fn: (locals) =>
+ {
+ CheckSymbol(locals, "c0", "8364 '€'");
+ CheckSymbol(locals, "c1", "65 'A'");
+ }
+ );
+
+ [Fact]
+ public async Task InspectLocalsTypesAtBreakpointSite() =>
+ await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-test2.cs", 48, 8, "Types",
+ "window.setTimeout(function() { invoke_static_method (\"[debugger-test] Fancy:Types\")(); }, 1);",
+ use_cfo: false,
+ test_fn: (locals) =>
+ {
+ CheckNumber(locals, "dPI", Math.PI);
+ CheckNumber(locals, "fPI", (float)Math.PI);
+ CheckNumber(locals, "iMax", int.MaxValue);
+ CheckNumber(locals, "iMin", int.MinValue);
+ CheckNumber(locals, "uiMax", uint.MaxValue);
+ CheckNumber(locals, "uiMin", uint.MinValue);
+
+ CheckNumber(locals, "l", uint.MaxValue * (long)2);
+ //CheckNumber (locals, "lMax", long.MaxValue); // cannot be represented as double
+ //CheckNumber (locals, "lMin", long.MinValue); // cannot be represented as double
+
+ CheckNumber(locals, "sbMax", sbyte.MaxValue);
+ CheckNumber(locals, "sbMin", sbyte.MinValue);
+ CheckNumber(locals, "bMax", byte.MaxValue);
+ CheckNumber(locals, "bMin", byte.MinValue);
+
+ CheckNumber(locals, "sMax", short.MaxValue);
+ CheckNumber(locals, "sMin", short.MinValue);
+ CheckNumber(locals, "usMin", ushort.MinValue);
+ CheckNumber(locals, "usMax", ushort.MaxValue);
+ }
+ );
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsWithGenericTypesAtBreakpointSite(bool use_cfo) =>
+ await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-test.cs", 74, 8, "GenericTypesTest",
+ "window.setTimeout(function() { invoke_generic_types_test (); }, 1);",
+ use_cfo: use_cfo,
+ test_fn: (locals) =>
+ {
+ CheckObject(locals, "list", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>");
+ CheckObject(locals, "list_null", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>", is_null: true);
+
+ CheckArray(locals, "list_arr", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", 1);
+ CheckObject(locals, "list_arr_null", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", is_null: true);
+
+ // Unused locals
+ CheckObject(locals, "list_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>");
+ CheckObject(locals, "list_null_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>", is_null: true);
+
+ CheckArray(locals, "list_arr_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", 1);
+ CheckObject(locals, "list_arr_null_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", is_null: true);
+ }
+ );
+
+ object TGenericStruct(string typearg, string stringField) => new
+ {
+ List = TObject($"System.Collections.Generic.List<{typearg}>"),
+ StringField = TString(stringField)
+ };
+
+ [Fact]
+ public async Task RuntimeGetPropertiesWithInvalidScopeIdTest()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 49, 8);
+
+ await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_delegates_test (); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 49, 8,
+ "DelegatesTest",
+ wait_for_event_fn: async (pause_location) =>
+ {
+ //make sure we're on the right bp
+ Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());
+
+ var top_frame = pause_location["callFrames"][0];
+
+ var scope = top_frame["scopeChain"][0];
+ Assert.Equal("dotnet:scope:0", scope["object"]["objectId"]);
+
+ // Try to get an invalid scope!
+ var get_prop_req = JObject.FromObject(new
+ {
+ objectId = "dotnet:scope:23490871",
+ });
+
+ var frame_props = await cli.SendCommand("Runtime.getProperties", get_prop_req, token);
+ Assert.True(frame_props.IsErr);
+ }
+ );
+ });
+ }
+
+ [Fact]
+ public async Task TrivalStepping()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8);
+
+ await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_add(); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 10, 8,
+ "IntAdd",
+ wait_for_event_fn: (pause_location) =>
+ {
+ //make sure we're on the right bp
+ Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());
+
+ var top_frame = pause_location["callFrames"][0];
+ CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]);
+ return Task.CompletedTask;
+ }
+ );
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 11, 8, "IntAdd",
+ wait_for_event_fn: (pause_location) =>
+ {
+ var top_frame = pause_location["callFrames"][0];
+ CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]);
+ return Task.CompletedTask;
+ }
+ );
+ });
+ }
+
+ [Fact]
+ public async Task InspectLocalsDuringStepping()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+ await SetBreakpoint(debugger_test_loc, 10, 8);
+
+ await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_add(); }, 1);",
+ debugger_test_loc, 10, 8, "IntAdd",
+ locals_fn: (locals) =>
+ {
+ CheckNumber(locals, "a", 10);
+ CheckNumber(locals, "b", 20);
+ CheckNumber(locals, "c", 30);
+ CheckNumber(locals, "d", 0);
+ CheckNumber(locals, "e", 0);
+ }
+ );
+
+ await StepAndCheck(StepKind.Over, debugger_test_loc, 11, 8, "IntAdd",
+ locals_fn: (locals) =>
+ {
+ CheckNumber(locals, "a", 10);
+ CheckNumber(locals, "b", 20);
+ CheckNumber(locals, "c", 30);
+ CheckNumber(locals, "d", 50);
+ CheckNumber(locals, "e", 0);
+ }
+ );
+
+ //step and get locals
+ await StepAndCheck(StepKind.Over, debugger_test_loc, 12, 8, "IntAdd",
+ locals_fn: (locals) =>
+ {
+ CheckNumber(locals, "a", 10);
+ CheckNumber(locals, "b", 20);
+ CheckNumber(locals, "c", 30);
+ CheckNumber(locals, "d", 50);
+ CheckNumber(locals, "e", 60);
+ }
+ );
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsInPreviousFramesDuringSteppingIn2(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+
+ var dep_cs_loc = "dotnet://debugger-test.dll/dependency.cs";
+ await SetBreakpoint(dep_cs_loc, 33, 8);
+
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+
+ // Will stop in Complex.DoEvenMoreStuff
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_use_complex (); }, 1);",
+ dep_cs_loc, 33, 8, "DoEvenMoreStuff",
+ locals_fn: (locals) =>
+ {
+ Assert.Single(locals);
+ CheckObject(locals, "this", "Simple.Complex");
+ }
+ );
+
+ var props = await GetObjectOnFrame(pause_location["callFrames"][0], "this");
+ Assert.Equal(3, props.Count());
+ CheckNumber(props, "A", 10);
+ CheckString(props, "B", "xx");
+ CheckObject(props, "c", "object");
+
+ // Check UseComplex frame
+ var locals_m1 = await GetLocalsForFrame(pause_location["callFrames"][3], debugger_test_loc, 23, 8, "UseComplex");
+ Assert.Equal(7, locals_m1.Count());
+
+ CheckNumber(locals_m1, "a", 10);
+ CheckNumber(locals_m1, "b", 20);
+ CheckObject(locals_m1, "complex", "Simple.Complex");
+ CheckNumber(locals_m1, "c", 30);
+ CheckNumber(locals_m1, "d", 50);
+ CheckNumber(locals_m1, "e", 60);
+ CheckNumber(locals_m1, "f", 0);
+
+ props = await GetObjectOnFrame(pause_location["callFrames"][3], "complex");
+ Assert.Equal(3, props.Count());
+ CheckNumber(props, "A", 10);
+ CheckString(props, "B", "xx");
+ CheckObject(props, "c", "object");
+
+ pause_location = await StepAndCheck(StepKind.Over, dep_cs_loc, 23, 8, "DoStuff", times: 2);
+ // Check UseComplex frame again
+ locals_m1 = await GetLocalsForFrame(pause_location["callFrames"][1], debugger_test_loc, 23, 8, "UseComplex");
+ Assert.Equal(7, locals_m1.Count());
+
+ CheckNumber(locals_m1, "a", 10);
+ CheckNumber(locals_m1, "b", 20);
+ CheckObject(locals_m1, "complex", "Simple.Complex");
+ CheckNumber(locals_m1, "c", 30);
+ CheckNumber(locals_m1, "d", 50);
+ CheckNumber(locals_m1, "e", 60);
+ CheckNumber(locals_m1, "f", 0);
+
+ props = await GetObjectOnFrame(pause_location["callFrames"][1], "complex");
+ Assert.Equal(3, props.Count());
+ CheckNumber(props, "A", 10);
+ CheckString(props, "B", "xx");
+ CheckObject(props, "c", "object");
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsInPreviousFramesDuringSteppingIn(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+ await SetBreakpoint(debugger_test_loc, 111, 12);
+
+ // Will stop in InnerMethod
+ var wait_res = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_outer_method(); }, 1);",
+ debugger_test_loc, 111, 12, "InnerMethod",
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(4, locals.Count());
+ CheckNumber(locals, "i", 5);
+ CheckNumber(locals, "j", 24);
+ CheckString(locals, "foo_str", "foo");
+ CheckObject(locals, "this", "Math.NestedInMath");
+ }
+ );
+
+ var this_props = await GetObjectOnFrame(wait_res["callFrames"][0], "this");
+ Assert.Equal(2, this_props.Count());
+ CheckObject(this_props, "m", "Math");
+ CheckValueType(this_props, "SimpleStructProperty", "Math.SimpleStruct");
+
+ var ss_props = await GetObjectOnLocals(this_props, "SimpleStructProperty");
+ var dt = new DateTime(2020, 1, 2, 3, 4, 5);
+ await CheckProps(ss_props, new
+ {
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("Math.GenericStruct<System.DateTime>")
+ }, "ss_props");
+
+ await CheckDateTime(ss_props, "dt", new DateTime(2020, 1, 2, 3, 4, 5));
+
+ // Check OuterMethod frame
+ var locals_m1 = await GetLocalsForFrame(wait_res["callFrames"][1], debugger_test_loc, 87, 8, "OuterMethod");
+ Assert.Equal(5, locals_m1.Count());
+ // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
+ // FIXME: Failing test CheckString (locals_m1, "text", "Hello");
+ CheckNumber(locals_m1, "new_i", 0);
+ CheckNumber(locals_m1, "k", 0);
+ CheckObject(locals_m1, "nim", "Math.NestedInMath");
+
+ // step back into OuterMethod
+ await StepAndCheck(StepKind.Over, debugger_test_loc, 91, 8, "OuterMethod", times: 9,
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(5, locals.Count());
+
+ // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
+ CheckString(locals, "text", "Hello");
+ // FIXME: Failing test CheckNumber (locals, "new_i", 24);
+ CheckNumber(locals, "k", 19);
+ CheckObject(locals, "nim", "Math.NestedInMath");
+ }
+ );
+
+ //await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 81, 2, "OuterMethod", times: 2);
+
+ // step into InnerMethod2
+ await StepAndCheck(StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 96, 4, "InnerMethod2",
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(3, locals.Count());
+
+ CheckString(locals, "s", "test string");
+ //out var: CheckNumber (locals, "k", 0);
+ CheckNumber(locals, "i", 24);
+ }
+ );
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 100, 4, "InnerMethod2", times: 4,
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(3, locals.Count());
+
+ CheckString(locals, "s", "test string");
+ // FIXME: Failing test CheckNumber (locals, "k", 34);
+ CheckNumber(locals, "i", 24);
+ }
+ );
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 92, 8, "OuterMethod", times: 2,
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(5, locals.Count());
+
+ CheckString(locals, "text", "Hello");
+ // FIXME: failing test CheckNumber (locals, "i", 5);
+ CheckNumber(locals, "new_i", 22);
+ CheckNumber(locals, "k", 34);
+ CheckObject(locals, "nim", "Math.NestedInMath");
+ }
+ );
+ });
+ }
+
+ [Fact]
+ public async Task InspectLocalsDuringSteppingIn()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 86, 8);
+
+ await EvaluateAndCheck("window.setTimeout(function() { invoke_outer_method(); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 86, 8, "OuterMethod",
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(5, locals.Count());
+
+ CheckObject(locals, "nim", "Math.NestedInMath");
+ CheckNumber(locals, "i", 5);
+ CheckNumber(locals, "k", 0);
+ CheckNumber(locals, "new_i", 0);
+ CheckString(locals, "text", null);
+ }
+ );
+
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 87, 8, "OuterMethod",
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(5, locals.Count());
+
+ CheckObject(locals, "nim", "Math.NestedInMath");
+ // FIXME: Failing test CheckNumber (locals, "i", 5);
+ CheckNumber(locals, "k", 0);
+ CheckNumber(locals, "new_i", 0);
+ CheckString(locals, "text", "Hello");
+ }
+ );
+
+ // 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,
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(4, locals.Count());
+
+ CheckNumber(locals, "i", 5);
+ CheckNumber(locals, "j", 15);
+ CheckString(locals, "foo_str", "foo");
+ CheckObject(locals, "this", "Math.NestedInMath");
+ }
+ );
+
+ // Step back to OuterMethod
+ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 88, 8, "OuterMethod", times: 6,
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(5, locals.Count());
+
+ CheckObject(locals, "nim", "Math.NestedInMath");
+ // FIXME: Failing test CheckNumber (locals, "i", 5);
+ CheckNumber(locals, "k", 0);
+ CheckNumber(locals, "new_i", 24);
+ CheckString(locals, "text", "Hello");
+ }
+ );
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsInAsyncMethods(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+
+ await SetBreakpoint(debugger_test_loc, 120, 12);
+ await SetBreakpoint(debugger_test_loc, 135, 12);
+
+ // Will stop in Asyncmethod0
+ var wait_res = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_async_method_with_await(); }, 1);",
+ debugger_test_loc, 120, 12, "MoveNext", //FIXME:
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(4, locals.Count());
+ CheckString(locals, "s", "string from js");
+ CheckNumber(locals, "i", 42);
+ CheckString(locals, "local0", "value0");
+ CheckObject(locals, "this", "Math.NestedInMath");
+ }
+ );
+ Console.WriteLine(wait_res);
- [Fact]
- public async Task CreateGoodBreakpointAndHit () {
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var bp = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 5, 2);
-
- var eval_req = JObject.FromObject(new {
- expression = "window.setTimeout(function() { invoke_add(); }, 1);",
- });
-
- await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_add(); }, 1);",
- "dotnet://debugger-test.dll/debugger-test.cs", 5, 2,
- "IntAdd",
- wait_for_event_fn: (pause_location) => {
- Assert.Equal ("other", pause_location ["reason"]?.Value<string> ());
- Assert.Equal (bp.Value["breakpointId"]?.ToString(), pause_location ["hitBreakpoints"]?[0]?.Value<string> ());
-
- var top_frame = pause_location ["callFrames"][0];
- Assert.Equal ("IntAdd", top_frame ["functionName"].Value<string>());
- Assert.Contains ("debugger-test.cs", top_frame ["url"].Value<string> ());
-
- CheckLocation ("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, top_frame["functionLocation"]);
-
- //now check the scope
- var scope = top_frame ["scopeChain"][0];
- Assert.Equal ("local", scope ["type"]);
- Assert.Equal ("IntAdd", scope ["name"]);
-
- Assert.Equal ("object", scope ["object"]["type"]);
- Assert.Equal ("dotnet:scope:0", scope ["object"]["objectId"]);
- CheckLocation ("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, scope["startLocation"]);
- CheckLocation ("dotnet://debugger-test.dll/debugger-test.cs", 9, 1, scripts, scope["endLocation"]);
- return Task.CompletedTask;
- }
- );
-
- });
- }
-
- [Fact]
- public async Task ExceptionThrownInJS () {
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- var eval_req = JObject.FromObject(new {
- expression = "invoke_bad_js_test();"
- });
-
- var eval_res = await cli.SendCommand ("Runtime.evaluate", eval_req, token);
- Assert.True (eval_res.IsErr);
- Assert.Equal ("Uncaught", eval_res.Error ["exceptionDetails"]? ["text"]? .Value<string> ());
- });
- }
-
- [Fact]
- public async Task ExceptionThrownInJSOutOfBand () {
- var insp = new Inspector ();
-
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- await SetBreakpoint ("/debugger-driver.html", 27, 2);
-
- var eval_req = JObject.FromObject(new {
- expression = "window.setTimeout(function() { invoke_bad_js_test(); }, 1);",
- });
-
- var eval_res = await cli.SendCommand ("Runtime.evaluate", eval_req, token);
- // Response here will be the id for the timer from JS!
- Assert.True (eval_res.IsOk);
-
- var ex = await Assert.ThrowsAsync<ArgumentException> (async () => await insp.WaitFor("Runtime.exceptionThrown"));
- var ex_json = JObject.Parse (ex.Message);
- Assert.Equal (dicFileToUrl["/debugger-driver.html"], ex_json ["exceptionDetails"]? ["url"]? .Value<string> ());
- });
-
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsAtBreakpointSite (bool use_cfo) =>
- await CheckInspectLocalsAtBreakpointSite (
- "dotnet://debugger-test.dll/debugger-test.cs", 5, 2, "IntAdd",
- "window.setTimeout(function() { invoke_add(); }, 1);",
- use_cfo: use_cfo,
- test_fn: (locals) => {
- CheckNumber (locals, "a", 10);
- CheckNumber (locals, "b", 20);
- CheckNumber (locals, "c", 30);
- CheckNumber (locals, "d", 0);
- CheckNumber (locals, "e", 0);
- }
- );
-
- [Fact]
- public async Task InspectPrimitiveTypeLocalsAtBreakpointSite () =>
- await CheckInspectLocalsAtBreakpointSite (
- "dotnet://debugger-test.dll/debugger-test.cs", 145, 2, "PrimitiveTypesTest",
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:PrimitiveTypesTest'); }, 1);",
- test_fn: (locals) => {
- CheckSymbol (locals, "c0", "8364 '€'");
- CheckSymbol (locals, "c1", "65 'A'");
- }
- );
-
- [Fact]
- public async Task InspectLocalsTypesAtBreakpointSite () =>
- await CheckInspectLocalsAtBreakpointSite (
- "dotnet://debugger-test.dll/debugger-test2.cs", 40, 2, "Types",
- "window.setTimeout(function() { invoke_static_method (\"[debugger-test] Fancy:Types\")(); }, 1);",
- use_cfo: false,
- test_fn: (locals) => {
- CheckNumber (locals, "dPI", Math.PI);
- CheckNumber (locals, "fPI", (float)Math.PI);
- CheckNumber (locals, "iMax", int.MaxValue);
- CheckNumber (locals, "iMin", int.MinValue);
- CheckNumber (locals, "uiMax", uint.MaxValue);
- CheckNumber (locals, "uiMin", uint.MinValue);
-
- CheckNumber (locals, "l", uint.MaxValue * (long)2);
- //CheckNumber (locals, "lMax", long.MaxValue); // cannot be represented as double
- //CheckNumber (locals, "lMin", long.MinValue); // cannot be represented as double
-
- CheckNumber (locals, "sbMax", sbyte.MaxValue);
- CheckNumber (locals, "sbMin", sbyte.MinValue);
- CheckNumber (locals, "bMax", byte.MaxValue);
- CheckNumber (locals, "bMin", byte.MinValue);
-
- CheckNumber (locals, "sMax", short.MaxValue);
- CheckNumber (locals, "sMin", short.MinValue);
- CheckNumber (locals, "usMin", ushort.MinValue);
- CheckNumber (locals, "usMax", ushort.MaxValue);
- }
- );
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsWithGenericTypesAtBreakpointSite (bool use_cfo) =>
- await CheckInspectLocalsAtBreakpointSite (
- "dotnet://debugger-test.dll/debugger-test.cs", 65, 2, "GenericTypesTest",
- "window.setTimeout(function() { invoke_generic_types_test (); }, 1);",
- use_cfo: use_cfo,
- test_fn: (locals) => {
- CheckObject (locals, "list", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>");
- CheckObject (locals, "list_null", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>", is_null: true);
-
- CheckArray (locals, "list_arr", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]");
- CheckObject (locals, "list_arr_null", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", is_null: true);
-
- // Unused locals
- CheckObject (locals, "list_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>");
- CheckObject (locals, "list_null_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>", is_null: true);
-
- CheckObject (locals, "list_arr_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]");
- CheckObject (locals, "list_arr_null_unused", "System.Collections.Generic.Dictionary<Math[], Math.IsMathNull>[]", is_null: true);
- }
- );
-
- object TGenericStruct(string typearg, string stringField)
- => new {
- List = TObject ($"System.Collections.Generic.List<{typearg}>"),
- StringField = TString (stringField)
- };
-
- [Fact]
- public async Task RuntimeGetPropertiesWithInvalidScopeIdTest () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var bp = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 41, 2);
-
- await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_delegates_test (); }, 1);",
- "dotnet://debugger-test.dll/debugger-test.cs", 41, 2,
- "DelegatesTest",
- wait_for_event_fn: async (pause_location) => {
- //make sure we're on the right bp
- Assert.Equal (bp.Value ["breakpointId"]?.ToString (), pause_location ["hitBreakpoints"]?[0]?.Value<string> ());
-
- var top_frame = pause_location ["callFrames"][0];
-
- var scope = top_frame ["scopeChain"][0];
- Assert.Equal ("dotnet:scope:0", scope ["object"]["objectId"]);
-
- // Try to get an invalid scope!
- var get_prop_req = JObject.FromObject(new {
- objectId = "dotnet:scope:23490871",
- });
-
- var frame_props = await cli.SendCommand ("Runtime.getProperties", get_prop_req, token);
- Assert.True (frame_props.IsErr);
- }
- );
- });
- }
-
- [Fact]
- public async Task TrivalStepping () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var bp = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 5, 2);
-
- await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_add(); }, 1);",
- "dotnet://debugger-test.dll/debugger-test.cs", 5, 2,
- "IntAdd",
- wait_for_event_fn: (pause_location) => {
- //make sure we're on the right bp
- Assert.Equal (bp.Value ["breakpointId"]?.ToString (), pause_location ["hitBreakpoints"]?[0]?.Value<string> ());
-
- var top_frame = pause_location ["callFrames"][0];
- CheckLocation ("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, top_frame["functionLocation"]);
- return Task.CompletedTask;
- }
- );
-
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 6, 2, "IntAdd",
- wait_for_event_fn: (pause_location) => {
- var top_frame = pause_location ["callFrames"][0];
- CheckLocation ("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, top_frame["functionLocation"]);
- return Task.CompletedTask;
- }
- );
- });
- }
-
- [Fact]
- public async Task InspectLocalsDuringStepping () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
- await SetBreakpoint (debugger_test_loc, 4, 2);
-
- await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_add(); }, 1);",
- debugger_test_loc, 4, 2, "IntAdd",
- locals_fn: (locals) => {
- CheckNumber (locals, "a", 10);
- CheckNumber (locals, "b", 20);
- CheckNumber (locals, "c", 0);
- CheckNumber (locals, "d", 0);
- CheckNumber (locals, "e", 0);
- }
- );
-
- await StepAndCheck (StepKind.Over, debugger_test_loc, 5, 2, "IntAdd",
- locals_fn: (locals) => {
- CheckNumber (locals, "a", 10);
- CheckNumber (locals, "b", 20);
- CheckNumber (locals, "c", 30);
- CheckNumber (locals, "d", 0);
- CheckNumber (locals, "e", 0);
- }
- );
-
- //step and get locals
- await StepAndCheck (StepKind.Over, debugger_test_loc, 6, 2, "IntAdd",
- locals_fn: (locals) => {
- CheckNumber (locals, "a", 10);
- CheckNumber (locals, "b", 20);
- CheckNumber (locals, "c", 30);
- CheckNumber (locals, "d", 50);
- CheckNumber (locals, "e", 0);
- }
- );
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsInPreviousFramesDuringSteppingIn2 (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
-
- var dep_cs_loc = "dotnet://Simple.Dependency.dll/dependency.cs";
- await SetBreakpoint (dep_cs_loc, 24, 2);
-
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
-
- // Will stop in Complex.DoEvenMoreStuff
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_use_complex (); }, 1);",
- dep_cs_loc, 24, 2, "DoEvenMoreStuff",
- locals_fn: (locals) => {
- Assert.Single (locals);
- CheckObject (locals, "this", "Simple.Complex");
- }
- );
-
- var props = await GetObjectOnFrame (pause_location["callFrames"][0], "this");
- Assert.Equal (3, props.Count());
- CheckNumber (props, "A", 10);
- CheckString (props, "B", "xx");
- CheckObject (props, "c", "object");
-
- // Check UseComplex frame
- var locals_m1 = await GetLocalsForFrame (pause_location ["callFrames"][3], debugger_test_loc, 17, 2, "UseComplex");
- Assert.Equal (7, locals_m1.Count());
-
- CheckNumber (locals_m1, "a", 10);
- CheckNumber (locals_m1, "b", 20);
- CheckObject (locals_m1, "complex", "Simple.Complex");
- CheckNumber (locals_m1, "c", 30);
- CheckNumber (locals_m1, "d", 50);
- CheckNumber (locals_m1, "e", 60);
- CheckNumber (locals_m1, "f", 0);
-
- props = await GetObjectOnFrame (pause_location["callFrames"][3], "complex");
- Assert.Equal (3, props.Count());
- CheckNumber (props, "A", 10);
- CheckString (props, "B", "xx");
- CheckObject (props, "c", "object");
-
- pause_location = await StepAndCheck (StepKind.Over, dep_cs_loc, 16, 2, "DoStuff", times: 2);
- // Check UseComplex frame again
- locals_m1 = await GetLocalsForFrame (pause_location ["callFrames"][1], debugger_test_loc, 17, 2, "UseComplex");
- Assert.Equal (7, locals_m1.Count());
-
- CheckNumber (locals_m1, "a", 10);
- CheckNumber (locals_m1, "b", 20);
- CheckObject (locals_m1, "complex", "Simple.Complex");
- CheckNumber (locals_m1, "c", 30);
- CheckNumber (locals_m1, "d", 50);
- CheckNumber (locals_m1, "e", 60);
- CheckNumber (locals_m1, "f", 0);
-
- props = await GetObjectOnFrame (pause_location["callFrames"][1], "complex");
- Assert.Equal (3, props.Count());
- CheckNumber (props, "A", 10);
- CheckString (props, "B", "xx");
- CheckObject (props, "c", "object");
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsInPreviousFramesDuringSteppingIn (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
-
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
- await SetBreakpoint (debugger_test_loc, 102, 3);
-
- // Will stop in InnerMethod
- var wait_res = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_outer_method(); }, 1);",
- debugger_test_loc, 102, 3, "InnerMethod",
- locals_fn: (locals) => {
- Assert.Equal (4, locals.Count());
- CheckNumber (locals, "i", 5);
- CheckNumber (locals, "j", 24);
- CheckString (locals, "foo_str", "foo");
- CheckObject (locals, "this", "Math.NestedInMath");
- }
- );
-
- var this_props = await GetObjectOnFrame (wait_res["callFrames"][0], "this");
- Assert.Equal (2, this_props.Count());
- CheckObject (this_props, "m", "Math");
- CheckValueType (this_props, "SimpleStructProperty", "Math.SimpleStruct");
-
- var ss_props = await GetObjectOnLocals (this_props, "SimpleStructProperty");
- Assert.Equal (2, ss_props.Count());
- CheckValueType (ss_props, "dt", "System.DateTime");
- CheckValueType (ss_props, "gs", "Math.GenericStruct<System.DateTime>");
-
- await CheckDateTime (ss_props, "dt", new DateTime (2020, 1, 2, 3, 4, 5));
-
- // Check OuterMethod frame
- var locals_m1 = await GetLocalsForFrame (wait_res ["callFrames"][1], debugger_test_loc, 78, 2, "OuterMethod");
- Assert.Equal (5, locals_m1.Count());
- // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
- // FIXME: Failing test CheckString (locals_m1, "text", "Hello");
- CheckNumber (locals_m1, "new_i", 0);
- CheckNumber (locals_m1, "k", 0);
- CheckObject (locals_m1, "nim", "Math.NestedInMath");
-
- // step back into OuterMethod
- await StepAndCheck (StepKind.Over, debugger_test_loc, 82, 2, "OuterMethod", times: 9,
- locals_fn: (locals) => {
- Assert.Equal (5, locals.Count());
-
- // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
- CheckString (locals, "text", "Hello");
- // FIXME: Failing test CheckNumber (locals, "new_i", 24);
- CheckNumber (locals, "k", 19);
- CheckObject (locals, "nim", "Math.NestedInMath");
- }
- );
-
- //await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 81, 2, "OuterMethod", times: 2);
-
- // step into InnerMethod2
- await StepAndCheck (StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 87, 1, "InnerMethod2",
- locals_fn: (locals) => {
- Assert.Equal (3, locals.Count());
-
- CheckString (locals, "s", "test string");
- //out var: CheckNumber (locals, "k", 0);
- CheckNumber (locals, "i", 24);
- }
- );
-
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 91, 1, "InnerMethod2", times: 4,
- locals_fn: (locals) => {
- Assert.Equal (3, locals.Count());
-
- CheckString (locals, "s", "test string");
- // FIXME: Failing test CheckNumber (locals, "k", 34);
- CheckNumber (locals, "i", 24);
- }
- );
-
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 83, 2, "OuterMethod", times: 2,
- locals_fn: (locals) => {
- Assert.Equal (5, locals.Count());
-
- CheckString (locals, "text", "Hello");
- // FIXME: failing test CheckNumber (locals, "i", 5);
- CheckNumber (locals, "new_i", 22);
- CheckNumber (locals, "k", 34);
- CheckObject (locals, "nim", "Math.NestedInMath");
- }
- );
- });
- }
-
- [Fact]
- public async Task InspectLocalsDuringSteppingIn () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 77, 2);
-
- await EvaluateAndCheck ("window.setTimeout(function() { invoke_outer_method(); }, 1);",
- "dotnet://debugger-test.dll/debugger-test.cs", 77, 2, "OuterMethod",
- locals_fn: (locals) => {
- Assert.Equal (5, locals.Count());
-
- CheckObject (locals, "nim", "Math.NestedInMath");
- CheckNumber (locals, "i", 5);
- CheckNumber (locals, "k", 0);
- CheckNumber (locals, "new_i", 0);
- CheckString (locals, "text", null);
- }
- );
-
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 78, 2, "OuterMethod",
- locals_fn: (locals) => {
- Assert.Equal (5, locals.Count());
-
- CheckObject (locals, "nim", "Math.NestedInMath");
- // FIXME: Failing test CheckNumber (locals, "i", 5);
- CheckNumber (locals, "k", 0);
- CheckNumber (locals, "new_i", 0);
- CheckString (locals, "text", "Hello");
- }
- );
-
- // Step into InnerMethod
- await StepAndCheck (StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 96, 2, "InnerMethod");
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 100, 3, "InnerMethod", times: 5,
- locals_fn: (locals) => {
- Assert.Equal (4, locals.Count());
-
- CheckNumber (locals, "i", 5);
- CheckNumber (locals, "j", 15);
- CheckString (locals, "foo_str", "foo");
- CheckObject (locals, "this", "Math.NestedInMath");
- }
- );
-
- // Step back to OuterMethod
- await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 79, 2, "OuterMethod", times: 6,
- locals_fn: (locals) => {
- Assert.Equal (5, locals.Count());
-
- CheckObject (locals, "nim", "Math.NestedInMath");
- // FIXME: Failing test CheckNumber (locals, "i", 5);
- CheckNumber (locals, "k", 0);
- CheckNumber (locals, "new_i", 24);
- CheckString (locals, "text", "Hello");
- }
- );
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsInAsyncMethods (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
-
- await SetBreakpoint (debugger_test_loc, 111, 3);
- await SetBreakpoint (debugger_test_loc, 126, 3);
-
- // Will stop in Asyncmethod0
- var wait_res = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_async_method_with_await(); }, 1);",
- debugger_test_loc, 111, 3, "MoveNext", //FIXME:
- locals_fn: (locals) => {
- Assert.Equal (4, locals.Count());
- CheckString (locals, "s", "string from js");
- CheckNumber (locals, "i", 42);
- CheckString (locals, "local0", "value0");
- CheckObject (locals, "this", "Math.NestedInMath");
- }
- );
- Console.WriteLine (wait_res);
-
#if false // Disabled for now, as we don't have proper async traces
- var locals = await GetProperties (wait_res ["callFrames"][2]["callFrameId"].Value<string> ());
- Assert.Equal (4, locals.Count());
- CheckString (locals, "ls", "string from jstest");
- CheckNumber (locals, "li", 52);
+ var locals = await GetProperties(wait_res["callFrames"][2]["callFrameId"].Value<string>());
+ Assert.Equal(4, locals.Count());
+ CheckString(locals, "ls", "string from jstest");
+ CheckNumber(locals, "li", 52);
#endif
- // TODO: previous frames have async machinery details, so no point checking that right now
-
- var pause_loc = await SendCommandAndCheck (null, "Debugger.resume", debugger_test_loc, 126, 3, /*FIXME: "AsyncMethodNoReturn"*/ "MoveNext",
- locals_fn: (locals) => {
- Assert.Equal (4, locals.Count());
- CheckString (locals, "str", "AsyncMethodNoReturn's local");
- CheckObject (locals, "this", "Math.NestedInMath");
- //FIXME: check fields
- CheckValueType (locals, "ss", "Math.SimpleStruct");
- CheckArray (locals, "ss_arr", "Math.SimpleStruct[]");
- // TODO: struct fields
- }
- );
-
- var this_props = await GetObjectOnFrame (pause_loc ["callFrames"][0], "this");
- Assert.Equal (2, this_props.Count ());
- CheckObject (this_props, "m", "Math");
- CheckValueType (this_props, "SimpleStructProperty", "Math.SimpleStruct");
-
- // TODO: Check `this` properties
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsWithStructs (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- await SetBreakpoint (debugger_test_loc, 16, 2);
-
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_method_with_structs(); }, 1);",
- debugger_test_loc, 16, 2, "MethodWithLocalStructs",
- locals_fn: (locals) => {
- Assert.Equal (3, locals.Count ());
-
- CheckValueType (locals, "ss_local", "DebuggerTests.ValueTypesTest.SimpleStruct");
- CheckValueType (locals, "gs_local", "DebuggerTests.ValueTypesTest.GenericStruct<DebuggerTests.ValueTypesTest>");
- CheckObject (locals, "vt_local", "DebuggerTests.ValueTypesTest");
- }
- );
-
- var dt = new DateTime (2021, 2, 3, 4, 6, 7);
- // Check ss_local's properties
- var ss_local_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "ss_local");
- await CheckProps (ss_local_props, new {
- str_member = TString ("set in MethodWithLocalStructs#SimpleStruct#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Utc")
- }, "ss_local");
-
- {
- // Check ss_local.dt
- await CheckDateTime (ss_local_props, "dt", dt);
-
- // Check ss_local.gs
- var gs_props = await GetObjectOnLocals (ss_local_props, "gs");
- CheckString (gs_props, "StringField", "set in MethodWithLocalStructs#SimpleStruct#gs#StringField");
- CheckObject (gs_props, "List", "System.Collections.Generic.List<System.DateTime>");
- }
-
- // Check gs_local's properties
- var gs_local_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "gs_local");
- await CheckProps (gs_local_props, new {
- StringField = TString ("gs_local#GenericStruct<ValueTypesTest>#StringField"),
- List = TObject ("System.Collections.Generic.List<DebuggerTests.ValueTypesTest>", is_null: true),
- Options = TEnum ("DebuggerTests.Options", "None")
- }, "gs_local");
-
- // Check vt_local's properties
- var vt_local_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "vt_local");
- Assert.Equal (5, vt_local_props.Count());
-
- CheckString (vt_local_props, "StringField", "string#0");
- CheckValueType (vt_local_props, "SimpleStructField", "DebuggerTests.ValueTypesTest.SimpleStruct");
- CheckValueType (vt_local_props, "SimpleStructProperty", "DebuggerTests.ValueTypesTest.SimpleStruct");
- await CheckDateTime (vt_local_props, "DT", new DateTime (2020, 1, 2, 3, 4, 5));
- CheckEnum (vt_local_props, "RGB", "DebuggerTests.RGB", "Blue");
-
- {
- // SimpleStructProperty
- dt = new DateTime (2022, 3, 4, 5, 7, 8);
- var ssp_props = await CompareObjectPropertiesFor (vt_local_props, "SimpleStructProperty",
- new {
- str_member = TString ("SimpleStructProperty#string#0#SimpleStruct#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Utc")
- },
- label: "vt_local_props.SimpleStructProperty");
-
- await CheckDateTime (ssp_props, "dt", dt);
-
- // SimpleStructField
- dt = new DateTime (2025, 6, 7, 8, 10, 11);
- var ssf_props = await CompareObjectPropertiesFor (vt_local_props, "SimpleStructField",
- new {
- str_member = TString ("SimpleStructField#string#0#SimpleStruct#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Local")
- },
- label: "vt_local_props.SimpleStructField");
-
- await CheckDateTime (ssf_props, "dt", dt);
- }
-
- // FIXME: check ss_local.gs.List's members
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectValueTypeMethodArgs (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- await SetBreakpoint (debugger_test_loc, 27, 3);
-
-
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:TestStructsAsMethodArgs'); }, 1);",
- debugger_test_loc, 27, 3, "MethodWithStructArgs",
- locals_fn: (locals) => {
- Assert.Equal (3, locals.Count ());
-
- CheckString (locals, "label", "TestStructsAsMethodArgs#label");
- CheckValueType (locals, "ss_arg", "DebuggerTests.ValueTypesTest.SimpleStruct");
- CheckNumber (locals, "x", 3);
- }
- );
-
- var dt = new DateTime (2025, 6, 7, 8, 10, 11);
- var ss_local_as_ss_arg = new {
- str_member = TString ("ss_local#SimpleStruct#string#0#SimpleStruct#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Local")
- };
- var ss_local_gs = new {
- StringField = TString ("ss_local#SimpleStruct#string#0#SimpleStruct#gs#StringField"),
- List = TObject ("System.Collections.Generic.List<System.DateTime>"),
- Options = TEnum ("DebuggerTests.Options", "Option1")
- };
-
- // Check ss_arg's properties
- var ss_arg_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "ss_arg");
- await CheckProps (ss_arg_props, ss_local_as_ss_arg, "ss_arg");
-
- {
- // Check ss_local.dt
- await CheckDateTime (ss_arg_props, "dt", dt);
-
- // Check ss_local.gs
- await CompareObjectPropertiesFor (ss_arg_props, "gs", ss_local_gs);
- }
-
- pause_location = await StepAndCheck (StepKind.Over, debugger_test_loc, 31, 3, "MethodWithStructArgs", times: 4,
- locals_fn: (locals) => {
- Assert.Equal (3, locals.Count());
-
- CheckString (locals, "label", "TestStructsAsMethodArgs#label");
- CheckValueType (locals, "ss_arg", "DebuggerTests.ValueTypesTest.SimpleStruct");
- CheckNumber (locals, "x", 3);
-
- }
- );
-
- var ss_arg_updated = new {
- str_member = TString ("ValueTypesTest#MethodWithStructArgs#updated#ss_arg#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Utc")
- };
-
- ss_arg_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "ss_arg");
- await CheckProps (ss_arg_props, ss_arg_updated, "ss_ar");
-
- {
- // Check ss_local.gs
- await CompareObjectPropertiesFor (ss_arg_props, "gs", new {
- StringField = TString ("ValueTypesTest#MethodWithStructArgs#updated#gs#StringField#3"),
- List = TObject ("System.Collections.Generic.List<System.DateTime>"),
- Options = TEnum ("DebuggerTests.Options", "Option1")
- });
-
- await CheckDateTime (ss_arg_props, "dt", dt);
- }
-
- // Check locals on previous frame, same as earlier in this test
- ss_arg_props = await GetObjectOnFrame (pause_location ["callFrames"][1], "ss_local");
- await CheckProps (ss_arg_props, ss_local_as_ss_arg, "ss_local");
-
- {
- // Check ss_local.dt
- await CheckDateTime (ss_arg_props, "dt", dt);
-
- // Check ss_local.gs
- var gs_props = await GetObjectOnLocals (ss_arg_props, "gs");
- CheckString (gs_props, "StringField", "ss_local#SimpleStruct#string#0#SimpleStruct#gs#StringField");
- CheckObject (gs_props, "List", "System.Collections.Generic.List<System.DateTime>");
- }
-
- // ----------- Step back to the caller ---------
-
- pause_location = await StepAndCheck (StepKind.Over, debugger_test_loc, 22, 3, "TestStructsAsMethodArgs",
- times: 2, locals_fn: (l) => { /* non-null to make sure that locals get fetched */} );
- var locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckProps (locals, new {
- ss_local = TValueType ("DebuggerTests.ValueTypesTest.SimpleStruct"),
- ss_ret = TValueType ("DebuggerTests.ValueTypesTest.SimpleStruct")
- },
- "locals#0");
-
- ss_arg_props = await GetObjectOnFrame (pause_location ["callFrames"] [0], "ss_local");
- await CheckProps (ss_arg_props, ss_local_as_ss_arg, "ss_local");
-
- {
- // Check ss_local.gs
- await CompareObjectPropertiesFor (ss_arg_props, "gs", ss_local_gs, label: "ss_local_gs");
- }
-
- // FIXME: check ss_local.gs.List's members
- });
- }
-
- [Fact]
- public async Task CheckUpdatedValueTypeFieldsOnResume ()
- {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- var lines = new [] {186, 189};
- await SetBreakpoint (debugger_test_loc, lines [0], 3);
- await SetBreakpoint (debugger_test_loc, lines [1], 3);
-
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeMembers'); }, 1);",
- debugger_test_loc, lines [0], 3, "MethodUpdatingValueTypeMembers");
-
- var dt = new DateTime (1, 2, 3, 4, 5, 6);
- await CheckLocals (pause_location, dt);
-
- // Resume
- dt = new DateTime (9, 8, 7, 6, 5, 4);
- pause_location = await SendCommandAndCheck (JObject.FromObject (new{}), "Debugger.resume", debugger_test_loc, lines[1], 3, "MethodUpdatingValueTypeMembers");
- await CheckLocals (pause_location, dt);
- });
-
- async Task CheckLocals (JToken pause_location, DateTime dt)
- {
- var locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckProps (locals, new {
- obj = TObject ("DebuggerTests.ClassForToStringTests"),
- vt = TObject ("DebuggerTests.StructForToStringTests")
- }, "locals");
-
- var obj_props = await GetObjectOnLocals (locals, "obj");
- {
- await CheckProps (obj_props, new {
- DT = TValueType ("System.DateTime", dt.ToString ())
- }, "locals#obj.DT", num_fields: 5);
-
- await CheckDateTime (obj_props, "DT", dt);
- }
-
- var vt_props = await GetObjectOnLocals (locals, "obj");
- {
- await CheckProps (vt_props, new {
- DT = TValueType ("System.DateTime", dt.ToString ())
- }, "locals#obj.DT", num_fields: 5);
-
- await CheckDateTime (vt_props, "DT", dt);
- }
- }
- }
-
- [Fact]
- public async Task CheckUpdatedValueTypeLocalsOnResumeAsync ()
- {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- var lines = new [] { 195, 197 };
- await SetBreakpoint (debugger_test_loc, lines [0], 3);
- await SetBreakpoint (debugger_test_loc, lines [1], 3);
-
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeLocalsAsync'); }, 1);",
- debugger_test_loc, lines [0], 3, "MoveNext");
-
- var dt = new DateTime (1, 2, 3, 4, 5, 6);
- var locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckDateTime (locals, "dt", dt);
-
- // Resume
- dt = new DateTime (9, 8, 7, 6, 5, 4);
- pause_location = await SendCommandAndCheck (JObject.FromObject (new{}), "Debugger.resume", debugger_test_loc, lines[1], 3, "MoveNext");
- locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckDateTime (locals, "dt", dt);
- });
- }
-
- [Fact]
- public async Task CheckUpdatedVTArrayMembersOnResume ()
- {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- var lines = new [] { 205, 207 };
- await SetBreakpoint (debugger_test_loc, lines [0], 3);
- await SetBreakpoint (debugger_test_loc, lines [1], 3);
-
- var dt = new DateTime (1, 2, 3, 4, 5, 6);
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingVTArrayMembers'); }, 1);",
- debugger_test_loc, lines [0], 3, "MethodUpdatingVTArrayMembers");
- await CheckArrayElements (pause_location, dt);
-
- // Resume
- dt = new DateTime (9, 8, 7, 6, 5, 4);
- pause_location = await SendCommandAndCheck (JObject.FromObject (new{}), "Debugger.resume", debugger_test_loc, lines[1], 3, "MethodUpdatingVTArrayMembers");
- await CheckArrayElements (pause_location, dt);
- });
-
- async Task CheckArrayElements (JToken pause_location, DateTime dt)
- {
- var locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckProps (locals, new {
- ssta = TArray ("DebuggerTests.StructForToStringTests[]", 1)
- }, "locals");
-
- var ssta = await GetObjectOnLocals (locals, "ssta");
- var sst0 = await GetObjectOnLocals (ssta, "0");
- await CheckProps (sst0, new {
- DT = TValueType ("System.DateTime", dt.ToString ())
- }, "dta [0]", num_fields: 5);
-
- await CheckDateTime (sst0, "DT", dt);
- }
- }
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsWithStructsStaticAsync (bool use_cfo) {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- await SetBreakpoint (debugger_test_loc, 47, 3);
-
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method_async ("
- + "'[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalStructsStaticAsync'"
- + "); }, 1);",
- debugger_test_loc, 47, 3, "MoveNext"); //BUG: method name
-
- var locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string> ());
- await CheckProps (locals, new {
- ss_local = TObject ("DebuggerTests.ValueTypesTest.SimpleStruct"),
- gs_local = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<int>"),
- result = TBool (true)
- },
- "locals#0");
-
- var dt = new DateTime (2021, 2, 3, 4, 6, 7);
- // Check ss_local's properties
- var ss_local_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "ss_local");
- await CheckProps (ss_local_props, new {
- str_member = TString ("set in MethodWithLocalStructsStaticAsync#SimpleStruct#str_member"),
- dt = TValueType ("System.DateTime", dt.ToString ()),
- gs = TValueType ("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
- Kind = TEnum ("System.DateTimeKind", "Utc")
- }, "ss_local");
-
- {
- // Check ss_local.dt
- await CheckDateTime (ss_local_props, "dt", dt);
-
- // Check ss_local.gs
- await CompareObjectPropertiesFor (ss_local_props, "gs",
- new {
- StringField = TString ("set in MethodWithLocalStructsStaticAsync#SimpleStruct#gs#StringField"),
- List = TObject ("System.Collections.Generic.List<System.DateTime>"),
- Options = TEnum ("DebuggerTests.Options", "Option1")
- }
- );
- }
-
- // Check gs_local's properties
- var gs_local_props = await GetObjectOnFrame (pause_location ["callFrames"][0], "gs_local");
- await CheckProps (gs_local_props, new {
- StringField = TString ("gs_local#GenericStruct<ValueTypesTest>#StringField"),
- List = TObject ("System.Collections.Generic.List<int>"),
- Options = TEnum ("DebuggerTests.Options", "Option2")
- }, "gs_local");
-
- // FIXME: check ss_local.gs.List's members
- });
- }
-
- [Theory]
- [InlineData (123, 3, "MethodWithLocalsForToStringTest", false, false)]
- [InlineData (133, 3, "MethodWithArgumentsForToStringTest", true, false)]
- [InlineData (175, 3, "MethodWithArgumentsForToStringTestAsync", true, true)]
- [InlineData (165, 3, "MethodWithArgumentsForToStringTestAsync", false, true)]
- public async Task InspectLocalsForToStringDescriptions (int line, int col, string method_name, bool call_other, bool invoke_async)
- {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
- string entry_method_name = $"[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalsForToStringTest{(invoke_async ? "Async" : String.Empty)}";
- int frame_idx = 0;
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
- var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
-
- await SetBreakpoint (debugger_test_loc, line, col);
-
- var eval_expr = "window.setTimeout(function() {"
- + (invoke_async ? "invoke_static_method_async (" : "invoke_static_method (")
- + $"'{entry_method_name}',"
- + (call_other ? "true" : "false")
- + "); }, 1);";
- Console.WriteLine ($"{eval_expr}");
-
- var pause_location = await EvaluateAndCheck (eval_expr, debugger_test_loc, line, col, invoke_async ? "MoveNext" : method_name);
-
- var dt0 = new DateTime (2020, 1, 2, 3, 4, 5);
- var dt1 = new DateTime (2010, 5, 4, 3, 2, 1);
- var ts = dt0 - dt1;
- var dto = new DateTimeOffset (dt0, new TimeSpan(4, 5, 0));
-
- var frame_locals = await GetProperties (pause_location ["callFrames"][frame_idx]["callFrameId"].Value<string> ());
- await CheckProps (frame_locals, new {
- call_other = TBool (call_other),
- dt0 = TValueType ("System.DateTime", dt0.ToString ()),
- dt1 = TValueType ("System.DateTime", dt1.ToString ()),
- dto = TValueType ("System.DateTimeOffset", dto.ToString ()),
- ts = TValueType ("System.TimeSpan", ts.ToString ()),
- dec = TValueType ("System.Decimal", "123987123"),
- guid = TValueType ("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014"),
- dts = TArray ("System.DateTime[]", 2),
- obj = TObject ("DebuggerTests.ClassForToStringTests"),
- sst = TObject ("DebuggerTests.StructForToStringTests")
- }, "locals#0");
-
- var dts_0 = new DateTime (1983, 6, 7, 5, 6, 10);
- var dts_1 = new DateTime (1999, 10, 15, 1, 2, 3);
- var dts_elements = await GetObjectOnLocals (frame_locals, "dts");
- await CheckDateTime (dts_elements, "0", dts_0);
- await CheckDateTime (dts_elements, "1", dts_1);
-
- // TimeSpan
- await CompareObjectPropertiesFor (frame_locals, "ts",
- new {
- Days = TNumber (3530),
- Minutes = TNumber (2),
- Seconds = TNumber (4),
- }, "ts_props", num_fields: 12);
-
- // DateTimeOffset
- await CompareObjectPropertiesFor (frame_locals, "dto",
- new {
- Day = TNumber (2),
- Year = TNumber (2020),
- DayOfWeek = TEnum ("System.DayOfWeek", "Thursday")
- }, "dto_props", num_fields: 22);
-
- var DT = new DateTime (2004, 10, 15, 1, 2, 3);
- var DTO = new DateTimeOffset (dt0, new TimeSpan(2, 14, 0));
-
- var obj_props = await CompareObjectPropertiesFor (frame_locals, "obj",
- new {
- DT = TValueType ("System.DateTime", DT.ToString ()),
- DTO = TValueType ("System.DateTimeOffset", DTO.ToString ()),
- TS = TValueType ("System.TimeSpan", ts.ToString ()),
- Dec = TValueType ("System.Decimal", "1239871"),
- Guid = TValueType ("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014")
- }, "obj_props");
-
- DTO = new DateTimeOffset (dt0, new TimeSpan (3, 15, 0));
- var sst_props = await CompareObjectPropertiesFor (frame_locals, "sst",
- new {
- DT = TValueType ("System.DateTime", DT.ToString ()),
- DTO = TValueType ("System.DateTimeOffset", DTO.ToString ()),
- TS = TValueType ("System.TimeSpan", ts.ToString ()),
- Dec = TValueType ("System.Decimal", "1239871"),
- Guid = TValueType ("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014")
- }, "sst_props");
- });
- }
-
- [Fact]
- public async Task InspectLocals () {
- var insp = new Inspector ();
- var scripts = SubscribeToScripts (insp);
-
- await Ready();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var wait_res = await RunUntil ("locals_inner");
- var locals = await GetProperties (wait_res ["callFrames"][1]["callFrameId"].Value<string> ());
- });
- }
-
- [Theory]
- [InlineData (false)]
- [InlineData (true)]
- public async Task InspectLocalsForStructInstanceMethod (bool use_cfo)
- => await CheckInspectLocalsAtBreakpointSite (
- "dotnet://debugger-test.dll/debugger-array-test.cs", 236, 3,
- "GenericInstanceMethod<DebuggerTests.SimpleClass>",
- "window.setTimeout(function() { invoke_static_method_async ('[debugger-test] DebuggerTests.EntryClass:run'); })",
- use_cfo: use_cfo,
- wait_for_event_fn: async (pause_location) => {
- var frame_locals = await GetProperties (pause_location ["callFrames"][0]["callFrameId"].Value<string>());
-
- await CheckProps (frame_locals, new {
- sc_arg = TObject ("DebuggerTests.SimpleClass"),
- @this = TValueType ("DebuggerTests.Point"),
- local_gs = TValueType ("DebuggerTests.SimpleGenericStruct<int>")
- },
- "locals#0");
-
- await CompareObjectPropertiesFor (frame_locals, "local_gs",
- new {
- Id = TString ("local_gs#Id"),
- Color = TEnum ("DebuggerTests.RGB", "Green"),
- Value = TNumber (4)
- },
- label: "local_gs#0");
-
- await CompareObjectPropertiesFor (frame_locals, "sc_arg",
- TSimpleClass (10, 45, "sc_arg#Id", "Blue"),
- label: "sc_arg#0");
-
- await CompareObjectPropertiesFor (frame_locals, "this",
- TPoint (90, -4, "point#Id", "Green"),
- label: "this#0");
-
- });
-
- [Fact]
- public async Task SteppingIntoMscorlib () {
- var insp = new Inspector ();
- //Collect events
- var scripts = SubscribeToScripts(insp);
-
- await Ready ();
- await insp.Ready (async (cli, token) => {
- ctx = new DebugTestContext (cli, insp, token, scripts);
-
- var bp = await SetBreakpoint ("dotnet://debugger-test.dll/debugger-test.cs", 74, 2);
- var pause_location = await EvaluateAndCheck (
- "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:OuterMethod'); }, 1);",
- "dotnet://debugger-test.dll/debugger-test.cs", 74, 2,
- "OuterMethod");
-
- //make sure we're on the right bp
- Assert.Equal (bp.Value ["breakpointId"]?.ToString (), pause_location ["hitBreakpoints"]?[0]?.Value<string> ());
-
- pause_location = await SendCommandAndCheck (null, $"Debugger.stepInto", null, -1, -1, null);
- var top_frame = pause_location ["callFrames"][0];
-
- AssertEqual ("WriteLine", top_frame ["functionName"]?.Value<string> (), "Expected to be in WriteLine method");
- var script_id = top_frame ["functionLocation"]["scriptId"].Value<string> ();
- AssertEqual ("dotnet://mscorlib.dll/Console.cs", scripts [script_id], "Expected to stopped in System.Console.WriteLine");
- });
- }
-
- //TODO add tests covering basic stepping behavior as step in/out/over
- }
+ // TODO: previous frames have async machinery details, so no point checking that right now
+
+ var pause_loc = await SendCommandAndCheck(null, "Debugger.resume", debugger_test_loc, 135, 12, /*FIXME: "AsyncMethodNoReturn"*/ "MoveNext",
+ locals_fn: (locals) =>
+ {
+ Assert.Equal(4, locals.Count());
+ CheckString(locals, "str", "AsyncMethodNoReturn's local");
+ CheckObject(locals, "this", "Math.NestedInMath");
+ //FIXME: check fields
+ CheckValueType(locals, "ss", "Math.SimpleStruct");
+ CheckArray(locals, "ss_arr", "Math.SimpleStruct[]", 0);
+ // TODO: struct fields
+ }
+ );
+
+ var this_props = await GetObjectOnFrame(pause_loc["callFrames"][0], "this");
+ Assert.Equal(2, this_props.Count());
+ CheckObject(this_props, "m", "Math");
+ CheckValueType(this_props, "SimpleStructProperty", "Math.SimpleStruct");
+
+ // TODO: Check `this` properties
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsWithStructs(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ await SetBreakpoint(debugger_test_loc, 24, 8);
+
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_method_with_structs(); }, 1);",
+ debugger_test_loc, 24, 8, "MethodWithLocalStructs");
+
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckProps(locals, new
+ {
+ ss_local = TValueType("DebuggerTests.ValueTypesTest.SimpleStruct"),
+ gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<DebuggerTests.ValueTypesTest>"),
+ vt_local = TObject("DebuggerTests.ValueTypesTest")
+ }, "locals");
+
+ var dt = new DateTime(2021, 2, 3, 4, 6, 7);
+ var vt_local_props = await GetObjectOnFrame(pause_location["callFrames"][0], "vt_local");
+ Assert.Equal(5, vt_local_props.Count());
+
+ CheckString(vt_local_props, "StringField", "string#0");
+ CheckValueType(vt_local_props, "SimpleStructField", "DebuggerTests.ValueTypesTest.SimpleStruct");
+ CheckValueType(vt_local_props, "SimpleStructProperty", "DebuggerTests.ValueTypesTest.SimpleStruct");
+ await CheckDateTime(vt_local_props, "DT", new DateTime(2020, 1, 2, 3, 4, 5));
+ CheckEnum(vt_local_props, "RGB", "DebuggerTests.RGB", "Blue");
+
+ // Check ss_local's properties
+ var ss_local_props = await GetObjectOnFrame(pause_location["callFrames"][0], "ss_local");
+ await CheckProps(ss_local_props, new
+ {
+ V = TGetter("V"),
+ str_member = TString("set in MethodWithLocalStructs#SimpleStruct#str_member"),
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
+ Kind = TEnum("System.DateTimeKind", "Utc")
+ }, "ss_local");
+
+ {
+ var gres = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_local"), "V");
+ await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + 2), $"ss_local#V");
+ // Check ss_local.dt
+ await CheckDateTime(ss_local_props, "dt", dt);
+
+ // Check ss_local.gs
+ var gs_props = await GetObjectOnLocals(ss_local_props, "gs");
+ CheckString(gs_props, "StringField", "set in MethodWithLocalStructs#SimpleStruct#gs#StringField");
+ CheckObject(gs_props, "List", "System.Collections.Generic.List<System.DateTime>");
+ }
+
+ // Check gs_local's properties
+ var gs_local_props = await GetObjectOnFrame(pause_location["callFrames"][0], "gs_local");
+ await CheckProps(gs_local_props, new
+ {
+ StringField = TString("gs_local#GenericStruct<ValueTypesTest>#StringField"),
+ List = TObject("System.Collections.Generic.List<DebuggerTests.ValueTypesTest>", is_null: true),
+ Options = TEnum("DebuggerTests.Options", "None")
+ }, "gs_local");
+
+ // Check vt_local's properties
+
+ var exp = new[]
+ {
+ ("SimpleStructProperty", 2, "Utc"),
+ ("SimpleStructField", 5, "Local")
+ };
+
+ foreach (var (name, bias, dt_kind) in exp)
+ {
+ dt = new DateTime(2020 + bias, 1 + bias, 2 + bias, 3 + bias, 5 + bias, 6 + bias);
+ var ssp_props = await CompareObjectPropertiesFor(vt_local_props, name,
+ new
+ {
+ V = TGetter("V"),
+ str_member = TString($"{name}#string#0#SimpleStruct#str_member"),
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
+ Kind = TEnum("System.DateTimeKind", dt_kind)
+ },
+ label: $"vt_local_props.{name}");
+
+ await CheckDateTime(ssp_props, "dt", dt);
+ var gres = await InvokeGetter(GetAndAssertObjectWithName(vt_local_props, name), "V");
+ await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + (uint)dt.Month), $"{name}#V");
+ }
+
+ // FIXME: check ss_local.gs.List's members
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectValueTypeMethodArgs(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ await SetBreakpoint(debugger_test_loc, 36, 12);
+
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:TestStructsAsMethodArgs'); }, 1);",
+ debugger_test_loc, 36, 12, "MethodWithStructArgs");
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ {
+ Assert.Equal(3, locals.Count());
+ CheckString(locals, "label", "TestStructsAsMethodArgs#label");
+ CheckValueType(locals, "ss_arg", "DebuggerTests.ValueTypesTest.SimpleStruct");
+ CheckNumber(locals, "x", 3);
+ }
+
+ var dt = new DateTime(2025, 6, 7, 8, 10, 11);
+ var ss_local_as_ss_arg = new
+ {
+ V = TGetter("V"),
+ str_member = TString("ss_local#SimpleStruct#string#0#SimpleStruct#str_member"),
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
+ Kind = TEnum("System.DateTimeKind", "Local")
+ };
+ var ss_local_gs = new
+ {
+ StringField = TString("ss_local#SimpleStruct#string#0#SimpleStruct#gs#StringField"),
+ List = TObject("System.Collections.Generic.List<System.DateTime>"),
+ Options = TEnum("DebuggerTests.Options", "Option1")
+ };
+
+ // Check ss_arg's properties
+ var ss_arg_props = await GetObjectOnFrame(pause_location["callFrames"][0], "ss_arg");
+ await CheckProps(ss_arg_props, ss_local_as_ss_arg, "ss_arg");
+
+ var res = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_arg"), "V");
+ await CheckValue(res.Value["result"], TNumber(0xDEADBEEF + (uint)dt.Month), "ss_arg#V");
+
+ {
+ // Check ss_local.dt
+ await CheckDateTime(ss_arg_props, "dt", dt);
+
+ // Check ss_local.gs
+ await CompareObjectPropertiesFor(ss_arg_props, "gs", ss_local_gs);
+ }
+
+ pause_location = await StepAndCheck(StepKind.Over, debugger_test_loc, 40, 8, "MethodWithStructArgs", times: 4,
+ locals_fn: (l) => { /* non-null to make sure that locals get fetched */ });
+ locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ {
+ Assert.Equal(3, locals.Count());
+
+ CheckString(locals, "label", "TestStructsAsMethodArgs#label");
+ CheckValueType(locals, "ss_arg", "DebuggerTests.ValueTypesTest.SimpleStruct");
+ CheckNumber(locals, "x", 3);
+ }
+
+ var ss_arg_updated = new
+ {
+ V = TGetter("V"),
+ str_member = TString("ValueTypesTest#MethodWithStructArgs#updated#ss_arg#str_member"),
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
+ Kind = TEnum("System.DateTimeKind", "Utc")
+ };
+
+ ss_arg_props = await GetObjectOnFrame(pause_location["callFrames"][0], "ss_arg");
+ await CheckProps(ss_arg_props, ss_arg_updated, "ss_arg");
+
+ res = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_arg"), "V");
+ await CheckValue(res.Value["result"], TNumber(0xDEADBEEF + (uint)dt.Month), "ss_arg#V");
+
+ {
+ // Check ss_local.gs
+ await CompareObjectPropertiesFor(ss_arg_props, "gs", new
+ {
+ StringField = TString("ValueTypesTest#MethodWithStructArgs#updated#gs#StringField#3"),
+ List = TObject("System.Collections.Generic.List<System.DateTime>"),
+ Options = TEnum("DebuggerTests.Options", "Option1")
+ });
+
+ await CheckDateTime(ss_arg_props, "dt", dt);
+ }
+
+ // Check locals on previous frame, same as earlier in this test
+ ss_arg_props = await GetObjectOnFrame(pause_location["callFrames"][1], "ss_local");
+ await CheckProps(ss_arg_props, ss_local_as_ss_arg, "ss_local");
+
+ {
+ // Check ss_local.dt
+ await CheckDateTime(ss_arg_props, "dt", dt);
+
+ // Check ss_local.gs
+ var gs_props = await GetObjectOnLocals(ss_arg_props, "gs");
+ CheckString(gs_props, "StringField", "ss_local#SimpleStruct#string#0#SimpleStruct#gs#StringField");
+ CheckObject(gs_props, "List", "System.Collections.Generic.List<System.DateTime>");
+ }
+
+ // ----------- 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 */ });
+ locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckProps(locals, new
+ {
+ ss_local = TValueType("DebuggerTests.ValueTypesTest.SimpleStruct"),
+ ss_ret = TValueType("DebuggerTests.ValueTypesTest.SimpleStruct")
+ },
+ "locals#0");
+
+ ss_arg_props = await GetObjectOnFrame(pause_location["callFrames"][0], "ss_local");
+ await CheckProps(ss_arg_props, ss_local_as_ss_arg, "ss_local");
+
+ {
+ // Check ss_local.gs
+ await CompareObjectPropertiesFor(ss_arg_props, "gs", ss_local_gs, label: "ss_local_gs");
+ }
+
+ // FIXME: check ss_local.gs.List's members
+ });
+ }
+
+ [Fact]
+ public async Task CheckUpdatedValueTypeFieldsOnResume()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ var lines = new[] { 205, 208 };
+ await SetBreakpoint(debugger_test_loc, lines[0], 12);
+ await SetBreakpoint(debugger_test_loc, lines[1], 12);
+
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeMembers'); }, 1);",
+ debugger_test_loc, lines[0], 12, "MethodUpdatingValueTypeMembers");
+
+ await CheckLocals(pause_location, new DateTime(1, 2, 3, 4, 5, 6), new DateTime(4, 5, 6, 7, 8, 9));
+
+ // Resume
+ pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MethodUpdatingValueTypeMembers");
+ await CheckLocals(pause_location, new DateTime(9, 8, 7, 6, 5, 4), new DateTime(5, 1, 3, 7, 9, 10));
+ });
+
+ async Task CheckLocals(JToken pause_location, DateTime obj_dt, DateTime vt_dt)
+ {
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckProps(locals, new
+ {
+ obj = TObject("DebuggerTests.ClassForToStringTests"),
+ vt = TObject("DebuggerTests.StructForToStringTests")
+ }, "locals");
+
+ var obj_props = await GetObjectOnLocals(locals, "obj");
+ {
+ await CheckProps(obj_props, new
+ {
+ DT = TValueType("System.DateTime", obj_dt.ToString())
+ }, "locals#obj.DT", num_fields: 5);
+
+ await CheckDateTime(obj_props, "DT", obj_dt);
+ }
+
+ var vt_props = await GetObjectOnLocals(locals, "vt");
+ {
+ await CheckProps(vt_props, new
+ {
+ DT = TValueType("System.DateTime", vt_dt.ToString())
+ }, "locals#obj.DT", num_fields: 5);
+
+ await CheckDateTime(vt_props, "DT", vt_dt);
+ }
+ }
+ }
+
+ [Fact]
+ public async Task CheckUpdatedValueTypeLocalsOnResumeAsync()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ var lines = new[] { 214, 216 };
+ await SetBreakpoint(debugger_test_loc, lines[0], 12);
+ await SetBreakpoint(debugger_test_loc, lines[1], 12);
+
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeLocalsAsync'); }, 1);",
+ debugger_test_loc, lines[0], 12, "MoveNext");
+
+ var dt = new DateTime(1, 2, 3, 4, 5, 6);
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckDateTime(locals, "dt", dt);
+
+ // Resume
+ dt = new DateTime(9, 8, 7, 6, 5, 4);
+ pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MoveNext");
+ locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckDateTime(locals, "dt", dt);
+ });
+ }
+
+ [Fact]
+ public async Task CheckUpdatedVTArrayMembersOnResume()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ var lines = new[] { 225, 227 };
+ await SetBreakpoint(debugger_test_loc, lines[0], 12);
+ await SetBreakpoint(debugger_test_loc, lines[1], 12);
+
+ var dt = new DateTime(1, 2, 3, 4, 5, 6);
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingVTArrayMembers'); }, 1);",
+ debugger_test_loc, lines[0], 12, "MethodUpdatingVTArrayMembers");
+ await CheckArrayElements(pause_location, dt);
+
+ // Resume
+ dt = new DateTime(9, 8, 7, 6, 5, 4);
+ pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MethodUpdatingVTArrayMembers");
+ await CheckArrayElements(pause_location, dt);
+ });
+
+ async Task CheckArrayElements(JToken pause_location, DateTime dt)
+ {
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckProps(locals, new
+ {
+ ssta = TArray("DebuggerTests.StructForToStringTests[]", 1)
+ }, "locals");
+
+ var ssta = await GetObjectOnLocals(locals, "ssta");
+ var sst0 = await GetObjectOnLocals(ssta, "0");
+ await CheckProps(sst0, new
+ {
+ DT = TValueType("System.DateTime", dt.ToString())
+ }, "dta [0]", num_fields: 5);
+
+ await CheckDateTime(sst0, "DT", dt);
+ }
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsWithStructsStaticAsync(bool use_cfo)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ ctx.UseCallFunctionOnBeforeGetProperties = use_cfo;
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ await SetBreakpoint(debugger_test_loc, 54, 12);
+
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method_async (" +
+ "'[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalStructsStaticAsync'" +
+ "); }, 1);",
+ debugger_test_loc, 54, 12, "MoveNext"); //BUG: method name
+
+ var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+ await CheckProps(locals, new
+ {
+ ss_local = TObject("DebuggerTests.ValueTypesTest.SimpleStruct"),
+ gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<int>"),
+ result = TBool(true)
+ },
+ "locals#0");
+
+ var dt = new DateTime(2021, 2, 3, 4, 6, 7);
+ // Check ss_local's properties
+ var ss_local_props = await GetObjectOnFrame(pause_location["callFrames"][0], "ss_local");
+ await CheckProps(ss_local_props, new
+ {
+ V = TGetter("V"),
+ str_member = TString("set in MethodWithLocalStructsStaticAsync#SimpleStruct#str_member"),
+ dt = TValueType("System.DateTime", dt.ToString()),
+ gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct<System.DateTime>"),
+ Kind = TEnum("System.DateTimeKind", "Utc")
+ }, "ss_local");
+
+ {
+ var gres = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_local"), "V");
+ await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + 2), $"ss_local#V");
+
+ // Check ss_local.dt
+ await CheckDateTime(ss_local_props, "dt", dt);
+
+ // Check ss_local.gs
+ await CompareObjectPropertiesFor(ss_local_props, "gs",
+ new
+ {
+ StringField = TString("set in MethodWithLocalStructsStaticAsync#SimpleStruct#gs#StringField"),
+ List = TObject("System.Collections.Generic.List<System.DateTime>"),
+ Options = TEnum("DebuggerTests.Options", "Option1")
+ }
+ );
+ }
+
+ // Check gs_local's properties
+ var gs_local_props = await GetObjectOnFrame(pause_location["callFrames"][0], "gs_local");
+ await CheckProps(gs_local_props, new
+ {
+ StringField = TString("gs_local#GenericStruct<ValueTypesTest>#StringField"),
+ List = TObject("System.Collections.Generic.List<int>"),
+ Options = TEnum("DebuggerTests.Options", "Option2")
+ }, "gs_local");
+
+ // FIXME: check ss_local.gs.List's members
+ });
+ }
+
+ [Theory]
+ [InlineData(137, 12, "MethodWithLocalsForToStringTest", false, false)]
+ [InlineData(147, 12, "MethodWithArgumentsForToStringTest", true, false)]
+ [InlineData(192, 12, "MethodWithArgumentsForToStringTestAsync", true, true)]
+ [InlineData(182, 12, "MethodWithArgumentsForToStringTestAsync", false, true)]
+ public async Task InspectLocalsForToStringDescriptions(int line, int col, string method_name, bool call_other, bool invoke_async)
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+ string entry_method_name = $"[debugger-test] DebuggerTests.ValueTypesTest:MethodWithLocalsForToStringTest{(invoke_async ? "Async" : String.Empty)}";
+ int frame_idx = 0;
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs";
+
+ await SetBreakpoint(debugger_test_loc, line, col);
+
+ var eval_expr = "window.setTimeout(function() {" +
+ (invoke_async ? "invoke_static_method_async (" : "invoke_static_method (") +
+ $"'{entry_method_name}'," +
+ (call_other ? "true" : "false") +
+ "); }, 1);";
+ Console.WriteLine($"{eval_expr}");
+
+ var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, invoke_async ? "MoveNext" : method_name);
+
+ var dt0 = new DateTime(2020, 1, 2, 3, 4, 5);
+ var dt1 = new DateTime(2010, 5, 4, 3, 2, 1);
+ var ts = dt0 - dt1;
+ var dto = new DateTimeOffset(dt0, new TimeSpan(4, 5, 0));
+
+ var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value<string>());
+ await CheckProps(frame_locals, new
+ {
+ call_other = TBool(call_other),
+ dt0 = TValueType("System.DateTime", dt0.ToString()),
+ dt1 = TValueType("System.DateTime", dt1.ToString()),
+ dto = TValueType("System.DateTimeOffset", dto.ToString()),
+ ts = TValueType("System.TimeSpan", ts.ToString()),
+ dec = TValueType("System.Decimal", "123987123"),
+ guid = TValueType("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014"),
+ dts = TArray("System.DateTime[]", 2),
+ obj = TObject("DebuggerTests.ClassForToStringTests"),
+ sst = TObject("DebuggerTests.StructForToStringTests")
+ }, "locals#0");
+
+ var dts_0 = new DateTime(1983, 6, 7, 5, 6, 10);
+ var dts_1 = new DateTime(1999, 10, 15, 1, 2, 3);
+ var dts_elements = await GetObjectOnLocals(frame_locals, "dts");
+ await CheckDateTime(dts_elements, "0", dts_0);
+ await CheckDateTime(dts_elements, "1", dts_1);
+
+ // TimeSpan
+ await CompareObjectPropertiesFor(frame_locals, "ts",
+ new
+ {
+ Days = TNumber(3530),
+ Minutes = TNumber(2),
+ Seconds = TNumber(4),
+ }, "ts_props", num_fields: 12);
+
+ // DateTimeOffset
+ await CompareObjectPropertiesFor(frame_locals, "dto",
+ new
+ {
+ Day = TNumber(2),
+ Year = TNumber(2020),
+ DayOfWeek = TEnum("System.DayOfWeek", "Thursday")
+ }, "dto_props", num_fields: 22);
+
+ var DT = new DateTime(2004, 10, 15, 1, 2, 3);
+ var DTO = new DateTimeOffset(dt0, new TimeSpan(2, 14, 0));
+
+ var obj_props = await CompareObjectPropertiesFor(frame_locals, "obj",
+ new
+ {
+ DT = TValueType("System.DateTime", DT.ToString()),
+ DTO = TValueType("System.DateTimeOffset", DTO.ToString()),
+ TS = TValueType("System.TimeSpan", ts.ToString()),
+ Dec = TValueType("System.Decimal", "1239871"),
+ Guid = TValueType("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014")
+ }, "obj_props");
+
+ DTO = new DateTimeOffset(dt0, new TimeSpan(3, 15, 0));
+ var sst_props = await CompareObjectPropertiesFor(frame_locals, "sst",
+ new
+ {
+ DT = TValueType("System.DateTime", DT.ToString()),
+ DTO = TValueType("System.DateTimeOffset", DTO.ToString()),
+ TS = TValueType("System.TimeSpan", ts.ToString()),
+ Dec = TValueType("System.Decimal", "1239871"),
+ Guid = TValueType("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014")
+ }, "sst_props");
+ });
+ }
+
+ [Fact]
+ public async Task InspectLocals()
+ {
+ var insp = new Inspector();
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var wait_res = await RunUntil("locals_inner");
+ var locals = await GetProperties(wait_res["callFrames"][1]["callFrameId"].Value<string>());
+ });
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task InspectLocalsForStructInstanceMethod(bool use_cfo) => await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-array-test.cs", 258, 12,
+ "GenericInstanceMethod<DebuggerTests.SimpleClass>",
+ "window.setTimeout(function() { invoke_static_method_async ('[debugger-test] DebuggerTests.EntryClass:run'); })",
+ use_cfo: use_cfo,
+ wait_for_event_fn: async (pause_location) =>
+ {
+ var frame_locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+
+ await CheckProps(frame_locals, new
+ {
+ sc_arg = TObject("DebuggerTests.SimpleClass"),
+ @this = TValueType("DebuggerTests.Point"),
+ local_gs = TValueType("DebuggerTests.SimpleGenericStruct<int>")
+ },
+ "locals#0");
+
+ await CompareObjectPropertiesFor(frame_locals, "local_gs",
+ new
+ {
+ Id = TString("local_gs#Id"),
+ Color = TEnum("DebuggerTests.RGB", "Green"),
+ Value = TNumber(4)
+ },
+ label: "local_gs#0");
+
+ await CompareObjectPropertiesFor(frame_locals, "sc_arg",
+ TSimpleClass(10, 45, "sc_arg#Id", "Blue"),
+ label: "sc_arg#0");
+
+ await CompareObjectPropertiesFor(frame_locals, "this",
+ TPoint(90, -4, "point#Id", "Green"),
+ label: "this#0");
+
+ });
+
+ [Fact]
+ public async Task SteppingIntoMscorlib()
+ {
+ var insp = new Inspector();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready(async (cli, token) =>
+ {
+ ctx = new DebugTestContext(cli, insp, token, scripts);
+
+ var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 83, 8);
+ var pause_location = await EvaluateAndCheck(
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:OuterMethod'); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 83, 8,
+ "OuterMethod");
+
+ //make sure we're on the right bp
+ Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());
+
+ pause_location = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null);
+ var top_frame = pause_location["callFrames"][0];
+
+ AssertEqual("WriteLine", top_frame["functionName"]?.Value<string>(), "Expected to be in WriteLine method");
+ var script_id = top_frame["functionLocation"]["scriptId"].Value<string>();
+ Assert.Matches ("^dotnet://(mscorlib|System\\.Console)\\.dll/Console.cs", scripts[script_id]);
+ });
+ }
+
+ [Fact]
+ public async Task InvalidValueTypeData()
+ {
+ await CheckInspectLocalsAtBreakpointSite(
+ "dotnet://debugger-test.dll/debugger-test.cs", 85, 8,
+ "OuterMethod",
+ "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:OuterMethod'); })",
+ wait_for_event_fn: async (pause_location) =>
+ {
+ var new_id = await CreateNewId(@"MONO._new_or_add_id_props ({ scheme: 'valuetype', idArgs: { containerId: 1 }, props: { klass: 3, value64: 4 }});");
+ await _invoke_getter(new_id, "NonExistant", expect_ok: false);
+
+ new_id = await CreateNewId(@"MONO._new_or_add_id_props ({ scheme: 'valuetype', idArgs: { containerId: 1 }, props: { klass: 3 }});");
+ await _invoke_getter(new_id, "NonExistant", expect_ok: false);
+
+ new_id = await CreateNewId(@"MONO._new_or_add_id_props ({ scheme: 'valuetype', idArgs: { containerId: 1 }, props: { klass: 3, value64: 'AA' }});");
+ await _invoke_getter(new_id, "NonExistant", expect_ok: false);
+ });
+
+ async Task<string> CreateNewId(string expr)
+ {
+ var res = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = expr }), ctx.token);
+ Assert.True(res.IsOk, "Expected Runtime.evaluate to succeed");
+ AssertEqual("string", res.Value["result"]?["type"]?.Value<string>(), "Expected Runtime.evaluate to return a string type result");
+ return res.Value["result"]?["value"]?.Value<string>();
+ }
+
+ async Task<Result> _invoke_getter(string obj_id, string property_name, bool expect_ok)
+ {
+ var expr = $"MONO._invoke_getter ('{obj_id}', '{property_name}')";
+ var res = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = expr }), ctx.token);
+ AssertEqual(expect_ok, res.IsOk, "Runtime.evaluate result not as expected for {expr}");
+
+ return res;
+ }
+ }
+
+ //TODO add tests covering basic stepping behavior as step in/out/over
+ }
}