예제 #1
0
    public Task CanCompleteAsyncCallsWithErrorsDuringDeserialization()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        // Act/Assert: Tasks not initially completed
        var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
        var task          = runtime.InvokeAsync <int>("test identifier", Array.Empty <object>());

        Assert.False(unrelatedTask.IsCompleted);
        Assert.False(task.IsCompleted);
        var bytes  = Encoding.UTF8.GetBytes("Not a string");
        var reader = new Utf8JsonReader(bytes);

        // Act/Assert: Task can be failed
        runtime.EndInvokeJS(
            runtime.BeginInvokeCalls[1].AsyncHandle,
            /* succeeded: */ true,
            ref reader);
        Assert.False(unrelatedTask.IsCompleted);

        return(AssertTask());

        async Task AssertTask()
        {
            var jsException = await Assert.ThrowsAsync <JSException>(async() => await task);

            Assert.IsAssignableFrom <JsonException>(jsException.InnerException);
        }
    }
        public async Task CanCompleteAsyncCallsWithErrorsDuringDeserialization()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act/Assert: Tasks not initially completed
            var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
            var task          = runtime.InvokeAsync <int>("test identifier", Array.Empty <object>());

            Assert.False(unrelatedTask.IsCompleted);
            Assert.False(task.IsCompleted);
            using var jsonDocument = JsonDocument.Parse("\"Not a string\"");

            // Act/Assert: Task can be failed
            runtime.OnEndInvoke(
                runtime.BeginInvokeCalls[1].AsyncHandle,
                /* succeeded: */ true,
                new JSAsyncCallResult(jsonDocument, jsonDocument.RootElement));
            Assert.False(unrelatedTask.IsCompleted);

            var jsException = await Assert.ThrowsAsync <JSException>(() => task);

            Assert.IsType <JsonException>(jsException.InnerException);

            // Verify we've disposed the JsonDocument.
            Assert.Throws <ObjectDisposedException>(() => jsonDocument.RootElement.Type);
        }
예제 #3
0
    public void CanCompleteAsyncCallsAsFailure()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        // Act/Assert: Tasks not initially completed
        var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
        var task          = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());

        Assert.False(unrelatedTask.IsCompleted);
        Assert.False(task.IsCompleted);
        var bytes  = Encoding.UTF8.GetBytes("\"This is a test exception\"");
        var reader = new Utf8JsonReader(bytes);

        reader.Read();

        // Act/Assert: Task can be failed
        runtime.EndInvokeJS(
            runtime.BeginInvokeCalls[1].AsyncHandle,
            /* succeeded: */ false,
            ref reader);
        Assert.False(unrelatedTask.IsCompleted);
        Assert.True(task.IsCompleted);

        var exception   = Assert.IsType <AggregateException>(task.AsTask().Exception);
        var jsException = Assert.IsType <JSException>(exception.InnerException);

        Assert.Equal("This is a test exception", jsException.Message);
    }
예제 #4
0
        public void CanCompleteAsyncCallsAsFailure()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act/Assert: Tasks not initially completed
            var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
            var task          = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());

            Assert.False(unrelatedTask.IsCompleted);
            Assert.False(task.IsCompleted);
            using var jsonDocument = JsonDocument.Parse("\"This is a test exception\"");

            // Act/Assert: Task can be failed
            runtime.OnEndInvoke(
                runtime.BeginInvokeCalls[1].AsyncHandle,
                /* succeeded: */ false,
                new JSAsyncCallResult(jsonDocument, jsonDocument.RootElement));
            Assert.False(unrelatedTask.IsCompleted);
            Assert.True(task.IsCompleted);

            Assert.IsType <AggregateException>(task.Exception);
            Assert.IsType <JSException>(task.Exception.InnerException);
            Assert.Equal("This is a test exception", ((JSException)task.Exception.InnerException).Message);
        }
예제 #5
0
        public void SerializesDotNetObjectWrappersInKnownFormat()
        {
            // Arrange
            var runtime = new TestJSRuntime();
            var obj1    = new object();
            var obj2    = new object();
            var obj3    = new object();

            // Act
            // Showing we can pass the DotNetObject either as top-level args or nested
            var obj1Ref          = new DotNetObjectRef(obj1);
            var obj1DifferentRef = new DotNetObjectRef(obj1);

            runtime.InvokeAsync <object>("test identifier",
                                         obj1Ref,
                                         new Dictionary <string, object>
            {
                { "obj2", new DotNetObjectRef(obj2) },
                { "obj3", new DotNetObjectRef(obj3) },
                { "obj1SameRef", obj1Ref },
                { "obj1DifferentRef", obj1DifferentRef },
            });

            // Assert: Serialized as expected
            var call = runtime.BeginInvokeCalls.Single();

            Assert.Equal("test identifier", call.Identifier);
            Assert.Equal("[\"__dotNetObject:1\",{\"obj2\":\"__dotNetObject:2\",\"obj3\":\"__dotNetObject:3\",\"obj1SameRef\":\"__dotNetObject:1\",\"obj1DifferentRef\":\"__dotNetObject:4\"}]", call.ArgsJson);

            // Assert: Objects were tracked
            Assert.Same(obj1, runtime.ArgSerializerStrategy.FindDotNetObject(1));
            Assert.Same(obj2, runtime.ArgSerializerStrategy.FindDotNetObject(2));
            Assert.Same(obj3, runtime.ArgSerializerStrategy.FindDotNetObject(3));
            Assert.Same(obj1, runtime.ArgSerializerStrategy.FindDotNetObject(4));
        }
