Skip to content

Commit fa2d2c2

Browse files
authored
test(web_socket...tests): close connections (#1908)
1 parent c29a1e8 commit fa2d2c2

7 files changed

Lines changed: 64 additions & 4 deletions

File tree

pkgs/web_socket_conformance_tests/lib/src/close_local_tests.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'close_local_server_vm.dart'
1515
import 'continuously_writing_server_vm.dart'
1616
if (dart.library.html) 'continuously_writing_server_web.dart'
1717
as writing_server;
18+
import 'utils.dart';
1819

1920
/// Tests that the [WebSocket] can correctly close the connection to the peer.
2021
void testCloseLocal(
@@ -36,6 +37,7 @@ void testCloseLocal(
3637

3738
test('peer writes after close are ignored', () async {
3839
final channel = await channelFactory(uri);
40+
addTearDown(() => closeWebSocket(channel));
3941
await channel.close();
4042
expect(await channel.events.isEmpty, true);
4143
});
@@ -57,30 +59,35 @@ void testCloseLocal(
5759

5860
test('reserved close code: 1004', () async {
5961
final channel = await channelFactory(uri);
62+
addTearDown(() => closeWebSocket(channel));
6063
await expectLater(
6164
() => channel.close(1004), throwsA(isA<ArgumentError>()));
6265
});
6366

6467
test('reserved close code: 2999', () async {
6568
final channel = await channelFactory(uri);
69+
addTearDown(() => closeWebSocket(channel));
6670
await expectLater(
6771
() => channel.close(2999), throwsA(isA<ArgumentError>()));
6872
});
6973

7074
test('reserved close code: 5000', () async {
7175
final channel = await channelFactory(uri);
76+
addTearDown(() => closeWebSocket(channel));
7277
await expectLater(
7378
() => channel.close(5000), throwsA(isA<ArgumentError>()));
7479
});
7580

7681
test('too long close reason', () async {
7782
final channel = await channelFactory(uri);
83+
addTearDown(() => closeWebSocket(channel));
7884
await expectLater(() => channel.close(3000, 'a'.padLeft(124)),
7985
throwsA(isA<ArgumentError>()));
8086
});
8187

8288
test('close', () async {
8389
final channel = await channelFactory(uri);
90+
addTearDown(() => closeWebSocket(channel));
8491

8592
await channel.close();
8693
final closeCode = await httpServerQueue.next as int?;
@@ -93,6 +100,7 @@ void testCloseLocal(
93100

94101
test('close with 1000', () async {
95102
final channel = await channelFactory(uri);
103+
addTearDown(() => closeWebSocket(channel));
96104

97105
await channel.close(1000);
98106
final closeCode = await httpServerQueue.next as int?;
@@ -105,6 +113,7 @@ void testCloseLocal(
105113

106114
test('with code 3000', () async {
107115
final channel = await channelFactory(uri);
116+
addTearDown(() => closeWebSocket(channel));
108117

109118
await channel.close(3000);
110119
final closeCode = await httpServerQueue.next as int?;
@@ -117,6 +126,7 @@ void testCloseLocal(
117126

118127
test('with code 4999', () async {
119128
final channel = await channelFactory(uri);
129+
addTearDown(() => closeWebSocket(channel));
120130

121131
await channel.close(4999);
122132
final closeCode = await httpServerQueue.next as int?;
@@ -129,6 +139,7 @@ void testCloseLocal(
129139

130140
test('with code and reason', () async {
131141
final channel = await channelFactory(uri);
142+
addTearDown(() => closeWebSocket(channel));
132143

133144
await channel.close(3000, 'Client initiated closure');
134145
final closeCode = await httpServerQueue.next as int?;
@@ -141,6 +152,7 @@ void testCloseLocal(
141152

142153
test('close after close', () async {
143154
final channel = await channelFactory(uri);
155+
addTearDown(() => closeWebSocket(channel));
144156

145157
await channel.close(3000, 'Client initiated closure');
146158

@@ -151,6 +163,7 @@ void testCloseLocal(
151163

152164
test('sendBytes after close', () async {
153165
final channel = await channelFactory(uri);
166+
addTearDown(() => closeWebSocket(channel));
154167

155168
await channel.close(3000, 'Client initiated closure');
156169

@@ -160,6 +173,7 @@ void testCloseLocal(
160173

161174
test('sendText after close', () async {
162175
final channel = await channelFactory(uri);
176+
addTearDown(() => closeWebSocket(channel));
163177

164178
await channel.close(3000, 'Client initiated closure');
165179

pkgs/web_socket_conformance_tests/lib/src/close_remote_tests.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:web_socket/web_socket.dart';
1111

1212
import 'close_remote_server_vm.dart'
1313
if (dart.library.html) 'close_remote_server_web.dart';
14+
import 'utils.dart';
1415

1516
/// Tests that the [WebSocket] can correctly receive Close frames from the peer.
1617
void testCloseRemote(
@@ -32,6 +33,7 @@ void testCloseRemote(
3233

3334
test('with code and reason', () async {
3435
final channel = await channelFactory(uri);
36+
addTearDown(() => closeWebSocket(channel));
3537

3638
channel.sendText('Please close');
3739
expect(await channel.events.toList(),
@@ -40,6 +42,7 @@ void testCloseRemote(
4042

4143
test('sendBytes after close received', () async {
4244
final channel = await channelFactory(uri);
45+
addTearDown(() => closeWebSocket(channel));
4346

4447
channel.sendBytes(Uint8List(10));
4548
expect(await channel.events.toList(),
@@ -50,6 +53,7 @@ void testCloseRemote(
5053

5154
test('sendText after close received', () async {
5255
final channel = await channelFactory(uri);
56+
addTearDown(() => closeWebSocket(channel));
5357

5458
channel.sendText('Please close');
5559
expect(await channel.events.toList(),
@@ -60,6 +64,7 @@ void testCloseRemote(
6064

6165
test('close after close received', () async {
6266
final channel = await channelFactory(uri);
67+
addTearDown(() => closeWebSocket(channel));
6368

6469
channel.sendText('Please close');
6570
expect(await channel.events.toList(),
@@ -71,6 +76,7 @@ void testCloseRemote(
7176
test('with invalid reason', () async {
7277
final channel =
7378
await channelFactory(uri.replace(queryParameters: {'badutf8': ''}));
79+
addTearDown(() => closeWebSocket(channel));
7480

7581
channel.sendText('Please close');
7682
final events = await channel.events.toList();

pkgs/web_socket_conformance_tests/lib/src/disconnect_after_upgrade_tests.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:web_socket/web_socket.dart';
99

1010
import 'disconnect_after_upgrade_server_vm.dart'
1111
if (dart.library.html) 'disconnect_after_upgrade_server_web.dart';
12+
import 'utils.dart';
1213

1314
/// Tests that the [WebSocket] generates a correct [CloseReceived] event if
1415
/// the peer disconnects after WebSocket upgrade.
@@ -29,6 +30,7 @@ void testDisconnectAfterUpgrade(
2930

3031
test('disconnect after upgrade', () async {
3132
final channel = await channelFactory(uri);
33+
addTearDown(() => closeWebSocket(channel));
3234
channel.sendText('test');
3335
expect(
3436
(await channel.events.single as CloseReceived).code,

pkgs/web_socket_conformance_tests/lib/src/payload_transfer_tests.dart

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:test/test.dart';
1010
import 'package:web_socket/web_socket.dart';
1111

1212
import 'echo_server_vm.dart' if (dart.library.html) 'echo_server_web.dart';
13+
import 'utils.dart';
1314

1415
/// Tests that the [WebSocket] can correctly transmit and receive text
1516
/// and binary payloads.
@@ -20,48 +21,57 @@ void testPayloadTransfer(
2021
late Uri uri;
2122
late StreamChannel<Object?> httpServerChannel;
2223
late StreamQueue<Object?> httpServerQueue;
23-
late WebSocket webSocket;
2424

2525
setUp(() async {
2626
httpServerChannel = await startServer();
2727
httpServerQueue = StreamQueue(httpServerChannel.stream);
2828
uri = Uri.parse('ws://localhost:${await httpServerQueue.next}');
29-
webSocket = await webSocketFactory(uri);
3029
});
3130
tearDown(() async {
3231
httpServerChannel.sink.add(null);
33-
await webSocket.close();
3432
});
3533

3634
test('empty string request and response', () async {
35+
final webSocket = await webSocketFactory(uri);
36+
addTearDown(() => closeWebSocket(webSocket));
3737
webSocket.sendText('');
3838
expect(await webSocket.events.first, TextDataReceived(''));
3939
});
4040

4141
test('empty binary request and response', () async {
42+
final webSocket = await webSocketFactory(uri);
43+
addTearDown(() => closeWebSocket(webSocket));
4244
webSocket.sendBytes(Uint8List(0));
4345
expect(await webSocket.events.first, BinaryDataReceived(Uint8List(0)));
4446
});
4547

4648
test('string request and response', () async {
49+
final webSocket = await webSocketFactory(uri);
50+
addTearDown(() => closeWebSocket(webSocket));
4751
webSocket.sendText('Hello World!');
4852
expect(await webSocket.events.first, TextDataReceived('Hello World!'));
4953
});
5054

5155
test('binary request and response', () async {
56+
final webSocket = await webSocketFactory(uri);
57+
addTearDown(() => closeWebSocket(webSocket));
5258
webSocket.sendBytes(Uint8List.fromList([1, 2, 3, 4, 5]));
5359
expect(await webSocket.events.first,
5460
BinaryDataReceived(Uint8List.fromList([1, 2, 3, 4, 5])));
5561
});
5662

5763
test('large string request and response', () async {
64+
final webSocket = await webSocketFactory(uri);
65+
addTearDown(() => closeWebSocket(webSocket));
5866
final data = 'Hello World!' * 10000;
5967

6068
webSocket.sendText(data);
6169
expect(await webSocket.events.first, TextDataReceived(data));
6270
});
6371

6472
test('large binary request and response', () async {
73+
final webSocket = await webSocketFactory(uri);
74+
addTearDown(() => closeWebSocket(webSocket));
6575
final data = Uint8List(1000000);
6676
data
6777
..fillRange(0, data.length ~/ 10, 1)
@@ -80,11 +90,15 @@ void testPayloadTransfer(
8090
});
8191

8292
test('non-ascii string request and response', () async {
93+
final webSocket = await webSocketFactory(uri);
94+
addTearDown(() => closeWebSocket(webSocket));
8395
webSocket.sendText('🎨⛳🌈');
8496
expect(await webSocket.events.first, TextDataReceived('🎨⛳🌈'));
8597
});
8698

8799
test('alternative string and binary request and response', () async {
100+
final webSocket = await webSocketFactory(uri);
101+
addTearDown(() => closeWebSocket(webSocket));
88102
webSocket
89103
..sendBytes(Uint8List.fromList([1]))
90104
..sendText('Hello!')

pkgs/web_socket_conformance_tests/lib/src/peer_protocol_errors_tests.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:web_socket/web_socket.dart';
99

1010
import 'peer_protocol_errors_server_vm.dart'
1111
if (dart.library.html) 'peer_protocol_errors_server_web.dart';
12+
import 'utils.dart';
1213

1314
/// Tests that the [WebSocket] can correctly handle incorrect WebSocket frames.
1415
void testPeerProtocolErrors(
@@ -28,6 +29,7 @@ void testPeerProtocolErrors(
2829

2930
test('bad data after upgrade', () async {
3031
final channel = await channelFactory(uri);
32+
addTearDown(() => closeWebSocket(channel));
3133
expect(
3234
(await channel.events.single as CloseReceived).code,
3335
anyOf([
@@ -39,6 +41,7 @@ void testPeerProtocolErrors(
3941

4042
test('bad data after upgrade with write', () async {
4143
final channel = await channelFactory(uri);
44+
addTearDown(() => closeWebSocket(channel));
4245
channel.sendText('test');
4346
expect(
4447
(await channel.events.single as CloseReceived).code,

pkgs/web_socket_conformance_tests/lib/src/protocol_tests.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:web_socket/web_socket.dart';
99

1010
import 'protocol_server_vm.dart'
1111
if (dart.library.html) 'protocol_server_web.dart';
12+
import 'utils.dart';
1213

1314
/// Tests that the [WebSocket] can correctly negotiate a subprotocol with the
1415
/// peer.
@@ -28,10 +29,13 @@ void testProtocols(
2829
httpServerQueue = StreamQueue(httpServerChannel.stream);
2930
uri = Uri.parse('ws://localhost:${await httpServerQueue.next}');
3031
});
31-
tearDown(() => httpServerChannel.sink.add(null));
32+
tearDown(() async {
33+
httpServerChannel.sink.add(null);
34+
});
3235

3336
test('no protocol', () async {
3437
final socket = await channelFactory(uri);
38+
addTearDown(() => closeWebSocket(socket));
3539

3640
expect(await httpServerQueue.next, null);
3741
expect(socket.protocol, '');
@@ -42,6 +46,7 @@ void testProtocols(
4246
final socket = await channelFactory(
4347
uri.replace(queryParameters: {'protocol': 'chat.example.com'}),
4448
protocols: ['chat.example.com']);
49+
addTearDown(() => closeWebSocket(socket));
4550

4651
expect(await httpServerQueue.next, ['chat.example.com']);
4752
expect(socket.protocol, 'chat.example.com');
@@ -52,6 +57,7 @@ void testProtocols(
5257
final socket = await channelFactory(
5358
uri.replace(queryParameters: {'protocol': 'text.example.com'}),
5459
protocols: ['chat.example.com', 'text.example.com']);
60+
addTearDown(() => closeWebSocket(socket));
5561

5662
expect(
5763
await httpServerQueue.next, ['chat.example.com, text.example.com']);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:web_socket/web_socket.dart';
6+
7+
/// Closes the [socket] and ignores [WebSocketConnectionClosed] if it's already
8+
/// closed.
9+
Future<void> closeWebSocket(WebSocket socket) async {
10+
try {
11+
await socket.close();
12+
} on WebSocketConnectionClosed {
13+
// Already closed.
14+
}
15+
}

0 commit comments

Comments
 (0)