From 59af34481bf12c50b2a246808494aa479f3a75cc Mon Sep 17 00:00:00 2001
From: Ankit Jain <radical@gmail.com>
Date: Wed, 2 Feb 2022 19:38:02 -0500
Subject: [PATCH 1/3] re-enable some tests

---
 src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs | 4 ++--
 src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs       | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
index 32f209a9646fda..e4112e08cf7aa3 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
@@ -294,8 +294,8 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test2.cs"
         }
 
         [Fact]
-        [Trait("Category", "windows-failing")] // https://github.com/dotnet/runtime/issues/62823
-        [Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62823
+        //[Trait("Category", "windows-failing")] // https://github.com/dotnet/runtime/issues/62823
+        //[Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62823
         public async Task BreakpointInAssemblyUsingTypeFromAnotherAssembly_BothDynamicallyLoaded()
         {
             int line = 7;
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
index 9ec9f2cfdafd3f..62004cfbb2aa7c 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
@@ -755,7 +755,7 @@ await LoadAssemblyDynamically(
         }
 
         [Fact]
-        [Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62667
+        //[Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62667
         public async Task DebugLazyLoadedAssemblyWithEmbeddedPdb()
         {
             int line = 9;

From b4962bbe40aceb9ae1ed0da78fe6582a22db07bd Mon Sep 17 00:00:00 2001
From: Ankit Jain <radical@gmail.com>
Date: Wed, 2 Feb 2022 18:33:30 -0500
Subject: [PATCH 2/3] [wasm][debugger] Fix racy test -
 ExceptionTestAllWithReload

This test is set up to pause on all exceptions. So, it has some code to
hit `Debugger.resume` 100 times, hoping to skip all the non-user code
exceptions. But this can sometimes not be enough, and you might have
more exceptions which breaks rest of the test.

Instead, we try to resume till we won't get paused for a period of
10secs. And after that, we can call the user code, and execute rest of
the test.

Fixes https://github.com/dotnet/runtime/issues/62666 .
---
 .../DebuggerTestSuite/ExceptionTests.cs       | 28 +++++++++++++------
 .../debugger/DebuggerTestSuite/Inspector.cs   |  6 ++++
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs
index 46e3acc16dd941..9fbfa920f259b6 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs
@@ -235,7 +235,6 @@ await CheckValue(pause_location["data"], JObject.FromObject(new
         [Theory]
         [InlineData("[debugger-test] DebuggerTests.ExceptionTestsClassDefault:TestExceptions", "System.Exception", 76)]
         [InlineData("[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions", "DebuggerTests.CustomException", 28)]
-        [Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62666
         public async Task ExceptionTestAllWithReload(string entry_method_name, string class_name, int line_number)
         {
             var debugger_test_loc = "dotnet://debugger-test.dll/debugger-exception-test.cs";
@@ -249,14 +248,26 @@ public async Task ExceptionTestAllWithReload(string entry_method_name, string cl
                                     }), "Page.reload",null, 0, 0, null);
             Thread.Sleep(1000);
 
-            //send a lot of resumes to "skip" all the pauses on caught exception and completely reload the page
-            int i = 0;
-            while (i < 100)
+            // Hit resume to skip 
+            int count = 0;
+            while(true)
             {
-                Result res = await cli.SendCommand("Debugger.resume", null, token);
-                i++;
-            }
+                await cli.SendCommand("Debugger.resume", null, token);
+                count++;
 
+                try
+                {
+                    await insp.WaitFor(Inspector.PAUSE)
+                                .WaitAsync(TimeSpan.FromSeconds(10));
+                }
+                catch (TimeoutException)
+                {
+                    // timed out waiting for a PAUSE
+                    insp.ClearWaiterFor(Inspector.PAUSE);
+                    break;
+                }
+            }
+            Console.WriteLine ($"* Resumed {count} times");
 
             var eval_expr = "window.setTimeout(function() { invoke_static_method (" +
                 $"'{entry_method_name}'" +
@@ -309,7 +320,8 @@ async Task<JObject> WaitForManagedException(JObject pause_location)
                     AssertEqual("exception", pause_location["reason"]?.Value<string>(), $"Expected to only pause because of an exception. {pause_location}");
 
                     // return in case of a managed exception, and ignore JS ones
-                    if (pause_location["data"]?["objectId"]?.Value<string>()?.StartsWith("dotnet:object:") == true)
+                    if (pause_location["data"]?["objectId"]?.Value<string>()?.StartsWith("dotnet:object:", StringComparison.Ordinal) == true ||
+                        pause_location["data"]?["uncaught"]?.Value<bool>() == true)
                     {
                         break;
                     }
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
index c70f42f5d8449f..e48a211c08b93f 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
@@ -73,6 +73,12 @@ public Task<JObject> WaitFor(string what)
             }
         }
 
+        public void ClearWaiterFor(string what)
+        {
+            if (notifications.ContainsKey(what))
+                notifications.Remove(what);
+        }
+
         void NotifyOf(string what, JObject args)
         {
             if (notifications.TryGetValue(what, out TaskCompletionSource<JObject>? tcs))

From 58a7925f4cca12eddd6731c458e052e71a4cc8ff Mon Sep 17 00:00:00 2001
From: Ankit Jain <radical@gmail.com>
Date: Wed, 2 Feb 2022 21:06:06 -0500
Subject: [PATCH 3/3] [wasm][debugger] Fix racy tests that use late loaded
 assemblies

`DebuggerTests.MiscTests.DebugLazyLoadedAssemblyWithEmbeddedPdb`
`DebuggerTests.BreakpointTests.BreakpointInAssemblyUsingTypeFromAnotherAssembly_BothDynamicallyLoaded`

These tests load assemblies dynamically, and depend on breakpoints in
those assemblies being resolved. But the tests don't wait for that to
happen. So, they can some times fail when the managed method is invoked
before the breakpoint being resolved.

Fixes https://github.com/dotnet/runtime/issues/62823
Fixes https://github.com/dotnet/runtime/issues/62667
---
 .../debugger/DebuggerTestSuite/BreakpointTests.cs  | 10 ++++++----
 .../debugger/DebuggerTestSuite/DebuggerTestBase.cs | 14 ++++++++++++++
 .../wasm/debugger/DebuggerTestSuite/Inspector.cs   | 12 ++++++++++++
 .../wasm/debugger/DebuggerTestSuite/MiscTests.cs   | 10 ++++++++--
 4 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
index e4112e08cf7aa3..a56fdf6b988c9b 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
@@ -2,13 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Linq;
 using System.Threading.Tasks;
 using Microsoft.WebAssembly.Diagnostics;
 using Newtonsoft.Json.Linq;
 using System.IO;
 using Xunit;
-using System.Threading;
+using Xunit.Sdk;
 
 namespace DebuggerTests
 {
@@ -294,11 +293,12 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test2.cs"
         }
 
         [Fact]
-        //[Trait("Category", "windows-failing")] // https://github.com/dotnet/runtime/issues/62823
-        //[Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62823
         public async Task BreakpointInAssemblyUsingTypeFromAnotherAssembly_BothDynamicallyLoaded()
         {
             int line = 7;
+
+            // Start the task earlier than loading the assemblies, so we don't miss the event
+            Task<JObject> bpResolved = WaitForBreakpointResolvedEvent();
             await SetBreakpoint(".*/library-dependency-debugger-test1.cs$", line, 0, use_regex: true);
             await LoadAssemblyDynamically(
                     Path.Combine(DebuggerTestAppPath, "library-dependency-debugger-test2.dll"),
@@ -310,6 +310,8 @@ await LoadAssemblyDynamically(
             var source_location = "dotnet://library-dependency-debugger-test1.dll/library-dependency-debugger-test1.cs";
             Assert.Contains(source_location, scripts.Values);
 
+            await bpResolved;
+
             var pause_location = await EvaluateAndCheck(
                "window.setTimeout(function () { invoke_static_method('[library-dependency-debugger-test1] TestDependency:IntAdd', 5, 10); }, 1);",
                source_location, line, 8,
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs
index 99c718e17a7f49..26ea6e47e1ee31 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs
@@ -1328,6 +1328,20 @@ internal async Task<JObject> LoadAssemblyAndTestHotReload(string asm_file, strin
             return await insp.WaitFor(Inspector.PAUSE);
         }
 
+        public async Task<JObject> WaitForBreakpointResolvedEvent()
+        {
+            try
+            {
+                var res = await insp.WaitForEvent("Debugger.breakpointResolved");
+                Console.WriteLine ($"breakpoint resolved to {res}");
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                throw new XunitException($"Timed out waiting for Debugger.breakpointResolved event");
+            }
+        }
+
         internal async Task SetJustMyCode(bool enabled)
         {
             var req = JObject.FromObject(new { enabled = enabled });
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
index e48a211c08b93f..b44dddd02dbded 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs
@@ -102,6 +102,18 @@ public void On(string evtName, Func<JObject, CancellationToken, Task> cb)
             eventListeners[evtName] = cb;
         }
 
+        public Task<JObject> WaitForEvent(string evtName)
+        {
+            var eventReceived = new TaskCompletionSource<JObject>();
+            On(evtName, async (args, token) =>
+            {
+                eventReceived.SetResult(args);
+                await Task.CompletedTask;
+            });
+
+            return eventReceived.Task.WaitAsync(Token);
+        }
+
         void FailAllWaiters(Exception? exception = null)
         {
             // Because we can create already completed tasks,
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
index 62004cfbb2aa7c..6f705edcbcfb51 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
@@ -7,6 +7,7 @@
 using System.Threading.Tasks;
 using Newtonsoft.Json.Linq;
 using Xunit;
+using Xunit.Sdk;
 
 [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
 
@@ -736,6 +737,7 @@ JObject FindFrame(JObject pause_location, string function_name)
         [Fact]
         public async Task DebugLazyLoadedAssemblyWithPdb()
         {
+            Task<JObject> bpResolved = WaitForBreakpointResolvedEvent();
             int line = 9;
             await SetBreakpoint(".*/lazy-debugger-test.cs$", line, 0, use_regex: true);
             await LoadAssemblyDynamically(
@@ -744,7 +746,9 @@ await LoadAssemblyDynamically(
 
             var source_location = "dotnet://lazy-debugger-test.dll/lazy-debugger-test.cs";
             Assert.Contains(source_location, scripts.Values);
-            System.Threading.Thread.Sleep(1000);
+
+            await bpResolved;
+
             var pause_location = await EvaluateAndCheck(
                "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test] LazyMath:IntAdd', 5, 10); }, 1);",
                source_location, line, 8,
@@ -755,9 +759,9 @@ await LoadAssemblyDynamically(
         }
 
         [Fact]
-        //[Trait("Category", "linux-failing")] // https://github.com/dotnet/runtime/issues/62667
         public async Task DebugLazyLoadedAssemblyWithEmbeddedPdb()
         {
+            Task<JObject> bpResolved = WaitForBreakpointResolvedEvent();
             int line = 9;
             await SetBreakpoint(".*/lazy-debugger-test-embedded.cs$", line, 0, use_regex: true);
             await LoadAssemblyDynamically(
@@ -767,6 +771,8 @@ await LoadAssemblyDynamically(
             var source_location = "dotnet://lazy-debugger-test-embedded.dll/lazy-debugger-test-embedded.cs";
             Assert.Contains(source_location, scripts.Values);
 
+            await bpResolved;
+
             var pause_location = await EvaluateAndCheck(
                "window.setTimeout(function () { invoke_static_method('[lazy-debugger-test-embedded] LazyMath:IntAdd', 5, 10); }, 1);",
                source_location, line, 8,
