async Task CheckLocalsOnFrame(JToken frame, DebugTestContext ctx, Action <JToken> test_fn = null) { var get_prop_req = JObject.FromObject(new { objectId = frame["callFrameId"] }); var frame_props = await ctx.cli.SendCommand("Runtime.getProperties", get_prop_req, ctx.token); if (!frame_props.IsOk) { Assert.True(false, $"Runtime.getProperties failed for {get_prop_req.ToString ()}"); } if (test_fn == null) { return; } var locals = frame_props.Value ["result"]; try { test_fn(locals); } catch { Console.WriteLine($"Failed trying to check locals: {locals.ToString ()}"); throw; } }
public async Task CheckErrorsWithSilent(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("dotnet://debugger-test.dll/debugger-test.cs", 311, 2); // callFunctionOn var eval_expr = "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:CallFunctionOnTest', 10); }, 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); // Check the object at the bp var cfo_args = JObject.FromObject(new { functionDeclaration = "function () { throw Error ('test error'); }", objectId = "dotnet:object:xyasd", }); if (silent.HasValue) { cfo_args ["silent"] = silent; } // callFunctionOn result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); Assert.True((silent ?? false) == result.IsOk); }); }
public async Task CreateGoodBreakpoint() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var bp1_res = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 5, 2, ctx); Assert.EndsWith("debugger-test.cs", bp1_res.Value ["breakpointId"].ToString()); Assert.Equal(1, bp1_res.Value ["locations"]?.Value <JArray> ()?.Count); var loc = bp1_res.Value ["locations"]?.Value <JArray> ()[0]; Assert.NotNull(loc ["scriptId"]); Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts [loc["scriptId"]?.Value <string> ()]); Assert.Equal(5, loc ["lineNumber"]); Assert.Equal(2, loc ["columnNumber"]); }); }
public async Task CheckUpdatedValueTypeLocalsOnResumeAsync() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; var lines = new[] { 214, 216 }; await SetBreakpoint(debugger_test_loc, lines[0], 12); await SetBreakpoint(debugger_test_loc, lines[1], 12); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeLocalsAsync'); }, 1);", debugger_test_loc, lines[0], 12, "MoveNext"); var dt = new DateTime(1, 2, 3, 4, 5, 6); var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value <string>()); await CheckDateTime(locals, "dt", dt); // Resume dt = new DateTime(9, 8, 7, 6, 5, 4); pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MoveNext"); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value <string>()); await CheckDateTime(locals, "dt", dt); }); }
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); // 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); var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value <string>()); var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); var ptd_id = ptd["value"]["objectId"].Value <string>(); var cfo_args = JObject.FromObject(new { functionDeclaration = "function () { return 0; }", objectId = ptd_id + "_invalid" }); var res = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); Assert.True(res.IsErr); }); }
public async Task InspectLocalsWithStructs() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { var ctx = new DebugTestContext(cli, insp, token, scripts); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs"; await SetBreakpoint(debugger_test_loc, 139, 3, ctx); var wait_res = await EvaluateAndCheck( "window.setTimeout(function() { invoke_method_with_structs(); }, 1);", debugger_test_loc, 139, 3, "MethodWithStructs", ctx, locals_fn: (locals) => { Assert.Equal(4, locals.Count()); CheckObject(locals, "m", "Math", subtype: "null"); CheckObject(locals, "ss", "Math.SimpleStruct", subtype: "null"); CheckObject(locals, "gs", "Math.GenericStruct<Math>", subtype: "null"); CheckArray(locals, "ss_arr", "Math.SimpleStruct[]"); } ); }); }
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; // 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); var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value <string>()); var ptd = GetAndAssertObjectWithName(frame_locals, "ptd"); var ptd_id = ptd["value"]["objectId"].Value <string>(); 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}"); } }); }
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"); 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 <string>()); CheckString(exception_members, "message", exception_message); }); }
public async Task BadRaiseDebugEventsTest() { var insp = new Inspector(); var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { 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({})", "MONO.mono_wasm_raise_debug_event({eventName:'foo'}, '')", "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}"); } }); }
// [Fact] //https://github.com/dotnet/runtime/issues/42421 public async Task BreakAfterAwaitThenStepOverTillBackToCaller() { 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 SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.AsyncStepClass", "TestAsyncStepOut2", 2); await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method_async('[debugger-test] DebuggerTests.AsyncStepClass:TestAsyncStepOut'); }, 1);", "dotnet://debugger-test.dll/debugger-async-step.cs", 21, 12, "MoveNext"); await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 23, 12, "MoveNext"); await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 24, 8, "MoveNext"); await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 15, 12, "MoveNext"); }); }
public async Task InvalidScopeId() { 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); 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); 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); }); }
public async Task CreateGoodBreakpointAndHitAndRemoveAndDontHitAndCreateAgainAndHit() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); var 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, "IntAdd"); Assert.Equal("other", pause_location["reason"]?.Value <string>()); Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value <string>()); await RemoveBreakpoint(bp.Value["breakpointId"]?.ToString()); await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", 12, 8, "IntAdd"); await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", 12, 8, "IntAdd"); bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, "IntAdd"); }); }
public async Task SteppingIntoMscorlib() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 83, 8); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:OuterMethod'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", 83, 8, "OuterMethod"); //make sure we're on the right bp Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value <string>()); pause_location = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); var top_frame = pause_location["callFrames"][0]; AssertEqual("WriteLine", top_frame["functionName"]?.Value <string>(), "Expected to be in WriteLine method"); var script_id = top_frame["functionLocation"]["scriptId"].Value <string>(); Assert.Matches("^dotnet://(mscorlib|System\\.Console)\\.dll/Console.cs", scripts[script_id]); }); }
async Task <JObject> SendCommandAndCheck(JObject args, string method, DebugTestContext ctx, Func <JObject, Task> wait_for_event_fn = null, Action <JToken> locals_fn = null, string waitForEvent = Inspector.PAUSE) { var res = await ctx.cli.SendCommand(method, 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 wait_res = await ctx.insp.WaitFor(waitForEvent); if (wait_for_event_fn != null) { await wait_for_event_fn(wait_res); } if (locals_fn != null) { await CheckLocalsOnFrame(wait_res ["callFrames"][0], ctx, locals_fn); } return(wait_res); }
public async Task ExceptionThrownInJSOutOfBand() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); await SetBreakpoint("/debugger-driver.html", 27, 2, ctx); var eval_req = JObject.FromObject(new { expression = "window.setTimeout(function() { invoke_bad_js_test(); }, 1);", }); var eval_res = await cli.SendCommand("Runtime.evaluate", eval_req, token); // Response here will be the id for the timer from JS! Assert.True(eval_res.IsOk); var ex = await Assert.ThrowsAsync <ArgumentException> (async() => await insp.WaitFor("Runtime.exceptionThrown")); var ex_json = JObject.Parse(ex.Message); Assert.Equal(dicFileToUrl["/debugger-driver.html"], ex_json ["exceptionDetails"]? ["url"]? .Value <string> ()); }); }
public async Task InspectValueTypeArrayLocalsInAsyncStaticStructMethod(bool use_cfo) { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); int line = 222; int col = 3; 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"; 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);"; // 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 <string> ()); await CheckProps(frame_locals, new { call_other = TBool(false), local_i = TNumber(5), sc = TSimpleClass(10, 45, "sc#Id", "Blue") }, "InspectValueTypeArrayLocalsInAsyncStaticStructMethod#locals"); }); }
public async Task InspectLocalsInPreviousFramesDuringSteppingIn2() { 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 dep_cs_loc = "dotnet://Simple.Dependency.dll/dependency.cs"; await SetBreakpoint(dep_cs_loc, 24, 2, ctx); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs"; // Will stop in Complex.DoEvenMoreStuff var wait_res = await EvaluateAndCheck( "window.setTimeout(function() { invoke_use_complex (); }, 1);", dep_cs_loc, 24, 2, "DoEvenMoreStuff", ctx, locals_fn: (locals) => { Assert.Equal(1, locals.Count()); CheckObject(locals, "this", "Simple.Complex"); } ); // Check UseComplex frame await CheckLocalsOnFrame(wait_res ["callFrames"][3], debugger_test_loc, 17, 2, "UseComplex", ctx, test_fn: (locals_m1) => { Assert.Equal(7, locals_m1.Count()); CheckNumber(locals_m1, "a", 10); CheckNumber(locals_m1, "b", 20); CheckObject(locals_m1, "complex", "Simple.Complex"); CheckNumber(locals_m1, "c", 30); CheckNumber(locals_m1, "d", 50); CheckNumber(locals_m1, "e", 60); CheckNumber(locals_m1, "f", 0); } ); wait_res = await StepAndCheck(StepKind.Over, dep_cs_loc, 16, 2, "DoStuff", ctx, times: 2); // Check UseComplex frame again await CheckLocalsOnFrame(wait_res ["callFrames"][1], debugger_test_loc, 17, 2, "UseComplex", ctx, test_fn: (locals_m1) => { Assert.Equal(7, locals_m1.Count()); CheckNumber(locals_m1, "a", 10); CheckNumber(locals_m1, "b", 20); CheckObject(locals_m1, "complex", "Simple.Complex"); CheckNumber(locals_m1, "c", 30); CheckNumber(locals_m1, "d", 50); CheckNumber(locals_m1, "e", 60); CheckNumber(locals_m1, "f", 0); } ); }); }
public async Task ExceptionTestAll() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); int line = 15; int col = 20; string entry_method_name = "[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions"; 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"); 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); AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value <string>(), "pause0"); 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 <string>()); CheckString(exception_members, "message", "not implemented caught"); pause_location = await WaitForManagedException(null); AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value <string>(), "pause1"); //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 <string>()); CheckString(exception_members, "message", "not implemented uncaught"); }); }
public async Task CheckUpdatedValueTypeFieldsOnResume() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; var lines = new[] { 205, 208 }; await SetBreakpoint(debugger_test_loc, lines[0], 12); await SetBreakpoint(debugger_test_loc, lines[1], 12); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingValueTypeMembers'); }, 1);", debugger_test_loc, lines[0], 12, "MethodUpdatingValueTypeMembers"); await CheckLocals(pause_location, new DateTime(1, 2, 3, 4, 5, 6), new DateTime(4, 5, 6, 7, 8, 9)); // Resume pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MethodUpdatingValueTypeMembers"); await CheckLocals(pause_location, new DateTime(9, 8, 7, 6, 5, 4), new DateTime(5, 1, 3, 7, 9, 10)); }); async Task CheckLocals(JToken pause_location, DateTime obj_dt, DateTime vt_dt) { var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value <string>()); await CheckProps(locals, new { obj = TObject("DebuggerTests.ClassForToStringTests"), vt = TObject("DebuggerTests.StructForToStringTests") }, "locals"); var obj_props = await GetObjectOnLocals(locals, "obj"); { await CheckProps(obj_props, new { DT = TDateTime(obj_dt) }, "locals#obj.DT", num_fields : 5); } var vt_props = await GetObjectOnLocals(locals, "vt"); { await CheckProps(vt_props, new { DT = TDateTime(vt_dt) }, "locals#obj.DT", num_fields : 5); } } }
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"; await SetBreakpoint(debugger_test_loc, line, col); 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"); var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value <string>()); await CheckProps(frame_locals, new { t1 = TObject("DebuggerTests.SimpleGenericStruct<DebuggerTests.Point>"), @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") }); 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")); }); }
public async Task FixupNameValueObjectsWithMissingParts() { 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 names = new JObject[] { JObject.FromObject(new { name = "Abc" }), JObject.FromObject(new { name = "Def" }), JObject.FromObject(new { name = "Xyz" }) }; var values = new JObject[] { JObject.FromObject(new { value = TObject("testclass") }), JObject.FromObject(new { value = TString("test string") }), }; 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); await CheckProps(res.Value["result"]["value"], new { Abc = TSymbol("<unreadable value>"), Def = TObject("testclass"), Xyz = TGetter("xyz") }, "#1", num_fields: 4); JObject.DeepEquals(getters[1], res.Value["result"]["value"].Values <JObject>().ToArray()[3]); JObject GetterRes(string name) => JObject.FromObject(new { get = new { className = "Function", description = $"get {name} () {{}}", type = "function" } }); }); }
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"; await SetBreakpoint(debugger_test_loc, line, col); 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"); var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value <string>()); await CheckProps(frame_locals, new { sc_arg = TObject("DebuggerTests.SimpleClass"), @this = TValueType("DebuggerTests.Point"), local_gs = TValueType("DebuggerTests.SimpleGenericStruct<int>") }, "locals#0"); await CompareObjectPropertiesFor(frame_locals, "local_gs", new { Id = TString("local_gs#Id"), Color = TEnum("DebuggerTests.RGB", "Green"), Value = TNumber(4) }, label: "local_gs#0"); await CompareObjectPropertiesFor(frame_locals, "sc_arg", TSimpleClass(10, 45, "sc_arg#Id", "Blue"), label: "sc_arg#0"); await CompareObjectPropertiesFor(frame_locals, "this", TPoint(90, -4, "point#Id", "Green"), label: "this#0"); }); }
public async Task InspectLocalsDuringStepping() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs"; await SetBreakpoint(debugger_test_loc, 10, 8); await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); }, 1);", debugger_test_loc, 10, 8, "IntAdd", locals_fn: (locals) => { CheckNumber(locals, "a", 10); CheckNumber(locals, "b", 20); CheckNumber(locals, "c", 30); CheckNumber(locals, "d", 0); CheckNumber(locals, "e", 0); } ); await StepAndCheck(StepKind.Over, debugger_test_loc, 11, 8, "IntAdd", locals_fn: (locals) => { CheckNumber(locals, "a", 10); CheckNumber(locals, "b", 20); CheckNumber(locals, "c", 30); CheckNumber(locals, "d", 50); CheckNumber(locals, "e", 0); } ); //step and get locals await StepAndCheck(StepKind.Over, debugger_test_loc, 12, 8, "IntAdd", locals_fn: (locals) => { CheckNumber(locals, "a", 10); CheckNumber(locals, "b", 20); CheckNumber(locals, "c", 30); CheckNumber(locals, "d", 50); CheckNumber(locals, "e", 60); } ); }); }
async Task <Result> SetBreakpoint(string url_key, int line, int column, DebugTestContext ctx, bool expect_ok = true) { var bp1_req = JObject.FromObject(new { lineNumber = line, columnNumber = column, url = dicFileToUrl[url_key], }); var bp1_res = await ctx.cli.SendCommand("Debugger.setBreakpointByUrl", bp1_req, ctx.token); Assert.True(expect_ok ? bp1_res.IsOk : bp1_res.IsErr); return(bp1_res); }
// 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 <JToken> locals_fn = null, Func <JObject, Task> 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; 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 pause_location = await ctx.insp.WaitFor(Inspector.PAUSE); if (bp_function_name != null) { Assert.Equal(bp_function_name, pause_location["callFrames"]?[0]?["functionName"]?.Value <string>()); } Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value <string>()); var top_frame = pause_location["callFrames"][0]; var scope = top_frame["scopeChain"][0]; Assert.Equal("dotnet:scope:0", scope["object"]["objectId"]); 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 <string>()); locals_fn(locals); } }); }
public async Task CheckUpdatedVTArrayMembersOnResume() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var debugger_test_loc = "dotnet://debugger-test.dll/debugger-valuetypes-test.cs"; var lines = new[] { 225, 227 }; await SetBreakpoint(debugger_test_loc, lines[0], 12); await SetBreakpoint(debugger_test_loc, lines[1], 12); var dt = new DateTime(1, 2, 3, 4, 5, 6); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ValueTypesTest:MethodUpdatingVTArrayMembers'); }, 1);", debugger_test_loc, lines[0], 12, "MethodUpdatingVTArrayMembers"); await CheckArrayElements(pause_location, dt); // Resume dt = new DateTime(9, 8, 7, 6, 5, 4); pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", debugger_test_loc, lines[1], 12, "MethodUpdatingVTArrayMembers"); await CheckArrayElements(pause_location, dt); }); async Task CheckArrayElements(JToken pause_location, DateTime dt) { var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value <string>()); await CheckProps(locals, new { ssta = TArray("DebuggerTests.StructForToStringTests[]", 1) }, "locals"); var ssta = await GetObjectOnLocals(locals, "ssta"); var sst0 = await GetObjectOnLocals(ssta, "0"); await CheckProps(sst0, new { DT = TDateTime(dt) }, "dta [0]", num_fields : 5); } }
internal async Task CheckInspectLocalsAtBreakpointSite(string url_key, int line, int column, string function_name, string eval_expression, Action <JToken> test_fn = null, Func <JObject, Task> wait_for_event_fn = null, 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); ctx.UseCallFunctionOnBeforeGetProperties = use_cfo; 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) => { //make sure we're on the right bp Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value <string>()); var top_frame = pause_location["callFrames"][0]; var scope = top_frame["scopeChain"][0]; Assert.Equal("dotnet:scope:0", scope["object"]["objectId"]); 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); } } ); }); }
public async Task CreateGoodBreakpointAndHit() { var insp = new Inspector(); //Collect events var scripts = SubscribeToScripts(insp); await Ready(); await insp.Ready(async (cli, token) => { ctx = new DebugTestContext(cli, insp, token, scripts); var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 5, 2, ctx); var eval_req = JObject.FromObject(new { expression = "window.setTimeout(function() { invoke_add(); }, 1);", }); await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", 5, 2, "IntAdd", ctx, wait_for_event_fn: (pause_location) => { Assert.Equal("other", pause_location ["reason"]?.Value <string> ()); Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location ["hitBreakpoints"]?[0]?.Value <string> ()); var top_frame = pause_location ["callFrames"][0]; Assert.Equal("IntAdd", top_frame ["functionName"].Value <string>()); Assert.Contains("debugger-test.cs", top_frame ["url"].Value <string> ()); CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, top_frame["functionLocation"]); //now check the scope var scope = top_frame ["scopeChain"][0]; Assert.Equal("local", scope ["type"]); Assert.Equal("IntAdd", scope ["name"]); Assert.Equal("object", scope ["object"]["type"]); Assert.Equal("dotnet:scope:0", scope ["object"]["objectId"]); CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 3, 41, scripts, scope["startLocation"]); CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 9, 1, scripts, scope["endLocation"]); return(Task.CompletedTask); } ); }); }
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); // 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); var frame_locals = await GetProperties(pause_location["callFrames"][0]["scopeChain"][0]["object"]["objectId"].Value <string>()); var obj = GetAndAssertObjectWithName(frame_locals, "big"); var big_obj_id = obj["value"]["objectId"].Value <string>(); 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 }); 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"); var hasErrorMessage = result.Error["exceptionDetails"]?["exception"]?["description"]?.Value <string>()?.Contains(error_msg); Assert.True((hasErrorMessage ?? false), "Exception message not found"); }); }
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 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); // Um for js we get "scriptId": "6" // CheckLocation (bp_loc, line, col, ctx.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 <string>()); var obj = GetAndAssertObjectWithName(frame_locals, "big"); var obj_id = obj["value"]["objectId"].Value <string>(); 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; } // callFunctionOn result = await ctx.cli.SendCommand("Runtime.callFunctionOn", cfo_args, ctx.token); await CheckValue(result.Value["result"], TNumber(5), "cfo-res"); }); }