예제 #6
0
        public void CanCompleteAsyncCallsAsSuccess()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act/Assert: Tasks not initially completed
            var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
            var task          = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());

            Assert.False(unrelatedTask.IsCompleted);
            Assert.False(task.IsCompleted);

            // Act/Assert: Task can be completed
            runtime.OnEndInvoke(
                runtime.BeginInvokeCalls[1].AsyncHandle,
                /* succeeded: */ true,
                "my result");
            Assert.False(unrelatedTask.IsCompleted);
            Assert.True(task.IsCompleted);
            Assert.Equal("my result", task.Result);
        }
예제 #7
0
    public async Task InvokeAsync_CancelsAsyncTask_AfterDefaultTimeout()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        runtime.DefaultTimeout = TimeSpan.FromSeconds(1);

        // Act
        var task = runtime.InvokeAsync <object>("test identifier 1", "arg1", 123, true);

        // Assert
        await Assert.ThrowsAsync <TaskCanceledException>(async() => await task);
    }
예제 #8
0
    public async Task InvokeAsync_CancelsAsyncTasksWhenCancellationTokenFires()
    {
        // Arrange
        using var cts = new CancellationTokenSource();
        var runtime = new TestJSRuntime();

        // Act
        var task = runtime.InvokeAsync <object>("test identifier 1", cts.Token, new object[] { "arg1", 123, true });

        cts.Cancel();

        // Assert
        await Assert.ThrowsAsync <TaskCanceledException>(async() => await task);
    }
예제 #9
0
        public void DispatchesAsyncCallsWithDistinctAsyncHandles()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act
            runtime.InvokeAsync <object>("test identifier 1", "arg1", 123, true);
            runtime.InvokeAsync <object>("test identifier 2", "some other arg");

            // Assert
            Assert.Collection(runtime.BeginInvokeCalls,
                              call =>
            {
                Assert.Equal("test identifier 1", call.Identifier);
                Assert.Equal("[\"arg1\",123,true]", call.ArgsJson);
            },
                              call =>
            {
                Assert.Equal("test identifier 2", call.Identifier);
                Assert.Equal("[\"some other arg\"]", call.ArgsJson);
                Assert.NotEqual(runtime.BeginInvokeCalls[0].AsyncHandle, call.AsyncHandle);
            });
        }
예제 #10
0
        public void SupportsCustomSerializationForArguments()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Arrange/Act
            runtime.InvokeAsync <object>("test identifier",
                                         new WithCustomArgSerializer());

            // Asssert
            var call = runtime.BeginInvokeCalls.Single();

            Assert.Equal("[{\"key1\":\"value1\",\"key2\":123}]", call.ArgsJson);
        }
예제 #11
0
    public void CanCompleteAsyncCallsAsSuccess()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        // Act/Assert: Tasks not initially completed
        var unrelatedTask = runtime.InvokeAsync <string>("unrelated call", Array.Empty <object>());
        var task          = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());

        Assert.False(unrelatedTask.IsCompleted);
        Assert.False(task.IsCompleted);
        var bytes  = Encoding.UTF8.GetBytes("\"my result\"");
        var reader = new Utf8JsonReader(bytes);

        // Act/Assert: Task can be completed
        runtime.EndInvokeJS(
            runtime.BeginInvokeCalls[1].AsyncHandle,
            /* succeeded: */ true,
            ref reader);
        Assert.False(unrelatedTask.IsCompleted);
        Assert.True(task.IsCompleted);
        Assert.Equal("my result", task.Result);
    }
예제 #12
0
        public async Task InvokeAsync_CompletesSuccessfullyBeforeTimeout()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            runtime.DefaultTimeout = TimeSpan.FromSeconds(10);

            // Act
            var task = runtime.InvokeAsync <object>("test identifier 1", "arg1", 123, true);

            runtime.EndInvokeJS(2, succeeded: true, null);

            // Assert
            await task;
        }
예제 #13
0
    public void InvokeAsync_CompletesSuccessfullyBeforeTimeout()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        runtime.DefaultTimeout = TimeSpan.FromSeconds(10);
        var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes("null"));

        // Act
        var task = runtime.InvokeAsync <object>("test identifier 1", "arg1", 123, true);

        runtime.EndInvokeJS(2, succeeded: true, ref reader);

        Assert.True(task.IsCompletedSuccessfully);
    }
