Skip to content

Commit d5cf36a

Browse files
[TS Client] Test message size (#15099)
1 parent 6a4a856 commit d5cf36a

File tree

9 files changed

+295
-80
lines changed

9 files changed

+295
-80
lines changed

src/SignalR/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,28 @@ export class MessagePackHubProtocol implements IHubProtocol {
221221

222222
private writeInvocation(invocationMessage: InvocationMessage): ArrayBuffer {
223223
const msgpack = msgpack5();
224-
const payload = msgpack.encode([MessageType.Invocation, invocationMessage.headers || {}, invocationMessage.invocationId || null,
225-
invocationMessage.target, invocationMessage.arguments, invocationMessage.streamIds]);
224+
let payload: any;
225+
if (invocationMessage.streamIds) {
226+
payload = msgpack.encode([MessageType.Invocation, invocationMessage.headers || {}, invocationMessage.invocationId || null,
227+
invocationMessage.target, invocationMessage.arguments, invocationMessage.streamIds]);
228+
} else {
229+
payload = msgpack.encode([MessageType.Invocation, invocationMessage.headers || {}, invocationMessage.invocationId || null,
230+
invocationMessage.target, invocationMessage.arguments]);
231+
}
226232

227233
return BinaryMessageFormat.write(payload.slice());
228234
}
229235

230236
private writeStreamInvocation(streamInvocationMessage: StreamInvocationMessage): ArrayBuffer {
231237
const msgpack = msgpack5();
232-
const payload = msgpack.encode([MessageType.StreamInvocation, streamInvocationMessage.headers || {}, streamInvocationMessage.invocationId,
233-
streamInvocationMessage.target, streamInvocationMessage.arguments, streamInvocationMessage.streamIds]);
238+
let payload: any;
239+
if (streamInvocationMessage.streamIds) {
240+
payload = msgpack.encode([MessageType.StreamInvocation, streamInvocationMessage.headers || {}, streamInvocationMessage.invocationId,
241+
streamInvocationMessage.target, streamInvocationMessage.arguments, streamInvocationMessage.streamIds]);
242+
} else {
243+
payload = msgpack.encode([MessageType.StreamInvocation, streamInvocationMessage.headers || {}, streamInvocationMessage.invocationId,
244+
streamInvocationMessage.target, streamInvocationMessage.arguments]);
245+
}
234246

235247
return BinaryMessageFormat.write(payload.slice());
236248
}

src/SignalR/clients/ts/signalr/src/HubConnection.ts

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -818,23 +818,40 @@ export class HubConnection {
818818

819819
private createInvocation(methodName: string, args: any[], nonblocking: boolean, streamIds: string[]): InvocationMessage {
820820
if (nonblocking) {
821-
return {
822-
arguments: args,
823-
streamIds,
824-
target: methodName,
825-
type: MessageType.Invocation,
826-
};
821+
if (streamIds.length !== 0) {
822+
return {
823+
arguments: args,
824+
streamIds,
825+
target: methodName,
826+
type: MessageType.Invocation,
827+
};
828+
} else {
829+
return {
830+
arguments: args,
831+
target: methodName,
832+
type: MessageType.Invocation,
833+
};
834+
}
827835
} else {
828836
const invocationId = this.invocationId;
829837
this.invocationId++;
830838

831-
return {
832-
arguments: args,
833-
invocationId: invocationId.toString(),
834-
streamIds,
835-
target: methodName,
836-
type: MessageType.Invocation,
837-
};
839+
if (streamIds.length !== 0) {
840+
return {
841+
arguments: args,
842+
invocationId: invocationId.toString(),
843+
streamIds,
844+
target: methodName,
845+
type: MessageType.Invocation,
846+
};
847+
} else {
848+
return {
849+
arguments: args,
850+
invocationId: invocationId.toString(),
851+
target: methodName,
852+
type: MessageType.Invocation,
853+
};
854+
}
838855
}
839856
}
840857

@@ -903,13 +920,22 @@ export class HubConnection {
903920
const invocationId = this.invocationId;
904921
this.invocationId++;
905922

906-
return {
907-
arguments: args,
908-
invocationId: invocationId.toString(),
909-
streamIds,
910-
target: methodName,
911-
type: MessageType.StreamInvocation,
912-
};
923+
if (streamIds.length !== 0) {
924+
return {
925+
arguments: args,
926+
invocationId: invocationId.toString(),
927+
streamIds,
928+
target: methodName,
929+
type: MessageType.StreamInvocation,
930+
};
931+
} else {
932+
return {
933+
arguments: args,
934+
invocationId: invocationId.toString(),
935+
target: methodName,
936+
type: MessageType.StreamInvocation,
937+
};
938+
}
913939
}
914940

915941
private createCancelInvocation(id: string): CancelInvocationMessage {

src/SignalR/clients/ts/signalr/src/IHubProtocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export interface InvocationMessage extends HubInvocationMessage {
6565
/** The target method arguments. */
6666
readonly arguments: any[];
6767
/** The target methods stream IDs. */
68-
readonly streamIds: string[];
68+
readonly streamIds?: string[];
6969
}
7070

7171
/** A hub message representing a streaming invocation. */
@@ -80,7 +80,7 @@ export interface StreamInvocationMessage extends HubInvocationMessage {
8080
/** The target method arguments. */
8181
readonly arguments: any[];
8282
/** The target methods stream IDs. */
83-
readonly streamIds: string[];
83+
readonly streamIds?: string[];
8484
}
8585

8686
/** A hub message representing a single item produced as part of a result stream. */

src/SignalR/clients/ts/signalr/tests/HubConnection.test.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ describe("HubConnection", () => {
184184
"arg",
185185
42,
186186
],
187-
streamIds: [],
188187
target: "testMethod",
189188
type: MessageType.Invocation,
190189
});
@@ -213,7 +212,6 @@ describe("HubConnection", () => {
213212
"arg",
214213
null,
215214
],
216-
streamIds: [],
217215
target: "testMethod",
218216
type: MessageType.Invocation,
219217
});
@@ -245,7 +243,6 @@ describe("HubConnection", () => {
245243
42,
246244
],
247245
invocationId: connection.lastInvocationId,
248-
streamIds: [],
249246
target: "testMethod",
250247
type: MessageType.Invocation,
251248
});
@@ -998,7 +995,6 @@ describe("HubConnection", () => {
998995
42,
999996
],
1000997
invocationId: connection.lastInvocationId,
1001-
streamIds: [],
1002998
target: "testStream",
1003999
type: MessageType.StreamInvocation,
10041000
});
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
import { HubConnection } from "../src/HubConnection";
5+
import { IConnection } from "../src/IConnection";
6+
import { IHubProtocol, MessageType } from "../src/IHubProtocol";
7+
import { ILogger } from "../src/ILogger";
8+
import { JsonHubProtocol } from "../src/JsonHubProtocol";
9+
import { NullLogger } from "../src/Loggers";
10+
import { Subject } from "../src/Subject";
11+
import { VerifyLogger } from "./Common";
12+
import { TestConnection } from "./TestConnection";
13+
import { delayUntil, registerUnhandledRejectionHandler } from "./Utils";
14+
15+
registerUnhandledRejectionHandler();
16+
17+
function createHubConnection(connection: IConnection, logger?: ILogger | null, protocol?: IHubProtocol | null) {
18+
return HubConnection.create(connection, logger || NullLogger.instance, protocol || new JsonHubProtocol());
19+
}
20+
21+
// These tests check that the message size doesn't change without us being aware of it and making a conscious decision to increase the size
22+
23+
describe("Message size", () => {
24+
it("send invocation", async () => {
25+
await VerifyLogger.run(async (logger) => {
26+
const connection = new TestConnection();
27+
28+
const hubConnection = createHubConnection(connection, logger);
29+
try {
30+
// We don't actually care to wait for the send.
31+
// tslint:disable-next-line:no-floating-promises
32+
hubConnection.send("target", 1)
33+
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
34+
35+
// Verify the message is sent
36+
expect(connection.sentData.length).toBe(1);
37+
expect(connection.parsedSentData[0].type).toEqual(MessageType.Invocation);
38+
expect((connection.sentData[0] as string).length).toEqual(44);
39+
} finally {
40+
// Close the connection
41+
await hubConnection.stop();
42+
}
43+
});
44+
});
45+
46+
it("invoke invocation", async () => {
47+
await VerifyLogger.run(async (logger) => {
48+
const connection = new TestConnection();
49+
50+
const hubConnection = createHubConnection(connection, logger);
51+
try {
52+
// We don't actually care to wait for the invoke.
53+
// tslint:disable-next-line:no-floating-promises
54+
hubConnection.invoke("target", 1)
55+
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
56+
57+
// Verify the message is sent
58+
expect(connection.sentData.length).toBe(1);
59+
expect(connection.parsedSentData[0].type).toEqual(MessageType.Invocation);
60+
expect((connection.sentData[0] as string).length).toEqual(63);
61+
} finally {
62+
// Close the connection
63+
await hubConnection.stop();
64+
}
65+
});
66+
});
67+
68+
it("stream invocation", async () => {
69+
await VerifyLogger.run(async (logger) => {
70+
const connection = new TestConnection();
71+
72+
const hubConnection = createHubConnection(connection, logger);
73+
try {
74+
hubConnection.stream("target", 1);
75+
76+
// Verify the message is sent
77+
expect(connection.sentData.length).toBe(1);
78+
expect(connection.parsedSentData[0].type).toEqual(MessageType.StreamInvocation);
79+
expect((connection.sentData[0] as string).length).toEqual(63);
80+
} finally {
81+
// Close the connection
82+
await hubConnection.stop();
83+
}
84+
});
85+
});
86+
87+
it("upload invocation", async () => {
88+
await VerifyLogger.run(async (logger) => {
89+
const connection = new TestConnection();
90+
91+
const hubConnection = createHubConnection(connection, logger);
92+
try {
93+
// We don't actually care to wait for the invoke.
94+
// tslint:disable-next-line:no-floating-promises
95+
hubConnection.invoke("target", 1, new Subject())
96+
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
97+
98+
// Verify the message is sent
99+
expect(connection.sentData.length).toBe(1);
100+
expect(connection.parsedSentData[0].type).toEqual(MessageType.Invocation);
101+
expect((connection.sentData[0] as string).length).toEqual(81);
102+
} finally {
103+
// Close the connection
104+
await hubConnection.stop();
105+
}
106+
});
107+
});
108+
109+
it("upload stream invocation", async () => {
110+
await VerifyLogger.run(async (logger) => {
111+
const connection = new TestConnection();
112+
113+
const hubConnection = createHubConnection(connection, logger);
114+
try {
115+
hubConnection.stream("target", 1, new Subject());
116+
117+
// Verify the message is sent
118+
expect(connection.sentData.length).toBe(1);
119+
expect(connection.parsedSentData[0].type).toEqual(MessageType.StreamInvocation);
120+
expect((connection.sentData[0] as string).length).toEqual(81);
121+
} finally {
122+
// Close the connection
123+
await hubConnection.stop();
124+
}
125+
});
126+
});
127+
128+
it("completion message", async () => {
129+
await VerifyLogger.run(async (logger) => {
130+
const connection = new TestConnection();
131+
132+
const hubConnection = createHubConnection(connection, logger);
133+
try {
134+
const subject = new Subject();
135+
hubConnection.stream("target", 1, subject);
136+
subject.complete();
137+
138+
await delayUntil(1000, () => connection.sentData.length === 2);
139+
140+
// Verify the message is sent
141+
expect(connection.sentData.length).toBe(2);
142+
expect(connection.parsedSentData[1].type).toEqual(MessageType.Completion);
143+
expect((connection.sentData[1] as string).length).toEqual(29);
144+
} finally {
145+
// Close the connection
146+
await hubConnection.stop();
147+
}
148+
});
149+
});
150+
151+
it("cancel message", async () => {
152+
await VerifyLogger.run(async (logger) => {
153+
const connection = new TestConnection();
154+
155+
const hubConnection = createHubConnection(connection, logger);
156+
try {
157+
hubConnection.stream("target", 1).subscribe({
158+
complete: () => {},
159+
error: () => {},
160+
next: () => {},
161+
}).dispose();
162+
163+
await delayUntil(1000, () => connection.sentData.length === 2);
164+
165+
// Verify the message is sent
166+
expect(connection.sentData.length).toBe(2);
167+
expect(connection.parsedSentData[1].type).toEqual(MessageType.CancelInvocation);
168+
expect((connection.sentData[1] as string).length).toEqual(29);
169+
} finally {
170+
// Close the connection
171+
await hubConnection.stop();
172+
}
173+
});
174+
});
175+
});

