From ffb16d5f0b624dbfabaddef7ab65997e79395440 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 1 Feb 2022 12:21:22 -0500 Subject: [PATCH 1/3] [wasm][debugger] Fix racy test HarnessTests.ExceptionThrown The test fails sometimes with: ``` [02:40:04] dbug: Inspector-3[0] Failing all waiters because: Runtime.exceptionThrown: { "timestamp": 1643683204929.399, "exceptionDetails": { "exceptionId": 2, "text": "Uncaught", "lineNumber": 0, "columnNumber": 31, "scriptId": "32", "stackTrace": { "callFrames": [ { "functionName": "", "scriptId": "32", "url": "", "lineNumber": 0, "columnNumber": 31 } ] }, "exception": { "type": "object", "subtype": "error", "className": "ReferenceError", "description": "ReferenceError: non_existant_fn is not defined\n at :1:32", "objectId": "1487416918028189685.1.57", "preview": { "type": "object", "subtype": "error", "description": "ReferenceError: non_existant_fn is not defined\n at :1:32", "overflow": false, "properties": [ { "name": "stack", "type": "string", "value": "ReferenceError: non_existant_fn is not defined\n at :1:32" }, { "name": "message", "type": "string", "value": "non_existant_fn is not defined" } ] } }, "executionContextId": 1 } } [02:41:02] dbug: InspectorClient-3[0] Socket is no longer open [02:41:02] dbug: InspectorClient-3[0] RunLoop stopped, reason: Cancelled. (parentToken: True, linked: True): [02:41:02] dbug: InspectorClient-3[0] Failing 0 pending cmds [02:41:02] dbug: InspectorClient-3[0] Loop ended with socket: Aborted [02:41:03] dbug: InspectorClient-4[0] connecting to ws://localhost:9400/launch-chrome-and-connect/?test_id=4 [xUnit.net 00:02:07.56] DebuggerTests.HarnessTests.ExceptionThrown [FAIL] [02:41:03] info: Microsoft.WebAssembly.Diagnostics.TestHarnessProxy[0] [testId: 4] New test request for test id 4 Failed DebuggerTests.HarnessTests.ExceptionThrown [58 s] Error Message: Assert.Throws() Failure Expected: typeof(System.ArgumentException) Actual: typeof(System.Threading.Tasks.TaskCanceledException): Test timed out (elapsed time: 60.0062617) ---- System.Threading.Tasks.TaskCanceledException : Test timed out (elapsed time: 60.0062617) Stack Trace: at DebuggerTests.DebuggerTestBase.SendCommandAndCheck(JObject args, String method, String script_loc, Int32 line, Int32 column, String function_name, Func`2 wait_for_event_fn, Func`2 locals_fn, String waitForEvent) in /_/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs:line 523 at DebuggerTests.DebuggerTestBase.EvaluateAndCheck(String expression, String script_loc, Int32 line, Int32 column, String function_name, Func`2 wait_for_event_fn, Func`2 locals_fn) in /_/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs:line 507 at DebuggerTests.HarnessTests.b__1_0() in /_/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs:line 30 ----- Inner Stack Trace ----- at DebuggerTests.DebuggerTestBase.SendCommandAndCheck(JObject args, String method, String script_loc, Int32 line, Int32 column, String function_name, Func`2 wait_for_event_fn, Func`2 locals_fn, String waitForEvent) in /_/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs:line 523 at DebuggerTests.DebuggerTestBase.EvaluateAndCheck(String expression, String script_loc, Int32 line, Int32 column, String function_name, Func`2 wait_for_event_fn, Func`2 locals_fn) in /_/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs:line 507 at DebuggerTests.HarnessTests.b__1_0() in /_/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs:line 30 ``` The test uses `SendCommand` to evaluate `("window.setTimeout(function() { non_existant_fn(); }, 1)` which tries to invoke the `non_existant_fn` after 1ms. This causes a `Runtime.exceptionThrown` event message to be received, and the `Inspector` fails any waiters (eg. `insp.WaitFor(READY)`). So we have: 1. SendCommand 2. insp.WaitFor But the `Runtime.exceptionThrown` can be received before we get to (2), thus the waiter from (2) never gets failed, and instead times out. --- src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs index 865eaa8c630f5e..1593e6b04367ee 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs @@ -27,7 +27,7 @@ public async Task TimedOutWaitingForInvalidBreakpoint() public async Task ExceptionThrown() { var ae = await Assert.ThrowsAsync( - async () => await EvaluateAndCheck("window.setTimeout(function() { non_existant_fn(); }, 1);", null, -1, -1, null)); + async () => await EvaluateAndCheck("window.setTimeout(function() { non_existant_fn(); }, 3000);", null, -1, -1, null)); Assert.Contains("non_existant_fn is not defined", ae.Message); } From c9cf2ae55b431f1da90a14bb3100121a6c0ef5e5 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 1 Feb 2022 12:33:16 -0500 Subject: [PATCH 2/3] [wasm][debugger] Remove HarnessTests.BrowserClose This is an inherently racy test because we might get the socket closed exception first, or the ArgumentException for the cdp events. And effectively, it's not a useful test. --- src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs index 1593e6b04367ee..d164b9663887af 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/HarnessTests.cs @@ -35,15 +35,6 @@ public async Task ExceptionThrown() public async Task BrowserCrash() => await Assert.ThrowsAsync(async () => await SendCommandAndCheck(null, "Browser.crash", null, -1, -1, null)); - [Fact] - public async Task BrowserClose() - { - ArgumentException ae = await Assert.ThrowsAsync(async () => - await SendCommandAndCheck(null, "Browser.close", null, -1, -1, null)); - Assert.Contains("Inspector.detached", ae.Message); - Assert.Contains("target_close", ae.Message); - } - [Fact] public async Task InspectorWaitForAfterMessageAlreadyReceived() { From eba1515f2f1de171f298c2f18a2a21ea5b624153 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 1 Feb 2022 18:28:47 -0500 Subject: [PATCH 3/3] [wasm][debugger] Update two array tests `ArrayTests.InvalidValueTypeArrayIndex` isn't needed any more because array members don't have special ids now. Fixes https://github.com/dotnet/runtime/issues/63560 --- .../debugger/DebuggerTestSuite/ArrayTests.cs | 48 +------------------ 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs index a9d17696c4faa9..438eceea378d3e 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs @@ -551,14 +551,12 @@ await CompareObjectPropertiesFor(frame_locals, "this", label: "this#0"); } -#if false // https://github.com/dotnet/runtime/issues/63560 [Fact] public async Task InvalidArrayId() => await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.Container", "PlaceholderMethod", 1, "PlaceholderMethod", "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ArrayTestsClass:ObjectArrayMembers'); }, 1);", wait_for_event_fn: async (pause_location) => { - int frame_idx = 1; var frame_locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); var c_obj = GetAndAssertObjectWithName(frame_locals, "c"); @@ -568,56 +566,12 @@ public async Task InvalidArrayId() => await CheckInspectLocalsAtBreakpointSite( // Invalid format await GetProperties("dotnet:array:4123", expect_ok: false); - // Invalid object id - await GetProperties("dotnet:array:{ \"arrayId\": 234980 }", expect_ok: false); - // Trying to access object as an array if (!DotnetObjectId.TryParse(c_obj_id, out var id) || id.Scheme != "object") Assert.True(false, "Unexpected object id format. Maybe this test is out of sync with the object id format in dotnet.cjs.lib.js?"); - if (!int.TryParse(id.Value, out var idNum)) - Assert.True(false, "Expected a numeric value part of the object id: {c_obj_id}"); - await GetProperties($"dotnet:array:{{\"arrayId\":{idNum}}}", expect_ok: false); - }); - - [Fact] - public async Task InvalidValueTypeArrayIndex() => await CheckInspectLocalsAtBreakpointSite( - "DebuggerTests.Container", "PlaceholderMethod", 1, "PlaceholderMethod", - "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.ArrayTestsClass:ObjectArrayMembers'); }, 1);", - locals_fn: async (locals) => - { - var this_obj = GetAndAssertObjectWithName(locals, "this"); - var c_obj = GetAndAssertObjectWithName(await GetProperties(this_obj["value"]["objectId"].Value()), "c"); - var c_obj_id = c_obj["value"]?["objectId"]?.Value(); - Assert.NotNull(c_obj_id); - - var c_props = await GetProperties(c_obj_id); - - var pf_arr = GetAndAssertObjectWithName(c_props, "PointsField"); - var pf_arr_elems = await GetProperties(pf_arr["value"]["objectId"].Value()); - - if (!DotnetObjectId.TryParse(pf_arr_elems[0]["value"]?["objectId"]?.Value(), out var id)) - Assert.True(false, "Couldn't parse objectId for PointsFields' elements"); - - AssertEqual("valuetype", id.Scheme, "Expected a valuetype id"); - var id_args = id.ValueAsJson; - Assert.True(id_args["arrayId"] != null, "ObjectId format for array seems to have changed. Expected to find 'arrayId' in the value. Update this test"); - Assert.True(id_args != null, "Expected to get a json as the value part of {id}"); - - // Try one valid query, to confirm that the id format hasn't changed! - id_args["arrayIdx"] = 0; - await GetProperties($"dotnet:valuetype:{id_args.ToString(Newtonsoft.Json.Formatting.None)}", expect_ok: true); - - id_args["arrayIdx"] = 12399; - await GetProperties($"dotnet:valuetype:{id_args.ToString(Newtonsoft.Json.Formatting.None)}", expect_ok: false); - - id_args["arrayIdx"] = -1; - await GetProperties($"dotnet:valuetype:{id_args.ToString(Newtonsoft.Json.Formatting.None)}", expect_ok: false); - - id_args["arrayIdx"] = "qwe"; - await GetProperties($"dotnet:valuetype:{id_args.ToString(Newtonsoft.Json.Formatting.None)}", expect_ok: false); + await GetProperties($"dotnet:array:{id.Value}", expect_ok: false); }); -#endif [Fact] public async Task InvalidAccessors() => await CheckInspectLocalsAtBreakpointSite(