예제 #14
0
        public async Task CompletingSameAsyncCallMoreThanOnce_IgnoresSecondResultAsync()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act/Assert
            var task        = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());
            var asyncHandle = runtime.BeginInvokeCalls[0].AsyncHandle;

            runtime.OnEndInvoke(asyncHandle, true, new JSAsyncCallResult(JsonDocument.Parse("{}"), JsonDocument.Parse("{\"Message\": \"Some data\"}").RootElement.GetProperty("Message")));
            runtime.OnEndInvoke(asyncHandle, false, new JSAsyncCallResult(null, JsonDocument.Parse("{\"Message\": \"Exception\"}").RootElement.GetProperty("Message")));

            var result = await task;

            Assert.Equal("Some data", result);
        }
예제 #15
0
    public async Task InvokeAsync_DoesNotStartWorkWhenCancellationHasBeenRequested()
    {
        // Arrange
        using var cts = new CancellationTokenSource();
        cts.Cancel();
        var runtime = new TestJSRuntime();

        // Act
        var task = runtime.InvokeAsync <object>("test identifier 1", cts.Token, new object[] { "arg1", 123, true });

        cts.Cancel();

        // Assert
        await Assert.ThrowsAsync <TaskCanceledException>(async() => await task);

        Assert.Empty(runtime.BeginInvokeCalls);
    }
예제 #16
0
        public void CannotCompleteSameAsyncCallMoreThanOnce()
        {
            // Arrange
            var runtime = new TestJSRuntime();

            // Act/Assert
            runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());
            var asyncHandle = runtime.BeginInvokeCalls[0].AsyncHandle;

            runtime.OnEndInvoke(asyncHandle, true, null);
            var ex = Assert.Throws <ArgumentException>(() =>
            {
                // Second "end invoke" will fail
                runtime.OnEndInvoke(asyncHandle, true, null);
            });

            Assert.Equal($"There is no pending task with handle '{asyncHandle}'.", ex.Message);
        }
예제 #17
0
    public void CanCompleteAsyncCallsWithComplexType()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        var task   = runtime.InvokeAsync <TestPoco>("test identifier", Array.Empty <object>());
        var bytes  = Encoding.UTF8.GetBytes("{\"id\":10, \"name\": \"Test\"}");
        var reader = new Utf8JsonReader(bytes);

        // Act/Assert: Task can be completed
        runtime.EndInvokeJS(
            runtime.BeginInvokeCalls[0].AsyncHandle,
            /* succeeded: */ true,
            ref reader);
        Assert.True(task.IsCompleted);
        var poco = task.Result;

        Debug.Assert(poco != null);
        Assert.Equal(10, poco.Id);
        Assert.Equal("Test", poco.Name);
    }
예제 #18
0
    public Task CompletingSameAsyncCallMoreThanOnce_IgnoresSecondResultAsync()
    {
        // Arrange
        var runtime = new TestJSRuntime();

        // Act/Assert
        var task         = runtime.InvokeAsync <string>("test identifier", Array.Empty <object>());
        var asyncHandle  = runtime.BeginInvokeCalls[0].AsyncHandle;
        var firstReader  = new Utf8JsonReader(Encoding.UTF8.GetBytes("\"Some data\""));
        var secondReader = new Utf8JsonReader(Encoding.UTF8.GetBytes("\"Exception\""));

        runtime.EndInvokeJS(asyncHandle, true, ref firstReader);
        runtime.EndInvokeJS(asyncHandle, false, ref secondReader);

        return(AssertTask());

        async Task AssertTask()
        {
            var result = await task;

            Assert.Equal("Some data", result);
        }
    }
예제 #19
0
    public void SerializesDotNetObjectWrappersInKnownFormat()
    {
        // Arrange
        var runtime = new TestJSRuntime();
        var obj1    = new object();
        var obj2    = new object();
        var obj3    = new object();

        // Act
        // Showing we can pass the DotNetObject either as top-level args or nested
        var obj1Ref          = DotNetObjectReference.Create(obj1);
        var obj1DifferentRef = DotNetObjectReference.Create(obj1);

        runtime.InvokeAsync <object>("test identifier",
                                     obj1Ref,
                                     new Dictionary <string, object>
        {
            { "obj2", DotNetObjectReference.Create(obj2) },
            { "obj3", DotNetObjectReference.Create(obj3) },
            { "obj1SameRef", obj1Ref },
            { "obj1DifferentRef", obj1DifferentRef },
        });

        // Assert: Serialized as expected
        var call = runtime.BeginInvokeCalls.Single();

        Assert.Equal("test identifier", call.Identifier);
        Assert.Equal("[{\"__dotNetObject\":1},{\"obj2\":{\"__dotNetObject\":2},\"obj3\":{\"__dotNetObject\":3},\"obj1SameRef\":{\"__dotNetObject\":1},\"obj1DifferentRef\":{\"__dotNetObject\":4}}]", call.ArgsJson);

        // Assert: Objects were tracked
        Assert.Same(obj1Ref, runtime.GetObjectReference(1));
        Assert.Same(obj1, obj1Ref.Value);
        Assert.NotSame(obj1Ref, runtime.GetObjectReference(2));
        Assert.Same(obj2, runtime.GetObjectReference(2).Value);
        Assert.Same(obj3, runtime.GetObjectReference(3).Value);
        Assert.Same(obj1, runtime.GetObjectReference(4).Value);
    }