From 89922a399fcd474e4eaa09afdc999bbed40d09b7 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 14:43:56 +1200 Subject: [PATCH 01/28] Capture server logs in tests --- .../HubConnectionTests.cs | 85 ++++++++++++++++--- .../ServerFixture.cs | 39 +++++++++ .../VerifiableLoggedTest.cs | 54 +++++++++++- .../EndToEndTests.cs | 4 +- .../WebSocketsTransportTests.cs | 4 +- 5 files changed, 167 insertions(+), 19 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 0121d2577f..b198d664ff 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -30,11 +30,10 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Collection(HubConnectionTestsCollection.Name)] - public class HubConnectionTests : VerifiableLoggedTest + public class HubConnectionTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; - public HubConnectionTests(ServerFixture serverFixture, ITestOutputHelper output) - : base(output) + public HubConnectionTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { if (serverFixture == null) { @@ -436,8 +435,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ExceptionFromStreamingSentToClient(string protocolName, HttpTransportType transportType, string path) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var protocol = HubProtocols[protocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ExceptionFromStreamingSentToClient)}_{protocol.Name}_{transportType}_{path.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ExceptionFromStreamingSentToClient)}_{protocol.Name}_{transportType}_{path.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(path, transportType, protocol, loggerFactory); try @@ -464,8 +469,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionIfHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "UnknownHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfHubMethodCannotBeResolved)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfHubMethodCannotBeResolved)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -491,8 +502,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionOnHubMethodArgumentCountMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnHubMethodArgumentCountMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnHubMethodArgumentCountMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -518,8 +535,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -545,8 +568,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionIfStreamingHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "UnknownHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfStreamingHubMethodCannotBeResolved)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfStreamingHubMethodCannotBeResolved)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -573,8 +602,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentCountMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnStreamingHubMethodArgumentCountMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnStreamingHubMethodArgumentCountMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { loggerFactory.AddConsole(LogLevel.Trace); var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); @@ -602,8 +637,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnStreamingHubMethodArgumentTypeMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionOnStreamingHubMethodArgumentTypeMismatch)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -630,8 +671,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionIfNonStreamMethodInvokedWithStreamAsync(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "NonStreamingMethodCalledWithStream"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfNonStreamMethodInvokedWithStreamAsync)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfNonStreamMethodInvokedWithStreamAsync)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -657,8 +704,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionIfStreamMethodInvokedWithInvoke(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "StreamingMethodCalledWithInvoke"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfStreamMethodInvokedWithInvoke)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfStreamMethodInvokedWithInvoke)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try @@ -684,8 +737,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] public async Task ServerThrowsHubExceptionIfBuildingAsyncEnumeratorIsNotPossible(string hubProtocolName, HttpTransportType transportType, string hubPath) { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + writeContext.EventId.Name == "InvalidReturnValueFromStreamingMethod"; + } + var hubProtocol = HubProtocols[hubProtocolName]; - using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfBuildingAsyncEnumeratorIsNotPossible)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}")) + using (StartVerifableLog(out var loggerFactory, $"{nameof(ServerThrowsHubExceptionIfBuildingAsyncEnumeratorIsNotPossible)}_{hubProtocol.Name}_{transportType}_{hubPath.TrimStart('/')}", expectedErrorsFilter: ExpectedErrors)) { var connection = CreateHubConnection(hubPath, transportType, hubProtocol, loggerFactory); try diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs index 462201fd75..31330b9181 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs @@ -29,6 +29,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly LogSinkProvider _logSinkProvider; + internal event Action ServerLogged + { + add => _logSinkProvider.RecordLogged += value; + remove => _logSinkProvider.RecordLogged -= value; + } + public string WebSocketsUrl => Url.Replace("http", "ws"); public string Url { get; private set; } @@ -146,11 +152,42 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + //internal class ForwardingLoggerProvider : ILoggerProvider + //{ + // private readonly HashSet _loggerFactories; + + // public ForwardingLoggerProvider() + // { + // _loggerFactories = new HashSet(); + // } + + // public void AddFactory(ILoggerFactory loggerFactory) + // { + // _loggerFactories.Add(loggerFactory); + // } + + // public void RemoveFactory(ILoggerFactory loggerFactory) + // { + // _loggerFactories.Remove(loggerFactory); + // } + + // public void Dispose() + // { + // } + + // public ILogger CreateLogger(string categoryName) + // { + // return _loggerFactory.CreateLogger(categoryName); + // } + //} + // TestSink doesn't seem to be thread-safe :(. internal class LogSinkProvider : ILoggerProvider { private readonly ConcurrentQueue _logs = new ConcurrentQueue(); + public event Action RecordLogged; + public ILogger CreateLogger(string categoryName) { return new LogSinkLogger(categoryName, this); @@ -176,6 +213,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests Formatter = (o, e) => formatter((TState)o, e), }); _logs.Enqueue(record); + + RecordLogged?.Invoke(record); } private class LogSinkLogger : ILogger diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs index 1968f3bcdd..9359c41876 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs @@ -11,20 +11,70 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Tests { + public class VerifiableServerLoggedTest : VerifiableLoggedTest where TStartup : class + { + public ServerFixture ServerFixture { get; } + + public VerifiableServerLoggedTest(ServerFixture serverFixture, ITestOutputHelper output) : base(output) + { + ServerFixture = serverFixture; + } + + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName = null, Func expectedErrorsFilter = null) + { + var disposable = base.StartVerifableLog(out loggerFactory, minLogLevel, testName, expectedErrorsFilter); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); + } + + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, string testName = null, Func expectedErrorsFilter = null) + { + var disposable = base.StartVerifableLog(out loggerFactory, testName, expectedErrorsFilter); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); + } + } + + public class ServerLogScope : IDisposable where TStartup : class + { + private readonly ServerFixture _serverFixture; + private readonly IDisposable _wrappedDisposable; + private readonly ILogger _logger; + + public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) + { + _serverFixture = serverFixture; + _wrappedDisposable = wrappedDisposable; + _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + + _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + } + + private void ServerFixtureOnServerLogged(LogRecord logRecord) + { + _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + } + + public void Dispose() + { + _serverFixture.ServerLogged -= ServerFixtureOnServerLogged; + + _wrappedDisposable?.Dispose(); + } + } + public class VerifiableLoggedTest : LoggedTest { public VerifiableLoggedTest(ITestOutputHelper output) : base(output) { } - public IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) + public virtual IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) { var disposable = StartLog(out loggerFactory, testName); return new VerifyNoErrorsScope(loggerFactory, disposable, expectedErrorsFilter); } - public IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) + public virtual IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) { var disposable = StartLog(out loggerFactory, minLogLevel, testName); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 8c5096b319..168e2e77d8 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -34,11 +34,11 @@ namespace Microsoft.AspNetCore.SignalR.Tests } [Collection(EndToEndTestsCollection.Name)] - public class EndToEndTests : VerifiableLoggedTest + public class EndToEndTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; - public EndToEndTests(ServerFixture serverFixture, ITestOutputHelper output) : base(output) + public EndToEndTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { if (serverFixture == null) { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs index 18c3d64437..4f7aaae831 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs @@ -22,11 +22,11 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Tests { [Collection(EndToEndTestsCollection.Name)] - public class WebSocketsTransportTests : VerifiableLoggedTest + public class WebSocketsTransportTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; - public WebSocketsTransportTests(ServerFixture serverFixture, ITestOutputHelper output) : base(output) + public WebSocketsTransportTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { if (serverFixture == null) { From a13f3f4765ca75e703badb72af84bffda302ca7b Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 17:11:09 +1200 Subject: [PATCH 02/28] Clean up --- .../ServerLogScope.cs | 36 +++++++++++++ .../VerifiableLoggedTest.cs | 50 ------------------- .../VerifiableServerLoggedTest.cs | 32 ++++++++++++ 3 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs create mode 100644 test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs new file mode 100644 index 0000000000..3e5518a466 --- /dev/null +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.SignalR.Tests +{ + public class ServerLogScope : IDisposable where TStartup : class + { + private readonly ServerFixture _serverFixture; + private readonly IDisposable _wrappedDisposable; + private readonly ILogger _logger; + + public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) + { + _serverFixture = serverFixture; + _wrappedDisposable = wrappedDisposable; + _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + + _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + } + + private void ServerFixtureOnServerLogged(LogRecord logRecord) + { + _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + } + + public void Dispose() + { + _serverFixture.ServerLogged -= ServerFixtureOnServerLogged; + + _wrappedDisposable?.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs index 9359c41876..061823836c 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableLoggedTest.cs @@ -11,56 +11,6 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Tests { - public class VerifiableServerLoggedTest : VerifiableLoggedTest where TStartup : class - { - public ServerFixture ServerFixture { get; } - - public VerifiableServerLoggedTest(ServerFixture serverFixture, ITestOutputHelper output) : base(output) - { - ServerFixture = serverFixture; - } - - public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName = null, Func expectedErrorsFilter = null) - { - var disposable = base.StartVerifableLog(out loggerFactory, minLogLevel, testName, expectedErrorsFilter); - return new ServerLogScope(ServerFixture, loggerFactory, disposable); - } - - public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, string testName = null, Func expectedErrorsFilter = null) - { - var disposable = base.StartVerifableLog(out loggerFactory, testName, expectedErrorsFilter); - return new ServerLogScope(ServerFixture, loggerFactory, disposable); - } - } - - public class ServerLogScope : IDisposable where TStartup : class - { - private readonly ServerFixture _serverFixture; - private readonly IDisposable _wrappedDisposable; - private readonly ILogger _logger; - - public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) - { - _serverFixture = serverFixture; - _wrappedDisposable = wrappedDisposable; - _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); - - _serverFixture.ServerLogged += ServerFixtureOnServerLogged; - } - - private void ServerFixtureOnServerLogged(LogRecord logRecord) - { - _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); - } - - public void Dispose() - { - _serverFixture.ServerLogged -= ServerFixtureOnServerLogged; - - _wrappedDisposable?.Dispose(); - } - } - public class VerifiableLoggedTest : LoggedTest { public VerifiableLoggedTest(ITestOutputHelper output) : base(output) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs new file mode 100644 index 0000000000..e92eb61d70 --- /dev/null +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.SignalR.Tests +{ + public class VerifiableServerLoggedTest : VerifiableLoggedTest where TStartup : class + { + public ServerFixture ServerFixture { get; } + + public VerifiableServerLoggedTest(ServerFixture serverFixture, ITestOutputHelper output) : base(output) + { + ServerFixture = serverFixture; + } + + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName = null, Func expectedErrorsFilter = null) + { + var disposable = base.StartVerifableLog(out loggerFactory, minLogLevel, testName, expectedErrorsFilter); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); + } + + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, string testName = null, Func expectedErrorsFilter = null) + { + var disposable = base.StartVerifableLog(out loggerFactory, testName, expectedErrorsFilter); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); + } + } +} \ No newline at end of file From c835288e8493ac49910cc3e08453b07f53bf8949 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 17:51:31 +1200 Subject: [PATCH 03/28] Suppress web socket closing without handshake --- .../Internal/Transports/WebSocketsTransport.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs index 82e091b5b5..902f4a9d7d 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports while (true) { #if NETCOREAPP2_1 - // Do a 0 byte read so that idle connections don't allocate a buffer when waiting for a read +// Do a 0 byte read so that idle connections don't allocate a buffer when waiting for a read var result = await socket.ReceiveAsync(Memory.Empty, CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) @@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports var memory = _application.Output.GetMemory(); #if NETCOREAPP2_1 - // Because we checked the CloseStatus from the 0 byte read above, we don't need to check again after reading +// Because we checked the CloseStatus from the 0 byte read above, we don't need to check again after reading var receiveResult = await socket.ReceiveAsync(memory, CancellationToken.None); #else var isArray = MemoryMarshal.TryGetArray(memory, out var arraySegment); @@ -182,6 +182,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports } } } + catch (WebSocketException ex) when (ex.ErrorCode == 997) + { + // The remote party closed the WebSocket connection without completing the close handshake + // Don't long an error for this exception + } catch (OperationCanceledException) { // Ignore aborts, don't treat them like transport errors From 9d033aa9f9f2fe5f24b01a862b40a380df2a3788 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 18:16:23 +1200 Subject: [PATCH 04/28] Blah --- .../Internal/Transports/WebSocketsTransport.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs index 902f4a9d7d..3632e29c52 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs @@ -182,7 +182,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports } } } - catch (WebSocketException ex) when (ex.ErrorCode == 997) + catch (WebSocketException ex) when ( + ex.ErrorCode == 997 || + // Sometimes this error is raised without the ErrorCode + ex.Message == "The remote party closed the WebSocket connection without completing the close handshake.") { // The remote party closed the WebSocket connection without completing the close handshake // Don't long an error for this exception From 05739820d28d44d7a64b4dc59e62900c0941aa73 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 18:40:53 +1200 Subject: [PATCH 05/28] Test --- .../ServerLogScope.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 3e5518a466..85ff860600 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -10,20 +10,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests { private readonly ServerFixture _serverFixture; private readonly IDisposable _wrappedDisposable; - private readonly ILogger _logger; + //private readonly ILogger _logger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _wrappedDisposable = wrappedDisposable; - _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + //_logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _serverFixture.ServerLogged += ServerFixtureOnServerLogged; } private void ServerFixtureOnServerLogged(LogRecord logRecord) { - _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + //_logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() From 585bcc3ee0dbaa0801b877b46c6d14b4105f1558 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 19:02:56 +1200 Subject: [PATCH 06/28] How about this? --- .../HubConnectionTests.cs | 2 +- .../ServerFixture.cs | 24 ++++++++++++++----- .../ServerLogScope.cs | 6 ++--- .../VerifiableServerLoggedTest.cs | 10 ++++---- .../EndToEndTests.cs | 6 ++++- .../WebSocketsTransportTests.cs | 2 +- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index b198d664ff..922c80a7eb 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Collection(HubConnectionTestsCollection.Name)] - public class HubConnectionTests : VerifiableServerLoggedTest + public class HubConnectionTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; public HubConnectionTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs index 31330b9181..79e7bc89e4 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs @@ -18,7 +18,18 @@ using Microsoft.Extensions.Logging.Testing; namespace Microsoft.AspNetCore.SignalR.Tests { - public class ServerFixture : IDisposable + public abstract class ServerFixture : IDisposable + { + internal abstract event Action ServerLogged; + + public abstract string WebSocketsUrl { get; } + + public abstract string Url { get; } + + public abstract void Dispose(); + } + + public class ServerFixture : ServerFixture where TStartup : class { private readonly ILoggerFactory _loggerFactory; @@ -28,16 +39,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly IDisposable _logToken; private readonly LogSinkProvider _logSinkProvider; + private string _url; - internal event Action ServerLogged + internal override event Action ServerLogged { add => _logSinkProvider.RecordLogged += value; remove => _logSinkProvider.RecordLogged -= value; } - public string WebSocketsUrl => Url.Replace("http", "ws"); + public override string WebSocketsUrl => Url.Replace("http", "ws"); - public string Url { get; private set; } + public override string Url => _url; public ServerFixture() : this(loggerFactory: null) { @@ -98,7 +110,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests _logger.LogInformation("Test Server started"); // Get the URL from the server - Url = _host.ServerFeatures.Get().Addresses.Single(); + _url = _host.ServerFeatures.Get().Addresses.Single(); _lifetime.ApplicationStopped.Register(() => { @@ -125,7 +137,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests return builder.ToString(); } - public void Dispose() + public override void Dispose() { _logger.LogInformation("Shutting down test server"); _host.Dispose(); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 85ff860600..5faf9674d9 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -6,13 +6,13 @@ using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.SignalR.Tests { - public class ServerLogScope : IDisposable where TStartup : class + public class ServerLogScope : IDisposable { - private readonly ServerFixture _serverFixture; + private readonly ServerFixture _serverFixture; private readonly IDisposable _wrappedDisposable; //private readonly ILogger _logger; - public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) + public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _wrappedDisposable = wrappedDisposable; diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs index e92eb61d70..44059b3616 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs @@ -8,11 +8,11 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Tests { - public class VerifiableServerLoggedTest : VerifiableLoggedTest where TStartup : class + public class VerifiableServerLoggedTest : VerifiableLoggedTest { - public ServerFixture ServerFixture { get; } + public ServerFixture ServerFixture { get; } - public VerifiableServerLoggedTest(ServerFixture serverFixture, ITestOutputHelper output) : base(output) + public VerifiableServerLoggedTest(ServerFixture serverFixture, ITestOutputHelper output) : base(output) { ServerFixture = serverFixture; } @@ -20,13 +20,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName = null, Func expectedErrorsFilter = null) { var disposable = base.StartVerifableLog(out loggerFactory, minLogLevel, testName, expectedErrorsFilter); - return new ServerLogScope(ServerFixture, loggerFactory, disposable); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); } public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, string testName = null, Func expectedErrorsFilter = null) { var disposable = base.StartVerifableLog(out loggerFactory, testName, expectedErrorsFilter); - return new ServerLogScope(ServerFixture, loggerFactory, disposable); + return new ServerLogScope(ServerFixture, loggerFactory, disposable); } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 168e2e77d8..6aa8e679c2 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests } [Collection(EndToEndTestsCollection.Name)] - public class EndToEndTests : VerifiableServerLoggedTest + public class EndToEndTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; @@ -44,6 +44,10 @@ namespace Microsoft.AspNetCore.SignalR.Tests { throw new ArgumentNullException(nameof(serverFixture)); } + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } _serverFixture = serverFixture; } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs index 4f7aaae831..f83452da37 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs @@ -22,7 +22,7 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Tests { [Collection(EndToEndTestsCollection.Name)] - public class WebSocketsTransportTests : VerifiableServerLoggedTest + public class WebSocketsTransportTests : VerifiableServerLoggedTest { private readonly ServerFixture _serverFixture; From 25aea395da3160ac0d1aebb3a7bec626a6439fe1 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 19:10:37 +1200 Subject: [PATCH 07/28] ah-ha! --- .../ServerLogScope.cs | 6 +++--- .../VerifiableServerLoggedTest.cs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 5faf9674d9..5ff8ad4c52 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -10,20 +10,20 @@ namespace Microsoft.AspNetCore.SignalR.Tests { private readonly ServerFixture _serverFixture; private readonly IDisposable _wrappedDisposable; - //private readonly ILogger _logger; + private readonly ILogger _logger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _wrappedDisposable = wrappedDisposable; - //_logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _serverFixture.ServerLogged += ServerFixtureOnServerLogged; } private void ServerFixtureOnServerLogged(LogRecord logRecord) { - //_logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs index 44059b3616..1035116e6a 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/VerifiableServerLoggedTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Runtime.CompilerServices; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Xunit.Abstractions; @@ -17,13 +18,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests ServerFixture = serverFixture; } - public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName = null, Func expectedErrorsFilter = null) + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) { var disposable = base.StartVerifableLog(out loggerFactory, minLogLevel, testName, expectedErrorsFilter); return new ServerLogScope(ServerFixture, loggerFactory, disposable); } - public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, string testName = null, Func expectedErrorsFilter = null) + public override IDisposable StartVerifableLog(out ILoggerFactory loggerFactory, [CallerMemberName] string testName = null, Func expectedErrorsFilter = null) { var disposable = base.StartVerifableLog(out loggerFactory, testName, expectedErrorsFilter); return new ServerLogScope(ServerFixture, loggerFactory, disposable); From 81b593fdbeb08f64a77f452393b5fb09f41779c9 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 19:18:36 +1200 Subject: [PATCH 08/28] More logging! --- test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 6aa8e679c2..a9512d1ea6 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [MemberData(nameof(TransportTypes))] public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { - using (StartVerifableLog(out var loggerFactory)) + using (StartVerifableLog(out var loggerFactory, minLogLevel: LogLevel.Trace)) { var url = _serverFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); From 1d900fe1396929ab302f54539c4d5c2af6a56a45 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 19:19:24 +1200 Subject: [PATCH 09/28] More logging! --- test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index a9512d1ea6..7fe4cd086a 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [MemberData(nameof(TransportTypes))] public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { - using (StartVerifableLog(out var loggerFactory, minLogLevel: LogLevel.Trace)) + using (StartVerifableLog(out var loggerFactory, testName: $"CanStartAndStopConnectionUsingGivenTransport_{transportType}", minLogLevel: LogLevel.Trace)) { var url = _serverFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); From 5b188018f082b7a4e7bf85a22c45189ea8766cd2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 19:56:46 +1200 Subject: [PATCH 10/28] Log level --- .../ServerFixture.cs | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs index 79e7bc89e4..952a29ef83 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerFixture.cs @@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests _host = new WebHostBuilder() .ConfigureLogging(builder => builder - .SetMinimumLevel(LogLevel.Debug) + .SetMinimumLevel(LogLevel.Trace) .AddProvider(_logSinkProvider) .AddProvider(new ForwardingLoggerProvider(_loggerFactory))) .UseStartup(typeof(TStartup)) @@ -164,35 +164,6 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - //internal class ForwardingLoggerProvider : ILoggerProvider - //{ - // private readonly HashSet _loggerFactories; - - // public ForwardingLoggerProvider() - // { - // _loggerFactories = new HashSet(); - // } - - // public void AddFactory(ILoggerFactory loggerFactory) - // { - // _loggerFactories.Add(loggerFactory); - // } - - // public void RemoveFactory(ILoggerFactory loggerFactory) - // { - // _loggerFactories.Remove(loggerFactory); - // } - - // public void Dispose() - // { - // } - - // public ILogger CreateLogger(string categoryName) - // { - // return _loggerFactory.CreateLogger(categoryName); - // } - //} - // TestSink doesn't seem to be thread-safe :(. internal class LogSinkProvider : ILoggerProvider { From 5a64429fd5af930d030305588243792c1a630ac8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 20:21:45 +1200 Subject: [PATCH 11/28] Improvements! --- .../HubConnectionTests.cs | 15 ++++++++------- .../ServerLogScope.cs | 10 +++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 922c80a7eb..8f889b95af 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections.Client; +using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing.xunit; @@ -437,7 +438,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -471,7 +472,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -570,7 +571,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -639,7 +640,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -673,7 +674,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "NonStreamingMethodCalledWithStream"; } @@ -706,7 +707,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "StreamingMethodCalledWithInvoke"; } @@ -739,7 +740,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "InvalidReturnValueFromStreamingMethod"; } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 5ff8ad4c52..ead19e80a3 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Concurrent; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.SignalR.Tests @@ -9,21 +10,24 @@ namespace Microsoft.AspNetCore.SignalR.Tests public class ServerLogScope : IDisposable { private readonly ServerFixture _serverFixture; + private readonly ILoggerFactory _loggerFactory; private readonly IDisposable _wrappedDisposable; - private readonly ILogger _logger; + private readonly ConcurrentDictionary _loggers; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; + _loggerFactory = loggerFactory; _wrappedDisposable = wrappedDisposable; - _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + _loggers = new ConcurrentDictionary(StringComparer.Ordinal); _serverFixture.ServerLogged += ServerFixtureOnServerLogged; } private void ServerFixtureOnServerLogged(LogRecord logRecord) { - _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + var logger = _loggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); + logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() From 0a5dd8f6d34ca2f3e2090628d35a874b7d2ccfe3 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 15 Apr 2018 20:26:54 +1200 Subject: [PATCH 12/28] Fix tests --- .../HubConnectionTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 8f889b95af..beb281a7f7 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -505,7 +505,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -538,7 +538,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -605,7 +605,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Tests.ServerLogScope" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } From 64f52d10984fa5b2051813c72ba56ac89196bfdf Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 08:33:19 +1200 Subject: [PATCH 13/28] y u no log? --- .../HubConnectionTests.cs | 49 ++++++++----------- .../ServerLogScope.cs | 3 ++ .../EndToEndTests.cs | 34 +++++-------- .../WebSocketsTransportTests.cs | 22 +++------ 4 files changed, 40 insertions(+), 68 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index beb281a7f7..5290c528cb 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -5,14 +5,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections.Client; -using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing.xunit; @@ -33,15 +31,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Collection(HubConnectionTestsCollection.Name)] public class HubConnectionTests : VerifiableServerLoggedTest { - private readonly ServerFixture _serverFixture; public HubConnectionTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { - if (serverFixture == null) - { - throw new ArgumentNullException(nameof(serverFixture)); - } - - _serverFixture = serverFixture; } private HubConnection CreateHubConnection( @@ -66,7 +57,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { return async format => { - var connection = new HttpConnection(new Uri(_serverFixture.Url + path), transportType, loggerFactory); + var connection = new HttpConnection(new Uri(ServerFixture.Url + path), transportType, loggerFactory); await connection.StartAsync(format); return connection; }; @@ -81,7 +72,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + path, transportType); + .WithUrl(ServerFixture.Url + path, transportType); connectionBuilder.Services.AddSingleton(protocol); var connection = connectionBuilder.Build(); @@ -438,7 +429,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -472,7 +463,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -505,7 +496,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -538,7 +529,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -571,7 +562,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -605,7 +596,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -640,7 +631,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -674,7 +665,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "NonStreamingMethodCalledWithStream"; } @@ -707,7 +698,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "StreamingMethodCalledWithInvoke"; } @@ -740,7 +731,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "InvalidReturnValueFromStreamingMethod"; } @@ -775,14 +766,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { async Task AccessTokenProvider() { - var httpResponse = await new HttpClient().GetAsync(_serverFixture.Url + "/generateJwtToken"); + var httpResponse = await new HttpClient().GetAsync(ServerFixture.Url + "/generateJwtToken"); httpResponse.EnsureSuccessStatusCode(); return await httpResponse.Content.ReadAsStringAsync(); }; var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + "/authorizedhub", transportType, options => + .WithUrl(ServerFixture.Url + "/authorizedhub", transportType, options => { options.AccessTokenProvider = AccessTokenProvider; }) @@ -813,7 +804,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + "/default", transportType, options => + .WithUrl(ServerFixture.Url + "/default", transportType, options => { options.Headers["X-test"] = "42"; options.Headers["X-42"] = "test"; @@ -845,11 +836,11 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { // System.Net has a HttpTransportType type which means we need to fully-qualify this rather than 'use' the namespace var cookieJar = new System.Net.CookieContainer(); - cookieJar.Add(new System.Net.Cookie("Foo", "Bar", "/", new Uri(_serverFixture.Url).Host)); + cookieJar.Add(new System.Net.Cookie("Foo", "Bar", "/", new Uri(ServerFixture.Url).Host)); var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + "/default", HttpTransportType.WebSockets, options => + .WithUrl(ServerFixture.Url + "/default", HttpTransportType.WebSockets, options => { options.WebSocketConfiguration = o => o.Cookies = cookieJar; }) @@ -880,7 +871,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + "/default", transportType) + .WithUrl(ServerFixture.Url + "/default", transportType) .Build(); try { @@ -917,7 +908,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests var hubConnectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) .AddMessagePackProtocol() - .WithUrl(_serverFixture.Url + "/default-nowebsockets"); + .WithUrl(ServerFixture.Url + "/default-nowebsockets"); var hubConnection = hubConnectionBuilder.Build(); try @@ -947,7 +938,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests PollTrackingMessageHandler pollTracker = null; var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) - .WithUrl(_serverFixture.Url + "/default", options => + .WithUrl(ServerFixture.Url + "/default", options => { options.Transports = HttpTransportType.LongPolling; options.HttpMessageHandlerFactory = handler => diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index ead19e80a3..fb1e491ca1 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -13,11 +13,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly ILoggerFactory _loggerFactory; private readonly IDisposable _wrappedDisposable; private readonly ConcurrentDictionary _loggers; + private readonly ILogger _logger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _loggerFactory = loggerFactory; + _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _wrappedDisposable = wrappedDisposable; _loggers = new ConcurrentDictionary(StringComparer.Ordinal); @@ -28,6 +30,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = _loggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 7fe4cd086a..3a8f03e534 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -36,26 +36,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Collection(EndToEndTestsCollection.Name)] public class EndToEndTests : VerifiableServerLoggedTest { - private readonly ServerFixture _serverFixture; - public EndToEndTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { - if (serverFixture == null) - { - throw new ArgumentNullException(nameof(serverFixture)); - } - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - _serverFixture = serverFixture; } [Fact] public async Task CanStartAndStopConnectionUsingDefaultTransport() { - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. var connection = new HttpConnection(new Uri(url)); @@ -66,7 +54,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public async Task TransportThatFallsbackCreatesNewConnection() { - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. // On Windows 7/2008R2 it should use ServerSentEvents transport to connect to the server. @@ -82,7 +70,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { using (StartVerifableLog(out var loggerFactory, testName: $"CanStartAndStopConnectionUsingGivenTransport_{transportType}", minLogLevel: LogLevel.Trace)) { - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.DisposeAsync().OrTimeout(); @@ -100,7 +88,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests const string message = "Hello, World!"; using (var ws = new ClientWebSocket()) { - var socketUrl = _serverFixture.WebSocketsUrl + "/echo"; + var socketUrl = ServerFixture.WebSocketsUrl + "/echo"; logger.LogInformation("Connecting WebSocket to {socketUrl}", socketUrl); await ws.ConnectAsync(new Uri(socketUrl), CancellationToken.None).OrTimeout(); @@ -137,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests const string message = "Hello, World!"; using (var ws = new ClientWebSocket()) { - var socketUrl = _serverFixture.WebSocketsUrl + "/echo"; + var socketUrl = ServerFixture.WebSocketsUrl + "/echo"; logger.LogInformation("Connecting WebSocket to {socketUrl}", socketUrl); await ws.ConnectAsync(new Uri(socketUrl), CancellationToken.None).OrTimeout(); @@ -171,7 +159,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var logger = loggerFactory.CreateLogger(); - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; var mockHttpHandler = new Mock(); mockHttpHandler.Protected() @@ -222,7 +210,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests const string message = "Major Key"; - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); try { @@ -284,7 +272,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = loggerFactory.CreateLogger(); - var url = _serverFixture.Url + "/echo"; + var url = ServerFixture.Url + "/echo"; var connection = new HttpConnection(new Uri(url), HttpTransportType.WebSockets, loggerFactory); try @@ -332,7 +320,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = loggerFactory.CreateLogger(); - var url = _serverFixture.Url + "/auth"; + var url = ServerFixture.Url + "/auth"; var connection = new HttpConnection(new Uri(url), HttpTransportType.WebSockets, loggerFactory); try @@ -371,7 +359,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = loggerFactory.CreateLogger(); - var url = _serverFixture.Url + "/auth"; + var url = ServerFixture.Url + "/auth"; var connection = new HttpConnection(new Uri(url), transportType, loggerFactory); try @@ -428,7 +416,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = loggerFactory.CreateLogger(); - var url = _serverFixture.Url + "/uncreatable"; + var url = ServerFixture.Url + "/uncreatable"; var connection = new HubConnectionBuilder() .WithLoggerFactory(loggerFactory) .WithUrl(url, transportType) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs index f83452da37..90dc73b020 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/WebSocketsTransportTests.cs @@ -3,7 +3,6 @@ using System; using System.Buffers; -using System.IO.Pipelines; using System.Net; using System.Net.WebSockets; using System.Reflection; @@ -14,7 +13,6 @@ using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Client; using Microsoft.AspNetCore.Http.Connections.Client.Internal; using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging.Testing; using Moq; using Xunit; using Xunit.Abstractions; @@ -24,16 +22,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Collection(EndToEndTestsCollection.Name)] public class WebSocketsTransportTests : VerifiableServerLoggedTest { - private readonly ServerFixture _serverFixture; - public WebSocketsTransportTests(ServerFixture serverFixture, ITestOutputHelper output) : base(serverFixture, output) { - if (serverFixture == null) - { - throw new ArgumentNullException(nameof(serverFixture)); - } - - _serverFixture = serverFixture; } [ConditionalFact] @@ -70,7 +60,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/echo"), TransferFormat.Binary).OrTimeout(); await webSocketsTransport.StopAsync().OrTimeout(); await webSocketsTransport.Running.OrTimeout(); @@ -84,7 +74,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/httpheader"), + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/httpheader"), TransferFormat.Binary).OrTimeout(); await webSocketsTransport.Output.WriteAsync(Encoding.UTF8.GetBytes("User-Agent")); @@ -112,7 +102,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/httpheader"), + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/httpheader"), TransferFormat.Binary).OrTimeout(); await webSocketsTransport.Output.WriteAsync(Encoding.UTF8.GetBytes("X-Requested-With")); @@ -135,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/echo"), TransferFormat.Binary); webSocketsTransport.Output.Complete(); await webSocketsTransport.Running.OrTimeout(TimeSpan.FromSeconds(10)); @@ -151,7 +141,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests using (StartVerifableLog(out var loggerFactory)) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echoAndClose"), transferFormat); + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/echoAndClose"), transferFormat); await webSocketsTransport.Output.WriteAsync(new byte[] { 0x42 }); @@ -174,7 +164,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: loggerFactory); - await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), + await webSocketsTransport.StartAsync(new Uri(ServerFixture.WebSocketsUrl + "/echo"), transferFormat).OrTimeout(); await webSocketsTransport.StopAsync().OrTimeout(); From 75ade2d674e0ede01c210b60b573f4385fa6311a Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 08:48:58 +1200 Subject: [PATCH 14/28] y u no log? --- .../ServerLogScope.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index fb1e491ca1..3652dd66e2 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -13,13 +13,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly ILoggerFactory _loggerFactory; private readonly IDisposable _wrappedDisposable; private readonly ConcurrentDictionary _loggers; - private readonly ILogger _logger; + //private readonly ILogger _logger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _loggerFactory = loggerFactory; - _logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + //_logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _wrappedDisposable = wrappedDisposable; _loggers = new ConcurrentDictionary(StringComparer.Ordinal); @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = _loggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); - _logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + //_logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() From aec323d8d266b10d821e2d75b2f198af1763da12 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 09:03:01 +1200 Subject: [PATCH 15/28] Clean up --- .../HubConnectionTests.cs | 22 ++++++++++--------- .../ServerLogScope.cs | 3 --- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 5290c528cb..8a70874b33 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -5,12 +5,14 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections.Client; +using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing.xunit; @@ -429,7 +431,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -463,7 +465,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -496,7 +498,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -529,7 +531,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -562,7 +564,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "UnknownHubMethod"; } @@ -596,7 +598,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -631,7 +633,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; } @@ -665,7 +667,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "NonStreamingMethodCalledWithStream"; } @@ -698,7 +700,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "StreamingMethodCalledWithInvoke"; } @@ -731,7 +733,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { bool ExpectedErrors(WriteContext writeContext) { - return //writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "InvalidReturnValueFromStreamingMethod"; } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 3652dd66e2..ead19e80a3 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -13,13 +13,11 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly ILoggerFactory _loggerFactory; private readonly IDisposable _wrappedDisposable; private readonly ConcurrentDictionary _loggers; - //private readonly ILogger _logger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _loggerFactory = loggerFactory; - //_logger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _wrappedDisposable = wrappedDisposable; _loggers = new ConcurrentDictionary(StringComparer.Ordinal); @@ -30,7 +28,6 @@ namespace Microsoft.AspNetCore.SignalR.Tests { var logger = _loggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); - //_logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() From fbb13c4c1f2e6c0633b3dd39839ac3678fba2184 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 09:38:47 +1200 Subject: [PATCH 16/28] Improve response status logging --- .../Internal/LoggingHttpMessageHandler.cs | 6 +++--- .../HubConnectionTests.cs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LoggingHttpMessageHandler.cs b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LoggingHttpMessageHandler.cs index 7d8df64783..d8a90205fa 100644 --- a/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LoggingHttpMessageHandler.cs +++ b/src/Microsoft.AspNetCore.Http.Connections.Client/Internal/LoggingHttpMessageHandler.cs @@ -43,8 +43,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal private static readonly Action _sendingHttpRequest = LoggerMessage.Define(LogLevel.Trace, new EventId(1, "SendingHttpRequest"), "Sending HTTP request {RequestMethod} '{RequestUrl}'."); - private static readonly Action _unsuccessfulHttpResponse = - LoggerMessage.Define(LogLevel.Warning, new EventId(2, "UnsuccessfulHttpResponse"), "Unsuccessful HTTP response status code of {StatusCode} return from {RequestMethod} '{RequestUrl}'."); + private static readonly Action _unsuccessfulHttpResponse = + LoggerMessage.Define(LogLevel.Warning, new EventId(2, "UnsuccessfulHttpResponse"), "Unsuccessful HTTP response {StatusCode} return from {RequestMethod} '{RequestUrl}'."); public static void SendingHttpRequest(ILogger logger, HttpMethod requestMethod, Uri requestUrl) { @@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal } public static void UnsuccessfulHttpResponse(ILogger logger, HttpStatusCode statusCode, HttpMethod requestMethod, Uri requestUrl) { - _unsuccessfulHttpResponse(logger, statusCode, requestMethod, requestUrl, null); + _unsuccessfulHttpResponse(logger, (int)statusCode, requestMethod, requestUrl, null); } } } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 8a70874b33..9d9dc2829d 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -5,14 +5,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections.Client; -using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing.xunit; From 62f14054ebe3f2dd2b7e7faedcd898322efdbe19 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 10:41:35 +1200 Subject: [PATCH 17/28] Capture and log prematurely closed connections --- .../Internal/Transports/WebSocketsTransport.Log.cs | 7 +++++++ .../Internal/Transports/WebSocketsTransport.cs | 9 +++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.Log.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.Log.cs index 13df2672c6..29067a65b5 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.Log.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.Log.cs @@ -50,6 +50,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports private static readonly Action _sendFailed = LoggerMessage.Define(LogLevel.Error, new EventId(13, "SendFailed"), "Socket failed to send."); + private static readonly Action _closedPrematurely = + LoggerMessage.Define(LogLevel.Debug, new EventId(14, "ClosedPrematurely"), "Socket connection closed prematurely."); + public static void SocketOpened(ILogger logger, string subProtocol) { _socketOpened(logger, subProtocol, null); @@ -115,6 +118,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports _sendFailed(logger, ex); } + public static void ClosedPrematurely(ILogger logger, Exception ex) + { + _closedPrematurely(logger, ex); + } } } } diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs index 3632e29c52..0442ae6a5f 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs @@ -182,13 +182,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports } } } - catch (WebSocketException ex) when ( - ex.ErrorCode == 997 || - // Sometimes this error is raised without the ErrorCode - ex.Message == "The remote party closed the WebSocket connection without completing the close handshake.") + catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) { - // The remote party closed the WebSocket connection without completing the close handshake - // Don't long an error for this exception + // Client has closed the WebSocket connection without completing the close handshake + Log.ClosedPrematurely(_logger, ex); } catch (OperationCanceledException) { From a17320221efd7ca04e50a094368d4e178c990bc2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 16 Apr 2018 10:43:06 +1200 Subject: [PATCH 18/28] Derp --- .../Internal/Transports/WebSocketsTransport.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs index 0442ae6a5f..b3c7126834 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/Transports/WebSocketsTransport.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports while (true) { #if NETCOREAPP2_1 -// Do a 0 byte read so that idle connections don't allocate a buffer when waiting for a read + // Do a 0 byte read so that idle connections don't allocate a buffer when waiting for a read var result = await socket.ReceiveAsync(Memory.Empty, CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) @@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports var memory = _application.Output.GetMemory(); #if NETCOREAPP2_1 -// Because we checked the CloseStatus from the 0 byte read above, we don't need to check again after reading + // Because we checked the CloseStatus from the 0 byte read above, we don't need to check again after reading var receiveResult = await socket.ReceiveAsync(memory, CancellationToken.None); #else var isArray = MemoryMarshal.TryGetArray(memory, out var arraySegment); From 818497de643ee472d1cab89239b0826cc2529285 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 17 Apr 2018 16:57:55 +1200 Subject: [PATCH 19/28] Improvements --- .../HubConnectionTests.cs | 5 +++-- .../RedisEndToEnd.cs | 9 +++++---- .../ServerLogScope.cs | 14 +++++++++++--- .../EndToEndTests.cs | 5 +++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 9d9dc2829d..24bb82caa7 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -22,10 +22,11 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { - [CollectionDefinition(Name)] + // Disable running server tests in parallel so server logs can accurately be captured per test + [CollectionDefinition(Name, DisableParallelization = true)] public class HubConnectionTestsCollection : ICollectionFixture> { - public const string Name = "EndToEndTests"; + public const string Name = nameof(HubConnectionTestsCollection); } [Collection(HubConnectionTestsCollection.Name)] diff --git a/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisEndToEnd.cs b/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisEndToEnd.cs index 5f1ad5a929..3071d7ab91 100644 --- a/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisEndToEnd.cs +++ b/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisEndToEnd.cs @@ -17,13 +17,14 @@ using Xunit.Abstractions; namespace Microsoft.AspNetCore.SignalR.Redis.Tests { - [CollectionDefinition(Name)] - public class EndToEndTestsCollection : ICollectionFixture> + // Disable running server tests in parallel so server logs can accurately be captured per test + [CollectionDefinition(Name, DisableParallelization = true)] + public class RedisEndToEndTestsCollection : ICollectionFixture> { - public const string Name = "RedisEndToEndTests"; + public const string Name = nameof(RedisEndToEndTestsCollection); } - [Collection(EndToEndTestsCollection.Name)] + [Collection(RedisEndToEndTestsCollection.Name)] public class RedisEndToEndTests : VerifiableLoggedTest { private readonly RedisServerFixture _serverFixture; diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index ead19e80a3..6f01448bcb 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.SignalR.Tests @@ -12,26 +13,33 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly ServerFixture _serverFixture; private readonly ILoggerFactory _loggerFactory; private readonly IDisposable _wrappedDisposable; - private readonly ConcurrentDictionary _loggers; + private readonly ConcurrentDictionary _serverLoggers; + private readonly ILogger _scopeLogger; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; _loggerFactory = loggerFactory; _wrappedDisposable = wrappedDisposable; - _loggers = new ConcurrentDictionary(StringComparer.Ordinal); + _scopeLogger = loggerFactory.CreateLogger(typeof(ServerLogScope)); + _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + + _scopeLogger.LogInformation("Server log scope started."); } private void ServerFixtureOnServerLogged(LogRecord logRecord) { - var logger = _loggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); + // Create (or get) a logger with the same name as the server logger + var logger = _serverLoggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); } public void Dispose() { + _scopeLogger.LogInformation("Server log scope disposing."); + _serverFixture.ServerLogged -= ServerFixtureOnServerLogged; _wrappedDisposable?.Dispose(); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs index 3a8f03e534..da0f3e38c8 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EndToEndTests.cs @@ -27,10 +27,11 @@ using HttpConnectionOptions = Microsoft.AspNetCore.Http.Connections.Client.HttpC namespace Microsoft.AspNetCore.SignalR.Tests { - [CollectionDefinition(Name)] + // Disable running server tests in parallel so server logs can accurately be captured per test + [CollectionDefinition(Name, DisableParallelization = true)] public class EndToEndTestsCollection : ICollectionFixture> { - public const string Name = "EndToEndTests"; + public const string Name = nameof(EndToEndTestsCollection); } [Collection(EndToEndTestsCollection.Name)] From 8241acf3a1f7f1da4d0a0643d8e900e700985975 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 17 Apr 2018 18:00:04 +1200 Subject: [PATCH 20/28] Boop --- .../ServerLogScope.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 6f01448bcb..61dd375b72 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Concurrent; -using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.SignalR.Tests @@ -19,12 +18,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { _serverFixture = serverFixture; + _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + _loggerFactory = loggerFactory; _wrappedDisposable = wrappedDisposable; - _scopeLogger = loggerFactory.CreateLogger(typeof(ServerLogScope)); _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); - - _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + _scopeLogger = loggerFactory.CreateLogger(nameof(ServerLogScope)); _scopeLogger.LogInformation("Server log scope started."); } @@ -38,10 +37,10 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void Dispose() { - _scopeLogger.LogInformation("Server log scope disposing."); - _serverFixture.ServerLogged -= ServerFixtureOnServerLogged; + _scopeLogger.LogInformation("Server log scope stopped."); + _wrappedDisposable?.Dispose(); } } From 259dd04c9900642913e344c3c559820f3f912770 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 17 Apr 2018 20:58:18 +1200 Subject: [PATCH 21/28] Fix weird NRE --- .../HubConnectionTests.cs | 4 ++-- .../ServerLogScope.cs | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 24bb82caa7..85cff50b24 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -814,8 +814,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests try { await hubConnection.StartAsync().OrTimeout(); - var headerValues = await hubConnection.InvokeAsync(nameof(TestHub.GetHeaderValues), new[] { "X-test", "X-42" }).OrTimeout(); - Assert.Equal(new[] { "42", "test" }, headerValues); + var headerValues = await hubConnection.InvokeAsync(nameof(TestHub.GetHeaderValues), new[] {"X-test", "X-42"}).OrTimeout(); + Assert.Equal(new[] {"42", "test"}, headerValues); } catch (Exception ex) { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 61dd375b72..f8157b3b65 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -30,9 +30,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests private void ServerFixtureOnServerLogged(LogRecord logRecord) { + var write = logRecord.Write; + + if (write == null) + { + _scopeLogger.LogWarning("Server log has no data."); + return; + } + // Create (or get) a logger with the same name as the server logger - var logger = _serverLoggers.GetOrAdd(logRecord.Write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); - logger.Log(logRecord.Write.LogLevel, logRecord.Write.EventId, logRecord.Write.State, logRecord.Write.Exception, logRecord.Write.Formatter); + var logger = _serverLoggers.GetOrAdd(write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); + logger.Log(write.LogLevel, write.EventId, write.State, write.Exception, write.Formatter); } public void Dispose() From 9f526b74afdfa13d70be0728573586cf4a66bab8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 17 Apr 2018 21:09:16 +1200 Subject: [PATCH 22/28] This time? --- .../ServerLogScope.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index f8157b3b65..33d050a0a5 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -17,14 +17,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { - _serverFixture = serverFixture; - _serverFixture.ServerLogged += ServerFixtureOnServerLogged; - + _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); _loggerFactory = loggerFactory; _wrappedDisposable = wrappedDisposable; - _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); _scopeLogger = loggerFactory.CreateLogger(nameof(ServerLogScope)); + _serverFixture = serverFixture; + _serverFixture.ServerLogged += ServerFixtureOnServerLogged; + _scopeLogger.LogInformation("Server log scope started."); } From 707d79d3a131211ad14faac7f884729d98abad8a Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 17 Apr 2018 21:28:06 +1200 Subject: [PATCH 23/28] Comment --- .../ServerLogScope.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 33d050a0a5..702d43f706 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -17,12 +17,14 @@ namespace Microsoft.AspNetCore.SignalR.Tests public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { - _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); _loggerFactory = loggerFactory; - _wrappedDisposable = wrappedDisposable; - _scopeLogger = loggerFactory.CreateLogger(nameof(ServerLogScope)); - _serverFixture = serverFixture; + _wrappedDisposable = wrappedDisposable; + + _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); + _scopeLogger = _loggerFactory.CreateLogger(nameof(ServerLogScope)); + + // Attach last after everything else is initialized because a logged error can happen at any time _serverFixture.ServerLogged += ServerFixtureOnServerLogged; _scopeLogger.LogInformation("Server log scope started."); From 6842ae307f6272246216d70cc700d1212075a9e3 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 18 Apr 2018 09:46:21 +1200 Subject: [PATCH 24/28] Undo dev changes --- build/repo.props | 1 + clients/ts/signalr-protocol-msgpack/package-lock.json | 2 +- clients/ts/signalr-protocol-msgpack/package.json | 2 +- clients/ts/signalr/package-lock.json | 2 +- clients/ts/signalr/package.json | 2 +- korebuild.json | 4 ++-- version.props | 4 ++-- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build/repo.props b/build/repo.props index 097feaba63..38e1626110 100644 --- a/build/repo.props +++ b/build/repo.props @@ -15,6 +15,7 @@ Internal.AspNetCore.Universe.Lineup + 2.1.0-rc1-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/clients/ts/signalr-protocol-msgpack/package-lock.json b/clients/ts/signalr-protocol-msgpack/package-lock.json index 064dcdcba1..84c50c6f60 100644 --- a/clients/ts/signalr-protocol-msgpack/package-lock.json +++ b/clients/ts/signalr-protocol-msgpack/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aspnet/signalr-protocol-msgpack", - "version": "1.1.0-preview1-t000", + "version": "1.0.0-rc1-t000", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/clients/ts/signalr-protocol-msgpack/package.json b/clients/ts/signalr-protocol-msgpack/package.json index a232fc89f8..0dd9d8f47d 100644 --- a/clients/ts/signalr-protocol-msgpack/package.json +++ b/clients/ts/signalr-protocol-msgpack/package.json @@ -1,6 +1,6 @@ { "name": "@aspnet/signalr-protocol-msgpack", - "version": "1.1.0-preview1-t000", + "version": "1.0.0-preview3-t000", "description": "MsgPack Protocol support for ASP.NET Core SignalR", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", diff --git a/clients/ts/signalr/package-lock.json b/clients/ts/signalr/package-lock.json index bded6a88f4..e7e2e130b4 100644 --- a/clients/ts/signalr/package-lock.json +++ b/clients/ts/signalr/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aspnet/signalr", - "version": "1.1.0-preview1-t000", + "version": "1.0.0-rc1-t000", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/clients/ts/signalr/package.json b/clients/ts/signalr/package.json index c70d4dde4c..4674918d1a 100644 --- a/clients/ts/signalr/package.json +++ b/clients/ts/signalr/package.json @@ -1,6 +1,6 @@ { "name": "@aspnet/signalr", - "version": "1.1.0-preview1-t000", + "version": "1.0.0-preview3-t000", "description": "ASP.NET Core SignalR Client", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", diff --git a/korebuild.json b/korebuild.json index 19b76654e1..9260aaf1e6 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1", "toolsets": { "nodejs": { "required": true, diff --git a/version.props b/version.props index 573566501b..3f759a60f9 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.1.0 - preview1 + 1.0.0 + rc1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 0f0b9a73c15cf93f7bb4862356b32fd7ae9342ae Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 18 Apr 2018 10:13:12 +1200 Subject: [PATCH 25/28] Logger thread safety? --- .../ServerLogScope.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index 702d43f706..c9e110112e 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests private readonly IDisposable _wrappedDisposable; private readonly ConcurrentDictionary _serverLoggers; private readonly ILogger _scopeLogger; + private readonly object _lock; public ServerLogScope(ServerFixture serverFixture, ILoggerFactory loggerFactory, IDisposable wrappedDisposable) { @@ -21,6 +22,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests _serverFixture = serverFixture; _wrappedDisposable = wrappedDisposable; + _lock = new object(); + _serverLoggers = new ConcurrentDictionary(StringComparer.Ordinal); _scopeLogger = _loggerFactory.CreateLogger(nameof(ServerLogScope)); @@ -40,8 +43,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests return; } - // Create (or get) a logger with the same name as the server logger - var logger = _serverLoggers.GetOrAdd(write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); + ILogger logger; + + // There maybe thready safety issues in logging when creating multiple threads at the same time + // https://github.com/aspnet/Logging/issues/810 + lock (_lock) + { + // Create (or get) a logger with the same name as the server logger + logger = _serverLoggers.GetOrAdd(write.LoggerName, loggerName => _loggerFactory.CreateLogger(loggerName)); + } + logger.Log(write.LogLevel, write.EventId, write.State, write.Exception, write.Formatter); } From 61cce236fcbcf75fa1305af0b985c778c880c03f Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 18 Apr 2018 10:37:23 +1200 Subject: [PATCH 26/28] Derp --- test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs index c9e110112e..8ca3281e98 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/ServerLogScope.cs @@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests ILogger logger; - // There maybe thready safety issues in logging when creating multiple threads at the same time + // There maybe thready safety issues in logging when creating multiple loggers at the same time // https://github.com/aspnet/Logging/issues/810 lock (_lock) { From b4046b5ed83c6d06abd9783ef67ed794e8be5076 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 17 Apr 2018 20:08:07 -0700 Subject: [PATCH 27/28] Fix #1989 by adding a 'binding failure' pseudo-message (#2064) --- .../DefaultHubDispatcherBenchmark.cs | 22 ++++---- .../HubProtocolBenchmark.cs | 8 +-- .../ServerSentEventsBenchmark.cs | 10 ++-- .../HubConnection.Log.cs | 8 +++ .../HubConnection.cs | 14 +++-- .../Protocol/HubMethodInvocationMessage.cs | 41 ++++----------- .../InvocationBindingFailureMessage.cs | 22 ++++++++ .../DefaultHubLifetimeManager.cs | 2 +- .../Internal/DefaultHubDispatcher.cs | 35 +++++++------ .../Protocol/JsonHubProtocol.cs | 18 ++++--- .../Protocol/MessagePackHubProtocol.cs | 12 ++--- .../Internal/RedisProtocol.cs | 2 +- .../RedisHubLifetimeManager.cs | 2 +- .../Internal/Protocol/JsonHubProtocolTests.cs | 52 +++++++++---------- .../Protocol/MessagePackHubProtocolTests.cs | 41 +++++++-------- .../RedisProtocolTests.cs | 27 ++++++---- .../TestClient.cs | 4 +- .../HubConnectionHandlerTests.cs | 2 +- .../HubMethodInvocationMessageTests.cs | 29 ----------- 19 files changed, 173 insertions(+), 178 deletions(-) create mode 100644 src/Microsoft.AspNetCore.SignalR.Common/Protocol/InvocationBindingFailureMessage.cs delete mode 100644 test/Microsoft.AspNetCore.SignalR.Tests/HubMethodInvocationMessageTests.cs diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs index fe86df6f6c..bc0e2e57df 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs @@ -166,67 +166,67 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks [Benchmark] public Task Invocation() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "Invocation", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "Invocation", Array.Empty())); } [Benchmark] public Task InvocationAsync() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationAsync", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationAsync", Array.Empty())); } [Benchmark] public Task InvocationReturnValue() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnValue", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnValue", Array.Empty())); } [Benchmark] public Task InvocationReturnAsync() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnAsync", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationReturnAsync", Array.Empty())); } [Benchmark] public Task InvocationValueTaskAsync() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationValueTaskAsync", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new InvocationMessage("123", "InvocationValueTaskAsync", Array.Empty())); } [Benchmark] public Task StreamChannelReader() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReader", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReader", Array.Empty())); } [Benchmark] public Task StreamChannelReaderAsync() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderAsync", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderAsync", Array.Empty())); } [Benchmark] public Task StreamChannelReaderValueTaskAsync() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderValueTaskAsync", null, Array.Empty())); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderValueTaskAsync", Array.Empty())); } [Benchmark] public Task StreamChannelReaderCount_Zero() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", null, new object[] { 0 })); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 0 })); } [Benchmark] public Task StreamChannelReaderCount_One() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", null, new object[] { 1 })); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 1 })); } [Benchmark] public Task StreamChannelReaderCount_Thousand() { - return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", null, new object[] { 1000 })); + return _dispatcher.DispatchMessageAsync(_connectionContext, new StreamInvocationMessage("123", "StreamChannelReaderCount", new object[] { 1000 })); } } } diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubProtocolBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubProtocolBenchmark.cs index 08ad64bc70..5c089c0f7a 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubProtocolBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/HubProtocolBenchmark.cs @@ -37,16 +37,16 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks switch (Input) { case Message.NoArguments: - _hubMessage = new InvocationMessage("Target", null, Array.Empty()); + _hubMessage = new InvocationMessage("Target", Array.Empty()); break; case Message.FewArguments: - _hubMessage = new InvocationMessage("Target", null, new object[] { 1, "Foo", 2.0f }); + _hubMessage = new InvocationMessage("Target", new object[] { 1, "Foo", 2.0f }); break; case Message.ManyArguments: - _hubMessage = new InvocationMessage("Target", null, new object[] { 1, "string", 2.0f, true, (byte)9, new byte[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L }); + _hubMessage = new InvocationMessage("Target", new object[] { 1, "string", 2.0f, true, (byte)9, new byte[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L }); break; case Message.LargeArguments: - _hubMessage = new InvocationMessage("Target", null, new object[] { new string('F', 10240), new byte[10240] }); + _hubMessage = new InvocationMessage("Target", new object[] { new string('F', 10240), new byte[10240] }); break; } diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/ServerSentEventsBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/ServerSentEventsBenchmark.cs index 825992edac..33b9055428 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/ServerSentEventsBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/ServerSentEventsBenchmark.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Buffers; using System.IO; using System.Threading.Tasks; @@ -44,16 +44,16 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks switch (Input) { case Message.NoArguments: - hubMessage = new InvocationMessage("Target", null, Array.Empty()); + hubMessage = new InvocationMessage("Target", Array.Empty()); break; case Message.FewArguments: - hubMessage = new InvocationMessage("Target", null, new object[] { 1, "Foo", 2.0f }); + hubMessage = new InvocationMessage("Target", new object[] { 1, "Foo", 2.0f }); break; case Message.ManyArguments: - hubMessage = new InvocationMessage("Target", null, new object[] { 1, "string", 2.0f, true, (byte)9, new[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L }); + hubMessage = new InvocationMessage("Target", new object[] { 1, "string", 2.0f, true, (byte)9, new[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L }); break; case Message.LargeArguments: - hubMessage = new InvocationMessage("Target", null, new object[] { new string('F', 10240), new string('B', 10240) }); + hubMessage = new InvocationMessage("Target", new object[] { new string('F', 10240), new string('B', 10240) }); break; } diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.Log.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.Log.cs index b17ae06043..5dbcf2985e 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.Log.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.Log.cs @@ -168,6 +168,9 @@ namespace Microsoft.AspNetCore.SignalR.Client private static readonly Action _processingMessage = LoggerMessage.Define(LogLevel.Debug, new EventId(56, "ProcessingMessage"), "Processing {MessageLength} byte message from server."); + private static readonly Action _argumentBindingFailure = + LoggerMessage.Define(LogLevel.Error, new EventId(57, "ArgumentBindingFailure"), "Failed to bind arguments received in invocation '{InvocationId}' of '{MethodName}'."); + public static void PreparingNonBlockingInvocation(ILogger logger, string target, int count) { _preparingNonBlockingInvocation(logger, target, count, null); @@ -444,6 +447,11 @@ namespace Microsoft.AspNetCore.SignalR.Client { _unableToSendCancellation(logger, invocationId, null); } + + public static void ArgumentBindingFailure(ILogger logger, string invocationId, string target, Exception exception) + { + _argumentBindingFailure(logger, invocationId, target, exception); + } } } } diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs index 44d6bdb969..da41d807a2 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs @@ -300,7 +300,7 @@ namespace Microsoft.AspNetCore.SignalR.Client Log.PreparingBlockingInvocation(_logger, irq.InvocationId, methodName, irq.ResultType.FullName, args.Length); // Client invocations are always blocking - var invocationMessage = new InvocationMessage(irq.InvocationId, methodName, null, args); + var invocationMessage = new InvocationMessage(irq.InvocationId, methodName, args); Log.RegisteringInvocation(_logger, invocationMessage.InvocationId); @@ -327,7 +327,7 @@ namespace Microsoft.AspNetCore.SignalR.Client Log.PreparingStreamingInvocation(_logger, irq.InvocationId, methodName, irq.ResultType.FullName, args.Length); - var invocationMessage = new StreamInvocationMessage(irq.InvocationId, methodName, null, args); + var invocationMessage = new StreamInvocationMessage(irq.InvocationId, methodName, args); // I just want an excuse to use 'irq' as a variable name... Log.RegisteringInvocation(_logger, invocationMessage.InvocationId); @@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.SignalR.Client Log.PreparingNonBlockingInvocation(_logger, methodName, args.Length); - var invocationMessage = new InvocationMessage(null, methodName, null, args); + var invocationMessage = new InvocationMessage(null, methodName, args); await SendHubMessage(invocationMessage, cancellationToken); } @@ -390,9 +390,13 @@ namespace Microsoft.AspNetCore.SignalR.Client InvocationRequest irq; switch (message) { + case InvocationBindingFailureMessage bindingFailure: + // The server can't receive a response, so we just drop the message and log + // REVIEW: Is this the right approach? + Log.ArgumentBindingFailure(_logger, bindingFailure.InvocationId, bindingFailure.Target, bindingFailure.BindingFailure.SourceException); + break; case InvocationMessage invocation: - Log.ReceivedInvocation(_logger, invocation.InvocationId, invocation.Target, - invocation.ArgumentBindingException != null ? null : invocation.Arguments); + Log.ReceivedInvocation(_logger, invocation.InvocationId, invocation.Target, invocation.Arguments); await DispatchInvocationAsync(invocation); break; case CompletionMessage completion: diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HubMethodInvocationMessage.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HubMethodInvocationMessage.cs index f125981950..272e446d0b 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HubMethodInvocationMessage.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HubMethodInvocationMessage.cs @@ -3,33 +3,16 @@ using System; using System.Linq; -using System.Runtime.ExceptionServices; namespace Microsoft.AspNetCore.SignalR.Protocol { public abstract class HubMethodInvocationMessage : HubInvocationMessage { - private readonly ExceptionDispatchInfo _argumentBindingException; - private readonly object[] _arguments; - public string Target { get; } - public object[] Arguments - { - get - { - if (_argumentBindingException != null) - { - _argumentBindingException.Throw(); - } + public object[] Arguments { get; } - return _arguments; - } - } - - public Exception ArgumentBindingException => _argumentBindingException?.SourceException; - - protected HubMethodInvocationMessage(string invocationId, string target, ExceptionDispatchInfo argumentBindingException, object[] arguments) + protected HubMethodInvocationMessage(string invocationId, string target, object[] arguments) : base(invocationId) { if (string.IsNullOrEmpty(target)) @@ -37,26 +20,20 @@ namespace Microsoft.AspNetCore.SignalR.Protocol throw new ArgumentNullException(nameof(target)); } - if ((arguments == null && argumentBindingException == null) || (arguments?.Length > 0 && argumentBindingException != null)) - { - throw new ArgumentException($"'{nameof(argumentBindingException)}' and '{nameof(arguments)}' are mutually exclusive"); - } - Target = target; - _arguments = arguments; - _argumentBindingException = argumentBindingException; + Arguments = arguments; } } public class InvocationMessage : HubMethodInvocationMessage { - public InvocationMessage(string target, ExceptionDispatchInfo argumentBindingException, object[] arguments) - : this(null, target, argumentBindingException, arguments) + public InvocationMessage(string target, object[] arguments) + : this(null, target, arguments) { } - public InvocationMessage(string invocationId, string target, ExceptionDispatchInfo argumentBindingException, object[] arguments) - : base(invocationId, target, argumentBindingException, arguments) + public InvocationMessage(string invocationId, string target, object[] arguments) + : base(invocationId, target, arguments) { } @@ -77,8 +54,8 @@ namespace Microsoft.AspNetCore.SignalR.Protocol public class StreamInvocationMessage : HubMethodInvocationMessage { - public StreamInvocationMessage(string invocationId, string target, ExceptionDispatchInfo argumentBindingException, object[] arguments) - : base(invocationId, target, argumentBindingException, arguments) + public StreamInvocationMessage(string invocationId, string target, object[] arguments) + : base(invocationId, target, arguments) { if (string.IsNullOrEmpty(invocationId)) { diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/InvocationBindingFailureMessage.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/InvocationBindingFailureMessage.cs new file mode 100644 index 0000000000..74c88ddc85 --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/InvocationBindingFailureMessage.cs @@ -0,0 +1,22 @@ +using System.Runtime.ExceptionServices; + +namespace Microsoft.AspNetCore.SignalR.Protocol +{ + /// + /// Represents a failure to bind arguments for an invocation. This does not represent an actual + /// message that is sent on the wire, it is returned by + /// to indicate that a binding failure occurred when parsing an invocation. The invocation ID is associated + /// so that the error can be sent back to the client, associated with the appropriate invocation ID. + /// + public class InvocationBindingFailureMessage : HubInvocationMessage + { + public ExceptionDispatchInfo BindingFailure { get; } + public string Target { get; } + + public InvocationBindingFailureMessage(string invocationId, string target, ExceptionDispatchInfo bindingFailure) : base(invocationId) + { + Target = target; + BindingFailure = bindingFailure; + } + } +} diff --git a/src/Microsoft.AspNetCore.SignalR.Core/DefaultHubLifetimeManager.cs b/src/Microsoft.AspNetCore.SignalR.Core/DefaultHubLifetimeManager.cs index 4a5da0f4e0..c6cb42e36c 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/DefaultHubLifetimeManager.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/DefaultHubLifetimeManager.cs @@ -250,7 +250,7 @@ namespace Microsoft.AspNetCore.SignalR private HubMessage CreateInvocationMessage(string methodName, object[] args) { - return new InvocationMessage(methodName, null, args); + return new InvocationMessage(methodName, args); } public override Task SendUserAsync(string userId, string methodName, object[] args) diff --git a/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubDispatcher.cs b/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubDispatcher.cs index 748f345459..66046ebaa5 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubDispatcher.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubDispatcher.cs @@ -77,6 +77,10 @@ namespace Microsoft.AspNetCore.SignalR.Internal { switch (hubMessage) { + case InvocationBindingFailureMessage bindingFailureMessage: + await ProcessBindingFailure(connection, bindingFailureMessage); + break; + case InvocationMessage invocationMessage: Log.ReceivedHubInvocation(_logger, invocationMessage); await ProcessInvocation(connection, invocationMessage, isStreamedInvocation: false); @@ -113,6 +117,14 @@ namespace Microsoft.AspNetCore.SignalR.Internal } } + private Task ProcessBindingFailure(HubConnectionContext connection, InvocationBindingFailureMessage bindingFailureMessage) + { + Log.FailedInvokingHubMethod(_logger, bindingFailureMessage.Target, bindingFailureMessage.BindingFailure.SourceException); + var errorMessage = ErrorMessageHelper.BuildErrorMessage($"Failed to invoke '{bindingFailureMessage.Target}' due to an error on the server.", + bindingFailureMessage.BindingFailure.SourceException, _enableDetailedErrors); + return SendInvocationError(bindingFailureMessage.InvocationId, connection, errorMessage); + } + public override Type GetReturnType(string invocationId) { return typeof(object); @@ -163,7 +175,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal if (!await IsHubMethodAuthorized(scope.ServiceProvider, connection.User, descriptor.Policies)) { Log.HubMethodNotAuthorized(_logger, hubMethodInvocationMessage.Target); - await SendInvocationError(hubMethodInvocationMessage, connection, + await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection, $"Failed to invoke '{hubMethodInvocationMessage.Target}' because user is unauthorized"); return; } @@ -173,15 +185,6 @@ namespace Microsoft.AspNetCore.SignalR.Internal return; } - if (hubMethodInvocationMessage.ArgumentBindingException != null) - { - Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, hubMethodInvocationMessage.ArgumentBindingException); - var errorMessage = ErrorMessageHelper.BuildErrorMessage($"Failed to invoke '{hubMethodInvocationMessage.Target}' due to an error on the server.", - hubMethodInvocationMessage.ArgumentBindingException, _enableDetailedErrors); - await SendInvocationError(hubMethodInvocationMessage, connection, errorMessage); - return; - } - var hubActivator = scope.ServiceProvider.GetRequiredService>(); var hub = hubActivator.Create(); @@ -197,7 +200,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal { Log.InvalidReturnValueFromStreamingMethod(_logger, methodExecutor.MethodInfo.Name); - await SendInvocationError(hubMethodInvocationMessage, connection, + await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection, $"The value returned by the streaming method '{methodExecutor.MethodInfo.Name}' is not a ChannelReader<>."); return; } @@ -215,13 +218,13 @@ namespace Microsoft.AspNetCore.SignalR.Internal catch (TargetInvocationException ex) { Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex); - await SendInvocationError(hubMethodInvocationMessage, connection, + await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection, ErrorMessageHelper.BuildErrorMessage($"An unexpected error occurred invoking '{hubMethodInvocationMessage.Target}' on the server.", ex.InnerException, _enableDetailedErrors)); } catch (Exception ex) { Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex); - await SendInvocationError(hubMethodInvocationMessage, connection, + await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection, ErrorMessageHelper.BuildErrorMessage($"An unexpected error occurred invoking '{hubMethodInvocationMessage.Target}' on the server.", ex, _enableDetailedErrors)); } finally @@ -294,15 +297,15 @@ namespace Microsoft.AspNetCore.SignalR.Internal return null; } - private async Task SendInvocationError(HubMethodInvocationMessage hubMethodInvocationMessage, + private async Task SendInvocationError(string invocationId, HubConnectionContext connection, string errorMessage) { - if (string.IsNullOrEmpty(hubMethodInvocationMessage.InvocationId)) + if (string.IsNullOrEmpty(invocationId)) { return; } - await connection.WriteAsync(CompletionMessage.WithError(hubMethodInvocationMessage.InvocationId, errorMessage)); + await connection.WriteAsync(CompletionMessage.WithError(invocationId, errorMessage)); } private void InitializeHub(THub hub, HubConnectionContext connection) diff --git a/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs index 919d89399f..4c471386a7 100644 --- a/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs @@ -237,6 +237,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol { if (argumentsToken != null) { + // We weren't able to bind the arguments because they came before the 'target', so try to bind now that we've read everything. try { var paramTypes = binder.GetParameterTypes(target); @@ -248,13 +249,16 @@ namespace Microsoft.AspNetCore.SignalR.Protocol } } - message = BindInvocationMessage(invocationId, target, argumentBindingException, arguments, hasArguments, binder); + message = argumentBindingException != null + ? new InvocationBindingFailureMessage(invocationId, target, argumentBindingException) + : BindInvocationMessage(invocationId, target, arguments, hasArguments, binder); } break; case HubProtocolConstants.StreamInvocationMessageType: { if (argumentsToken != null) { + // We weren't able to bind the arguments because they came before the 'target', so try to bind now that we've read everything. try { var paramTypes = binder.GetParameterTypes(target); @@ -266,7 +270,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol } } - message = BindStreamInvocationMessage(invocationId, target, argumentBindingException, arguments, hasArguments, binder); + message = argumentBindingException != null + ? new InvocationBindingFailureMessage(invocationId, target, argumentBindingException) + : BindStreamInvocationMessage(invocationId, target, arguments, hasArguments, binder); } break; case HubProtocolConstants.StreamItemMessageType: @@ -539,7 +545,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol return new StreamItemMessage(invocationId, item); } - private HubMessage BindStreamInvocationMessage(string invocationId, string target, ExceptionDispatchInfo argumentBindingException, object[] arguments, bool hasArguments, IInvocationBinder binder) + private HubMessage BindStreamInvocationMessage(string invocationId, string target, object[] arguments, bool hasArguments, IInvocationBinder binder) { if (string.IsNullOrEmpty(invocationId)) { @@ -556,10 +562,10 @@ namespace Microsoft.AspNetCore.SignalR.Protocol throw new InvalidDataException($"Missing required property '{TargetPropertyName}'."); } - return new StreamInvocationMessage(invocationId, target, argumentBindingException, arguments); + return new StreamInvocationMessage(invocationId, target, arguments); } - private HubMessage BindInvocationMessage(string invocationId, string target, ExceptionDispatchInfo argumentBindingException, object[] arguments, bool hasArguments, IInvocationBinder binder) + private HubMessage BindInvocationMessage(string invocationId, string target, object[] arguments, bool hasArguments, IInvocationBinder binder) { if (string.IsNullOrEmpty(target)) { @@ -571,7 +577,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol throw new InvalidDataException($"Missing required property '{ArgumentsPropertyName}'."); } - return new InvocationMessage(invocationId, target, argumentBindingException, arguments); + return new InvocationMessage(invocationId, target, arguments); } private object[] BindArguments(JsonTextReader reader, IReadOnlyList paramTypes) diff --git a/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs index cc8009045a..02a8065def 100644 --- a/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol } } - private static InvocationMessage CreateInvocationMessage(byte[] input, ref int offset, IInvocationBinder binder, IFormatterResolver resolver) + private static HubMessage CreateInvocationMessage(byte[] input, ref int offset, IInvocationBinder binder, IFormatterResolver resolver) { var headers = ReadHeaders(input, ref offset); var invocationId = ReadInvocationId(input, ref offset); @@ -147,15 +147,15 @@ namespace Microsoft.AspNetCore.SignalR.Protocol try { var arguments = BindArguments(input, ref offset, parameterTypes, resolver); - return ApplyHeaders(headers, new InvocationMessage(invocationId, target, null, arguments)); + return ApplyHeaders(headers, new InvocationMessage(invocationId, target, arguments)); } catch (Exception ex) { - return ApplyHeaders(headers, new InvocationMessage(invocationId, target, ExceptionDispatchInfo.Capture(ex), null)); + return new InvocationBindingFailureMessage(invocationId, target, ExceptionDispatchInfo.Capture(ex)); } } - private static StreamInvocationMessage CreateStreamInvocationMessage(byte[] input, ref int offset, IInvocationBinder binder, IFormatterResolver resolver) + private static HubMessage CreateStreamInvocationMessage(byte[] input, ref int offset, IInvocationBinder binder, IFormatterResolver resolver) { var headers = ReadHeaders(input, ref offset); var invocationId = ReadInvocationId(input, ref offset); @@ -165,11 +165,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol try { var arguments = BindArguments(input, ref offset, parameterTypes, resolver); - return ApplyHeaders(headers, new StreamInvocationMessage(invocationId, target, null, arguments)); + return ApplyHeaders(headers, new StreamInvocationMessage(invocationId, target, arguments)); } catch (Exception ex) { - return ApplyHeaders(headers, new StreamInvocationMessage(invocationId, target, ExceptionDispatchInfo.Capture(ex), null)); + return new InvocationBindingFailureMessage(invocationId, target, ExceptionDispatchInfo.Capture(ex)); } } diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisProtocol.cs index 98dcd8955f..6d3c51659b 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisProtocol.cs @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Internal } WriteSerializedHubMessage(writer, - new SerializedHubMessage(new InvocationMessage(methodName, null, args))); + new SerializedHubMessage(new InvocationMessage(methodName, args))); return writer.ToArray(); } finally diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs b/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs index 6c471ce7f8..174abbebc5 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs @@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.SignalR.Redis var connection = _connections[connectionId]; if (connection != null) { - return connection.WriteAsync(new InvocationMessage(methodName, null, args)).AsTask(); + return connection.WriteAsync(new InvocationMessage(methodName, args)).AsTask(); } var message = _protocol.WriteInvocation(methodName, args); diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs index 18fea62dd5..c30209ccce 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs @@ -32,17 +32,17 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol public static IDictionary ProtocolTestData => new[] { - new JsonProtocolTestData("InvocationMessage_HasInvocationId", new InvocationMessage("123", "Target", null, new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":1,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), - new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", null, new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), - new JsonProtocolTestData("InvocationMessage_HasBoolArgument", new InvocationMessage(null, "Target", null, new object[] { true }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[true]}"), - new JsonProtocolTestData("InvocationMessage_HasNullArgument", new InvocationMessage(null, "Target", null, new object[] { null }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[null]}"), - new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNoCamelCase", new InvocationMessage(null, "Target", null, new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnore", new InvocationMessage(null, "Target", null, new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new InvocationMessage(null, "Target", null, new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueInclude", new InvocationMessage(null, "Target", null, new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("InvocationMessage_HasHeaders", AddHeaders(TestHeaders, new InvocationMessage("123", "Target", null, new object[] { 1, "Foo", 2.0f })), true, NullValueHandling.Ignore, "{\"type\":1," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), - new JsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", null, new object[] { "2016-05-10T13:51:20+12:34" }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"), - new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgument", new InvocationMessage("Method", null, new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"), + new JsonProtocolTestData("InvocationMessage_HasInvocationId", new InvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":1,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), + new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), + new JsonProtocolTestData("InvocationMessage_HasBoolArgument", new InvocationMessage(null, "Target", new object[] { true }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[true]}"), + new JsonProtocolTestData("InvocationMessage_HasNullArgument", new InvocationMessage(null, "Target", new object[] { null }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[null]}"), + new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnore", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueInclude", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("InvocationMessage_HasHeaders", AddHeaders(TestHeaders, new InvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f })), true, NullValueHandling.Ignore, "{\"type\":1," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), + new JsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"), + new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgument", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"), new JsonProtocolTestData("StreamItemMessage_HasIntegerItem", new StreamItemMessage("123", 1), true, NullValueHandling.Ignore, "{\"type\":2,\"invocationId\":\"123\",\"item\":1}"), new JsonProtocolTestData("StreamItemMessage_HasStringItem", new StreamItemMessage("123", "Foo"), true, NullValueHandling.Ignore, "{\"type\":2,\"invocationId\":\"123\",\"item\":\"Foo\"}"), @@ -70,15 +70,15 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol new JsonProtocolTestData("CompletionMessage_HasErrorAndCamelCase", CompletionMessage.Empty("123"), true, NullValueHandling.Ignore, "{\"type\":3,\"invocationId\":\"123\"}"), new JsonProtocolTestData("CompletionMessage_HasErrorAndHeadersAndCamelCase", AddHeaders(TestHeaders, CompletionMessage.Empty("123")), true, NullValueHandling.Ignore, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\"}"), - new JsonProtocolTestData("StreamInvocationMessage_HasInvocationId", new StreamInvocationMessage("123", "Target", null, new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", null, new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasBoolArgument", new StreamInvocationMessage("123", "Target", null, new object[] { true }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[true]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasNullArgument", new StreamInvocationMessage("123", "Target", null, new object[] { null }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[null]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNoCamelCase", new StreamInvocationMessage("123", "Target", null, new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnore", new StreamInvocationMessage("123", "Target", null, new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new StreamInvocationMessage("123", "Target", null, new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueInclude", new StreamInvocationMessage("123", "Target", null, new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), - new JsonProtocolTestData("StreamInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new StreamInvocationMessage("123", "Target", null, new object[] { new CustomObject() })), true, NullValueHandling.Include, "{\"type\":4," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasInvocationId", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasBoolArgument", new StreamInvocationMessage("123", "Target", new object[] { true }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[true]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasNullArgument", new StreamInvocationMessage("123", "Target", new object[] { null }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[null]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnore", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueInclude", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), + new JsonProtocolTestData("StreamInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() })), true, NullValueHandling.Include, "{\"type\":4," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"), new JsonProtocolTestData("CancelInvocationMessage_HasInvocationId", new CancelInvocationMessage("123"), true, NullValueHandling.Ignore, "{\"type\":5,\"invocationId\":\"123\"}"), new JsonProtocolTestData("CancelInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new CancelInvocationMessage("123")), true, NullValueHandling.Ignore, "{\"type\":5," + SerializedHeaders + ",\"invocationId\":\"123\"}"), @@ -95,10 +95,10 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol public static IDictionary OutOfOrderJsonTestData => new[] { - new JsonProtocolTestData("InvocationMessage_StringIsoDateArgumentFirst", new InvocationMessage("Method", null, new object[] { "2016-05-10T13:51:20+12:34" }), false, NullValueHandling.Ignore, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"), - new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgumentFirst", new InvocationMessage("Method", null, new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), false, NullValueHandling.Ignore, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"), - new JsonProtocolTestData("InvocationMessage_IntegerArrayArgumentFirst", new InvocationMessage("Method", null, new object[] { 1, 2 }), false, NullValueHandling.Ignore, "{ \"arguments\": [1,2], \"type\":1, \"target\": \"Method\" }"), - new JsonProtocolTestData("StreamInvocationMessage_IntegerArrayArgumentFirst", new StreamInvocationMessage("3", "Method", null, new object[] { 1, 2 }), false, NullValueHandling.Ignore, "{ \"type\":4, \"arguments\": [1,2], \"target\": \"Method\", \"invocationId\": \"3\" }"), + new JsonProtocolTestData("InvocationMessage_StringIsoDateArgumentFirst", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), false, NullValueHandling.Ignore, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"), + new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgumentFirst", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), false, NullValueHandling.Ignore, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"), + new JsonProtocolTestData("InvocationMessage_IntegerArrayArgumentFirst", new InvocationMessage("Method", new object[] { 1, 2 }), false, NullValueHandling.Ignore, "{ \"arguments\": [1,2], \"type\":1, \"target\": \"Method\" }"), + new JsonProtocolTestData("StreamInvocationMessage_IntegerArrayArgumentFirst", new StreamInvocationMessage("3", "Method", new object[] { 1, 2 }), false, NullValueHandling.Ignore, "{ \"type\":4, \"arguments\": [1,2], \"target\": \"Method\", \"invocationId\": \"3\" }"), new JsonProtocolTestData("CompletionMessage_ResultFirst", new CompletionMessage("15", null, 10, hasResult: true), false, NullValueHandling.Ignore, "{ \"type\":3, \"result\": 10, \"invocationId\": \"15\" }"), new JsonProtocolTestData("StreamItemMessage_ItemFirst", new StreamItemMessage("1a", "foo"), false, NullValueHandling.Ignore, "{ \"item\": \"foo\", \"invocationId\": \"1a\", \"type\":2 }") }.ToDictionary(t => t.Name); @@ -256,8 +256,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol var protocol = new JsonHubProtocol(); var data = new ReadOnlySequence(Encoding.UTF8.GetBytes(input)); protocol.TryParseMessage(ref data, binder, out var message); - var ex = Assert.Throws(() => ((HubMethodInvocationMessage)message).Arguments); - Assert.Equal(expectedMessage, ex.Message); + var bindingFailure = Assert.IsType(message); + Assert.Equal(expectedMessage, bindingFailure.BindingFailure.SourceException.Message); } private static string Frame(string input) diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs index dcfe2b23a1..c0fbec1baf 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs @@ -57,39 +57,39 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol // Invocation messages new ProtocolTestData( name: "InvocationWithNoHeadersAndNoArgs", - message: new InvocationMessage("xyz", "method", null, Array.Empty()), + message: new InvocationMessage("xyz", "method", Array.Empty()), binary: "lQGAo3h5eqZtZXRob2SQ"), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdAndNoArgs", - message: new InvocationMessage("method", null, Array.Empty()), + message: new InvocationMessage("method", Array.Empty()), binary: "lQGAwKZtZXRob2SQ"), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdAndSingleNullArg", - message: new InvocationMessage("method", null, new object[] { null }), + message: new InvocationMessage("method", new object[] { null }), binary: "lQGAwKZtZXRob2SRwA=="), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdAndSingleIntArg", - message: new InvocationMessage("method", null, new object[] { 42 }), + message: new InvocationMessage("method", new object[] { 42 }), binary: "lQGAwKZtZXRob2SRKg=="), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdIntAndStringArgs", - message: new InvocationMessage("method", null, new object[] { 42, "string" }), + message: new InvocationMessage("method", new object[] { 42, "string" }), binary: "lQGAwKZtZXRob2SSKqZzdHJpbmc="), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdIntAndEnumArgs", - message: new InvocationMessage("method", null, new object[] { 42, TestEnum.One }), + message: new InvocationMessage("method", new object[] { 42, TestEnum.One }), binary: "lQGAwKZtZXRob2SSKqNPbmU="), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdAndCustomObjectArg", - message: new InvocationMessage("method", null, new object[] { 42, "string", new CustomObject() }), + message: new InvocationMessage("method", new object[] { 42, "string", new CustomObject() }), binary: "lQGAwKZtZXRob2STKqZzdHJpbmeGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgM="), new ProtocolTestData( name: "InvocationWithNoHeadersNoIdAndArrayOfCustomObjectArgs", - message: new InvocationMessage("method", null, new object[] { new CustomObject(), new CustomObject() }), + message: new InvocationMessage("method", new object[] { new CustomObject(), new CustomObject() }), binary: "lQGAwKZtZXRob2SShqpTdHJpbmdQcm9wqFNpZ25hbFIhqkRvdWJsZVByb3DLQBkh+1RCzxKnSW50UHJvcCqsRGF0ZVRpbWVQcm9w1v9Y7ByAqE51bGxQcm9wwKtCeXRlQXJyUHJvcMQDAQIDhqpTdHJpbmdQcm9wqFNpZ25hbFIhqkRvdWJsZVByb3DLQBkh+1RCzxKnSW50UHJvcCqsRGF0ZVRpbWVQcm9w1v9Y7ByAqE51bGxQcm9wwKtCeXRlQXJyUHJvcMQDAQID"), new ProtocolTestData( name: "InvocationWithHeadersNoIdAndArrayOfCustomObjectArgs", - message: AddHeaders(TestHeaders, new InvocationMessage("method", null, new object[] { new CustomObject(), new CustomObject() })), + message: AddHeaders(TestHeaders, new InvocationMessage("method", new object[] { new CustomObject(), new CustomObject() })), binary: "lQGDo0Zvb6NCYXKyS2V5V2l0aApOZXcNCkxpbmVzq1N0aWxsIFdvcmtzsVZhbHVlV2l0aE5ld0xpbmVzsEFsc28KV29ya3MNCkZpbmXApm1ldGhvZJKGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgOGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgM="), // StreamItem Messages @@ -187,35 +187,35 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol // StreamInvocation Messages new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndNoArgs", - message: new StreamInvocationMessage("xyz", "method", null, Array.Empty()), + message: new StreamInvocationMessage("xyz", "method", Array.Empty()), binary: "lQSAo3h5eqZtZXRob2SQ"), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndNullArg", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { null }), + message: new StreamInvocationMessage("xyz", "method", new object[] { null }), binary: "lQSAo3h5eqZtZXRob2SRwA=="), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndIntArg", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { 42 }), + message: new StreamInvocationMessage("xyz", "method", new object[] { 42 }), binary: "lQSAo3h5eqZtZXRob2SRKg=="), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndEnumArg", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { TestEnum.One }), + message: new StreamInvocationMessage("xyz", "method", new object[] { TestEnum.One }), binary: "lQSAo3h5eqZtZXRob2SRo09uZQ=="), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndIntAndStringArgs", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { 42, "string" }), + message: new StreamInvocationMessage("xyz", "method", new object[] { 42, "string" }), binary: "lQSAo3h5eqZtZXRob2SSKqZzdHJpbmc="), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndIntStringAndCustomObjectArgs", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { 42, "string", new CustomObject() }), + message: new StreamInvocationMessage("xyz", "method", new object[] { 42, "string", new CustomObject() }), binary: "lQSAo3h5eqZtZXRob2STKqZzdHJpbmeGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgM="), new ProtocolTestData( name: "StreamInvocationWithNoHeadersAndCustomObjectArrayArg", - message: new StreamInvocationMessage("xyz", "method", null, new object[] { new CustomObject(), new CustomObject() }), + message: new StreamInvocationMessage("xyz", "method", new object[] { new CustomObject(), new CustomObject() }), binary: "lQSAo3h5eqZtZXRob2SShqpTdHJpbmdQcm9wqFNpZ25hbFIhqkRvdWJsZVByb3DLQBkh+1RCzxKnSW50UHJvcCqsRGF0ZVRpbWVQcm9w1v9Y7ByAqE51bGxQcm9wwKtCeXRlQXJyUHJvcMQDAQIDhqpTdHJpbmdQcm9wqFNpZ25hbFIhqkRvdWJsZVByb3DLQBkh+1RCzxKnSW50UHJvcCqsRGF0ZVRpbWVQcm9w1v9Y7ByAqE51bGxQcm9wwKtCeXRlQXJyUHJvcMQDAQID"), new ProtocolTestData( name: "StreamInvocationWithHeadersAndCustomObjectArrayArg", - message: AddHeaders(TestHeaders, new StreamInvocationMessage("xyz", "method", null, new object[] { new CustomObject(), new CustomObject() })), + message: AddHeaders(TestHeaders, new StreamInvocationMessage("xyz", "method", new object[] { new CustomObject(), new CustomObject() })), binary: "lQSDo0Zvb6NCYXKyS2V5V2l0aApOZXcNCkxpbmVzq1N0aWxsIFdvcmtzsVZhbHVlV2l0aE5ld0xpbmVzsEFsc28KV29ya3MNCkZpbmWjeHl6pm1ldGhvZJKGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgOGqlN0cmluZ1Byb3CoU2lnbmFsUiGqRG91YmxlUHJvcMtAGSH7VELPEqdJbnRQcm9wKqxEYXRlVGltZVByb3DW/1jsHICoTnVsbFByb3DAq0J5dGVBcnJQcm9wxAMBAgM="), // CancelInvocation Messages @@ -256,7 +256,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol [Fact] public void ParseMessageWithExtraData() { - var expectedMessage = new InvocationMessage("xyz", "method", null, Array.Empty()); + var expectedMessage = new InvocationMessage("xyz", "method", Array.Empty()); // Verify that the input binary string decodes to the expected MsgPack primitives var bytes = new byte[] { ArrayBytes(6), 1, 0x80, StringBytes(3), (byte)'x', (byte)'y', (byte)'z', StringBytes(6), (byte)'m', (byte)'e', (byte)'t', (byte)'h', (byte)'o', (byte)'d', ArrayBytes(0), StringBytes(2), (byte)'e', (byte)'x' }; @@ -422,9 +422,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol var binder = new TestBinder(new[] { typeof(string) }, typeof(string)); var data = new ReadOnlySequence(buffer); _hubProtocol.TryParseMessage(ref data, binder, out var message); - var exception = Assert.Throws(() => ((HubMethodInvocationMessage)message).Arguments); - - Assert.Equal(testData.ErrorMessage, exception.Message); + var bindingFailure = Assert.IsType(message); + Assert.Equal(testData.ErrorMessage, bindingFailure.BindingFailure.SourceException.Message); } [Theory] diff --git a/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisProtocolTests.cs index 7d1a4aa3e4..3a710f42cc 100644 --- a/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Redis.Tests/RedisProtocolTests.cs @@ -84,12 +84,14 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Tests } // The actual invocation message doesn't matter - private static InvocationMessage _testMessage = new InvocationMessage("target", null, Array.Empty()); - private static Dictionary> _invocationTestData = new[] + private static InvocationMessage _testMessage = new InvocationMessage("target", Array.Empty()); + + // We use a func so we are guaranteed to get a new SerializedHubMessage for each test + private static Dictionary>> _invocationTestData = new[] { - CreateTestData( + CreateTestData>( "NoExcludedIds", - new RedisInvocation(new SerializedHubMessage(_testMessage), null), + () => new RedisInvocation(new SerializedHubMessage(_testMessage), null), 0x92, 0x90, 0x82, @@ -97,9 +99,9 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Tests 0xC4, 0x01, 0x2A, 0xA2, (byte)'p', (byte)'2', 0xC4, 0x01, 0x2A), - CreateTestData( + CreateTestData>( "OneExcludedId", - new RedisInvocation(new SerializedHubMessage(_testMessage), new [] { "a" }), + () => new RedisInvocation(new SerializedHubMessage(_testMessage), new [] { "a" }), 0x92, 0x91, 0xA1, (byte)'a', @@ -108,9 +110,9 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Tests 0xC4, 0x01, 0x2A, 0xA2, (byte)'p', (byte)'2', 0xC4, 0x01, 0x2A), - CreateTestData( + CreateTestData>( "ManyExcludedIds", - new RedisInvocation(new SerializedHubMessage(_testMessage), new [] { "a", "b", "c", "d", "e", "f" }), + () => new RedisInvocation(new SerializedHubMessage(_testMessage), new [] { "a", "b", "c", "d", "e", "f" }), 0x92, 0x96, 0xA1, (byte)'a', @@ -136,15 +138,17 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Tests var hubProtocols = new[] { new DummyHubProtocol("p1"), new DummyHubProtocol("p2") }; var protocol = new RedisProtocol(hubProtocols); + var expected = testData.Decoded(); + var decoded = protocol.ReadInvocation(testData.Encoded); - Assert.Equal(testData.Decoded.ExcludedConnectionIds, decoded.ExcludedConnectionIds); + Assert.Equal(expected.ExcludedConnectionIds, decoded.ExcludedConnectionIds); // Verify the deserialized object has the necessary serialized forms foreach (var hubProtocol in hubProtocols) { Assert.Equal( - testData.Decoded.Message.GetSerializedMessage(hubProtocol).ToArray(), + expected.Message.GetSerializedMessage(hubProtocol).ToArray(), decoded.Message.GetSerializedMessage(hubProtocol).ToArray()); Assert.Equal(1, hubProtocol.SerializationCount); } @@ -159,7 +163,8 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Tests // Actual invocation doesn't matter because we're using a dummy hub protocol. // But the dummy protocol will check that we gave it the test message to make sure everything flows through properly. - var encoded = protocol.WriteInvocation(_testMessage.Target, _testMessage.Arguments, testData.Decoded.ExcludedConnectionIds); + var expected = testData.Decoded(); + var encoded = protocol.WriteInvocation(_testMessage.Target, _testMessage.Arguments, expected.ExcludedConnectionIds); Assert.Equal(testData.Encoded, encoded); } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs index 80f78c03bc..9ecf005342 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs @@ -164,13 +164,13 @@ namespace Microsoft.AspNetCore.SignalR.Tests public Task SendInvocationAsync(string methodName, bool nonBlocking, params object[] args) { var invocationId = nonBlocking ? null : GetInvocationId(); - return SendHubMessageAsync(new InvocationMessage(invocationId, methodName, null, args)); + return SendHubMessageAsync(new InvocationMessage(invocationId, methodName, args)); } public Task SendStreamInvocationAsync(string methodName, params object[] args) { var invocationId = GetInvocationId(); - return SendHubMessageAsync(new StreamInvocationMessage(invocationId, methodName, null, args)); + return SendHubMessageAsync(new StreamInvocationMessage(invocationId, methodName, args)); } public async Task SendHubMessageAsync(HubMessage message) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs index 9076587e92..3ea5d2e4f7 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs @@ -1429,7 +1429,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests await client.Connected.OrTimeout(); var invocationId = Guid.NewGuid().ToString("N"); - await client.SendHubMessageAsync(new StreamInvocationMessage(invocationId, nameof(StreamingHub.BlockingStream), null, Array.Empty())); + await client.SendHubMessageAsync(new StreamInvocationMessage(invocationId, nameof(StreamingHub.BlockingStream), Array.Empty())); // cancel the Streaming method await client.SendHubMessageAsync(new CancelInvocationMessage(invocationId)).OrTimeout(); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubMethodInvocationMessageTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubMethodInvocationMessageTests.cs deleted file mode 100644 index dedf151d0a..0000000000 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubMethodInvocationMessageTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.ExceptionServices; -using Microsoft.AspNetCore.SignalR.Protocol; -using Xunit; - -namespace Microsoft.AspNetCore.SignalR.Tests -{ - public class HubMethodInvocationMessageTests - { - [Fact] - public void InvocationMessageToStringPutsErrorInArgs() - { - var hubMessage = new InvocationMessage("echo", ExceptionDispatchInfo.Capture(new Exception("test")), null); - - Assert.Equal("InvocationMessage { InvocationId: \"\", Target: \"echo\", Arguments: [ Error: test ] }", hubMessage.ToString()); - } - - [Fact] - public void StreamInvocationMessageToStringPutsErrorInArgs() - { - var hubMessage = new StreamInvocationMessage("3", "echo", ExceptionDispatchInfo.Capture(new Exception("test")), null); - - Assert.Equal("StreamInvocation { InvocationId: \"3\", Target: \"echo\", Arguments: [ Error: test ] }", hubMessage.ToString()); - } - } -} From 7dd6d82bba4302bf403226e639e0f50e3c5c70c1 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 17 Apr 2018 21:07:53 -0700 Subject: [PATCH 28/28] remove verbose flag (#2067) --- clients/ts/FunctionalTests/selenium/run-ci-tests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/ts/FunctionalTests/selenium/run-ci-tests.ts b/clients/ts/FunctionalTests/selenium/run-ci-tests.ts index 044cf9e2e7..7e7d1050af 100644 --- a/clients/ts/FunctionalTests/selenium/run-ci-tests.ts +++ b/clients/ts/FunctionalTests/selenium/run-ci-tests.ts @@ -80,9 +80,9 @@ if (configuration) { args.push("--configuration"); args.push(configuration); } - +if (verbose) { args.push("--verbose"); - +} let command = "npm";