src/SignalR/clients/ts/signalr/tests/TestConnection.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class TestConnection implements IConnection {
1313
public onclose: ((error?: Error) => void) | null;
1414

1515
public sentData: any[];
16+
public parsedSentData: any[];
1617
public lastInvocationId: string | null;
1718

1819
private autoHandshake: boolean | null;
@@ -21,6 +22,7 @@ export class TestConnection implements IConnection {
2122
this.onreceive = null;
2223
this.onclose = null;
2324
this.sentData = [];
25+
this.parsedSentData = [];
2426
this.lastInvocationId = null;
2527
this.autoHandshake = autoHandshake;
2628
this.baseUrl = "http://example.com";
@@ -43,8 +45,10 @@ export class TestConnection implements IConnection {
4345
}
4446
if (this.sentData) {
4547
this.sentData.push(invocation);
48+
this.parsedSentData.push(parsedInvocation);
4649
} else {
4750
this.sentData = [invocation];
51+
this.parsedSentData = [parsedInvocation];
4852
}
4953
return Promise.resolve();
5054
}

src/SignalR/common/SignalR.Common/test/Internal/Protocol/JsonHubProtocolTestsBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ public void ReadCaseInsensitivePropertiesByDefault()
342342

343343
[Theory]
344344
[MemberData(nameof(MessageSizeDataNames))]
345+
// These tests check that the message size doesn't change without us being aware of it and making a conscious decision to increase the size
345346
public void VerifyMessageSize(string testDataName)
346347
{
347348
var testData = MessageSizeData[testDataName];

0 commit comments

Comments
 (0)