diff --git a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HttpConnectionOptions.java b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HttpConnectionOptions.java new file mode 100644 index 0000000000..70d7895bee --- /dev/null +++ b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HttpConnectionOptions.java @@ -0,0 +1,68 @@ +// 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. + +package com.microsoft.aspnet.signalr; + +public class HttpConnectionOptions { + private String url; + private Transport transport; + private LogLevel loglevel; + + private Logger logger; + private boolean skipNegotiate; + + public HttpConnectionOptions() {} + + public HttpConnectionOptions(String url, Transport transport, LogLevel logLevel, boolean skipNegotiate) { + this.url = url; + this.transport = transport; + this.skipNegotiate = skipNegotiate; + this.loglevel = logLevel; + } + + public HttpConnectionOptions(String url, Transport transport, Logger logger, boolean skipNegotiate) { + this.url = url; + this.transport = transport; + this.skipNegotiate = skipNegotiate; + this.logger = logger; + } + public void setUrl(String url) { + this.url = url; + } + + public void setTransport(Transport transport) { + this.transport = transport; + } + + public void setLoglevel(LogLevel loglevel) { + this.loglevel = loglevel; + } + + public void setSkipNegotiate(boolean skipNegotiate) { + this.skipNegotiate = skipNegotiate; + } + + public String getUrl() { + return url; + } + + public Transport getTransport() { + return transport; + } + + public LogLevel getLoglevel() { + return loglevel; + } + + public boolean getSkipNegotiate() { + return skipNegotiate; + } + + public Logger getLogger() { + return logger; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } +} diff --git a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnection.java b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnection.java index 06c3b34b55..488ee28dc2 100644 --- a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnection.java +++ b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnection.java @@ -36,6 +36,10 @@ public class HubConnection { private static int MAX_NEGOTIATE_ATTEMPTS = 100; public HubConnection(String url, Transport transport, Logger logger, boolean skipNegotiate) { + if (url == null || url.isEmpty()) { + throw new IllegalArgumentException("A valid url is required."); + } + this.url = url; this.protocol = new JsonHubProtocol(); @@ -44,6 +48,11 @@ public class HubConnection { } else { this.logger = new NullLogger(); } + + if (transport != null) { + this.transport = transport; + } + this.skipNegotiate = skipNegotiate; this.callback = (payload) -> { @@ -107,10 +116,6 @@ public class HubConnection { } } }; - - if (transport != null) { - this.transport = transport; - } } private NegotiateResponse handleNegotiate() throws IOException { @@ -136,43 +141,6 @@ public class HubConnection { return negotiateResponse; } - public HubConnection(String url, Transport transport, Logger logger) { - this(url, transport, logger, false); - } - - public HubConnection(String url, Transport transport, boolean skipNegotiate) { - this(url, transport, new NullLogger(), skipNegotiate); - } - - /** - * Initializes a new instance of the {@link HubConnection} class. - * - * @param url The url of the SignalR server to connect to. - * @param transport The {@link Transport} that the client will use to communicate with the server. - */ - public HubConnection(String url, Transport transport) { - this(url, transport, new NullLogger()); - } - - /** - * Initializes a new instance of the {@link HubConnection} class. - * - * @param url The url of the SignalR server to connect to. - */ - public HubConnection(String url) { - this(url, null, new NullLogger()); - } - - /** - * Initializes a new instance of the {@link HubConnection} class. - * - * @param url The url of the SignalR server to connect to. - * @param logLevel The minimum level of messages to log. - */ - public HubConnection(String url, LogLevel logLevel) { - this(url, null, new ConsoleLogger(logLevel)); - } - /** * Indicates the state of the {@link HubConnection} to the server. * diff --git a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnectionBuilder.java b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnectionBuilder.java index ac8fa99f8c..b677240c1d 100644 --- a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnectionBuilder.java +++ b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/HubConnectionBuilder.java @@ -4,22 +4,41 @@ package com.microsoft.aspnet.signalr; public class HubConnectionBuilder { - private boolean built; private String url; private Transport transport; private Logger logger; + private boolean skipNegotiate; public HubConnectionBuilder withUrl(String url) { + if (url == null || url.isEmpty()) { + throw new IllegalArgumentException("A valid url is required."); + } + this.url = url; return this; } public HubConnectionBuilder withUrl(String url, Transport transport) { + if (url == null || url.isEmpty()) { + throw new IllegalArgumentException("A valid url is required."); + } this.url = url; this.transport = transport; return this; } + public HubConnectionBuilder withUrl(String url, HttpConnectionOptions options) { + this.url = url; + this.transport = options.getTransport(); + if (options.getLogger() != null) { + this.logger = options.getLogger(); + } else if (options.getLoglevel() != null) { + this.logger = new ConsoleLogger(options.getLoglevel()); + } + this.skipNegotiate = options.getSkipNegotiate(); + return this; + } + public HubConnectionBuilder configureLogging(LogLevel logLevel) { this.logger = new ConsoleLogger(logLevel); return this; @@ -30,11 +49,10 @@ public class HubConnectionBuilder { return this; } - public HubConnection build() throws Exception { - if (!built) { - built = true; - return new HubConnection(url, transport, logger); + public HubConnection build() { + if (this.url == null) { + throw new RuntimeException("The 'HubConnectionBuilder.withUrl' method must be called before building the connection."); } - throw new Exception("HubConnectionBuilder allows creation only of a single instance of HubConnection."); + return new HubConnection(url, transport, logger, skipNegotiate); } } \ No newline at end of file diff --git a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/JsonHubProtocol.java b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/JsonHubProtocol.java index 4acc831226..37a09acc92 100644 --- a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/JsonHubProtocol.java +++ b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/JsonHubProtocol.java @@ -3,6 +3,7 @@ package com.microsoft.aspnet.signalr; +import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; @@ -12,6 +13,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; class JsonHubProtocol implements HubProtocol { private final JsonParser jsonParser = new JsonParser(); @@ -77,15 +79,8 @@ class JsonHubProtocol implements HubProtocol { break; case "arguments": if (target != null) { - reader.beginArray(); List> types = binder.getParameterTypes(target); - if (types != null && types.size() >= 1) { - arguments = new ArrayList<>(); - for (int i = 0; i < types.size(); i++) { - arguments.add(gson.fromJson(reader, types.get(i))); - } - } - reader.endArray(); + arguments = bindArguments(reader, types); } else { argumentsToken = (JsonArray)jsonParser.parse(reader); } @@ -106,12 +101,7 @@ class JsonHubProtocol implements HubProtocol { case INVOCATION: if (argumentsToken != null) { List> types = binder.getParameterTypes(target); - if (types != null && types.size() >= 1) { - arguments = new ArrayList<>(); - for (int i = 0; i < types.size(); i++) { - arguments.add(gson.fromJson(argumentsToken.get(i), types.get(i))); - } - } + arguments = bindArguments(argumentsToken, types); } if (arguments == null) { hubMessages.add(new InvocationMessage(invocationId, target, new Object[0])); @@ -151,4 +141,42 @@ class JsonHubProtocol implements HubProtocol { public String writeMessage(HubMessage hubMessage) { return gson.toJson(hubMessage) + RECORD_SEPARATOR; } + + private ArrayList bindArguments(JsonArray argumentsToken, List> paramTypes) { + if (argumentsToken.size() != paramTypes.size()) { + throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argumentsToken.size(), paramTypes.size())); + } + + ArrayList arguments = null; + if (paramTypes.size() >= 1) { + arguments = new ArrayList<>(); + for (int i = 0; i < paramTypes.size(); i++) { + arguments.add(gson.fromJson(argumentsToken.get(i), paramTypes.get(i))); + } + } + + return arguments; + } + + private ArrayList bindArguments(JsonReader reader, List> paramTypes) throws IOException { + reader.beginArray(); + int paramCount = paramTypes.size(); + int argCount = 0; + ArrayList arguments = new ArrayList<>(); + while (reader.peek() != JsonToken.END_ARRAY) { + if (argCount < paramCount) { + arguments.add(gson.fromJson(reader, paramTypes.get(argCount))); + } else { + reader.skipValue(); + } + argCount++; + } + + if (paramCount != argCount) { + throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argCount, paramCount)); + } + + reader.endArray(); + return arguments; + } } diff --git a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/WebSocketTransport.java b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/WebSocketTransport.java index 91cd290898..43281465f8 100644 --- a/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/WebSocketTransport.java +++ b/clients/java/signalr/src/main/java/com/microsoft/aspnet/signalr/WebSocketTransport.java @@ -29,10 +29,6 @@ class WebSocketTransport implements Transport { this.headers = headers; } - public WebSocketTransport(String url, Logger logger) throws URISyntaxException { - this(url, logger, null); - } - public URI getUrl() { return url; } diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HandshakeProtocolTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HandshakeProtocolTest.java index 69eb504189..ea3d4a6f69 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HandshakeProtocolTest.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HandshakeProtocolTest.java @@ -8,7 +8,6 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; class HandshakeProtocolTest { - @Test public void VerifyCreateHandshakerequestMessage() { HandshakeRequestMessage handshakeRequest = new HandshakeRequestMessage("json", 1); diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HttpConnectionOptionsTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HttpConnectionOptionsTest.java new file mode 100644 index 0000000000..b70d3a3c42 --- /dev/null +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HttpConnectionOptionsTest.java @@ -0,0 +1,22 @@ +// 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. + +package com.microsoft.aspnet.signalr; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class HttpConnectionOptionsTest { + @Test + public void CheckHttpConnectionOptionsFields() { + Transport mockTransport = new MockTransport(); + HttpConnectionOptions options = new HttpConnectionOptions("http://example.com", mockTransport, LogLevel.Information, true); + assertEquals("http://example.com",options.getUrl()); + assertEquals(LogLevel.Information, options.getLoglevel()); + assertTrue(options.getSkipNegotiate()); + assertNotNull(options.getTransport()); + } +} diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionBuilderTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionBuilderTest.java new file mode 100644 index 0000000000..fb2dea0d6f --- /dev/null +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionBuilderTest.java @@ -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. + +package com.microsoft.aspnet.signalr; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class HubConnectionBuilderTest { + @Test + public void callingBuildWithoutCallingWithUrlThrows() { + HubConnectionBuilder builder = new HubConnectionBuilder(); + Throwable exception = assertThrows(RuntimeException.class, () -> builder.build()); + assertEquals("The \'HubConnectionBuilder.withUrl\' method must be called before building the connection.", exception.getMessage()); + } + + @Test + public void passingInNullToWithUrlThrows() { + HubConnectionBuilder builder = new HubConnectionBuilder(); + Throwable exception = assertThrows(IllegalArgumentException.class, () -> builder.withUrl(null)); + assertEquals("A valid url is required.", exception.getMessage()); + } + + @Test + public void passingInEmptyStringToWihtUrlThrows() { + HubConnectionBuilder builder = new HubConnectionBuilder(); + Throwable exception = assertThrows(IllegalArgumentException.class, () -> builder.withUrl("")); + assertEquals("A valid url is required.", exception.getMessage()); + } +} diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionTest.java index d713bad31a..abeff622d1 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionTest.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/HubConnectionTest.java @@ -5,7 +5,6 @@ package com.microsoft.aspnet.signalr; import static org.junit.jupiter.api.Assertions.*; -import java.util.ArrayList; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -20,7 +19,22 @@ class HubConnectionTest { @Test public void checkHubConnectionState() throws Exception { Transport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(),true); + hubConnection.start(); + assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); + + hubConnection.stop(); + assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); + } + + @Test + public void constructHubConnectionWithHttpConnectionOptions() throws Exception { + Transport mockTransport = new MockTransport(); + HttpConnectionOptions options = new HttpConnectionOptions(); + options.setTransport(mockTransport); + options.setLoglevel(LogLevel.Information); + options.setSkipNegotiate(true); + HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://www.example.com", options).build(); hubConnection.start(); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); @@ -31,7 +45,7 @@ class HubConnectionTest { @Test public void hubConnectionClosesAfterCloseMessage() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); @@ -46,7 +60,7 @@ class HubConnectionTest { @Test public void hubConnectionReceiveHandshakeResponseWithError() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); Throwable exception = assertThrows(HubException.class, () -> mockTransport.receiveMessage("{\"error\":\"Requested protocol 'messagepack' is not available.\"}" + RECORD_SEPARATOR)); @@ -57,7 +71,7 @@ class HubConnectionTest { public void registeringMultipleHandlersAndBothGetTriggered() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); hubConnection.on("inc", action); @@ -83,7 +97,7 @@ class HubConnectionTest { public void removeHandlerByName() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); hubConnection.on("inc", action); @@ -110,7 +124,7 @@ class HubConnectionTest { public void addAndRemoveHandlerImmediately() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); hubConnection.on("inc", action); @@ -135,7 +149,7 @@ class HubConnectionTest { public void removingMultipleHandlersWithOneCallToRemove() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); Action secondAction = () -> value.getAndUpdate((val) -> val + 2); @@ -167,7 +181,7 @@ class HubConnectionTest { public void removeHandlerWithUnsubscribe() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); Subscription subscription = hubConnection.on("inc", action); @@ -200,7 +214,7 @@ class HubConnectionTest { public void unsubscribeTwice() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(),true); Action action = () -> value.getAndUpdate((val) -> val + 1); Subscription subscription = hubConnection.on("inc", action); @@ -234,7 +248,7 @@ class HubConnectionTest { public void removeSingleHandlerWithUnsubscribe() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); Action secondAction = () -> value.getAndUpdate((val) -> val + 2); @@ -264,7 +278,7 @@ class HubConnectionTest { public void addAndRemoveHandlerImmediatelyWithSubscribe() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action action = () -> value.getAndUpdate((val) -> val + 1); Subscription sub = hubConnection.on("inc", action); @@ -289,7 +303,7 @@ class HubConnectionTest { public void registeringMultipleHandlersThatTakeParamsAndBothGetTriggered() throws Exception { AtomicReference value = new AtomicReference<>(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); Action1 action = (number) -> value.getAndUpdate((val) -> val + number); @@ -308,13 +322,13 @@ class HubConnectionTest { @Test public void invokeWaitsForCompletionMessage() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); CompletableFuture result = hubConnection.invoke(Integer.class, "echo", "message"); - assertEquals("{\"type\":1,\"invocationId\":\"1\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.sentMessages.get(1)); + assertEquals("{\"type\":1,\"invocationId\":\"1\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.getSentMessages()[1]); assertFalse(result.isDone()); mockTransport.receiveMessage("{\"type\":3,\"invocationId\":\"1\",\"result\":42}" + RECORD_SEPARATOR); @@ -325,15 +339,15 @@ class HubConnectionTest { @Test public void multipleInvokesWaitForOwnCompletionMessage() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); CompletableFuture result = hubConnection.invoke(Integer.class, "echo", "message"); CompletableFuture result2 = hubConnection.invoke(String.class, "echo", "message"); - assertEquals("{\"type\":1,\"invocationId\":\"1\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.sentMessages.get(1)); - assertEquals("{\"type\":1,\"invocationId\":\"2\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.sentMessages.get(2)); + assertEquals("{\"type\":1,\"invocationId\":\"1\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.getSentMessages()[1]); + assertEquals("{\"type\":1,\"invocationId\":\"2\",\"target\":\"echo\",\"arguments\":[\"message\"]}" + RECORD_SEPARATOR, mockTransport.getSentMessages()[2]); assertFalse(result.isDone()); assertFalse(result2.isDone()); @@ -348,7 +362,7 @@ class HubConnectionTest { @Test public void invokeWorksForPrimitiveTypes() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); @@ -366,7 +380,7 @@ class HubConnectionTest { @Test public void completionMessageCanHaveError() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); @@ -390,7 +404,7 @@ class HubConnectionTest { @Test public void stopCancelsActiveInvokes() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); @@ -415,7 +429,7 @@ class HubConnectionTest { public void sendWithNoParamsTriggersOnHandler() throws Exception { AtomicReference value = new AtomicReference<>(0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", () ->{ assertEquals(Integer.valueOf(0), value.get()); @@ -434,7 +448,7 @@ class HubConnectionTest { public void sendWithParamTriggersOnHandler() throws Exception { AtomicReference value = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param) ->{ assertNull(value.get()); @@ -456,7 +470,7 @@ class HubConnectionTest { AtomicReference value2 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2) ->{ assertNull(value1.get()); @@ -483,7 +497,7 @@ class HubConnectionTest { AtomicReference value3 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3) ->{ assertNull(value1.get()); @@ -514,7 +528,7 @@ class HubConnectionTest { AtomicReference value4 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3, param4) ->{ assertNull(value1.get()); @@ -548,7 +562,7 @@ class HubConnectionTest { AtomicReference value5 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3, param4, param5) ->{ assertNull(value1.get()); @@ -586,7 +600,7 @@ class HubConnectionTest { AtomicReference value6 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3, param4, param5, param6) -> { assertNull(value1.get()); @@ -628,7 +642,7 @@ class HubConnectionTest { AtomicReference value7 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7) -> { assertNull(value1.get()); @@ -674,7 +688,7 @@ class HubConnectionTest { AtomicReference value8 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7, param8) -> { assertNull(value1.get()); @@ -721,7 +735,7 @@ class HubConnectionTest { AtomicReference value1 = new AtomicReference<>(); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", (param1) -> { assertNull(value1.get()); @@ -746,7 +760,7 @@ class HubConnectionTest { public void receiveHandshakeResponseAndMessage() throws Exception { AtomicReference value = new AtomicReference(0.0); MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.on("inc", () ->{ assertEquals(Double.valueOf(0), value.get()); @@ -768,7 +782,7 @@ class HubConnectionTest { public void onClosedCallbackRunsWhenStopIsCalled() throws Exception { AtomicReference value1 = new AtomicReference<>(); Transport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); hubConnection.onClosed((ex) -> { assertNull(value1.get()); @@ -785,7 +799,7 @@ class HubConnectionTest { AtomicReference value1 = new AtomicReference<>(); AtomicReference value2 = new AtomicReference<>(); Transport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.start(); hubConnection.onClosed((ex) -> { @@ -810,7 +824,7 @@ class HubConnectionTest { @Test public void hubConnectionClosesAndRunsOnClosedCallbackAfterCloseMessageWithError() throws Exception { MockTransport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); hubConnection.onClosed((ex) -> { assertEquals(ex.getMessage(), "There was an error"); }); @@ -827,7 +841,7 @@ class HubConnectionTest { @Test public void callingStartOnStartedHubConnectionNoOps() throws Exception { Transport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, true); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger() ,true); hubConnection.start(); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); @@ -841,49 +855,26 @@ class HubConnectionTest { @Test public void cannotSendBeforeStart() throws Exception { Transport mockTransport = new MockTransport(); - HubConnection hubConnection = new HubConnection("http://example.com", mockTransport); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); Throwable exception = assertThrows(HubException.class, () -> hubConnection.send("inc")); assertEquals("The 'send' method cannot be called if the connection is not active", exception.getMessage()); } - private class MockTransport implements Transport { - private OnReceiveCallBack onReceiveCallBack; - private ArrayList sentMessages = new ArrayList<>(); + @Test + public void errorWhenReceivingInvokeWithIncorrectArgumentLength() throws Exception { + MockTransport mockTransport = new MockTransport(); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true); + hubConnection.on("Send", (s) -> { + assertTrue(false); + }, String.class); - @Override - public CompletableFuture start() { - return CompletableFuture.completedFuture(null); - } + CompletableFuture startFuture = hubConnection.start(); + mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); - @Override - public CompletableFuture send(String message) { - sentMessages.add(message); - return CompletableFuture.completedFuture(null); - } - - @Override - public void setOnReceive(OnReceiveCallBack callback) { - this.onReceiveCallBack = callback; - } - - @Override - public void onReceive(String message) throws Exception { - this.onReceiveCallBack.invoke(message); - } - - @Override - public CompletableFuture stop() { - return CompletableFuture.completedFuture(null); - } - - public void receiveMessage(String message) throws Exception { - this.onReceive(message); - } - - public String[] getSentMessages() { - return sentMessages.toArray(new String[sentMessages.size()]); - } + startFuture.get(1000, TimeUnit.MILLISECONDS); + RuntimeException exception = assertThrows(RuntimeException.class, () -> mockTransport.receiveMessage("{\"type\":1,\"target\":\"Send\",\"arguments\":[]}" + RECORD_SEPARATOR)); + assertEquals("Invocation provides 0 argument(s) but target expects 1.", exception.getMessage()); } } \ No newline at end of file diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/JsonHubProtocolTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/JsonHubProtocolTest.java index ccd4cd33ec..b637058f15 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/JsonHubProtocolTest.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/JsonHubProtocolTest.java @@ -219,6 +219,33 @@ class JsonHubProtocolTest { assertEquals(42 , message.getResult()); } + @Test + public void errorWhileParsingTooManyArgumentsWithOutOfOrderProperties() throws Exception { + String stringifiedMessage = "{\"arguments\":[42, 24],\"type\":1,\"target\":\"test\"}\u001E"; + TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42 })); + + RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder)); + assertEquals("Invocation provides 2 argument(s) but target expects 1.", exception.getMessage()); + } + + @Test + public void errorWhileParsingTooManyArguments() throws Exception { + String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42, 24]}\u001E"; + TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42 })); + + RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder)); + assertEquals("Invocation provides 2 argument(s) but target expects 1.", exception.getMessage()); + } + + @Test + public void errorWhileParsingTooFewArguments() throws Exception { + String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E"; + TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42, 24 })); + + RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder)); + assertEquals("Invocation provides 1 argument(s) but target expects 2.", exception.getMessage()); + } + private class TestBinder implements InvocationBinder { private Class[] paramTypes = null; private Class returnType = null; diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/MockTransport.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/MockTransport.java new file mode 100644 index 0000000000..56099005a6 --- /dev/null +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/MockTransport.java @@ -0,0 +1,46 @@ +// 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. + +package com.microsoft.aspnet.signalr; + +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; + +class MockTransport implements Transport { + private OnReceiveCallBack onReceiveCallBack; + private ArrayList sentMessages = new ArrayList<>(); + + @Override + public CompletableFuture start() { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture send(String message) { + sentMessages.add(message); + return CompletableFuture.completedFuture(null); + } + + @Override + public void setOnReceive(OnReceiveCallBack callback) { + this.onReceiveCallBack = callback; + } + + @Override + public void onReceive(String message) throws Exception { + this.onReceiveCallBack.invoke(message); + } + + @Override + public CompletableFuture stop() { + return CompletableFuture.completedFuture(null); + } + + public void receiveMessage(String message) throws Exception { + this.onReceive(message); + } + + public String[] getSentMessages() { + return sentMessages.toArray(new String[sentMessages.size()]); + } +} diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportTest.java index d3a2985744..ebed559872 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportTest.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportTest.java @@ -5,6 +5,7 @@ package com.microsoft.aspnet.signalr; import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -12,7 +13,7 @@ import org.junit.jupiter.api.Test; class WebSocketTransportTest { @Test public void WebsocketThrowsIfItCantConnect() throws Exception { - Transport transport = new WebSocketTransport("www.notarealurl12345.fake", new NullLogger()); + Transport transport = new WebSocketTransport("www.notarealurl12345.fake", new NullLogger(), new HashMap<>()); Throwable exception = assertThrows(Exception.class, () -> transport.start().get(1,TimeUnit.SECONDS)); assertEquals("There was an error starting the Websockets transport.", exception.getCause().getMessage()); } diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportUrlFormatTest.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportUrlFormatTest.java index d4294cd642..15be4a89b2 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportUrlFormatTest.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/WebSocketTransportUrlFormatTest.java @@ -6,6 +6,7 @@ package com.microsoft.aspnet.signalr; import static org.junit.jupiter.api.Assertions.*; import java.net.URISyntaxException; +import java.util.HashMap; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; @@ -24,7 +25,7 @@ class WebSocketTransportUrlFormatTest { @ParameterizedTest @MethodSource("protocols") public void checkWebsocketUrlProtocol(String url, String expectedUrl) throws URISyntaxException { - WebSocketTransport webSocketTransport = new WebSocketTransport(url, new NullLogger()); + WebSocketTransport webSocketTransport = new WebSocketTransport(url, new NullLogger(), new HashMap<>()); assertEquals(expectedUrl, webSocketTransport.getUrl().toString()); } } \ No newline at end of file diff --git a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/sample/Chat.java b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/sample/Chat.java index cec5fe913c..2a9e61e061 100644 --- a/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/sample/Chat.java +++ b/clients/java/signalr/src/test/java/com/microsoft/aspnet/signalr/sample/Chat.java @@ -33,7 +33,7 @@ public class Chat { }); //This is a blocking call - hubConnection.start(); + hubConnection.start().get(); String message = ""; while (!message.equals("leave")) {