From 207f97b4f0bc9215dc091c0e0c4e9694db1af717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Mon, 8 Nov 2021 16:51:10 +0100 Subject: [PATCH 1/3] [wasm] Add task marshaling tests. Add various tests for marshaling task to JavaScript promise. - Sync and async. - Generic and non-generic. - Successful and failed. --- .../JavaScript/HelperMarshal.cs | 32 ++++++++ .../JavaScript/MarshalTests.cs | 75 +++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs index 4dbd576cc6ddff..5e4b9cb0816d1c 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices.JavaScript; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Xunit; namespace System.Runtime.InteropServices.JavaScript.Tests @@ -641,6 +642,37 @@ private static Func> CreateFunctionAcceptingArray() }; } + public static Task SynchronousTask() + { + return Task.CompletedTask; + } + + public static async Task AsynchronousTask() + { + await Task.Yield(); + } + + public static Task SynchronousTaskInt(int i) + { + return Task.FromResult(i); + } + + public static async Task AsynchronousTaskInt(int i) + { + await Task.Yield(); + return i; + } + + public static Task FailedSynchronousTask() + { + return Task.FromException(new Exception()); + } + + public static async Task FailedAsynchronousTask() + { + await Task.Yield(); + throw new Exception(); + } } public enum TestEnum : uint { diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index fb52d1d58f4a7c..221357447fcdbd 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -3,6 +3,8 @@ using System.Runtime.InteropServices.JavaScript; using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace System.Runtime.InteropServices.JavaScript.Tests @@ -899,5 +901,78 @@ public static void InvokeJSNotInGlobalScope() var result = Runtime.InvokeJS(@"var test_local_variable_name = 5; globalThis.test_local_variable_name"); Assert.Null(result); } + + private static async Task MarshalTask(string helperMethodName, string helperMethodArgs = "", string resolvedBody = "") + { + Runtime.InvokeJS( + @"globalThis.__test_promise_completed = false; " + + @"globalThis.__test_promise_resolved = false; " + + @"globalThis.__test_promise_failed = false; " + + $@"var t = App.call_test_method ('{helperMethodName}', [ {helperMethodArgs} ], 'i'); " + + "t.finally(result => { globalThis.__test_promise_completed = true; }); " + + "t.then(result => { globalThis.__test_promise_resolved = true; " + resolvedBody + " }); " + + "t.catch(e => { console.log(e); globalThis.__test_promise_failed = true; }); " + ); + + await Task.Delay(1); + + var completed = bool.Parse(Runtime.InvokeJS(@"globalThis.__test_promise_completed")); + Assert.True(completed, "JavasScript promise did not completed."); + + var resolved = bool.Parse(Runtime.InvokeJS(@"globalThis.__test_promise_resolved")); + return resolved; + } + + [Fact] + public static async Task MarshalSynchronousTask() + { + bool success = await MarshalTask("SynchronousTask"); + Assert.True(success, "SynchronousTask didn't succeeded."); + } + + [Fact] + public static async Task MarshalAsynchronousTask() + { + bool success = await MarshalTask("AsynchronousTask"); + Assert.True(success, "AsynchronousTask didn't succeeded."); + } + + [Fact] + public static async Task MarshalSynchronousTaskInt() + { + HelperMarshal._intValue = 0; + + bool success = await MarshalTask("SynchronousTaskInt", "7", "App.call_test_method ('InvokeInt', [ result ], 'i');"); + + Assert.True(success, "SynchronousTask didn't succeeded."); + Assert.Equal(7, HelperMarshal._intValue); + } + + [Fact] + public static async Task MarshalAsynchronousTaskInt() + { + HelperMarshal._intValue = 0; + + bool success = await MarshalTask("AsynchronousTaskInt", "7", "App.call_test_method ('InvokeInt', [ result ], 'i');"); + + Assert.True(success, "AsynchronousTask didn't succeeded."); + Assert.Equal(7, HelperMarshal._intValue); + } + + [Fact] + public static async Task MarshalFailedSynchronousTask() + { + bool success = await MarshalTask("FailedSynchronousTask"); + + Assert.False(success, "FailedSynchronousTask didn't failed."); + } + + [Fact] + public static async Task MarshalFailedAsynchronousTask() + { + bool success = await MarshalTask("FailedAsynchronousTask"); + + Assert.False(success, "FailedAsynchronousTask didn't failed."); + } } } From e00e249ac1bb0b974aaea6138ccf8ccd26ad33b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Tue, 9 Nov 2021 10:48:46 +0100 Subject: [PATCH 2/3] Add failing tests for ValueTasks. --- .../InteropServices/JavaScript/HelperMarshal.cs | 11 +++++++++++ .../InteropServices/JavaScript/MarshalTests.cs | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs index 5e4b9cb0816d1c..477f29ec0923d4 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs @@ -673,6 +673,17 @@ public static async Task FailedAsynchronousTask() await Task.Yield(); throw new Exception(); } + + public static async ValueTask AsynchronousValueTask() + { + await Task.Yield(); + } + + public static async ValueTask AsynchronousValueTaskInt(int i) + { + await Task.Yield(); + return i; + } } public enum TestEnum : uint { diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index 221357447fcdbd..8830b322be1ed0 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -974,5 +974,21 @@ public static async Task MarshalFailedAsynchronousTask() Assert.False(success, "FailedAsynchronousTask didn't failed."); } + + [Fact] + [Trait("Category","Marek")] + public static async Task MarshalAsynchronousValueTaskDoesNotWorkYet() + { + var exception = await Assert.ThrowsAsync(() => MarshalTask("AsynchronousValueTask")); + Assert.StartsWith("Error: no idea on how to unbox value types", exception.Message); + } + + [Fact] + [Trait("Category","Marek")] + public static async Task MarshalAsynchronousValueTaskIntDoesNotWorkYet() + { + var exception = await Assert.ThrowsAsync(() => MarshalTask("AsynchronousValueTaskInt", "7")); + Assert.StartsWith("Error: no idea on how to unbox value types", exception.Message); + } } } From 5f30ce333b28586cbfc3e92e1a11c97c32103fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Wed, 10 Nov 2021 08:01:39 +0100 Subject: [PATCH 3/3] Mark ValueTask unit tests with ActiveIssue attribute and make assertions as if the feature is implemented. --- .../JavaScript/HelperMarshal.cs | 21 ++++++ .../JavaScript/MarshalTests.cs | 74 +++++++++++++------ 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs index 477f29ec0923d4..f612dcb76be527 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs @@ -679,11 +679,32 @@ public static async ValueTask AsynchronousValueTask() await Task.Yield(); } + public static ValueTask SynchronousValueTask() + { + return ValueTask.CompletedTask; + } + + public static ValueTask SynchronousValueTaskInt(int i) + { + return ValueTask.FromResult(i); + } + public static async ValueTask AsynchronousValueTaskInt(int i) { await Task.Yield(); return i; } + + public static ValueTask FailedSynchronousValueTask() + { + return ValueTask.FromException(new Exception()); + } + + public static async ValueTask FailedAsynchronousValueTask() + { + await Task.Yield(); + throw new Exception(); + } } public enum TestEnum : uint { diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index 8830b322be1ed0..b4b20b30c80499 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -923,6 +923,16 @@ private static async Task MarshalTask(string helperMethodName, string help return resolved; } + private static async Task MarshalTaskReturningInt(string helperMethodName) + { + HelperMarshal._intValue = 0; + + bool success = await MarshalTask(helperMethodName, "7", "App.call_test_method ('InvokeInt', [ result ], 'i');"); + + Assert.True(success, $"{helperMethodName} didn't succeeded."); + Assert.Equal(7, HelperMarshal._intValue); + } + [Fact] public static async Task MarshalSynchronousTask() { @@ -938,32 +948,21 @@ public static async Task MarshalAsynchronousTask() } [Fact] - public static async Task MarshalSynchronousTaskInt() + public static Task MarshalSynchronousTaskInt() { - HelperMarshal._intValue = 0; - - bool success = await MarshalTask("SynchronousTaskInt", "7", "App.call_test_method ('InvokeInt', [ result ], 'i');"); - - Assert.True(success, "SynchronousTask didn't succeeded."); - Assert.Equal(7, HelperMarshal._intValue); + return MarshalTaskReturningInt("SynchronousTaskInt"); } [Fact] - public static async Task MarshalAsynchronousTaskInt() + public static Task MarshalAsynchronousTaskInt() { - HelperMarshal._intValue = 0; - - bool success = await MarshalTask("AsynchronousTaskInt", "7", "App.call_test_method ('InvokeInt', [ result ], 'i');"); - - Assert.True(success, "AsynchronousTask didn't succeeded."); - Assert.Equal(7, HelperMarshal._intValue); + return MarshalTaskReturningInt("AsynchronousTaskInt"); } [Fact] public static async Task MarshalFailedSynchronousTask() { bool success = await MarshalTask("FailedSynchronousTask"); - Assert.False(success, "FailedSynchronousTask didn't failed."); } @@ -971,24 +970,53 @@ public static async Task MarshalFailedSynchronousTask() public static async Task MarshalFailedAsynchronousTask() { bool success = await MarshalTask("FailedAsynchronousTask"); - Assert.False(success, "FailedAsynchronousTask didn't failed."); } [Fact] - [Trait("Category","Marek")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] + public static async Task MarshalSynchronousValueTaskDoesNotWorkYet() + { + bool success = await MarshalTask("SynchronousValueTask"); + Assert.True(success, "SynchronousValueTask didn't succeeded."); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] public static async Task MarshalAsynchronousValueTaskDoesNotWorkYet() { - var exception = await Assert.ThrowsAsync(() => MarshalTask("AsynchronousValueTask")); - Assert.StartsWith("Error: no idea on how to unbox value types", exception.Message); + bool success = await MarshalTask("AsynchronousValueTask"); + Assert.True(success, "AsynchronousValueTask didn't succeeded."); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] + public static Task MarshalSynchronousValueTaskIntDoesNotWorkYet() + { + return MarshalTaskReturningInt("SynchronousValueTaskInt"); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] + public static Task MarshalAsynchronousValueTaskIntDoesNotWorkYet() + { + return MarshalTaskReturningInt("AsynchronousValueTaskInt"); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] + public static async Task MarshalFailedSynchronousValueTaskDoesNotWorkYet() + { + bool success = await MarshalTask("FailedSynchronousValueTask"); + Assert.False(success, "FailedSynchronousValueTask didn't failed."); } [Fact] - [Trait("Category","Marek")] - public static async Task MarshalAsynchronousValueTaskIntDoesNotWorkYet() + [ActiveIssue("https://github.com/dotnet/runtime/issues/61368")] + public static async Task MarshalFailedAsynchronousValueTaskDoesNotWorkYet() { - var exception = await Assert.ThrowsAsync(() => MarshalTask("AsynchronousValueTaskInt", "7")); - Assert.StartsWith("Error: no idea on how to unbox value types", exception.Message); + bool success = await MarshalTask("FailedAsynchronousValueTask"); + Assert.False(success, "FailedAsynchronousValueTask didn't failed."); } } }