diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs index 6e5e4a948dd41c..dfe99aed5a7694 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs @@ -202,77 +202,68 @@ async Task TestSimpleArrayLocals(int line, int col, string entry_method_name, st string local_var_name_prefix, object[] array, object[] array_elem_props, bool test_prev_frame = false, int frame_idx = 0, bool use_cfo = false) { - 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-array-test.cs"; - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; - await SetBreakpoint(debugger_test_loc, line, col); + await SetBreakpoint(debugger_test_loc, line, col); - var eval_expr = "window.setTimeout(function() { invoke_static_method (" + - $"'{entry_method_name}', { (test_prev_frame ? "true" : "false") }" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + + $"'{entry_method_name}', { (test_prev_frame ? "true" : "false") }" + + "); }, 1);"; - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); - var locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - Assert.Equal(4, locals.Count()); - CheckArray(locals, $"{local_var_name_prefix}_arr", $"{etype_name}[]", array?.Length ?? 0); - CheckArray(locals, $"{local_var_name_prefix}_arr_empty", $"{etype_name}[]", 0); - CheckObject(locals, $"{local_var_name_prefix}_arr_null", $"{etype_name}[]", is_null: true); - CheckBool(locals, "call_other", test_prev_frame); + var locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + Assert.Equal(4, locals.Count()); + CheckArray(locals, $"{local_var_name_prefix}_arr", $"{etype_name}[]", array?.Length ?? 0); + CheckArray(locals, $"{local_var_name_prefix}_arr_empty", $"{etype_name}[]", 0); + CheckObject(locals, $"{local_var_name_prefix}_arr_null", $"{etype_name}[]", is_null: true); + CheckBool(locals, "call_other", test_prev_frame); - var local_arr_name = $"{local_var_name_prefix}_arr"; + var local_arr_name = $"{local_var_name_prefix}_arr"; - JToken prefix_arr; - if (use_cfo) - { // Use `Runtime.callFunctionOn` to get the properties - var frame = pause_location["callFrames"][frame_idx]; - var name = local_arr_name; - var fl = await GetProperties(frame["callFrameId"].Value()); - var l_obj = GetAndAssertObjectWithName(locals, name); - var l_objectId = l_obj["value"]["objectId"]?.Value(); + JToken prefix_arr; + if (use_cfo) + { // Use `Runtime.callFunctionOn` to get the properties + var frame = pause_location["callFrames"][frame_idx]; + var name = local_arr_name; + var fl = await GetProperties(frame["callFrameId"].Value()); + var l_obj = GetAndAssertObjectWithName(locals, name); + var l_objectId = l_obj["value"]["objectId"]?.Value(); - Assert.True(!String.IsNullOrEmpty(l_objectId), $"No objectId found for {name}"); + Assert.True(!String.IsNullOrEmpty(l_objectId), $"No objectId found for {name}"); - prefix_arr = await GetObjectWithCFO(l_objectId); - } - else - { - prefix_arr = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], local_arr_name); - } + prefix_arr = await GetObjectWithCFO(l_objectId); + } + else + { + prefix_arr = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], local_arr_name); + } - await CheckProps(prefix_arr, array, local_arr_name); + await CheckProps(prefix_arr, array, local_arr_name); - if (array_elem_props?.Length > 0) + if (array_elem_props?.Length > 0) + { + for (int i = 0; i < array_elem_props.Length; i++) { - for (int i = 0; i < array_elem_props.Length; i++) + var i_str = i.ToString(); + var label = $"{local_var_name_prefix}_arr[{i}]"; + if (array_elem_props[i] == null) { - var i_str = i.ToString(); - var label = $"{local_var_name_prefix}_arr[{i}]"; - if (array_elem_props[i] == null) - { - var act_i = prefix_arr.FirstOrDefault(jt => jt["name"]?.Value() == i_str); - Assert.True(act_i != null, $"[{label}] Couldn't find array element [{i_str}]"); + var act_i = prefix_arr.FirstOrDefault(jt => jt["name"]?.Value() == i_str); + Assert.True(act_i != null, $"[{label}] Couldn't find array element [{i_str}]"); - await CheckValue(act_i["value"], TObject(etype_name, is_null: true), label); - } - else - { - await CompareObjectPropertiesFor(prefix_arr, i_str, array_elem_props[i], label: label); - } + await CheckValue(act_i["value"], TObject(etype_name, is_null: true), label); + } + else + { + await CompareObjectPropertiesFor(prefix_arr, i_str, array_elem_props[i], label: label); } } + } - var props = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], $"{local_var_name_prefix}_arr_empty"); - await CheckProps(props, new object[0], "${local_var_name_prefix}_arr_empty"); - }); + var props = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], $"{local_var_name_prefix}_arr_empty"); + await CheckProps(props, new object[0], "${local_var_name_prefix}_arr_empty"); async Task GetObjectWithCFO(string objectId, JObject fn_args = null) { @@ -287,7 +278,7 @@ async Task GetObjectWithCFO(string objectId, JObject fn_args = null) cfo_args["arguments"] = fn_args; // callFunctionOn - var result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); + var result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); return await GetProperties(result.Value["result"]["objectId"]?.Value(), fn_args); } @@ -298,79 +289,71 @@ async Task GetObjectWithCFO(string objectId, JObject fn_args = null) [InlineData(true)] public async Task InspectObjectArrayMembers(bool use_cfo) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); int line = 227; int col = 12; string entry_method_name = "[debugger-test] DebuggerTests.ArrayTestsClass:ObjectArrayMembers"; string method_name = "PlaceholderMethod"; int frame_idx = 1; - 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-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; - await SetBreakpoint(debugger_test_loc, line, col); + await SetBreakpoint(debugger_test_loc, line, col); - var eval_expr = "window.setTimeout(function() { invoke_static_method (" + - $"'{entry_method_name}'" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + + $"'{entry_method_name}'" + + "); }, 1);"; - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); - var locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - Assert.Single(locals); - CheckObject(locals, "c", "DebuggerTests.Container"); + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); + var locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + Assert.Single(locals); + CheckObject(locals, "c", "DebuggerTests.Container"); - var c_props = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], "c"); - await CheckProps(c_props, new - { - id = TString("c#id"), - ClassArrayProperty = TArray("DebuggerTests.SimpleClass[]", 3), - ClassArrayField = TArray("DebuggerTests.SimpleClass[]", 3), - PointsProperty = TArray("DebuggerTests.Point[]", 2), - PointsField = TArray("DebuggerTests.Point[]", 2) - }, - "c" - ); + var c_props = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], "c"); + await CheckProps(c_props, new + { + id = TString("c#id"), + ClassArrayProperty = TArray("DebuggerTests.SimpleClass[]", 3), + ClassArrayField = TArray("DebuggerTests.SimpleClass[]", 3), + PointsProperty = TArray("DebuggerTests.Point[]", 2), + PointsField = TArray("DebuggerTests.Point[]", 2) + }, + "c" + ); - await CompareObjectPropertiesFor(c_props, "ClassArrayProperty", - new[] - { + await CompareObjectPropertiesFor(c_props, "ClassArrayProperty", + new[] + { TSimpleClass(5, -2, "ClassArrayProperty#Id#0", "Green"), TSimpleClass(30, 1293, "ClassArrayProperty#Id#1", "Green"), TObject("DebuggerTests.SimpleClass", is_null : true) - }, - label: "InspectLocalsWithStructsStaticAsync"); + }, + label: "InspectLocalsWithStructsStaticAsync"); - await CompareObjectPropertiesFor(c_props, "ClassArrayField", - new[] - { + await CompareObjectPropertiesFor(c_props, "ClassArrayField", + new[] + { TObject("DebuggerTests.SimpleClass", is_null : true), TSimpleClass(5, -2, "ClassArrayField#Id#1", "Blue"), TSimpleClass(30, 1293, "ClassArrayField#Id#2", "Green") - }, - label: "c#ClassArrayField"); + }, + label: "c#ClassArrayField"); - await CompareObjectPropertiesFor(c_props, "PointsProperty", - new[] - { + await CompareObjectPropertiesFor(c_props, "PointsProperty", + new[] + { TPoint(5, -2, "PointsProperty#Id#0", "Green"), TPoint(123, 0, "PointsProperty#Id#1", "Blue"), - }, - label: "c#PointsProperty"); + }, + label: "c#PointsProperty"); - await CompareObjectPropertiesFor(c_props, "PointsField", - new[] - { + await CompareObjectPropertiesFor(c_props, "PointsField", + new[] + { TPoint(5, -2, "PointsField#Id#0", "Green"), TPoint(123, 0, "PointsField#Id#1", "Blue"), - }, - label: "c#PointsField"); - }); + }, + label: "c#PointsField"); } [Theory] @@ -378,53 +361,46 @@ await CompareObjectPropertiesFor(c_props, "PointsField", [InlineData(true)] public async Task InspectValueTypeArrayLocalsStaticAsync(bool use_cfo) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); int line = 157; int col = 12; string entry_method_name = "[debugger-test] DebuggerTests.ArrayTestsClass:ValueTypeLocalsAsync"; string method_name = "MoveNext"; // BUG: this should be ValueTypeLocalsAsync int frame_idx = 0; - 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-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; - await SetBreakpoint(debugger_test_loc, line, col); + await SetBreakpoint(debugger_test_loc, line, col); - var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + - $"'{entry_method_name}', false" // *false* here keeps us only in the static method - + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + + $"'{entry_method_name}', false" // *false* here keeps us only in the static method + + + "); }, 1);"; - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); - var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - await CheckProps(frame_locals, new - { - call_other = TBool(false), - gvclass_arr = TArray("DebuggerTests.SimpleGenericStruct[]", 2), - gvclass_arr_empty = TArray("DebuggerTests.SimpleGenericStruct[]"), - gvclass_arr_null = TObject("DebuggerTests.SimpleGenericStruct[]", is_null: true), - gvclass = TValueType("DebuggerTests.SimpleGenericStruct"), - // BUG: this shouldn't be null! - points = TObject("DebuggerTests.Point[]", is_null: true) - }, "ValueTypeLocalsAsync#locals"); - - var local_var_name_prefix = "gvclass"; - await CompareObjectPropertiesFor(frame_locals, local_var_name_prefix, new - { - Id = TString(null), - Color = TEnum("DebuggerTests.RGB", "Red"), - Value = TPoint(0, 0, null, "Red") - }); + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, method_name); + var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + await CheckProps(frame_locals, new + { + call_other = TBool(false), + gvclass_arr = TArray("DebuggerTests.SimpleGenericStruct[]", 2), + gvclass_arr_empty = TArray("DebuggerTests.SimpleGenericStruct[]"), + gvclass_arr_null = TObject("DebuggerTests.SimpleGenericStruct[]", is_null: true), + gvclass = TValueType("DebuggerTests.SimpleGenericStruct"), + // BUG: this shouldn't be null! + points = TObject("DebuggerTests.Point[]", is_null: true) + }, "ValueTypeLocalsAsync#locals"); + + var local_var_name_prefix = "gvclass"; + await CompareObjectPropertiesFor(frame_locals, local_var_name_prefix, new + { + Id = TString(null), + Color = TEnum("DebuggerTests.RGB", "Red"), + Value = TPoint(0, 0, null, "Red") + }); - await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr", - new[] - { + await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr", + new[] + { new { Id = TString("gvclass_arr#1#Id"), @@ -437,11 +413,10 @@ await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr", Color = TEnum("DebuggerTests.RGB", "Blue"), Value = TPoint(10, 20, "gvclass_arr#2#Value#Id", "Green") } - } - ); - await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr_empty", - new object[0]); - }); + } + ); + await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr_empty", + new object[0]); } // TODO: Check previous frame too @@ -450,58 +425,51 @@ await CompareObjectPropertiesFor(frame_locals, $"{local_var_name_prefix}_arr_emp [InlineData(true)] public async Task InspectValueTypeArrayLocalsInstanceAsync(bool use_cfo) { - var insp = new Inspector(); //Collect events - var scripts = SubscribeToScripts(insp); int line = 170; int col = 12; string entry_method_name = "[debugger-test] DebuggerTests.ArrayTestsClass:ValueTypeLocalsAsync"; int frame_idx = 0; - 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-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; - await SetBreakpoint(debugger_test_loc, line, col); + await SetBreakpoint(debugger_test_loc, line, col); - var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + - $"'{entry_method_name}', true" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + + $"'{entry_method_name}', true" + + "); }, 1);"; - // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); + // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); - var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - await CheckProps(frame_locals, new + var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + await CheckProps(frame_locals, new + { + t1 = TObject("DebuggerTests.SimpleGenericStruct"), + @this = TObject("DebuggerTests.ArrayTestsClass"), + point_arr = TArray("DebuggerTests.Point[]", 2), + point = TValueType("DebuggerTests.Point") + }, "InspectValueTypeArrayLocalsInstanceAsync#locals"); + + await CompareObjectPropertiesFor(frame_locals, "t1", + new { - t1 = TObject("DebuggerTests.SimpleGenericStruct"), - @this = TObject("DebuggerTests.ArrayTestsClass"), - point_arr = TArray("DebuggerTests.Point[]", 2), - point = TValueType("DebuggerTests.Point") - }, "InspectValueTypeArrayLocalsInstanceAsync#locals"); - - await CompareObjectPropertiesFor(frame_locals, "t1", - new - { - Id = TString("gvclass_arr#1#Id"), - Color = TEnum("DebuggerTests.RGB", "Red"), - Value = TPoint(100, 200, "gvclass_arr#1#Value#Id", "Red") - }); + Id = TString("gvclass_arr#1#Id"), + Color = TEnum("DebuggerTests.RGB", "Red"), + Value = TPoint(100, 200, "gvclass_arr#1#Value#Id", "Red") + }); - await CompareObjectPropertiesFor(frame_locals, "point_arr", - new[] - { + await CompareObjectPropertiesFor(frame_locals, "point_arr", + new[] + { TPoint(5, -2, "point_arr#Id#0", "Red"), TPoint(123, 0, "point_arr#Id#1", "Blue"), - } - ); + } + ); - await CompareObjectPropertiesFor(frame_locals, "point", - TPoint(45, 51, "point#Id", "Green")); - }); + await CompareObjectPropertiesFor(frame_locals, "point", + TPoint(45, 51, "point#Id", "Green")); } [Theory] @@ -509,39 +477,31 @@ await CompareObjectPropertiesFor(frame_locals, "point", [InlineData(true)] public async Task InspectValueTypeArrayLocalsInAsyncStaticStructMethod(bool use_cfo) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); int line = 244; int col = 12; string entry_method_name = "[debugger-test] DebuggerTests.ArrayTestsClass:EntryPointForStructMethod"; int frame_idx = 0; - 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-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; - await SetBreakpoint(debugger_test_loc, line, col); - //await SetBreakpoint (debugger_test_loc, 143, 3); + await SetBreakpoint(debugger_test_loc, line, col); + //await SetBreakpoint (debugger_test_loc, 143, 3); - var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + - $"'{entry_method_name}', false" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + + $"'{entry_method_name}', false" + + "); }, 1);"; - // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); + // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); - var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - await CheckProps(frame_locals, new - { - call_other = TBool(false), - local_i = TNumber(5), - sc = TSimpleClass(10, 45, "sc#Id", "Blue") - }, "InspectValueTypeArrayLocalsInAsyncStaticStructMethod#locals"); - }); + var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + await CheckProps(frame_locals, new + { + call_other = TBool(false), + local_i = TNumber(5), + sc = TSimpleClass(10, 45, "sc#Id", "Blue") + }, "InspectValueTypeArrayLocalsInAsyncStaticStructMethod#locals"); } [Theory] @@ -549,56 +509,48 @@ await insp.Ready(async (cli, token) => [InlineData(true)] public async Task InspectValueTypeArrayLocalsInAsyncInstanceStructMethod(bool use_cfo) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); int line = 251; int col = 12; string entry_method_name = "[debugger-test] DebuggerTests.ArrayTestsClass:EntryPointForStructMethod"; int frame_idx = 0; - 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-array-test.cs"; + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; - await SetBreakpoint(debugger_test_loc, line, col); + await SetBreakpoint(debugger_test_loc, line, col); - var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + - $"'{entry_method_name}', true" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method_async (" + + $"'{entry_method_name}', true" + + "); }, 1);"; - // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync - var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); + // BUG: Should be InspectValueTypeArrayLocalsInstanceAsync + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, line, col, "MoveNext"); + + var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + await CheckProps(frame_locals, new + { + sc_arg = TObject("DebuggerTests.SimpleClass"), + @this = TValueType("DebuggerTests.Point"), + local_gs = TValueType("DebuggerTests.SimpleGenericStruct") + }, + "locals#0"); - var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); - await CheckProps(frame_locals, new + await CompareObjectPropertiesFor(frame_locals, "local_gs", + new { - sc_arg = TObject("DebuggerTests.SimpleClass"), - @this = TValueType("DebuggerTests.Point"), - local_gs = TValueType("DebuggerTests.SimpleGenericStruct") + Id = TString("local_gs#Id"), + Color = TEnum("DebuggerTests.RGB", "Green"), + Value = TNumber(4) }, - "locals#0"); + label: "local_gs#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"); - }); + 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] diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BadHarnessInitTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BadHarnessInitTests.cs index 9e09ade0dc5560..5d980dfc4aa7c8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BadHarnessInitTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BadHarnessInitTests.cs @@ -14,14 +14,7 @@ namespace DebuggerTests { public class BadHarnessInitTests : DebuggerTestBase { - internal Inspector insp; - protected Dictionary scripts; - - public BadHarnessInitTests(string driver = "debugger-driver.html") : base(driver) - { - insp = new Inspector(); - scripts = SubscribeToScripts(insp); - } + public override async Task InitializeAsync() => await Task.CompletedTask; [Fact] public async Task InvalidInitCommands() diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs index 09094cea2212ff..3b320494538dd7 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs @@ -30,12 +30,12 @@ await RunCallFunctionOn(eval_fn, vscode_fn0, "big", bp_loc, line, col, res_array { var is_js = bp_loc.EndsWith(".js", StringComparison.Ordinal); - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); if (is_js) await CheckProps(obj_accessors.Value["result"], new { __proto__ = TIgnore() }, "obj_accessors"); else @@ -43,12 +43,12 @@ await RunCallFunctionOn(eval_fn, vscode_fn0, "big", bp_loc, line, col, res_array // Check for a __proto__ object // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); await CheckProps(obj_own.Value["result"], new { @@ -90,12 +90,12 @@ await RunCallFunctionOn(eval_fn, vscode_fn1, "big", bp_loc, line, col, var is_js = bp_loc.EndsWith(".js", StringComparison.Ordinal); // isOwn = false, accessorPropertiesOnly = true - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); if (is_js) await CheckProps(obj_accessors.Value["result"], new { __proto__ = TIgnore() }, "obj_accessors"); else @@ -104,12 +104,12 @@ await RunCallFunctionOn(eval_fn, vscode_fn1, "big", bp_loc, line, col, // Ignoring the __proto__ property // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); var obj_own_val = obj_own.Value["result"]; var num_elems_recd = len == 0 ? 0 : num_elems_fetch; @@ -142,24 +142,24 @@ await RunCallFunctionOn(eval_fn, var is_js = bp_loc.EndsWith(".js", StringComparison.Ordinal); // getProperties (isOwn = false, accessorPropertiesOnly = true) - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); if (is_js) await CheckProps(obj_accessors.Value["result"], new { __proto__ = TIgnore() }, "obj_accessors"); else AssertEqual(0, obj_accessors.Value["result"]?.Count(), "obj_accessors-count"); // getProperties (isOwn = true, accessorPropertiesOnly = false) - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); await CheckProps(obj_own.Value["result"], new { @@ -188,12 +188,12 @@ await RunCallFunctionOn(eval_fn, var is_js = bp_loc.EndsWith(".js"); // getProperties (own=false) - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); if (is_js) await CheckProps(obj_accessors.Value["result"], new { __proto__ = TIgnore() }, "obj_accessors"); @@ -202,12 +202,12 @@ await RunCallFunctionOn(eval_fn, // getProperties (own=true) // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); // AssertEqual (2, obj_own.Value ["result"].Count (), $"{label}-obj_own.count"); @@ -239,23 +239,23 @@ public async Task RunOnVTArray(bool roundtrip) => await RunCallFunctionOn( var ret_len = 5; // getProperties (own=false) - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); AssertEqual(0, obj_accessors.Value["result"]?.Count(), "obj_accessors-count"); // getProperties (own=true) // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); var obj_own_val = obj_own.Value["result"]; await CheckProps(obj_own_val, new @@ -299,22 +299,22 @@ public async Task RunOnCFOValueTypeResult(bool roundtrip) => await RunCallFuncti { // getProperties (own=false) - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); AssertEqual(0, obj_accessors.Value["result"].Count(), "obj_accessors-count"); // getProperties (own=true) // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); var obj_own_val = obj_own.Value["result"]; var dt = new DateTime(2020, 1, 2, 3, 4, 5); @@ -345,23 +345,23 @@ public async Task RunOnJSObject(bool roundtrip) => await RunCallFunctionOn( { // getProperties (own=false) - var obj_accessors = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_accessors = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = true, ownProperties = false - }), ctx.token); + }), token); await CheckProps(obj_accessors.Value["result"], new { __proto__ = TIgnore() }, "obj_accessors"); // getProperties (own=true) // isOwn = true, accessorPropertiesOnly = false - var obj_own = await ctx.cli.SendCommand("Runtime.getProperties", JObject.FromObject(new + var obj_own = await cli.SendCommand("Runtime.getProperties", JObject.FromObject(new { objectId = result.Value["result"]["objectId"].Value(), accessorPropertiesOnly = false, ownProperties = true - }), ctx.token); + }), token); var obj_own_val = obj_own.Value["result"]; await CheckProps(obj_own_val, new @@ -442,74 +442,65 @@ public async Task RunOnArrayReturnArrayByValue(string eval_fn, string bp_loc, in [InlineData("invoke_static_method ('[debugger-test] DebuggerTests.CallFunctionOnTest:LocalsTest', 10);", "dotnet://debugger-test.dll/debugger-cfo-test.cs", 23, 12, true)] public async Task RunOnArrayReturnPrimitive(string eval_fn, string bp_loc, int line, int col, bool return_by_val) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); + await SetBreakpoint(bp_loc, line, col); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - await SetBreakpoint(bp_loc, line, col); - - // callFunctionOn - var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + // callFunctionOn + var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - // Um for js we get "scriptId": "6" - // CheckLocation (bp_loc, line, col, ctx.scripts, pause_location ["callFrames"][0]["location"]); + // Um for js we get "scriptId": "6" + // CheckLocation (bp_loc, line, col, scripts, pause_location ["callFrames"][0]["location"]); - // Check the object at the bp - var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); - var obj = GetAndAssertObjectWithName(frame_locals, "big"); - var obj_id = obj["value"]["objectId"].Value(); + // Check the object at the bp + var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); + var obj = GetAndAssertObjectWithName(frame_locals, "big"); + var obj_id = obj["value"]["objectId"].Value(); - var cfo_args = JObject.FromObject(new - { - functionDeclaration = "function () { return 5; }", - objectId = obj_id - }); + var cfo_args = JObject.FromObject(new + { + functionDeclaration = "function () { return 5; }", + objectId = obj_id + }); - // value of @returnByValue doesn't matter, as the returned value - // is a primitive - if (return_by_val) - cfo_args["returnByValue"] = return_by_val; + // value of @returnByValue doesn't matter, as the returned value + // is a primitive + if (return_by_val) + cfo_args["returnByValue"] = return_by_val; - // callFunctionOn - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - await CheckValue(result.Value["result"], TNumber(5), "cfo-res"); + // callFunctionOn + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + await CheckValue(result.Value["result"], TNumber(5), "cfo-res"); - cfo_args = JObject.FromObject(new - { - functionDeclaration = "function () { return 'test value'; }", - objectId = obj_id - }); + cfo_args = JObject.FromObject(new + { + functionDeclaration = "function () { return 'test value'; }", + objectId = obj_id + }); - // value of @returnByValue doesn't matter, as the returned value - // is a primitive - if (return_by_val) - cfo_args["returnByValue"] = return_by_val; + // value of @returnByValue doesn't matter, as the returned value + // is a primitive + if (return_by_val) + cfo_args["returnByValue"] = return_by_val; - // callFunctionOn - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - await CheckValue(result.Value["result"], JObject.FromObject(new { type = "string", value = "test value" }), "cfo-res"); + // callFunctionOn + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + await CheckValue(result.Value["result"], JObject.FromObject(new { type = "string", value = "test value" }), "cfo-res"); - cfo_args = JObject.FromObject(new - { - functionDeclaration = "function () { return null; }", - objectId = obj_id - }); + cfo_args = JObject.FromObject(new + { + functionDeclaration = "function () { return null; }", + objectId = obj_id + }); - // value of @returnByValue doesn't matter, as the returned value - // is a primitive - if (return_by_val) - cfo_args["returnByValue"] = return_by_val; + // value of @returnByValue doesn't matter, as the returned value + // is a primitive + if (return_by_val) + cfo_args["returnByValue"] = return_by_val; - // callFunctionOn - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - await CheckValue(result.Value["result"], JObject.Parse("{ type: 'object', subtype: 'null', value: null }"), "cfo-res"); - }); + // callFunctionOn + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + await CheckValue(result.Value["result"], JObject.Parse("{ type: 'object', subtype: 'null', value: null }"), "cfo-res"); } public static TheoryData SilentErrorsTestData(bool? silent) => new TheoryData @@ -523,45 +514,36 @@ await insp.Ready(async (cli, token) => [MemberData(nameof(SilentErrorsTestData), true)] public async Task CFOWithSilentReturnsErrors(string eval_fn, string bp_loc, int line, int col, bool? silent) { - 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(bp_loc, line, col); + await SetBreakpoint(bp_loc, line, col); - // callFunctionOn - var eval_expr = "window.setTimeout(function() { " + eval_fn + " }, 1);"; - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + // callFunctionOn + var eval_expr = "window.setTimeout(function() { " + eval_fn + " }, 1);"; + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); - var obj = GetAndAssertObjectWithName(frame_locals, "big"); - var big_obj_id = obj["value"]["objectId"].Value(); - var error_msg = "#This is an error message#"; + var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); + var obj = GetAndAssertObjectWithName(frame_locals, "big"); + var big_obj_id = obj["value"]["objectId"].Value(); + var error_msg = "#This is an error message#"; - // Check the object at the bp - var cfo_args = JObject.FromObject(new - { - functionDeclaration = $"function () {{ throw Error ('{error_msg}'); }}", - objectId = big_obj_id - }); + // Check the object at the bp + var cfo_args = JObject.FromObject(new + { + functionDeclaration = $"function () {{ throw Error ('{error_msg}'); }}", + objectId = big_obj_id + }); - if (silent.HasValue) - cfo_args["silent"] = silent; + if (silent.HasValue) + cfo_args["silent"] = silent; - // callFunctionOn, Silent does not change the result, except that the error - // doesn't get reported, and the execution is NOT paused even with setPauseOnException=true - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - Assert.False(result.IsOk, "result.IsOk"); - Assert.True(result.IsErr, "result.IsErr"); + // callFunctionOn, Silent does not change the result, except that the error + // doesn't get reported, and the execution is NOT paused even with setPauseOnException=true + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + Assert.False(result.IsOk, "result.IsOk"); + Assert.True(result.IsErr, "result.IsErr"); - var hasErrorMessage = result.Error["exceptionDetails"]?["exception"]?["description"]?.Value()?.Contains(error_msg); - Assert.True((hasErrorMessage ?? false), "Exception message not found"); - }); + var hasErrorMessage = result.Error["exceptionDetails"]?["exception"]?["description"]?.Value()?.Contains(error_msg); + Assert.True((hasErrorMessage ?? false), "Exception message not found"); } public static TheoryData, string, bool> GettersTestData(string local_name, bool use_cfo) => new TheoryData, string, bool> @@ -771,7 +753,7 @@ await RunCallFunctionOn( async Task GetPropertiesAndCheckAccessors(JObject get_prop_req, int num_fields) { - var res = await ctx.cli.SendCommand("Runtime.getProperties", get_prop_req, ctx.token); + var res = await cli.SendCommand("Runtime.getProperties", get_prop_req, token); if (!res.IsOk) Assert.True(false, $"Runtime.getProperties failed for {get_prop_req.ToString()}, with Result: {res}"); @@ -808,7 +790,7 @@ public async Task RunOnInvalidCfoId(string eval_fn, string bp_loc, int line, int objectId = ptd_id + "_invalid" }); - var res = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); + var res = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); Assert.True(res.IsErr); }); @@ -816,35 +798,26 @@ public async Task RunOnInvalidCfoId(string eval_fn, string bp_loc, int line, int [MemberData(nameof(NegativeTestsData), false)] public async Task RunOnInvalidThirdSegmentOfObjectId(string eval_fn, string bp_loc, int line, int col, 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; - await SetBreakpoint(bp_loc, line, col); + UseCallFunctionOnBeforeGetProperties = use_cfo; + await SetBreakpoint(bp_loc, line, col); - // callFunctionOn - var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + // callFunctionOn + var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); - var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); - var ptd_id = ptd["value"]["objectId"].Value(); - - var cfo_args = JObject.FromObject(new - { - functionDeclaration = "function () { return 0; }", - objectId = ptd_id + "_invalid" - }); + var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); + var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); + var ptd_id = ptd["value"]["objectId"].Value(); - var res = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - Assert.True(res.IsErr); + var cfo_args = JObject.FromObject(new + { + functionDeclaration = "function () { return 0; }", + objectId = ptd_id + "_invalid" }); + + var res = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + Assert.True(res.IsErr); } [Theory] @@ -852,33 +825,24 @@ await insp.Ready(async (cli, token) => [MemberData(nameof(NegativeTestsData), true)] public async Task InvalidPropertyGetters(string eval_fn, string bp_loc, int line, int col, 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); - await SetBreakpoint(bp_loc, line, col); - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + await SetBreakpoint(bp_loc, line, col); + UseCallFunctionOnBeforeGetProperties = use_cfo; - // callFunctionOn - var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; - await SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr })); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + // callFunctionOn + var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; + await SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr })); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); - var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); - var ptd_id = ptd["value"]["objectId"].Value(); + var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); + var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); + var ptd_id = ptd["value"]["objectId"].Value(); - var invalid_args = new object[] { "NonExistant", String.Empty, null, 12310 }; - foreach (var invalid_arg in invalid_args) - { - var getter_res = await InvokeGetter(JObject.FromObject(new { value = new { objectId = ptd_id } }), invalid_arg); - AssertEqual("undefined", getter_res.Value["result"]?["type"]?.ToString(), $"Expected to get undefined result for non-existant accessor - {invalid_arg}"); - } - }); + var invalid_args = new object[] { "NonExistant", String.Empty, null, 12310 }; + foreach (var invalid_arg in invalid_args) + { + var getter_res = await InvokeGetter(JObject.FromObject(new { value = new { objectId = ptd_id } }), invalid_arg); + AssertEqual("undefined", getter_res.Value["result"]?["type"]?.ToString(), $"Expected to get undefined result for non-existant accessor - {invalid_arg}"); + } } [Theory] @@ -922,81 +886,72 @@ public async Task ReturnNullFromCFO(string eval_fn, string bp_loc, int line, int async Task RunCallFunctionOn(string eval_fn, string fn_decl, string local_name, string bp_loc, int line, int col, int res_array_len = -1, Func test_fn = null, bool returnByValue = false, JArray fn_args = null, bool roundtrip = false) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); + await SetBreakpoint(bp_loc, line, col); + + // callFunctionOn + var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); + + // Um for js we get "scriptId": "6" + // CheckLocation (bp_loc, line, col, scripts, pause_location ["callFrames"][0]["location"]); + + // Check the object at the bp + var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); + var obj = GetAndAssertObjectWithName(frame_locals, local_name); + var obj_id = obj["value"]["objectId"].Value(); - await Ready(); - await insp.Ready(async (cli, token) => + var cfo_args = JObject.FromObject(new { - ctx = new DebugTestContext(cli, insp, token, scripts); - await SetBreakpoint(bp_loc, line, col); + functionDeclaration = fn_decl, + objectId = obj_id + }); - // callFunctionOn - var eval_expr = $"window.setTimeout(function() {{ {eval_fn} }}, 1);"; - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + if (fn_args != null) + cfo_args["arguments"] = fn_args; - // Um for js we get "scriptId": "6" - // CheckLocation (bp_loc, line, col, ctx.scripts, pause_location ["callFrames"][0]["location"]); + if (returnByValue) + cfo_args["returnByValue"] = returnByValue; - // Check the object at the bp - var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value()); - var obj = GetAndAssertObjectWithName(frame_locals, local_name); - var obj_id = obj["value"]["objectId"].Value(); + // callFunctionOn + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + await CheckCFOResult(result); - var cfo_args = JObject.FromObject(new + // If it wasn't `returnByValue`, then try to run a new function + // on that *returned* object + // This second function, just returns the object as-is, so the same + // test_fn is re-usable. + if (!returnByValue && roundtrip) + { + cfo_args = JObject.FromObject(new { - functionDeclaration = fn_decl, - objectId = obj_id + functionDeclaration = "function () { return this; }", + objectId = result.Value["result"]["objectId"]?.Value() }); if (fn_args != null) cfo_args["arguments"] = fn_args; - if (returnByValue) - cfo_args["returnByValue"] = returnByValue; + result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); - // callFunctionOn - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); await CheckCFOResult(result); + } - // If it wasn't `returnByValue`, then try to run a new function - // on that *returned* object - // This second function, just returns the object as-is, so the same - // test_fn is re-usable. - if (!returnByValue && roundtrip) - { - cfo_args = JObject.FromObject(new - { - functionDeclaration = "function () { return this; }", - objectId = result.Value["result"]["objectId"]?.Value() - }); - - if (fn_args != null) - cfo_args["arguments"] = fn_args; - - result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); - - await CheckCFOResult(result); - } - - if (test_fn != null) - await test_fn(result); + if (test_fn != null) + await test_fn(result); - return; + return; - async Task CheckCFOResult(Result result) - { - if (returnByValue) - return; + async Task CheckCFOResult(Result result) + { + if (returnByValue) + return; - if (res_array_len < 0) - await CheckValue(result.Value["result"], TObject("Object"), $"cfo-res"); - else - await CheckValue(result.Value["result"], TArray("Array", res_array_len), $"cfo-res"); - } - }); + if (res_array_len < 0) + await CheckValue(result.Value["result"], TObject("Object"), $"cfo-res"); + else + await CheckValue(result.Value["result"], TArray("Array", res_array_len), $"cfo-res"); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DateTimeTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DateTimeTests.cs index 40a156c4f31823..2d3707fec1d8d8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DateTimeTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DateTimeTests.cs @@ -18,39 +18,30 @@ public class DateTimeList : DebuggerTestBase [InlineData("de-DE", "dddd, d. MMMM yyyy HH:mm:ss", "dddd, d. MMMM yyyy", "HH:mm:ss", "dd.MM.yyyy", "HH:mm")] public async Task CheckDateTimeLocale(string locale, string fdtp, string ldp, string ltp, string sdp, string stp) { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-datetime-test.cs"; - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - var debugger_test_loc = "dotnet://debugger-test.dll/debugger-datetime-test.cs"; + await SetBreakpointInMethod("debugger-test", "DebuggerTests.DateTimeTest", "LocaleTest", 15); - await SetBreakpointInMethod("debugger-test", "DebuggerTests.DateTimeTest", "LocaleTest", 15); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.DateTimeTest:LocaleTest'," + + $"'{locale}'); }}, 1);", + debugger_test_loc, 25, 12, "LocaleTest", + locals_fn: async (locals) => + { + DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo(locale).DateTimeFormat; + CultureInfo.CurrentCulture = new CultureInfo(locale, false); - var pause_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.DateTimeTest:LocaleTest'," + - $"'{locale}'); }}, 1);", - debugger_test_loc, 25, 12, "LocaleTest", - locals_fn: async (locals) => + await CheckProps(locals, new { - DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo(locale).DateTimeFormat; - CultureInfo.CurrentCulture = new CultureInfo(locale, false); - - await CheckProps(locals, new - { - fdtp = TString(fdtp), - ldp = TString(ldp), - ltp = TString(ltp), - sdp = TString(sdp), - stp = TString(stp), - dt = TDateTime(new DateTime(2020, 1, 2, 3, 4, 5)) - }, "locals", num_fields: 8); - } - ); - - }); + fdtp = TString(fdtp), + ldp = TString(ldp), + ltp = TString(ltp), + sdp = TString(sdp), + stp = TString(stp), + dt = TDateTime(new DateTime(2020, 1, 2, 3, 4, 5)) + }, "locals", num_fields: 8); + } + ); } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 55d42ccba6ba70..247778b97454a5 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -19,10 +19,16 @@ namespace DebuggerTests { - public class DebuggerTestBase + public class DebuggerTestBase : IAsyncLifetime { + internal InspectorClient cli; + internal Inspector insp; + protected CancellationToken token; + protected Dictionary scripts; protected Task startTask; + public bool UseCallFunctionOnBeforeGetProperties; + static string s_debuggerTestAppPath; protected static string DebuggerTestAppPath { @@ -73,12 +79,37 @@ static string FindChromePath() public DebuggerTestBase(string driver = "debugger-driver.html") { + insp = new Inspector(); + cli = insp.Client; + scripts = SubscribeToScripts(insp); + startTask = TestHarnessProxy.Start(FindChromePath(), DebuggerTestAppPath, driver); } + public virtual async Task InitializeAsync() + { + Func)>> fn = (client, token) => + { + Func)> getInitCmdFn = (cmd) => (cmd, client.SendCommand(cmd, null, token)); + var init_cmds = new List<(string, Task)> + { + getInitCmdFn("Profiler.enable"), + getInitCmdFn("Runtime.enable"), + getInitCmdFn("Debugger.enable"), + getInitCmdFn("Runtime.runIfWaitingForDebugger") + }; + + return init_cmds; + }; + + await Ready(); + await insp.OpenSessionAsync(fn); + } + + public virtual async Task DisposeAsync() => await insp.ShutdownAsync().ConfigureAwait(false); + public Task Ready() => startTask; - internal DebugTestContext ctx; internal Dictionary dicScriptsIdToUrl; internal Dictionary dicFileToUrl; internal Dictionary SubscribeToScripts(Inspector insp) @@ -109,88 +140,70 @@ internal Dictionary SubscribeToScripts(Inspector insp) internal async Task CheckInspectLocalsAtBreakpointSite(string url_key, int line, int column, string function_name, string eval_expression, Action test_fn = null, Func wait_for_event_fn = null, bool use_cfo = false) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); + UseCallFunctionOnBeforeGetProperties = use_cfo; - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; - - var bp = await SetBreakpoint(url_key, line, column); + var bp = await SetBreakpoint(url_key, line, column); - await EvaluateAndCheck( - eval_expression, url_key, line, column, - function_name, - wait_for_event_fn: async (pause_location) => - { + await EvaluateAndCheck( + eval_expression, url_key, line, column, + function_name, + 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()); - var top_frame = pause_location["callFrames"][0]; + var top_frame = pause_location!["callFrames"]?[0]; - var scope = top_frame["scopeChain"][0]; - if (wait_for_event_fn != null) - await wait_for_event_fn(pause_location); - else - await Task.CompletedTask; - }, - locals_fn: (locals) => - { - if (test_fn != null) - test_fn(locals); - } - ); - }); + var scope = top_frame!["scopeChain"]?[0]; + if (wait_for_event_fn != null) + await wait_for_event_fn(pause_location); + else + await Task.CompletedTask; + }, + locals_fn: (locals) => + { + if (test_fn != null) + test_fn(locals); + } + ); } // sets breakpoint by method name and line offset internal async Task CheckInspectLocalsAtBreakpointSite(string type, string method, int line_offset, string bp_function_name, string eval_expression, Action locals_fn = null, Func wait_for_event_fn = null, bool use_cfo = false, string assembly = "debugger-test.dll", int col = 0) { - 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; + UseCallFunctionOnBeforeGetProperties = use_cfo; - var bp = await SetBreakpointInMethod(assembly, type, method, line_offset, col); + var bp = await SetBreakpointInMethod(assembly, type, method, line_offset, col); - var args = JObject.FromObject(new { expression = eval_expression }); - var res = await ctx.cli.SendCommand("Runtime.evaluate", args, ctx.token); - if (!res.IsOk) - { - Console.WriteLine($"Failed to run command {method} with args: {args?.ToString()}\nresult: {res.Error.ToString()}"); - Assert.True(false, $"SendCommand for {method} failed with {res.Error.ToString()}"); - } + var args = JObject.FromObject(new { expression = eval_expression }); + var res = await cli.SendCommand("Runtime.evaluate", args, token); + if (!res.IsOk) + { + Console.WriteLine($"Failed to run command {method} with args: {args?.ToString()}\nresult: {res.Error.ToString()}"); + Assert.True(false, $"SendCommand for {method} failed with {res.Error.ToString()}"); + } - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - if (bp_function_name != null) - Assert.Equal(bp_function_name, pause_location["callFrames"]?[0]?["functionName"]?.Value()); + if (bp_function_name != null) + Assert.Equal(bp_function_name, pause_location["callFrames"]?[0]?["functionName"]?.Value()); - Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); - var top_frame = pause_location["callFrames"][0]; + var top_frame = pause_location!["callFrames"]?[0]; - var scope = top_frame["scopeChain"][0]; + var scope = top_frame?["scopeChain"]?[0]; - if (wait_for_event_fn != null) - await wait_for_event_fn(pause_location); + if (wait_for_event_fn != null) + await wait_for_event_fn(pause_location); - if (locals_fn != null) - { - var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); - locals_fn(locals); - } - }); + if (locals_fn != null) + { + var locals = await GetProperties(pause_location?["callFrames"]?[0]?["callFrameId"]?.Value()); + locals_fn(locals); + } } internal void CheckLocation(string script_loc, int line, int column, Dictionary scripts, JToken location) @@ -254,13 +267,13 @@ internal async Task CheckDateTime(JToken value, DateTime expected, string label await CheckDateTimeValue(value, expected, label); } - internal async Task CheckDateTime(JToken locals, string name, DateTime expected, string label="") + internal async Task CheckDateTime(JToken locals, string name, DateTime expected, string label = "") { var obj = GetAndAssertObjectWithName(locals, name, label); await CheckDateTimeValue(obj["value"], expected, label); } - internal async Task CheckDateTimeValue(JToken value, DateTime expected, string label="") + internal async Task CheckDateTimeValue(JToken value, DateTime expected, string label = "") { await CheckDateTimeMembers(value, expected, label); @@ -269,7 +282,7 @@ internal async Task CheckDateTimeValue(JToken value, DateTime expected, string l // FIXME: check some float properties too - async Task CheckDateTimeMembers(JToken v, DateTime exp_dt, string label="") + async Task CheckDateTimeMembers(JToken v, DateTime exp_dt, string label = "") { AssertEqual("System.DateTime", v["className"]?.Value(), $"{label}#className"); AssertEqual(exp_dt.ToString(), v["description"]?.Value(), $"{label}#description"); @@ -318,7 +331,7 @@ internal void CheckArray(JToken locals, string name, string class_name, int leng GetAndAssertObjectWithName(locals, name)["value"], TArray(class_name, length), name).Wait(); - internal JToken GetAndAssertObjectWithName(JToken obj, string name, string label="") + internal JToken GetAndAssertObjectWithName(JToken obj, string name, string label = "") { var l = obj.FirstOrDefault(jt => jt["name"]?.Value() == name); if (l == null) @@ -328,7 +341,7 @@ internal JToken GetAndAssertObjectWithName(JToken obj, string name, string label internal async Task SendCommand(string method, JObject args) { - var res = await ctx.cli.SendCommand(method, args, ctx.token); + var res = await cli.SendCommand(method, args, token); if (!res.IsOk) { Console.WriteLine($"Failed to run command {method} with args: {args?.ToString()}\nresult: {res.Error.ToString()}"); @@ -354,7 +367,7 @@ internal async Task RunUntil(string methodName) await SetBreakpointInMethod("debugger-test", "DebuggerTest", methodName); // This will run all the tests until it hits the bp await Evaluate("window.setTimeout(function() { invoke_run_all (); }, 1);"); - var wait_res = await ctx.insp.WaitFor(Inspector.PAUSE); + var wait_res = await insp.WaitFor(Inspector.PAUSE); AssertLocation(wait_res, "locals_inner"); return wait_res; } @@ -370,7 +383,7 @@ internal async Task InvokeGetter(JToken obj, object arguments, string fn if (returnByValue != null) req["returnByValue"] = returnByValue.Value; - var res = await ctx.cli.SendCommand("Runtime.callFunctionOn", req, ctx.token); + var res = await cli.SendCommand("Runtime.callFunctionOn", req, token); Assert.True(expect_ok == res.IsOk, $"InvokeGetter failed for {req} with {res}"); return res; @@ -402,23 +415,23 @@ internal async Task EvaluateAndCheck(string expression, string script_l internal async Task SendCommandAndCheck(JObject args, string method, string script_loc, int line, int column, string function_name, Func wait_for_event_fn = null, Action locals_fn = null, string waitForEvent = Inspector.PAUSE) { - var res = await ctx.cli.SendCommand(method, args, ctx.token); + var res = await cli.SendCommand(method, args, token); if (!res.IsOk) { Console.WriteLine($"Failed to run command {method} with args: {args?.ToString()}\nresult: {res.Error.ToString()}"); Assert.True(false, $"SendCommand for {method} failed with {res.Error.ToString()}"); } - var wait_res = await ctx.insp.WaitFor(waitForEvent); + var wait_res = await insp.WaitFor(waitForEvent); JToken top_frame = wait_res["callFrames"]?[0]; if (function_name != null) { AssertEqual(function_name, wait_res["callFrames"]?[0]?["functionName"]?.Value(), top_frame?.ToString()); } - Console.WriteLine (top_frame); + Console.WriteLine(top_frame); if (script_loc != null && line >= 0) - CheckLocation(script_loc, line, column, ctx.scripts, top_frame["location"]); + CheckLocation(script_loc, line, column, scripts, top_frame["location"]); if (wait_for_event_fn != null) await wait_for_event_fn(wait_res); @@ -658,14 +671,14 @@ internal async Task CheckValue(JToken actual_val, JToken exp_val, string label) } catch { - Console.WriteLine ($"Expected: {exp_val}. Actual: {actual_val}"); + Console.WriteLine($"Expected: {exp_val}. Actual: {actual_val}"); throw; } } internal async Task GetLocalsForFrame(JToken frame, string script_loc, int line, int column, string function_name) { - CheckLocation(script_loc, line, column, ctx.scripts, frame["location"]); + CheckLocation(script_loc, line, column, scripts, frame["location"]); Assert.Equal(function_name, frame["functionName"].Value()); return await GetProperties(frame["callFrameId"].Value()); @@ -707,7 +720,7 @@ internal async Task GetObjectOnLocals(JToken locals, string name) /* @fn_args is for use with `Runtime.callFunctionOn` only */ internal async Task GetProperties(string id, JToken fn_args = null, bool? own_properties = null, bool? accessors_only = null, bool expect_ok = true) { - if (ctx.UseCallFunctionOnBeforeGetProperties && !id.StartsWith("dotnet:scope:")) + if (UseCallFunctionOnBeforeGetProperties && !id.StartsWith("dotnet:scope:")) { var fn_decl = "function () { return this; }"; var cfo_args = JObject.FromObject(new @@ -718,7 +731,7 @@ internal async Task GetProperties(string id, JToken fn_args = null, bool if (fn_args != null) cfo_args["arguments"] = fn_args; - var result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); + var result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); AssertEqual(expect_ok, result.IsOk, $"Runtime.getProperties returned {result.IsOk} instead of {expect_ok}, for {cfo_args.ToString()}, with Result: {result}"); if (!result.IsOk) return null; @@ -738,7 +751,7 @@ internal async Task GetProperties(string id, JToken fn_args = null, bool get_prop_req["accessorPropertiesOnly"] = accessors_only.Value; } - var frame_props = await ctx.cli.SendCommand("Runtime.getProperties", get_prop_req, ctx.token); + var frame_props = await cli.SendCommand("Runtime.getProperties", get_prop_req, token); AssertEqual(expect_ok, frame_props.IsOk, $"Runtime.getProperties returned {frame_props.IsOk} instead of {expect_ok}, for {get_prop_req}, with Result: {frame_props}"); if (!frame_props.IsOk) return null; @@ -769,7 +782,7 @@ internal async Task GetProperties(string id, JToken fn_args = null, bool expression = expression }); - var res = await ctx.cli.SendCommand("Debugger.evaluateOnCallFrame", evaluate_req, ctx.token); + var res = await cli.SendCommand("Debugger.evaluateOnCallFrame", evaluate_req, token); AssertEqual(expect_ok, res.IsOk, $"Debugger.evaluateOnCallFrame ('{expression}', scope: {id}) returned {res.IsOk} instead of {expect_ok}, with Result: {res}"); if (res.IsOk) return (res.Value["result"], res); @@ -784,7 +797,7 @@ internal async Task RemoveBreakpoint(string id, bool expect_ok = true) breakpointId = id }); - var res = await ctx.cli.SendCommand("Debugger.removeBreakpoint", remove_bp, ctx.token); + var res = await cli.SendCommand("Debugger.removeBreakpoint", remove_bp, token); Assert.True(expect_ok ? res.IsOk : res.IsErr); return res; @@ -796,7 +809,7 @@ internal async Task SetBreakpoint(string url_key, int line, int column, JObject.FromObject(new { lineNumber = line, columnNumber = column, url = dicFileToUrl[url_key], }) : JObject.FromObject(new { lineNumber = line, columnNumber = column, urlRegex = url_key, }); - var bp1_res = await ctx.cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, ctx.token); + var bp1_res = await cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, token); Assert.True(expect_ok ? bp1_res.IsOk : bp1_res.IsErr); return bp1_res; @@ -804,7 +817,7 @@ internal async Task SetBreakpoint(string url_key, int line, int column, internal async Task SetPauseOnException(string state) { - var exc_res = await ctx.cli.SendCommand("Debugger.setPauseOnExceptions", JObject.FromObject(new { state = state }), ctx.token); + var exc_res = await cli.SendCommand("Debugger.setPauseOnExceptions", JObject.FromObject(new { state = state }), token); return exc_res; } @@ -813,7 +826,7 @@ internal async Task SetBreakpointInMethod(string assembly, string type, var req = JObject.FromObject(new { assemblyName = assembly, typeName = type, methodName = method, lineOffset = lineOffset }); // Protocol extension - var res = await ctx.cli.SendCommand("DotnetDebugger.getMethodLocation", req, ctx.token); + var res = await cli.SendCommand("DotnetDebugger.getMethodLocation", req, token); Assert.True(res.IsOk); var m_url = res.Value["result"]["url"].Value(); @@ -826,7 +839,7 @@ internal async Task SetBreakpointInMethod(string assembly, string type, url = m_url }); - res = await ctx.cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, ctx.token); + res = await cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, token); Assert.True(res.IsOk); return res; @@ -916,24 +929,6 @@ internal static JObject TDateTime(DateTime dt) => JObject.FromObject(new }); } - class DebugTestContext - { - public InspectorClient cli; - public Inspector insp; - public CancellationToken token; - public Dictionary scripts; - - public bool UseCallFunctionOnBeforeGetProperties; - - public DebugTestContext(InspectorClient cli, Inspector insp, CancellationToken token, Dictionary scripts) - { - this.cli = cli; - this.insp = insp; - this.token = token; - this.scripts = scripts; - } - } - class DotnetObjectId { public string Scheme { get; } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 2218b9a7945114..6462e86505d331 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -49,26 +49,26 @@ public async Task EvaluateTypeInstanceMembers(string prefix, int bias, string ty var dateTime = new DateTime(2010, 9, 8, 7, 6, 5 + bias); var DTProp = dateTime.AddMinutes(10); - foreach (var pad in new[] { String.Empty, " " }) - { - var padded_prefix = pad + prefix; - await EvaluateOnCallFrameAndCheck(id, - ($"{padded_prefix}a", TNumber(4)), - - // fields - ($"{padded_prefix}dateTime.TimeOfDay", TValueType("System.TimeSpan", dateTime.TimeOfDay.ToString())), - ($"{padded_prefix}dateTime", TDateTime(dateTime)), - ($"{padded_prefix}dateTime.TimeOfDay.Minutes", TNumber(dateTime.TimeOfDay.Minutes)), - - // properties - ($"{padded_prefix}DTProp.TimeOfDay.Minutes", TNumber(DTProp.TimeOfDay.Minutes)), - ($"{padded_prefix}DTProp", TDateTime(DTProp)), - ($"{padded_prefix}DTProp.TimeOfDay", TValueType("System.TimeSpan", DTProp.TimeOfDay.ToString())), - - ($"{padded_prefix}IntProp", TNumber(9)), - ($"{padded_prefix}NullIfAIsNotZero", TObject("DebuggerTests.EvaluateTestsClassWithProperties", is_null: true)) - ); - } + foreach (var pad in new[] { String.Empty, " " }) + { + var padded_prefix = pad + prefix; + await EvaluateOnCallFrameAndCheck(id, + ($"{padded_prefix}a", TNumber(4)), + + // fields + ($"{padded_prefix}dateTime.TimeOfDay", TValueType("System.TimeSpan", dateTime.TimeOfDay.ToString())), + ($"{padded_prefix}dateTime", TDateTime(dateTime)), + ($"{padded_prefix}dateTime.TimeOfDay.Minutes", TNumber(dateTime.TimeOfDay.Minutes)), + + // properties + ($"{padded_prefix}DTProp.TimeOfDay.Minutes", TNumber(DTProp.TimeOfDay.Minutes)), + ($"{padded_prefix}DTProp", TDateTime(DTProp)), + ($"{padded_prefix}DTProp.TimeOfDay", TValueType("System.TimeSpan", DTProp.TimeOfDay.ToString())), + + ($"{padded_prefix}IntProp", TNumber(9)), + ($"{padded_prefix}NullIfAIsNotZero", TObject("DebuggerTests.EvaluateTestsClassWithProperties", is_null: true)) + ); + } }); [Theory] @@ -145,13 +145,13 @@ public async Task EvaluateLocalsAsync() => await CheckInspectLocalsAtBreakpointS { var id = pause_location["callFrames"][0]["callFrameId"].Value(); - // sc_arg - { + // sc_arg + { var (sc_arg, _) = await EvaluateOnCallFrame(id, "sc_arg"); await CheckValue(sc_arg, TObject("DebuggerTests.SimpleClass"), nameof(sc_arg)); - // Check that we did get the correct object - var sc_arg_props = await GetProperties(sc_arg["objectId"]?.Value()); + // Check that we did get the correct object + var sc_arg_props = await GetProperties(sc_arg["objectId"]?.Value()); await CheckProps(sc_arg_props, new { X = TNumber(10), @@ -167,8 +167,8 @@ await EvaluateOnCallFrameAndCheck(id, ("sc_arg.Id + (sc_arg.X==10 ? \"_is_ten\" : \"_not_ten\")", TString($"sc#Id_is_ten"))); } - // local_gs - { + // local_gs + { var (local_gs, _) = await EvaluateOnCallFrame(id, "local_gs"); await CheckValue(local_gs, TValueType("DebuggerTests.SimpleGenericStruct"), nameof(local_gs)); @@ -221,28 +221,28 @@ public async Task InheritedAndPrivateMembersInAClass(string prefix) { var id = pause_location["callFrames"][0]["callFrameId"].Value(); - foreach(var pad in new [] { String.Empty, " "}) - { - var padded_prefix = pad + prefix; - await EvaluateOnCallFrameAndCheck(id, - // overridden - ($"{padded_prefix}FirstName + \"_foo\"", TString("DerivedClass#FirstName_foo")), - ($"{padded_prefix}DateTimeForOverride.Date.Year", TNumber(2190)), - ($"{padded_prefix}DateTimeForOverride.Date.Year - 10", TNumber(2180)), - ($"\"foo_\" + {padded_prefix}StringPropertyForOverrideWithAutoProperty", TString("foo_DerivedClass#StringPropertyForOverrideWithAutoProperty")), - - // private - ($"{padded_prefix}_stringField + \"_foo\"", TString("DerivedClass#_stringField_foo")), - ($"{padded_prefix}_stringField", TString("DerivedClass#_stringField")), - ($"{padded_prefix}_dateTime.Second + 4", TNumber(7)), - ($"{padded_prefix}_DTProp.Second + 4", TNumber(13)), - - // inherited public - ($"\"foo_\" + {padded_prefix}Base_AutoStringProperty", TString("foo_base#Base_AutoStringProperty")), - // inherited private - ($"{padded_prefix}_base_dateTime.Date.Year - 10", TNumber(2124)) - ); - } + foreach (var pad in new[] { String.Empty, " " }) + { + var padded_prefix = pad + prefix; + await EvaluateOnCallFrameAndCheck(id, + // overridden + ($"{padded_prefix}FirstName + \"_foo\"", TString("DerivedClass#FirstName_foo")), + ($"{padded_prefix}DateTimeForOverride.Date.Year", TNumber(2190)), + ($"{padded_prefix}DateTimeForOverride.Date.Year - 10", TNumber(2180)), + ($"\"foo_\" + {padded_prefix}StringPropertyForOverrideWithAutoProperty", TString("foo_DerivedClass#StringPropertyForOverrideWithAutoProperty")), + + // private + ($"{padded_prefix}_stringField + \"_foo\"", TString("DerivedClass#_stringField_foo")), + ($"{padded_prefix}_stringField", TString("DerivedClass#_stringField")), + ($"{padded_prefix}_dateTime.Second + 4", TNumber(7)), + ($"{padded_prefix}_DTProp.Second + 4", TNumber(13)), + + // inherited public + ($"\"foo_\" + {padded_prefix}Base_AutoStringProperty", TString("foo_base#Base_AutoStringProperty")), + // inherited private + ($"{padded_prefix}_base_dateTime.Date.Year - 10", TNumber(2124)) + ); + } }); [Fact] @@ -322,8 +322,8 @@ public async Task EvaluateOnPreviousFrames(string type_name, bool is_valuetype) var dt_local = new DateTime(2020, 3, 4, 5, 6, 7); var dt_this = new DateTime(2010, 9, 8, 7, 6, 5); - // At EvaluateShadow - { + // At EvaluateShadow + { var id0 = pause_location["callFrames"][0]["callFrameId"].Value(); await EvaluateOnCallFrameAndCheck(id0, ("dateTime", TDateTime(dt_local)), @@ -339,38 +339,38 @@ await EvaluateOnCallFrameFail(id1, ("dateTime", "ReferenceError"), ("this.dateTime", "ReferenceError")); - // obj available only on the -1 frame - await EvaluateOnCallFrameAndCheck(id1, ("obj.IntProp", TNumber(7))); + // obj available only on the -1 frame + await EvaluateOnCallFrameAndCheck(id1, ("obj.IntProp", TNumber(7))); } await SetBreakpointInMethod("debugger-test.dll", type_name, "SomeMethod", 1); pause_location = await SendCommandAndCheck(null, "Debugger.resume", null, 0, 0, "SomeMethod"); - // At SomeMethod + // At SomeMethod - // TODO: change types also.. so, that `this` is different! + // TODO: change types also.. so, that `this` is different! - // Check frame0 - { + // Check frame0 + { var id0 = pause_location["callFrames"][0]["callFrameId"].Value(); - // 'me' and 'dateTime' are reversed in this method - await EvaluateOnCallFrameAndCheck(id0, - ("dateTime", is_valuetype ? TValueType(type_name) : TObject(type_name)), - ("this.dateTime", TDateTime(dt_this)), - ("me", TDateTime(dt_local)), + // 'me' and 'dateTime' are reversed in this method + await EvaluateOnCallFrameAndCheck(id0, + ("dateTime", is_valuetype ? TValueType(type_name) : TObject(type_name)), + ("this.dateTime", TDateTime(dt_this)), + ("me", TDateTime(dt_local)), - // local variable shadows field, but isn't "live" yet - ("DTProp", TString(null)), + // local variable shadows field, but isn't "live" yet + ("DTProp", TString(null)), - // access field via `this.` - ("this.DTProp", TDateTime(dt_this.AddMinutes(10)))); + // access field via `this.` + ("this.DTProp", TDateTime(dt_this.AddMinutes(10)))); await EvaluateOnCallFrameFail(id0, ("obj", "ReferenceError")); } - // check frame1 - { + // check frame1 + { var id1 = pause_location["callFrames"][1]["callFrameId"].Value(); await EvaluateOnCallFrameAndCheck(id1, @@ -388,15 +388,15 @@ await EvaluateOnCallFrameAndCheck(id1, await EvaluateOnCallFrameFail(id1, ("obj", "ReferenceError")); } - // check frame2 - { + // check frame2 + { var id2 = pause_location["callFrames"][2]["callFrameId"].Value(); - // Only obj should be available - await EvaluateOnCallFrameFail(id2, - ("dateTime", "ReferenceError"), - ("this.dateTime", "ReferenceError"), - ("me", "ReferenceError")); + // Only obj should be available + await EvaluateOnCallFrameFail(id2, + ("dateTime", "ReferenceError"), + ("this.dateTime", "ReferenceError"), + ("me", "ReferenceError")); await EvaluateOnCallFrameAndCheck(id2, ("obj", is_valuetype ? TValueType(type_name) : TObject(type_name))); } @@ -405,32 +405,23 @@ await EvaluateOnCallFrameFail(id2, [Fact] public async Task JSEvaluate() { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); - var bp_loc = "/other.js"; var line = 76; var col = 1; - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - await SetBreakpoint(bp_loc, line, col); + await SetBreakpoint(bp_loc, line, col); - var eval_expr = "window.setTimeout(function() { eval_call_on_frame_test (); }, 1)"; - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + var eval_expr = "window.setTimeout(function() { eval_call_on_frame_test (); }, 1)"; + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - var id = pause_location["callFrames"][0]["callFrameId"].Value(); + var id = pause_location["callFrames"][0]["callFrameId"].Value(); - await EvaluateOnCallFrameFail(id, - ("me.foo", null), - ("obj.foo.bar", null)); + await EvaluateOnCallFrameFail(id, + ("me.foo", null), + ("obj.foo.bar", null)); - await EvaluateOnCallFrame(id, "obj.foo", expect_ok: true); - }); + await EvaluateOnCallFrame(id, "obj.foo", expect_ok: true); } [Fact] @@ -441,23 +432,23 @@ public async Task NegativeTestsInInstanceMethod() => await CheckInspectLocalsAtB { var id = pause_location["callFrames"][0]["callFrameId"].Value(); - // Use '.' on a primitive member - await EvaluateOnCallFrameFail(id, - //BUG: TODO: - //("a)", "CompilationError"), + // Use '.' on a primitive member + await EvaluateOnCallFrameFail(id, + //BUG: TODO: + //("a)", "CompilationError"), - ("this.a.", "ReferenceError"), - ("a.", "ReferenceError"), + ("this.a.", "ReferenceError"), + ("a.", "ReferenceError"), - ("this..a", "CompilationError"), - (".a.", "ReferenceError"), + ("this..a", "CompilationError"), + (".a.", "ReferenceError"), - ("me.foo", "ReferenceError"), + ("me.foo", "ReferenceError"), - ("this.a + non_existant", "ReferenceError"), + ("this.a + non_existant", "ReferenceError"), - ("this.NullIfAIsNotZero.foo", "ReferenceError"), - ("NullIfAIsNotZero.foo", "ReferenceError")); + ("this.NullIfAIsNotZero.foo", "ReferenceError"), + ("NullIfAIsNotZero.foo", "ReferenceError")); }); [Fact] diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs index 6f339c28ea90fd..1be0b18f325b59 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs @@ -16,102 +16,83 @@ public class ExceptionTests : DebuggerTestBase [Fact] public async Task ExceptionTestAll() { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); string entry_method_name = "[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions"; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-exception-test.cs"; - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - var debugger_test_loc = "dotnet://debugger-test.dll/debugger-exception-test.cs"; - - await SetPauseOnException("all"); + await SetPauseOnException("all"); - var eval_expr = "window.setTimeout(function() { invoke_static_method (" + - $"'{entry_method_name}'" + - "); }, 1);"; + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + + $"'{entry_method_name}'" + + "); }, 1);"; - var pause_location = await EvaluateAndCheck(eval_expr, null, 0, 0, null); - //stop in the managed caught exception - pause_location = await WaitForManagedException(pause_location); + var pause_location = await EvaluateAndCheck(eval_expr, null, 0, 0, null); + //stop in the managed caught exception + pause_location = await WaitForManagedException(pause_location); - AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value(), "pause0"); + AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value(), "pause0"); - await CheckValue(pause_location["data"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "DebuggerTests.CustomException", - uncaught = false - }), "exception0.data"); + await CheckValue(pause_location["data"], JObject.FromObject(new + { + type = "object", + subtype = "error", + className = "DebuggerTests.CustomException", + uncaught = false + }), "exception0.data"); - var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "not implemented caught"); + var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); + CheckString(exception_members, "message", "not implemented caught"); - pause_location = await WaitForManagedException(null); - AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value(), "pause1"); + pause_location = await WaitForManagedException(null); + AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value(), "pause1"); - //stop in the uncaught exception - CheckLocation(debugger_test_loc, 28, 16, scripts, pause_location["callFrames"][0]["location"]); + //stop in the uncaught exception + CheckLocation(debugger_test_loc, 28, 16, scripts, pause_location["callFrames"][0]["location"]); - await CheckValue(pause_location["data"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "DebuggerTests.CustomException", - uncaught = true - }), "exception1.data"); - - exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "not implemented uncaught"); - }); + await CheckValue(pause_location["data"], JObject.FromObject(new + { + type = "object", + subtype = "error", + className = "DebuggerTests.CustomException", + uncaught = true + }), "exception1.data"); + + exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); + CheckString(exception_members, "message", "not implemented uncaught"); } [Fact] public async Task JSExceptionTestAll() { - 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 SetPauseOnException("all"); - await SetPauseOnException("all"); + var eval_expr = "window.setTimeout(function () { exceptions_test (); }, 1)"; + var pause_location = await EvaluateAndCheck(eval_expr, null, 0, 0, "exception_caught_test", null, null); - var eval_expr = "window.setTimeout(function () { exceptions_test (); }, 1)"; - var pause_location = await EvaluateAndCheck(eval_expr, null, 0, 0, "exception_caught_test", null, null); - - Assert.Equal("exception", pause_location["reason"]); - await CheckValue(pause_location["data"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "TypeError", - uncaught = false - }), "exception0.data"); + Assert.Equal("exception", pause_location["reason"]); + await CheckValue(pause_location["data"], JObject.FromObject(new + { + type = "object", + subtype = "error", + className = "TypeError", + uncaught = false + }), "exception0.data"); - var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "exception caught"); + var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); + CheckString(exception_members, "message", "exception caught"); - pause_location = await SendCommandAndCheck(null, "Debugger.resume", null, 0, 0, "exception_uncaught_test"); + pause_location = await SendCommandAndCheck(null, "Debugger.resume", null, 0, 0, "exception_uncaught_test"); - Assert.Equal("exception", pause_location["reason"]); - await CheckValue(pause_location["data"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "RangeError", - uncaught = true - }), "exception1.data"); - - exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "exception uncaught"); - }); + Assert.Equal("exception", pause_location["reason"]); + await CheckValue(pause_location["data"], JObject.FromObject(new + { + type = "object", + subtype = "error", + className = "RangeError", + uncaught = true + }), "exception1.data"); + + exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); + CheckString(exception_members, "message", "exception uncaught"); } // FIXME? BUG? We seem to get the stack trace for Runtime.exceptionThrown at `call_method`, @@ -119,88 +100,69 @@ await CheckValue(pause_location["data"], JObject.FromObject(new [Fact] public async Task ExceptionTestNone() { - var insp = new Inspector(); //Collect events - var scripts = SubscribeToScripts(insp); string entry_method_name = "[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions"; + await SetPauseOnException("none"); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + + $"'{entry_method_name}'" + + "); }, 1);"; - await SetPauseOnException("none"); + try + { + await EvaluateAndCheck(eval_expr, null, 0, 0, "", null, null); + } + catch (ArgumentException ae) + { + var eo = JObject.Parse(ae.Message); - var eval_expr = "window.setTimeout(function() { invoke_static_method (" + - $"'{entry_method_name}'" + - "); }, 1);"; + // AssertEqual (line, eo ["exceptionDetails"]?["lineNumber"]?.Value (), "lineNumber"); + AssertEqual("Uncaught", eo["exceptionDetails"]?["text"]?.Value(), "text"); - try - { - await EvaluateAndCheck(eval_expr, null, 0, 0, "", null, null); - } - catch (ArgumentException ae) + await CheckValue(eo["exceptionDetails"]?["exception"], JObject.FromObject(new { - var eo = JObject.Parse(ae.Message); - - // AssertEqual (line, eo ["exceptionDetails"]?["lineNumber"]?.Value (), "lineNumber"); - AssertEqual("Uncaught", eo["exceptionDetails"]?["text"]?.Value(), "text"); - - await CheckValue(eo["exceptionDetails"]?["exception"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "Error" // BUG?: "DebuggerTests.CustomException" - }), "exception"); + type = "object", + subtype = "error", + className = "Error" // BUG?: "DebuggerTests.CustomException" + }), "exception"); - return; - } + return; + } - Assert.True(false, "Expected to get an ArgumentException from the uncaught user exception"); - }); + Assert.True(false, "Expected to get an ArgumentException from the uncaught user exception"); } [Fact] public async Task JSExceptionTestNone() { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); + await SetPauseOnException("none"); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); + var eval_expr = "window.setTimeout(function () { exceptions_test (); }, 1)"; - await SetPauseOnException("none"); + int line = 44; + try + { + await EvaluateAndCheck(eval_expr, null, 0, 0, "", null, null); + } + catch (ArgumentException ae) + { + Console.WriteLine($"{ae}"); + var eo = JObject.Parse(ae.Message); - var eval_expr = "window.setTimeout(function () { exceptions_test (); }, 1)"; + AssertEqual(line, eo["exceptionDetails"]?["lineNumber"]?.Value(), "lineNumber"); + AssertEqual("Uncaught", eo["exceptionDetails"]?["text"]?.Value(), "text"); - int line = 44; - try - { - await EvaluateAndCheck(eval_expr, null, 0, 0, "", null, null); - } - catch (ArgumentException ae) + await CheckValue(eo["exceptionDetails"]?["exception"], JObject.FromObject(new { - Console.WriteLine($"{ae}"); - var eo = JObject.Parse(ae.Message); - - AssertEqual(line, eo["exceptionDetails"]?["lineNumber"]?.Value(), "lineNumber"); - AssertEqual("Uncaught", eo["exceptionDetails"]?["text"]?.Value(), "text"); - - await CheckValue(eo["exceptionDetails"]?["exception"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = "RangeError" - }), "exception"); + type = "object", + subtype = "error", + className = "RangeError" + }), "exception"); - return; - } + return; + } - Assert.True(false, "Expected to get an ArgumentException from the uncaught user exception"); - }); + Assert.True(false, "Expected to get an ArgumentException from the uncaught user exception"); } [Theory] @@ -211,31 +173,22 @@ await CheckValue(eo["exceptionDetails"]?["exception"], JObject.FromObject(new public async Task ExceptionTestUncaught(string eval_fn, string loc, int line, int col, string fn_name, string exception_type, string exception_message) { - 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 SetPauseOnException("uncaught"); + await SetPauseOnException("uncaught"); - var eval_expr = $"window.setTimeout({eval_fn}, 1);"; - var pause_location = await EvaluateAndCheck(eval_expr, loc, line, col, fn_name); + var eval_expr = $"window.setTimeout({eval_fn}, 1);"; + var pause_location = await EvaluateAndCheck(eval_expr, loc, line, col, fn_name); - Assert.Equal("exception", pause_location["reason"]); - await CheckValue(pause_location["data"], JObject.FromObject(new - { - type = "object", - subtype = "error", - className = exception_type, - uncaught = true - }), "exception.data"); - - var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", exception_message); - }); + Assert.Equal("exception", pause_location["reason"]); + await CheckValue(pause_location["data"], JObject.FromObject(new + { + type = "object", + subtype = "error", + className = exception_type, + uncaught = true + }), "exception.data"); + + var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); + CheckString(exception_members, "message", exception_message); } async Task WaitForManagedException(JObject pause_location) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs index 2f35e8cfdc0e09..3215ef1184d89c 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs @@ -188,7 +188,7 @@ public async Task InspectTypeInheritedMembers(string type_name, bool? own_proper }); public static IEnumerable MembersForLocalNestedStructData(bool is_async) - => StructGetPropertiesTestData(false).Select (datum => datum [1..]); + => StructGetPropertiesTestData(false).Select(datum => datum[1..]); [Theory] [MemberData(nameof(MembersForLocalNestedStructData), parameters: false)] @@ -217,7 +217,7 @@ public async Task MembersForLocalNestedStruct(bool? own_properties, bool? access AssertEqual(expected_names.Length, cs_props.Count(), $"expected number of properties"); }); - public static TheoryData JSGetPropertiesTestData(bool test_js)=> new TheoryData + public static TheoryData JSGetPropertiesTestData(bool test_js) => new TheoryData { // default, no args set { @@ -282,49 +282,40 @@ public async Task MembersForLocalNestedStruct(bool? own_properties, bool? access // [MemberData(nameof(JSGetPropertiesTestData), parameters: false)] public async Task GetPropertiesTestJSAndManaged(bool test_js, bool? own_properties, bool? accessors_only, string[] expected_names) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); - - - await Ready(); - await insp.Ready(async (cli, token) => + string eval_expr; + if (test_js) { - ctx = new DebugTestContext(cli, insp, token, scripts); - string eval_expr; - if (test_js) - { - await SetBreakpoint("/other.js", 93, 1); - eval_expr = "window.setTimeout(function() { get_properties_test (); }, 1)"; - } - else - { - await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.GetPropertiesTests.DerivedClassForJSTest", "run", 2); - eval_expr = "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.GetPropertiesTests.DerivedClassForJSTest:run'); }, 1)"; - } + await SetBreakpoint("/other.js", 93, 1); + eval_expr = "window.setTimeout(function() { get_properties_test (); }, 1)"; + } + else + { + await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.GetPropertiesTests.DerivedClassForJSTest", "run", 2); + eval_expr = "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.GetPropertiesTests.DerivedClassForJSTest:run'); }, 1)"; + } - var result = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), ctx.token); - var pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); + var result = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = eval_expr }), token); + var pause_location = await insp.WaitFor(Inspector.PAUSE); - var id = pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value(); + var id = pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value(); - var frame_locals = await GetProperties(id); - var obj = GetAndAssertObjectWithName(frame_locals, "obj"); - var obj_props = await GetProperties(obj["value"]?["objectId"]?.Value(), - own_properties: own_properties, accessors_only: accessors_only); + var frame_locals = await GetProperties(id); + var obj = GetAndAssertObjectWithName(frame_locals, "obj"); + var obj_props = await GetProperties(obj["value"]?["objectId"]?.Value(), + own_properties: own_properties, accessors_only: accessors_only); - IEnumerable filtered_props; - if (test_js) - { - filtered_props = obj_props.Children().Where(jt => jt["enumerable"]?.Value() == true); - } - else - { - // we don't set `enumerable` right now - filtered_props = obj_props.Children().Where(jt=> true); - } + IEnumerable filtered_props; + if (test_js) + { + filtered_props = obj_props.Children().Where(jt => jt["enumerable"]?.Value() == true); + } + else + { + // we don't set `enumerable` right now + filtered_props = obj_props.Children().Where(jt => true); + } - var expected_props = new Dictionary () + var expected_props = new Dictionary() { // own {"owner_name", (TString("foo"), true)}, @@ -336,13 +327,12 @@ await insp.Ready(async (cli, token) => {"available", (TGetter("available"), false)}, }; - await CheckExpectedProperties( - expected_names, - name => filtered_props.Where(jt => jt["name"]?.Value () == name).SingleOrDefault(), - expected_props); + await CheckExpectedProperties( + expected_names, + name => filtered_props.Where(jt => jt["name"]?.Value() == name).SingleOrDefault(), + expected_props); - AssertEqual(expected_names.Length, filtered_props.Count(), $"expected number of properties"); - }); + AssertEqual(expected_names.Length, filtered_props.Count(), $"expected number of properties"); } private async Task CheckExpectedProperties(string[] expected_names, Func get_actual_prop, Dictionary all_props) @@ -356,7 +346,7 @@ private async Task CheckExpectedProperties(string[] expected_names, Func () == true, $"{exp_name}#isOwn"); + AssertEqual(is_own, actual_prop["isOwn"]?.Value() == true, $"{exp_name}#isOwn"); if (exp_prop["__custom_type"]?.Value() == "getter") { @@ -373,14 +363,14 @@ private async Task CheckExpectedProperties(string[] expected_names, Func actual) + private static void AssertHasOnlyExpectedProperties(string[] expected_names, IEnumerable actual) { var exp = new HashSet(expected_names); foreach (var obj in actual) { - if (!exp.Contains(obj["name"]?.Value ())) - Console.WriteLine ($"Unexpected: {obj}"); + if (!exp.Contains(obj["name"]?.Value())) + Console.WriteLine($"Unexpected: {obj}"); } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs index a89e5ceb533530..2d72d66f3c3283 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs @@ -12,7 +12,7 @@ namespace DebuggerTests { - public class HarnessTests : SingleSessionTestBase + public class HarnessTests : DebuggerTestBase { [Fact] public async Task TimedOutWaitingForInvalidBreakpoint() @@ -42,10 +42,10 @@ public async Task InspectorWaitForAfterMessageAlreadyReceived() Result res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); Assert.True(res.IsOk, $"setBreakpoint failed with {res}"); - res = await ctx.cli.SendCommand( + res = await cli.SendCommand( "Runtime.evaluate", JObject.FromObject(new { expression = "window.setTimeout(function() { invoke_add(); }, 0);" }), - ctx.token); + token); Assert.True(res.IsOk, $"evaluating the function failed with {res}"); // delay, so that we can get the Debugger.pause event diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs index fe526ab06a3cd6..e7001473792669 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs @@ -131,40 +131,6 @@ async Task OnMessage(string method, JObject args, CancellationToken token) } } - public async Task Ready(Func? cb = null, TimeSpan? span = null) - { - try - { - Func)>> fn = (_client, _token) => - { - Func)> getInitCmdFn = (cmd_name) => (cmd_name, _client.SendCommand(cmd_name, null, _token)); - return new List<(string, Task)> - { - getInitCmdFn("Profiler.enable"), - getInitCmdFn("Runtime.enable"), - getInitCmdFn("Debugger.enable"), - getInitCmdFn("Runtime.runIfWaitingForDebugger") - }; - }; - - await OpenSessionAsync(fn, span); - if (cb != null) - await cb(Client, _cancellationTokenSource.Token).ConfigureAwait(false); - } - catch (Exception ex) - { - if (_logger != null) - _logger.LogError(ex.ToString()); - else - Console.WriteLine(ex); - throw; - } - finally - { - await ShutdownAsync().ConfigureAwait(false); - } - } - public async Task OpenSessionAsync(Func)>> getInitCmds, TimeSpan? span = null) { var start = DateTime.Now; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs index 892fe613f591c2..e2b796062e3086 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs @@ -1,3 +1,6 @@ +// 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.IO; using System.Linq; @@ -13,146 +16,111 @@ public class MonoJsTests : DebuggerTestBase [Fact] public async Task FixupNameValueObjectsWithMissingParts() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); + var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); - await Ready(); - await insp.Ready(async (cli, token) => + var names = new JObject[] { - ctx = new DebugTestContext(cli, insp, token, scripts); - - var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); - - var names = new JObject[] - { JObject.FromObject(new { name = "Abc" }), JObject.FromObject(new { name = "Def" }), JObject.FromObject(new { name = "Xyz" }) - }; + }; - var values = new JObject[] - { + var values = new JObject[] + { JObject.FromObject(new { value = TObject("testclass") }), JObject.FromObject(new { value = TString("test string") }), - }; + }; - var getters = new JObject[] - { + var getters = new JObject[] + { GetterRes("xyz"), GetterRes("unattached") - }; + }; - var list = new[] { names[0], names[1], values[0], names[2], getters[0], getters[1] }; - var res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression = $"MONO._fixup_name_value_objects({JsonConvert.SerializeObject(list)})", returnByValue = true }), ctx.token); - Assert.True(res.IsOk); + var list = new[] { names[0], names[1], values[0], names[2], getters[0], getters[1] }; + var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression = $"MONO._fixup_name_value_objects({JsonConvert.SerializeObject(list)})", returnByValue = true }), token); + Assert.True(res.IsOk); - await CheckProps(res.Value["result"]["value"], new - { - Abc = TSymbol(""), - Def = TObject("testclass"), - Xyz = TGetter("xyz") - }, "#1", num_fields: 4); + await CheckProps(res.Value["result"]["value"], new + { + Abc = TSymbol(""), + Def = TObject("testclass"), + Xyz = TGetter("xyz") + }, "#1", num_fields: 4); - JObject.DeepEquals(getters[1], res.Value["result"]["value"].Values().ToArray()[3]); + JObject.DeepEquals(getters[1], res.Value["result"]["value"].Values().ToArray()[3]); - JObject GetterRes(string name) => JObject.FromObject(new + static JObject GetterRes(string name) => JObject.FromObject(new + { + get = new { - get = new - { - className = "Function", - description = $"get {name} () {{}}", - type = "function" - } - }); + className = "Function", + description = $"get {name} () {{}}", + type = "function" + } }); } [Fact] public async Task GetParamsAndLocalsWithInvalidIndices() { - 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 SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); - var pause_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", - null, -1, -1, "IntAdd"); + var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", + null, -1, -1, "IntAdd"); - var scope_id = pause_location["callFrames"][0]["callFrameId"].Value(); - var scope = int.Parse(scope_id.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[2]); + var scope_id = pause_location["callFrames"][0]["callFrameId"].Value(); + var scope = int.Parse(scope_id.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[2]); - var var_ids = new[] - { + var var_ids = new[] + { new { index = 0, name = "one" }, new { index = -12, name = "bad0" }, new { index = 1231, name = "bad1" } }; - var expression = $"MONO.mono_wasm_get_variables({scope}, {JsonConvert.SerializeObject(var_ids)})"; + var expression = $"MONO.mono_wasm_get_variables({scope}, {JsonConvert.SerializeObject(var_ids)})"; - var res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), ctx.token); - Assert.True(res.IsOk); + var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); + Assert.True(res.IsOk); - await CheckProps(res.Value["result"]?["value"], new - { - one = TNumber(3), - bad0 = TSymbol(""), - bad1 = TSymbol("") - }, "results"); - }); + await CheckProps(res.Value["result"]?["value"], new + { + one = TNumber(3), + bad0 = TSymbol(""), + bad1 = TSymbol("") + }, "results"); } [Fact] public async Task InvalidScopeId() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); + var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", + null, -1, -1, "IntAdd"); - await Ready(); - await insp.Ready(async (cli, token) => + var var_ids = new[] { - ctx = new DebugTestContext(cli, insp, token, scripts); - - var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); - await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", - null, -1, -1, "IntAdd"); - - var var_ids = new[] - { new { index = 0, name = "one" }, }; - var scope_id = "-12"; - var expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; - var res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), ctx.token); - Assert.False(res.IsOk); + var scope_id = "-12"; + var expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; + var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); + Assert.False(res.IsOk); - scope_id = "30000"; - expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; - res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), ctx.token); - Assert.False(res.IsOk); - }); + scope_id = "30000"; + expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; + res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); + Assert.False(res.IsOk); } [Fact] public async Task BadRaiseDebugEventsTest() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); - - await Ready(); - await insp.Ready(async (cli, token) => + var bad_expressions = new[] { - ctx = new DebugTestContext(cli, insp, token, scripts); - - var bad_expressions = new[] - { "MONO.mono_wasm_raise_debug_event('')", "MONO.mono_wasm_raise_debug_event(undefined)", "MONO.mono_wasm_raise_debug_event({})", @@ -161,17 +129,16 @@ await insp.Ready(async (cli, token) => "MONO.mono_wasm_raise_debug_event({eventName:'foo'}, 12)" }; - foreach (var expression in bad_expressions) - { - var res = await ctx.cli.SendCommand($"Runtime.evaluate", - JObject.FromObject(new - { - expression, - returnByValue = true - }), ctx.token); - Assert.False(res.IsOk, $"Expected to fail for {expression}"); - } - }); + foreach (var expression in bad_expressions) + { + var res = await cli.SendCommand($"Runtime.evaluate", + JObject.FromObject(new + { + expression, + returnByValue = true + }), token); + Assert.False(res.IsOk, $"Expected to fail for {expression}"); + } } [Theory] @@ -180,38 +147,30 @@ await insp.Ready(async (cli, token) => [InlineData(null)] public async Task RaiseDebugEventTraceTest(bool? trace) { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); - - await Ready(); - await insp.Ready(async (cli, token) => + var tcs = new TaskCompletionSource(); + insp.On("Runtime.consoleAPICalled", async (args, token) => { - ctx = new DebugTestContext(cli, insp, token, scripts); - - var tcs = new TaskCompletionSource(); - insp.On("Runtime.consoleAPICalled", async (args, token) => { - if (args?["type"]?.Value() == "debug" && - args?["args"]?.Type == JTokenType.Array && - args?["args"]?[0]?["value"]?.Value()?.StartsWith("mono_wasm_debug_event_raised:") == true) - { - tcs.SetResult(true); - } + if (args?["type"]?.Value() == "debug" && + args?["args"]?.Type == JTokenType.Array && + args?["args"]?[0]?["value"]?.Value()?.StartsWith("mono_wasm_debug_event_raised:") == true) + { + tcs.SetResult(true); + } - await Task.CompletedTask; - }); + await Task.CompletedTask; + }); - var trace_str = trace.HasValue ? $"trace: {trace.ToString().ToLower()}" : String.Empty; - var expression = $"MONO.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; - var res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), ctx.token); - Assert.True(res.IsOk, $"Expected to pass for {expression}"); + var trace_str = trace.HasValue ? $"trace: {trace.ToString().ToLower()}" : String.Empty; + var expression = $"MONO.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; + var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); + Assert.True(res.IsOk, $"Expected to pass for {expression}"); - var t = await Task.WhenAny(tcs.Task, Task.Delay(2000)); + var t = await Task.WhenAny(tcs.Task, Task.Delay(2000)); - if (trace == true) - Assert.True(tcs.Task == t, "Timed out waiting for the event to be logged"); - else - Assert.False(tcs.Task == t, "Event should not have been logged"); - }); + if (trace == true) + Assert.True(tcs.Task == t, "Timed out waiting for the event to be logged"); + else + Assert.False(tcs.Task == t, "Event should not have been logged"); } [Theory] @@ -250,8 +209,6 @@ public async Task DuplicateAssemblyLoadedEventWithEmbeddedPdbNotLoadedFromBundle async Task AssemblyLoadedEventTest(string asm_name, string asm_path, string pdb_path, string source_file, int expected_count) { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); int event_count = 0; var tcs = new TaskCompletionSource(); @@ -262,7 +219,7 @@ async Task AssemblyLoadedEventTest(string asm_name, string asm_path, string pdb_ var url = args["url"]?.Value(); if (url?.EndsWith(source_file) == true) { - event_count ++; + event_count++; if (event_count > expected_count) tcs.SetResult(false); } @@ -275,40 +232,34 @@ async Task AssemblyLoadedEventTest(string asm_name, string asm_path, string pdb_ await Task.CompletedTask; }); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - - byte[] bytes = File.ReadAllBytes(asm_path); - string asm_base64 = Convert.ToBase64String(bytes); + byte[] bytes = File.ReadAllBytes(asm_path); + string asm_base64 = Convert.ToBase64String(bytes); - string pdb_base64 = String.Empty; - if (pdb_path != null) - { - bytes = File.ReadAllBytes(pdb_path); - pdb_base64 = Convert.ToBase64String(bytes); - } + string pdb_base64 = String.Empty; + if (pdb_path != null) + { + bytes = File.ReadAllBytes(pdb_path); + pdb_base64 = Convert.ToBase64String(bytes); + } - var expression = $@"MONO.mono_wasm_raise_debug_event({{ + var expression = $@"MONO.mono_wasm_raise_debug_event({{ eventName: 'AssemblyLoaded', assembly_name: '{asm_name}', assembly_b64: '{asm_base64}', pdb_b64: '{pdb_base64}' }});"; - var res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), ctx.token); - Assert.True(res.IsOk, $"Expected to pass for {expression}"); + var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); + Assert.True(res.IsOk, $"Expected to pass for {expression}"); - res = await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), ctx.token); - Assert.True(res.IsOk, $"Expected to pass for {expression}"); + res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); + Assert.True(res.IsOk, $"Expected to pass for {expression}"); - var t = await Task.WhenAny(tcs.Task, Task.Delay(2000)); - if (t.IsFaulted) - throw t.Exception; + var t = await Task.WhenAny(tcs.Task, Task.Delay(2000)); + if (t.IsFaulted) + throw t.Exception; - Assert.True(event_count <= expected_count, $"number of scriptParsed events received. Expected: {expected_count}, Actual: {event_count}"); - }); + Assert.True(event_count <= expected_count, $"number of scriptParsed events received. Expected: {expected_count}, Actual: {event_count}"); } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SingleSessionTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SingleSessionTestBase.cs deleted file mode 100644 index ec765d575bb6f3..00000000000000 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SingleSessionTestBase.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.WebAssembly.Diagnostics; -using Xunit; - -#nullable enable - -namespace DebuggerTests -{ - public abstract class SingleSessionTestBase : DebuggerTestBase, IAsyncLifetime - { - internal Inspector insp; - protected Dictionary scripts; - - public SingleSessionTestBase(string driver = "debugger-driver.html") : base(driver) - { - insp = new Inspector(); - scripts = SubscribeToScripts(insp); - } - - public virtual async Task InitializeAsync() - { - Func)>> fn = (client, token) => - { - Func)> getInitCmdFn = (cmd) => (cmd, client.SendCommand(cmd, null, token)); - var init_cmds = new List<(string, Task)> - { - getInitCmdFn("Profiler.enable"), - getInitCmdFn("Runtime.enable"), - getInitCmdFn("Debugger.enable"), - getInitCmdFn("Runtime.runIfWaitingForDebugger") - }; - - return init_cmds; - }; - - await Ready(); - await insp.OpenSessionAsync(fn); - ctx = new DebugTestContext(insp.Client, insp, insp.Token, scripts); - } - - public virtual async Task DisposeAsync() => await insp.ShutdownAsync().ConfigureAwait(false); - } -} diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs index d966320ded0f6e..a5da24b3691031 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs @@ -1,3 +1,6 @@ +// 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; @@ -6,7 +9,7 @@ namespace DebuggerTests { - public class SteppingTests : SingleSessionTestBase + public class SteppingTests : DebuggerTestBase { [Fact] public async Task TrivalStepping() @@ -86,7 +89,7 @@ await StepAndCheck(StepKind.Over, debugger_test_loc, 12, 8, "IntAdd", [InlineData(true)] public async Task InspectLocalsInPreviousFramesDuringSteppingIn2(bool use_cfo) { - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + UseCallFunctionOnBeforeGetProperties = use_cfo; var dep_cs_loc = "dotnet://debugger-test.dll/dependency.cs"; await SetBreakpoint(dep_cs_loc, 33, 8); @@ -153,7 +156,7 @@ public async Task InspectLocalsInPreviousFramesDuringSteppingIn2(bool use_cfo) [InlineData(true)] public async Task InspectLocalsInPreviousFramesDuringSteppingIn(bool use_cfo) { - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + UseCallFunctionOnBeforeGetProperties = use_cfo; var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs"; await SetBreakpoint(debugger_test_loc, 111, 12); @@ -313,7 +316,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", [InlineData(true)] public async Task InspectLocalsInAsyncMethods(bool use_cfo) { - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + UseCallFunctionOnBeforeGetProperties = use_cfo; var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs"; await SetBreakpoint(debugger_test_loc, 120, 12); @@ -369,7 +372,7 @@ public async Task InspectLocalsInAsyncMethods(bool use_cfo) [InlineData(true)] public async Task InspectValueTypeMethodArgsWhileStepping(bool use_cfo) { - ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; + UseCallFunctionOnBeforeGetProperties = use_cfo; var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; await SetBreakpoint(debugger_test_loc, 36, 12); @@ -610,7 +613,7 @@ public async Task SteppingIntoMscorlib() AssertEqual("WriteLine", top_frame["functionName"]?.Value(), "Expected to be in WriteLine method"); var script_id = top_frame["functionLocation"]["scriptId"].Value(); - Assert.Matches ("^dotnet://(mscorlib|System\\.Console)\\.dll/Console.cs", scripts[script_id]); + Assert.Matches("^dotnet://(mscorlib|System\\.Console)\\.dll/Console.cs", scripts[script_id]); } [Fact] @@ -620,7 +623,7 @@ public async Task CreateGoodBreakpointAndHitAndRemoveAndDontHit() var bp2 = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 12, 8); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); invoke_add()}, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, "IntAdd"); Assert.Equal("other", pause_location["reason"]?.Value()); @@ -638,7 +641,7 @@ public async Task CreateGoodBreakpointAndHitAndRemoveTwice() var bp2 = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 12, 8); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); invoke_add()}, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, "IntAdd"); Assert.Equal("other", pause_location["reason"]?.Value()); @@ -655,7 +658,7 @@ public async Task CreateGoodBreakpointAndHitAndRemoveAndDontHitAndCreateAgainAnd var bp2 = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 12, 8); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); invoke_add(); invoke_add(); invoke_add()}, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, "IntAdd"); Assert.Equal("other", pause_location["reason"]?.Value()); @@ -845,7 +848,7 @@ await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] HiddenSequencePointTest:StepOverHiddenSP'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", 546, 4, "StepOverHiddenSP2"); - } + } [Fact] public async Task BreakpointOnHiddenLineOfMethodWithNoNextVisibleLineShouldNotPause() @@ -853,7 +856,7 @@ public async Task BreakpointOnHiddenLineOfMethodWithNoNextVisibleLineShouldNotPa await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 554, 12); string expression = "window.setTimeout(function() { invoke_static_method ('[debugger-test] HiddenSequencePointTest:StepOverHiddenSP'); }, 1);"; - await ctx.cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), ctx.token); + await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); Task pause_task = insp.WaitFor(Inspector.PAUSE); Task t = await Task.WhenAny(pause_task, Task.Delay(2000)); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs index 84a313f5dd7f74..1b7657ddb87cd0 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs @@ -18,15 +18,8 @@ public class SourceList : DebuggerTestBase { [Fact] - public async Task CheckThatAllSourcesAreSent() + public void 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://debugger-test.dll/dependency.cs", scripts.Values); @@ -35,106 +28,74 @@ public async Task CheckThatAllSourcesAreSent() [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", 10, 8); + var bp1_res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); - Assert.EndsWith("debugger-test.cs", bp1_res.Value["breakpointId"].ToString()); - Assert.Equal(1, bp1_res.Value["locations"]?.Value()?.Count); + Assert.EndsWith("debugger-test.cs", bp1_res.Value["breakpointId"].ToString()); + Assert.Equal(1, bp1_res.Value["locations"]?.Value()?.Count); - var loc = bp1_res.Value["locations"]?.Value()[0]; + var loc = bp1_res.Value["locations"]?.Value()[0]; - Assert.NotNull(loc["scriptId"]); - Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts[loc["scriptId"]?.Value()]); - Assert.Equal(10, loc["lineNumber"]); - Assert.Equal(8, loc["columnNumber"]); - }); + Assert.NotNull(loc["scriptId"]); + Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts[loc["scriptId"]?.Value()]); + Assert.Equal(10, loc["lineNumber"]); + Assert.Equal(8, 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); + // 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()?.Count); + Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); + Assert.Equal(1, bp1_res.Value["locations"]?.Value()?.Count); - var loc = bp1_res.Value["locations"]?.Value()[0]; + var loc = bp1_res.Value["locations"]?.Value()[0]; - Assert.NotNull(loc["scriptId"]); - Assert.Equal(13, loc["lineNumber"]); - Assert.Equal(24, loc["columnNumber"]); + Assert.NotNull(loc["scriptId"]); + Assert.Equal(13, loc["lineNumber"]); + Assert.Equal(24, loc["columnNumber"]); - var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31); + 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()?.Count); + Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); + Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); - var loc2 = bp2_res.Value["locations"]?.Value()[0]; + var loc2 = bp2_res.Value["locations"]?.Value()[0]; - Assert.NotNull(loc2["scriptId"]); - Assert.Equal(13, loc2["lineNumber"]); - Assert.Equal(31, loc2["columnNumber"]); - }); + 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); + // 13 24 + // 13 31 + var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 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, 0); + Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); + Assert.Equal(1, bp1_res.Value["locations"]?.Value()?.Count); - Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); - Assert.Equal(1, bp1_res.Value["locations"]?.Value()?.Count); + var loc = bp1_res.Value["locations"]?.Value()[0]; - var loc = bp1_res.Value["locations"]?.Value()[0]; + Assert.NotNull(loc["scriptId"]); + Assert.Equal(13, loc["lineNumber"]); + Assert.Equal(24, loc["columnNumber"]); - Assert.NotNull(loc["scriptId"]); - Assert.Equal(13, loc["lineNumber"]); - Assert.Equal(24, loc["columnNumber"]); + var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31); - 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()?.Count); - Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); - Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); + var loc2 = bp2_res.Value["locations"]?.Value()[0]; - var loc2 = bp2_res.Value["locations"]?.Value()[0]; - - Assert.NotNull(loc2["scriptId"]); - Assert.Equal(13, loc2["lineNumber"]); - Assert.Equal(31, loc2["columnNumber"]); - }); + Assert.NotNull(loc2["scriptId"]); + Assert.Equal(13, loc2["lineNumber"]); + Assert.Equal(31, loc2["columnNumber"]); } [Theory] @@ -142,160 +103,109 @@ await insp.Ready(async (cli, token) => [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()?.Count); + 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()?.Count); - var loc = bp1_res.Value["locations"]?.Value()[0]; + var loc = bp1_res.Value["locations"]?.Value()[0]; - CheckLocation("dotnet://debugger-test.dll/debugger-array-test.cs", 219, 50, scripts, loc); + 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()?.Count); + 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()?.Count); - var loc2 = bp2_res.Value["locations"]?.Value()[0]; + var loc2 = bp2_res.Value["locations"]?.Value()[0]; - CheckLocation("dotnet://debugger-test.dll/debugger-array-test.cs", 219, 55, scripts, loc2); - }); + 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 { - var bp1_req = JObject.FromObject(new - { - lineNumber = 8, - columnNumber = 2, - url = "dotnet://debugger-test.dll/this-file-doesnt-exist.cs", - }); + 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); + var bp1_res = await cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, token); - Assert.True(bp1_res.IsOk); - Assert.Empty(bp1_res.Value["locations"].Values()); - //Assert.Equal ((int)MonoErrorCodes.BpNotFound, bp1_res.Error ["code"]?.Value ()); - }); + Assert.True(bp1_res.IsOk); + Assert.Empty(bp1_res.Value["locations"].Values()); + //Assert.Equal ((int)MonoErrorCodes.BpNotFound, bp1_res.Error ["code"]?.Value ()); } [Fact] public async Task CreateGoodBreakpointAndHit() { - var insp = new Inspector(); - - //Collect events - var scripts = SubscribeToScripts(insp); + var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); - await Ready(); - await insp.Ready(async (cli, token) => + var eval_req = JObject.FromObject(new { - ctx = new DebugTestContext(cli, insp, token, scripts); - - var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); + expression = "window.setTimeout(function() { invoke_add(); }, 1);", + }); - var eval_req = JObject.FromObject(new + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_add(); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "IntAdd", + wait_for_event_fn: (pause_location) => { - 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()); - Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); - - var top_frame = pause_location["callFrames"][0]; - Assert.Equal("IntAdd", top_frame["functionName"].Value()); - Assert.Contains("debugger-test.cs", top_frame["url"].Value()); + Assert.Equal("other", pause_location["reason"]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); - CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); + var top_frame = pause_location["callFrames"][0]; + Assert.Equal("IntAdd", top_frame["functionName"].Value()); + Assert.Contains("debugger-test.cs", top_frame["url"].Value()); - //now check the scope - var scope = top_frame["scopeChain"][0]; - Assert.Equal("local", scope["type"]); - Assert.Equal("IntAdd", scope["name"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); - Assert.Equal("object", scope["object"]["type"]); - 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; - } - ); + //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"]); + 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 { - 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()); + 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()); } [Fact] public async Task ExceptionThrownInJSOutOfBand() { - var insp = new Inspector(); - - //Collect events - var scripts = SubscribeToScripts(insp); + await SetBreakpoint("/debugger-driver.html", 27, 2); - await Ready(); - await insp.Ready(async (cli, token) => + var eval_req = JObject.FromObject(new { - 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);", - }); + expression = "window.setTimeout(function() { invoke_bad_js_test(); }, 1);", + }); - var task = insp.WaitFor("Runtime.exceptionThrown"); - 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 task = insp.WaitFor("Runtime.exceptionThrown"); + 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(async () => await task); - var ex_json = JObject.Parse(ex.Message); - Assert.Equal(dicFileToUrl["/debugger-driver.html"], ex_json["exceptionDetails"]?["url"]?.Value()); - }); + var ex = await Assert.ThrowsAsync(async () => await task); + var ex_json = JObject.Parse(ex.Message); + Assert.Equal(dicFileToUrl["/debugger-driver.html"], ex_json["exceptionDetails"]?["url"]?.Value()); } [Theory] @@ -409,25 +319,25 @@ public async Task InspectNullableLocals(string method_name, bool is_async) => aw var dt = new DateTime(2310, 1, 2, 3, 4, 5); await CheckProps(locals, new { - n_int = TNumber(5), - n_int_null = TObject("System.Nullable", null), + n_int = TNumber(5), + n_int_null = TObject("System.Nullable", null), - n_dt = TDateTime(dt), - n_dt_null = TObject("System.Nullable", null), + n_dt = TDateTime(dt), + n_dt_null = TObject("System.Nullable", null), - n_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - n_gs_null = TObject("System.Nullable>", null), + n_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + n_gs_null = TObject("System.Nullable>", null), }, "locals"); // check gs var n_gs = GetAndAssertObjectWithName(locals, "n_gs"); - var n_gs_props = await GetProperties(n_gs["value"]?["objectId"]?.Value ()); + var n_gs_props = await GetProperties(n_gs["value"]?["objectId"]?.Value()); await CheckProps(n_gs_props, new { - List = TObject("System.Collections.Generic.List", is_null: true), + List = TObject("System.Collections.Generic.List", is_null: true), StringField = TString("n_gs#StringField"), - Options = TEnum ("DebuggerTests.Options", "None") + Options = TEnum("DebuggerTests.Options", "None") }, nameof(n_gs)); }); @@ -459,41 +369,31 @@ await CheckInspectLocalsAtBreakpointSite( [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); + 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()); + 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()); - var top_frame = pause_location["callFrames"][0]; + var top_frame = pause_location["callFrames"][0]; - var scope = top_frame["scopeChain"][0]; + var scope = top_frame["scopeChain"][0]; - // Try to get an invalid scope! - var get_prop_req = JObject.FromObject(new - { - objectId = "dotnet:scope:23490871", - }); + // 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); - } - ); - }); + var frame_props = await cli.SendCommand("Runtime.getProperties", get_prop_req, token); + Assert.True(frame_props.IsErr); + } + ); } [Theory] @@ -501,99 +401,90 @@ await EvaluateAndCheck( [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()); - await CheckProps(locals, new - { - ss_local = TValueType("DebuggerTests.ValueTypesTest.SimpleStruct"), - gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - vt_local = TObject("DebuggerTests.ValueTypesTest") - }, "locals"); + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; - 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()); + await SetBreakpoint(debugger_test_loc, 24, 8); - 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"); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_method_with_structs(); }, 1);", + debugger_test_loc, 24, 8, "MethodWithLocalStructs"); - // 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 = TDateTime(dt), - gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - Kind = TEnum("System.DateTimeKind", "Utc") - }, "ss_local"); + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + await CheckProps(locals, new + { + ss_local = TValueType("DebuggerTests.ValueTypesTest.SimpleStruct"), + gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + 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 = TDateTime(dt), + gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + 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"); + { + var gres = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_local"), "V"); + await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + 2), $"ss_local#V"); - // 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"); - } + // 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"); + } - // 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#StringField"), - List = TObject("System.Collections.Generic.List", is_null: true), - Options = TEnum("DebuggerTests.Options", "None") - }, "gs_local"); + // 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#StringField"), + List = TObject("System.Collections.Generic.List", is_null: true), + Options = TEnum("DebuggerTests.Options", "None") + }, "gs_local"); - // Check vt_local's properties + // Check vt_local's properties - var exp = new[] - { + 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); - await CompareObjectPropertiesFor(vt_local_props, name, - new - { - V = TGetter("V"), - str_member = TString($"{name}#string#0#SimpleStruct#str_member"), - dt = TDateTime(dt), - gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - Kind = TEnum("System.DateTimeKind", dt_kind) - }, - label: $"vt_local_props.{name}"); - - var gres = await InvokeGetter(GetAndAssertObjectWithName(vt_local_props, name), "V"); - await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + (uint)dt.Month), $"{name}#V"); - } + foreach (var (name, bias, dt_kind) in exp) + { + dt = new DateTime(2020 + bias, 1 + bias, 2 + bias, 3 + bias, 5 + bias, 6 + bias); + await CompareObjectPropertiesFor(vt_local_props, name, + new + { + V = TGetter("V"), + str_member = TString($"{name}#string#0#SimpleStruct#str_member"), + dt = TDateTime(dt), + gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + Kind = TEnum("System.DateTimeKind", dt_kind) + }, + label: $"vt_local_props.{name}"); + + 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 - }); + // FIXME: check ss_local.gs.List's members } [Theory] @@ -611,33 +502,33 @@ public async Task InspectBoxedLocals(string method_name, bool is_async) => await var dt = new DateTime(2310, 1, 2, 3, 4, 5); await CheckProps(locals, new { - n_i = TNumber(5), - o_i = TNumber(5), - o_n_i = TNumber(5), - o_s = TString("foobar"), - o_obj = TObject("Math"), - - n_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - o_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + n_i = TNumber(5), + o_i = TNumber(5), + o_n_i = TNumber(5), + o_s = TString("foobar"), + o_obj = TObject("Math"), + + n_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + o_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), o_n_gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - n_dt = TDateTime(dt), - o_dt = TDateTime(dt), + n_dt = TDateTime(dt), + o_dt = TDateTime(dt), o_n_dt = TDateTime(dt), o_null = TObject("object", is_null: true), - o_ia = TArray("int[]", 2), + o_ia = TArray("int[]", 2), }, "locals"); foreach (var name in new[] { "n_gs", "o_gs", "o_n_gs" }) { var gs = GetAndAssertObjectWithName(locals, name); - var gs_props = await GetProperties(gs["value"]?["objectId"]?.Value ()); + var gs_props = await GetProperties(gs["value"]?["objectId"]?.Value()); await CheckProps(gs_props, new { - List = TObject("System.Collections.Generic.List", is_null: true), + List = TObject("System.Collections.Generic.List", is_null: true), StringField = TString("n_gs#StringField"), - Options = TEnum ("DebuggerTests.Options", "None") + Options = TEnum("DebuggerTests.Options", "None") }, name); } @@ -688,14 +579,14 @@ public async Task InspectBoxedAsClassLocals(string method_name, bool is_async) = { var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); var dt = new DateTime(2310, 1, 2, 3, 4, 5); - Console.WriteLine (locals); + Console.WriteLine(locals); await CheckProps(locals, new { vt_dt = TDateTime(new DateTime(4819, 5, 6, 7, 8, 9)), vt_gs = TValueType("Math.GenericStruct"), - e = TEnum("System.IO.FileMode", "0"), - ee = TEnum("System.IO.FileMode", "Append") + e = TEnum("System.IO.FileMode", "0"), + ee = TEnum("System.IO.FileMode", "Append") }, "locals"); }); @@ -704,72 +595,63 @@ public async Task InspectBoxedAsClassLocals(string method_name, bool is_async) = [InlineData(true)] public async Task InspectLocalsWithStructsStaticAsync(bool use_cfo) { - var insp = new Inspector(); - //Collect events - var scripts = SubscribeToScripts(insp); + UseCallFunctionOnBeforeGetProperties = use_cfo; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; - 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); - 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 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()); + await CheckProps(locals, new + { + ss_local = TObject("DebuggerTests.ValueTypesTest.SimpleStruct"), + gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + 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 = TDateTime(dt), + gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), + Kind = TEnum("System.DateTimeKind", "Utc") + }, "ss_local"); - var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); - await CheckProps(locals, new - { - ss_local = TObject("DebuggerTests.ValueTypesTest.SimpleStruct"), - gs_local = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - 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 = TDateTime(dt), - gs = TValueType("DebuggerTests.ValueTypesTest.GenericStruct"), - 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"); - { - var gres = await InvokeGetter(GetAndAssertObjectWithName(locals, "ss_local"), "V"); - await CheckValue(gres.Value["result"], TNumber(0xDEADBEEF + 2), $"ss_local#V"); - - // 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"), - Options = TEnum("DebuggerTests.Options", "Option1") - } - ); - } + // 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"), + 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#StringField"), - List = TObject("System.Collections.Generic.List"), - Options = TEnum("DebuggerTests.Options", "Option2") - }, "gs_local"); + // 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#StringField"), + List = TObject("System.Collections.Generic.List"), + Options = TEnum("DebuggerTests.Options", "Option2") + }, "gs_local"); - // FIXME: check ss_local.gs.List's members - }); + // FIXME: check ss_local.gs.List's members } [Theory] @@ -779,113 +661,95 @@ await CompareObjectPropertiesFor(ss_local_props, "gs", [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; + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; - 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); - 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 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 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 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()); - await CheckProps(frame_locals, new + var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); + await CheckProps(frame_locals, new + { + call_other = TBool(call_other), + dt0 = TDateTime(dt0), + dt1 = TDateTime(dt1), + 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 { - call_other = TBool(call_other), - dt0 = TDateTime(dt0), - dt1 = TDateTime(dt1), - 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); + 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 DT = new DateTime(2004, 10, 15, 1, 2, 3); + var DTO = new DateTimeOffset(dt0, new TimeSpan(2, 14, 0)); - await CompareObjectPropertiesFor(frame_locals, "obj", - new - { - DT = TDateTime(DT), - 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 = TDateTime(DT), - 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"); - }); + await CompareObjectPropertiesFor(frame_locals, "obj", + new + { + DT = TDateTime(DT), + 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 = TDateTime(DT), + 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()); - }); + var wait_res = await RunUntil("locals_inner"); + var locals = await GetProperties(wait_res["callFrames"][1]["callFrameId"].Value()); } [Theory] @@ -948,7 +812,7 @@ await CheckInspectLocalsAtBreakpointSite( async Task CreateNewId(string expr) { - var res = await ctx.cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = expr }), ctx.token); + var res = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = expr }), token); Assert.True(res.IsOk, "Expected Runtime.evaluate to succeed"); AssertEqual("string", res.Value["result"]?["type"]?.Value(), "Expected Runtime.evaluate to return a string type result"); return res.Value["result"]?["value"]?.Value(); @@ -957,7 +821,7 @@ async Task CreateNewId(string expr) async Task _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); + var res = await cli.SendCommand("Runtime.evaluate", JObject.FromObject(new { expression = expr }), token); AssertEqual(expect_ok, res.IsOk, "Runtime.evaluate result not as expected for {expr}"); return res; @@ -1057,84 +921,59 @@ JObject FindFrame(JObject pause_location, string function_name) [Fact] public async Task DebugLazyLoadedAssemblyWithPdb() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - - int line = 9; - await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true); - await LoadAssemblyDynamically( - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.dll"), - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.pdb")); - - var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs"; - Assert.Contains(source_location, scripts.Values); - - var pause_location = await EvaluateAndCheck( - "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test] LazyMath:IntAdd', 5, 10); }, 1);", - source_location, line, 8, - "IntAdd"); - var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); - CheckNumber(locals, "a", 5); - CheckNumber(locals, "b", 10); - }); + int line = 9; + await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true); + await LoadAssemblyDynamically( + Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.dll"), + Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.pdb")); + + var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs"; + Assert.Contains(source_location, scripts.Values); + + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test] LazyMath:IntAdd', 5, 10); }, 1);", + source_location, line, 8, + "IntAdd"); + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 5); + CheckNumber(locals, "b", 10); } [Fact] public async Task DebugLazyLoadedAssemblyWithEmbeddedPdb() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); - await Ready(); - - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); - - int line = 9; - await SetBreakpoint(".*/lazy-debugger-test-embedded.cs$", line, 0, use_regex: true); - await LoadAssemblyDynamically( - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test-embedded.dll"), - null); - - var source_location = "dotnet://lazy-debugger-test-embedded.dll/lazy-debugger-test-embedded.cs"; - Assert.Contains(source_location, scripts.Values); - - var pause_location = await EvaluateAndCheck( - "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test-embedded] LazyMath:IntAdd', 5, 10); }, 1);", - source_location, line, 8, - "IntAdd"); - var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); - CheckNumber(locals, "a", 5); - CheckNumber(locals, "b", 10); - }); + int line = 9; + await SetBreakpoint(".*/lazy-debugger-test-embedded.cs$", line, 0, use_regex: true); + await LoadAssemblyDynamically( + Path.Combine(DebuggerTestAppPath, "lazy-debugger-test-embedded.dll"), + null); + + var source_location = "dotnet://lazy-debugger-test-embedded.dll/lazy-debugger-test-embedded.cs"; + Assert.Contains(source_location, scripts.Values); + + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test-embedded] LazyMath:IntAdd', 5, 10); }, 1);", + source_location, line, 8, + "IntAdd"); + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + CheckNumber(locals, "a", 5); + CheckNumber(locals, "b", 10); } [Fact] public async Task CannotDebugLazyLoadedAssemblyWithoutPdb() { - var insp = new Inspector(); - var scripts = SubscribeToScripts(insp); - await Ready(); - await insp.Ready(async (cli, token) => - { - ctx = new DebugTestContext(cli, insp, token, scripts); + int line = 9; + await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true); + await LoadAssemblyDynamically( + Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.dll"), + null); - int line = 9; - await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true); - await LoadAssemblyDynamically( - Path.Combine(DebuggerTestAppPath, "lazy-debugger-test.dll"), - null); + // wait to bit to catch if the event might be raised a bit late + await Task.Delay(1000); - // wait to bit to catch if the event might be raised a bit late - await Task.Delay(1000); - - var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs"; - Assert.DoesNotContain(source_location, scripts.Values); - }); + var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs"; + Assert.DoesNotContain(source_location, scripts.Values); } async Task LoadAssemblyDynamically(string asm_file, string pdb_file) @@ -1144,7 +983,8 @@ async Task LoadAssemblyDynamically(string asm_file, string pdb_file) string asm_base64 = Convert.ToBase64String(bytes); string pdb_base64 = null; - if (pdb_file != null) { + if (pdb_file != null) + { bytes = File.ReadAllBytes(pdb_file); pdb_base64 = Convert.ToBase64String(bytes); } @@ -1154,26 +994,17 @@ async Task LoadAssemblyDynamically(string asm_file, string pdb_file) expression = $"{{ let asm_b64 = '{asm_base64}'; let pdb_b64 = '{pdb_base64}'; invoke_static_method('[debugger-test] LoadDebuggerTest:LoadLazyAssembly', asm_b64, pdb_b64); }}" }); - Result load_assemblies_res = await ctx.cli.SendCommand("Runtime.evaluate", load_assemblies, ctx.token); + Result load_assemblies_res = await cli.SendCommand("Runtime.evaluate", load_assemblies, token); Assert.True(load_assemblies_res.IsOk); } [Fact] public async Task BreakOnDebuggerBreak() { - 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 EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method_async('[debugger-test] UserBreak:BreakOnDebuggerBreakCommand'); }, 1);", - "dotnet://debugger-test.dll/debugger-test2.cs", 56, 4, - "BreakOnDebuggerBreakCommand"); - }); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method_async('[debugger-test] UserBreak:BreakOnDebuggerBreakCommand'); }, 1);", + "dotnet://debugger-test.dll/debugger-test2.cs", 56, 4, + "BreakOnDebuggerBreakCommand"); } //TODO add tests covering basic stepping behavior as step in/out/over }