OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // VMOptions= | 5 // VMOptions= |
6 // VMOptions=--short_socket_read | 6 // VMOptions=--short_socket_read |
7 // VMOptions=--short_socket_write | 7 // VMOptions=--short_socket_write |
8 // VMOptions=--short_socket_read --short_socket_write | 8 // VMOptions=--short_socket_read --short_socket_write |
9 | 9 |
10 import "dart:async"; | 10 import "dart:async"; |
11 import "dart:convert"; | 11 import "dart:convert"; |
12 import "dart:io"; | 12 import "dart:io"; |
13 import "dart:typed_data"; | 13 import "dart:typed_data"; |
14 | 14 |
15 import "package:async_helper/async_helper.dart"; | 15 import "package:async_helper/async_helper.dart"; |
16 import "package:convert/convert.dart"; | 16 import "package:convert/convert.dart"; |
17 import "package:crypto/crypto.dart"; | 17 import "package:crypto/crypto.dart"; |
18 import "package:expect/expect.dart"; | 18 import "package:expect/expect.dart"; |
19 import "package:path/path.dart"; | 19 import "package:path/path.dart"; |
20 | 20 |
21 const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 21 const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
22 | 22 |
23 const String HOST_NAME = 'localhost'; | 23 const String HOST_NAME = 'localhost'; |
24 | 24 |
25 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 25 String localFile(path) => Platform.script.resolve(path).toFilePath(); |
26 | 26 |
27 SecurityContext serverContext = new SecurityContext() | 27 SecurityContext serverContext = new SecurityContext() |
28 ..useCertificateChain(localFile('certificates/server_chain.pem')) | 28 ..useCertificateChain(localFile('certificates/server_chain.pem')) |
29 ..usePrivateKey(localFile('certificates/server_key.pem'), | 29 ..usePrivateKey(localFile('certificates/server_key.pem'), |
30 password: 'dartdart'); | 30 password: 'dartdart'); |
31 | 31 |
32 SecurityContext clientContext = new SecurityContext() | 32 SecurityContext clientContext = new SecurityContext() |
33 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 33 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); |
34 | 34 |
35 /** | 35 /** |
36 * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. | 36 * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. |
37 */ | 37 */ |
38 class SecurityConfiguration { | 38 class SecurityConfiguration { |
39 final bool secure; | 39 final bool secure; |
40 | 40 |
41 SecurityConfiguration({bool this.secure}); | 41 SecurityConfiguration({bool this.secure}); |
42 | 42 |
43 Future<HttpServer> createServer({int backlog: 0}) => | 43 Future<HttpServer> createServer({int backlog: 0}) => secure |
44 secure ? HttpServer.bindSecure(HOST_NAME, | 44 ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog) |
45 0, | 45 : HttpServer.bind(HOST_NAME, 0, backlog: backlog); |
46 serverContext, | |
47 backlog: backlog) | |
48 : HttpServer.bind(HOST_NAME, | |
49 0, | |
50 backlog: backlog); | |
51 | 46 |
52 Future<WebSocket> createClient(int port) => | 47 Future<WebSocket> createClient(int port) => |
53 // TODO(whesse): Add client context argument to WebSocket.connect | 48 // TODO(whesse): Add client context argument to WebSocket.connect |
54 WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); | 49 WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); |
55 | 50 |
56 checkCloseStatus(webSocket, closeStatus, closeReason) { | 51 checkCloseStatus(webSocket, closeStatus, closeReason) { |
57 Expect.equals(closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED | 52 Expect.equals( |
58 : closeStatus, webSocket.closeCode); | 53 closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED : closeStatus, |
59 Expect.equals(closeReason == null ? "" | 54 webSocket.closeCode); |
60 : closeReason, webSocket.closeReason); | 55 Expect.equals( |
| 56 closeReason == null ? "" : closeReason, webSocket.closeReason); |
61 } | 57 } |
62 | 58 |
63 void testRequestResponseClientCloses(int totalConnections, | 59 void testRequestResponseClientCloses(int totalConnections, int closeStatus, |
64 int closeStatus, | 60 String closeReason, int numberOfMessages) { |
65 String closeReason, | 61 assert(numberOfMessages >= 1); |
66 int numberOfMessages) { | |
67 assert (numberOfMessages >= 1); | |
68 | 62 |
69 asyncStart(); | 63 asyncStart(); |
70 createServer().then((server) { | 64 createServer().then((server) { |
71 server.transform(new WebSocketTransformer()).listen((webSocket) { | 65 server.transform(new WebSocketTransformer()).listen((webSocket) { |
72 asyncStart(); | 66 asyncStart(); |
73 webSocket.listen( | 67 webSocket.listen(webSocket.add, onDone: () { |
74 webSocket.add, | 68 checkCloseStatus(webSocket, closeStatus, closeReason); |
75 onDone: () { | |
76 checkCloseStatus(webSocket, closeStatus, closeReason); | |
77 asyncEnd(); | |
78 }); | |
79 }, onDone: () { | |
80 asyncEnd(); | 69 asyncEnd(); |
81 }); | 70 }); |
| 71 }, onDone: () { |
| 72 asyncEnd(); |
| 73 }); |
82 | 74 |
83 int closeCount = 0; | 75 int closeCount = 0; |
84 String messageText = "Hello, world!"; | 76 String messageText = "Hello, world!"; |
85 for (int i = 0; i < totalConnections; i++) { | 77 for (int i = 0; i < totalConnections; i++) { |
86 asyncStart(); | 78 asyncStart(); |
87 createClient(server.port).then((webSocket) { | 79 createClient(server.port).then((webSocket) { |
88 webSocket.add(messageText); | 80 webSocket.add(messageText); |
89 webSocket.listen( | 81 webSocket.listen((message) { |
90 (message) { | 82 numberOfMessages--; |
91 numberOfMessages--; | 83 Expect.equals(messageText, message); |
92 Expect.equals(messageText, message); | |
93 | 84 |
94 if (numberOfMessages > 0) { | 85 if (numberOfMessages > 0) { |
95 webSocket.add(message); | 86 webSocket.add(message); |
96 } else { | 87 } else { |
97 webSocket.close(closeStatus, closeReason); | 88 webSocket.close(closeStatus, closeReason); |
98 } | 89 } |
99 }, | 90 }, onDone: () { |
100 onDone: () { | 91 checkCloseStatus(webSocket, closeStatus, closeReason); |
101 checkCloseStatus(webSocket, closeStatus, closeReason); | 92 closeCount++; |
102 closeCount++; | 93 if (closeCount == totalConnections) { |
103 if (closeCount == totalConnections) { | 94 server.close(); |
104 server.close(); | 95 } |
105 } | 96 asyncEnd(); |
106 asyncEnd(); | |
107 }); | |
108 }); | 97 }); |
| 98 }); |
109 } | 99 } |
110 }); | 100 }); |
111 } | 101 } |
112 | 102 |
113 void testRequestResponseServerCloses(int totalConnections, | 103 void testRequestResponseServerCloses( |
114 int closeStatus, | 104 int totalConnections, int closeStatus, String closeReason) { |
115 String closeReason) { | |
116 createServer().then((server) { | 105 createServer().then((server) { |
117 int closeCount = 0; | 106 int closeCount = 0; |
118 server.transform(new WebSocketTransformer()).listen((webSocket) { | 107 server.transform(new WebSocketTransformer()).listen((webSocket) { |
119 String messageText = "Hello, world!"; | 108 String messageText = "Hello, world!"; |
120 int messageCount = 0; | 109 int messageCount = 0; |
121 webSocket.listen( | 110 webSocket.listen((message) { |
122 (message) { | 111 messageCount++; |
123 messageCount++; | 112 if (messageCount < 10) { |
124 if (messageCount < 10) { | 113 Expect.equals(messageText, message); |
125 Expect.equals(messageText, message); | 114 webSocket.add(message); |
126 webSocket.add(message); | 115 } else { |
127 } else { | 116 webSocket.close(closeStatus, closeReason); |
128 webSocket.close(closeStatus, closeReason); | 117 } |
129 } | 118 }, onDone: () { |
130 }, | 119 checkCloseStatus(webSocket, closeStatus, closeReason); |
131 onDone: () { | 120 closeCount++; |
132 checkCloseStatus(webSocket, closeStatus, closeReason); | 121 if (closeCount == totalConnections) { |
133 closeCount++; | 122 server.close(); |
134 if (closeCount == totalConnections) { | 123 } |
135 server.close(); | 124 }); |
136 } | |
137 }); | |
138 webSocket.add(messageText); | 125 webSocket.add(messageText); |
139 }); | 126 }); |
140 | 127 |
141 for (int i = 0; i < totalConnections; i++) { | 128 for (int i = 0; i < totalConnections; i++) { |
142 createClient(server.port).then((webSocket) { | 129 createClient(server.port).then((webSocket) { |
143 webSocket.listen( | 130 webSocket.listen(webSocket.add, onDone: () { |
144 webSocket.add, | 131 checkCloseStatus(webSocket, closeStatus, closeReason); |
145 onDone: () { | 132 }); |
146 checkCloseStatus(webSocket, closeStatus, closeReason); | 133 }); |
147 }); | |
148 }); | |
149 } | 134 } |
150 }); | 135 }); |
151 } | 136 } |
152 | 137 |
153 | |
154 void testMessageLength(int messageLength) { | 138 void testMessageLength(int messageLength) { |
155 createServer().then((server) { | 139 createServer().then((server) { |
156 Uint8List originalMessage = new Uint8List(messageLength); | 140 Uint8List originalMessage = new Uint8List(messageLength); |
157 server.transform(new WebSocketTransformer()).listen((webSocket) { | 141 server.transform(new WebSocketTransformer()).listen((webSocket) { |
158 webSocket.listen( | 142 webSocket.listen((message) { |
159 (message) { | 143 Expect.listEquals(originalMessage, message); |
160 Expect.listEquals(originalMessage, message); | 144 webSocket.add(message); |
161 webSocket.add(message); | 145 }); |
162 }); | |
163 }); | 146 }); |
164 | 147 |
165 createClient(server.port).then((webSocket) { | 148 createClient(server.port).then((webSocket) { |
166 webSocket.listen( | 149 webSocket.listen((message) { |
167 (message) { | 150 Expect.listEquals(originalMessage, message); |
168 Expect.listEquals(originalMessage, message); | 151 webSocket.close(); |
169 webSocket.close(); | 152 }, onDone: server.close); |
170 }, | |
171 onDone: server.close); | |
172 webSocket.add(originalMessage); | 153 webSocket.add(originalMessage); |
173 }); | 154 }); |
174 }); | 155 }); |
175 } | 156 } |
176 | 157 |
177 | |
178 void testCloseNoListen() { | 158 void testCloseNoListen() { |
179 createServer().then((server) { | 159 createServer().then((server) { |
180 server.transform(new WebSocketTransformer()).listen((webSocket) { | 160 server.transform(new WebSocketTransformer()).listen((webSocket) { |
181 server.close(); | 161 server.close(); |
182 webSocket.close(); | 162 webSocket.close(); |
183 }); | 163 }); |
184 | 164 |
185 createClient(server.port).then((webSocket) { | 165 createClient(server.port).then((webSocket) { |
186 webSocket.close(); | 166 webSocket.close(); |
187 }); | 167 }); |
188 }); | 168 }); |
189 } | 169 } |
190 | 170 |
191 | |
192 void testCancelThenClose() { | 171 void testCancelThenClose() { |
193 createServer().then((server) { | 172 createServer().then((server) { |
194 server.transform(new WebSocketTransformer()).listen((webSocket) { | 173 server.transform(new WebSocketTransformer()).listen((webSocket) { |
195 webSocket.listen(null).cancel(); | 174 webSocket.listen(null).cancel(); |
196 webSocket.close(); | 175 webSocket.close(); |
197 server.close(); | 176 server.close(); |
198 }); | 177 }); |
199 | 178 |
200 createClient(server.port).then((webSocket) { | 179 createClient(server.port).then((webSocket) { |
201 webSocket.close(); | 180 webSocket.close(); |
202 }); | 181 }); |
203 }); | 182 }); |
204 } | 183 } |
205 | 184 |
206 void testCloseThenCancel() { | 185 void testCloseThenCancel() { |
207 createServer().then((server) { | 186 createServer().then((server) { |
208 server.transform(new WebSocketTransformer()).listen((webSocket) { | 187 server.transform(new WebSocketTransformer()).listen((webSocket) { |
209 var subscription = webSocket.listen(null); | 188 var subscription = webSocket.listen(null); |
210 webSocket.close(); | 189 webSocket.close(); |
211 subscription.cancel(); | 190 subscription.cancel(); |
212 server.close(); | 191 server.close(); |
213 }); | 192 }); |
214 | 193 |
215 createClient(server.port).then((webSocket) { | 194 createClient(server.port).then((webSocket) { |
216 webSocket.close(); | 195 webSocket.close(); |
217 }); | 196 }); |
218 }); | 197 }); |
219 } | 198 } |
220 | 199 |
221 | |
222 void testListenAfterClose() { | 200 void testListenAfterClose() { |
223 createServer().then((server) { | 201 createServer().then((server) { |
224 server.transform(new WebSocketTransformer()).listen((webSocket) { | 202 server.transform(new WebSocketTransformer()).listen((webSocket) { |
225 server.close(); | 203 server.close(); |
226 webSocket.close(); | 204 webSocket.close(); |
227 Expect.throws(() => webSocket.drain()); | 205 Expect.throws(() => webSocket.drain()); |
228 }); | 206 }); |
229 | 207 |
230 createClient(server.port).then((webSocket) { | 208 createClient(server.port).then((webSocket) { |
231 webSocket.close(); | 209 webSocket.close(); |
232 Expect.throws(() => webSocket.drain()); | 210 Expect.throws(() => webSocket.drain()); |
233 }); | 211 }); |
234 }); | 212 }); |
235 } | 213 } |
236 | 214 |
237 | |
238 void testDoubleCloseClient() { | 215 void testDoubleCloseClient() { |
239 createServer().then((server) { | 216 createServer().then((server) { |
240 server.transform(new WebSocketTransformer()).listen((webSocket) { | 217 server.transform(new WebSocketTransformer()).listen((webSocket) { |
241 server.close(); | 218 server.close(); |
242 webSocket.listen((_) { }, onDone: webSocket.close); | 219 webSocket.listen((_) {}, onDone: webSocket.close); |
243 }); | 220 }); |
244 | 221 |
245 createClient(server.port).then((webSocket) { | 222 createClient(server.port).then((webSocket) { |
246 webSocket.listen((_) { }, onDone: webSocket.close); | 223 webSocket.listen((_) {}, onDone: webSocket.close); |
247 webSocket.close(); | 224 webSocket.close(); |
248 }); | 225 }); |
249 }); | 226 }); |
250 } | 227 } |
251 | 228 |
252 | |
253 void testDoubleCloseServer() { | 229 void testDoubleCloseServer() { |
254 createServer().then((server) { | 230 createServer().then((server) { |
255 server.transform(new WebSocketTransformer()).listen((webSocket) { | 231 server.transform(new WebSocketTransformer()).listen((webSocket) { |
256 server.close(); | 232 server.close(); |
257 webSocket.listen((_) { }, onDone: webSocket.close); | 233 webSocket.listen((_) {}, onDone: webSocket.close); |
258 webSocket.close(); | 234 webSocket.close(); |
259 }); | 235 }); |
260 | 236 |
261 createClient(server.port).then((webSocket) { | 237 createClient(server.port).then((webSocket) { |
262 webSocket.listen((_) { }, onDone: webSocket.close); | 238 webSocket.listen((_) {}, onDone: webSocket.close); |
263 }); | 239 }); |
264 }); | 240 }); |
265 } | 241 } |
266 | 242 |
267 | |
268 void testImmediateCloseServer() { | 243 void testImmediateCloseServer() { |
269 createServer().then((server) { | 244 createServer().then((server) { |
270 server.listen((request) { | 245 server.listen((request) { |
271 WebSocketTransformer.upgrade(request) | 246 WebSocketTransformer.upgrade(request).then((webSocket) { |
272 .then((webSocket) { | 247 webSocket.listen((_) { |
273 webSocket.listen( | 248 Expect.fail("Unexpected message"); |
274 (_) { Expect.fail("Unexpected message"); }, | 249 }, onDone: server.close); |
275 onDone: server.close); | 250 webSocket.close(); |
276 webSocket.close(); | 251 }); |
277 }); | |
278 }); | 252 }); |
279 | 253 |
280 createClient(server.port).then((webSocket) { | 254 createClient(server.port).then((webSocket) { |
281 webSocket.listen( | 255 webSocket.listen((_) { |
282 (_) { Expect.fail("Unexpected message"); }, | 256 Expect.fail("Unexpected message"); |
283 onDone: webSocket.close); | 257 }, onDone: webSocket.close); |
284 }); | 258 }); |
285 }); | 259 }); |
286 } | 260 } |
287 | 261 |
288 | |
289 void testImmediateCloseClient() { | 262 void testImmediateCloseClient() { |
290 createServer().then((server) { | 263 createServer().then((server) { |
291 server.listen((request) { | 264 server.listen((request) { |
292 WebSocketTransformer.upgrade(request) | 265 WebSocketTransformer.upgrade(request).then((webSocket) { |
293 .then((webSocket) { | 266 webSocket.listen((_) { |
294 webSocket.listen( | 267 Expect.fail("Unexpected message"); |
295 (_) { Expect.fail("Unexpected message"); }, | 268 }, onDone: () { |
296 onDone: () { | 269 server.close(); |
297 server.close(); | 270 webSocket.close(); |
298 webSocket.close(); | 271 }); |
299 }); | 272 }); |
300 }); | |
301 }); | 273 }); |
302 | 274 |
303 createClient(server.port).then((webSocket) { | 275 createClient(server.port).then((webSocket) { |
304 webSocket.listen( | 276 webSocket.listen((_) { |
305 (_) { Expect.fail("Unexpected message"); }, | 277 Expect.fail("Unexpected message"); |
306 onDone: webSocket.close); | 278 }, onDone: webSocket.close); |
307 webSocket.close(); | 279 webSocket.close(); |
308 }); | 280 }); |
309 }); | 281 }); |
310 } | 282 } |
311 | 283 |
312 | |
313 void testNoUpgrade() { | 284 void testNoUpgrade() { |
314 createServer().then((server) { | 285 createServer().then((server) { |
315 // Create a server which always responds with NOT_FOUND. | 286 // Create a server which always responds with NOT_FOUND. |
316 server.listen((request) { | 287 server.listen((request) { |
317 request.response.statusCode = HttpStatus.NOT_FOUND; | 288 request.response.statusCode = HttpStatus.NOT_FOUND; |
318 request.response.close(); | 289 request.response.close(); |
319 }); | 290 }); |
320 | 291 |
321 createClient(server.port).catchError((error) { | 292 createClient(server.port).catchError((error) { |
322 server.close(); | 293 server.close(); |
323 }); | 294 }); |
324 }); | 295 }); |
325 } | 296 } |
326 | 297 |
327 | |
328 void testUsePOST() { | 298 void testUsePOST() { |
329 asyncStart(); | 299 asyncStart(); |
330 createServer().then((server) { | 300 createServer().then((server) { |
331 server.transform(new WebSocketTransformer()).listen((webSocket) { | 301 server.transform(new WebSocketTransformer()).listen((webSocket) { |
332 Expect.fail("No connection expected"); | 302 Expect.fail("No connection expected"); |
333 }, onError: (e) { | 303 }, onError: (e) { |
334 asyncEnd(); | 304 asyncEnd(); |
335 }); | 305 }); |
336 | 306 |
337 HttpClient client = new HttpClient(); | 307 HttpClient client = new HttpClient(); |
338 client.postUrl(Uri.parse( | 308 client |
339 "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/")) | 309 .postUrl(Uri.parse( |
340 .then((request) => request.close()) | 310 "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/")) |
341 .then((response) { | 311 .then((request) => request.close()) |
342 Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode); | 312 .then((response) { |
343 client.close(); | 313 Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode); |
344 server.close(); | 314 client.close(); |
345 }); | 315 server.close(); |
| 316 }); |
346 }); | 317 }); |
347 } | 318 } |
348 | 319 |
349 void testConnections(int totalConnections, | 320 void testConnections( |
350 int closeStatus, | 321 int totalConnections, int closeStatus, String closeReason) { |
351 String closeReason) { | |
352 createServer().then((server) { | 322 createServer().then((server) { |
353 int closeCount = 0; | 323 int closeCount = 0; |
354 server.transform(new WebSocketTransformer()).listen((webSocket) { | 324 server.transform(new WebSocketTransformer()).listen((webSocket) { |
355 String messageText = "Hello, world!"; | 325 String messageText = "Hello, world!"; |
356 int messageCount = 0; | 326 int messageCount = 0; |
357 webSocket.listen( | 327 webSocket.listen((message) { |
358 (message) { | 328 messageCount++; |
359 messageCount++; | 329 if (messageCount < 10) { |
360 if (messageCount < 10) { | 330 Expect.equals(messageText, message); |
361 Expect.equals(messageText, message); | 331 webSocket.add(message); |
362 webSocket.add(message); | 332 } else { |
363 } else { | 333 webSocket.close(closeStatus, closeReason); |
364 webSocket.close(closeStatus, closeReason); | 334 } |
365 } | 335 }, onDone: () { |
366 }, | 336 checkCloseStatus(webSocket, closeStatus, closeReason); |
367 onDone: () { | 337 closeCount++; |
368 checkCloseStatus(webSocket, closeStatus, closeReason); | 338 if (closeCount == totalConnections) { |
369 closeCount++; | 339 server.close(); |
370 if (closeCount == totalConnections) { | 340 } |
371 server.close(); | 341 }); |
372 } | |
373 }); | |
374 webSocket.add(messageText); | 342 webSocket.add(messageText); |
375 }); | 343 }); |
376 | 344 |
377 void webSocketConnection() { | 345 void webSocketConnection() { |
378 bool onopenCalled = false; | 346 bool onopenCalled = false; |
379 int onmessageCalled = 0; | 347 int onmessageCalled = 0; |
380 bool oncloseCalled = false; | 348 bool oncloseCalled = false; |
381 | 349 |
382 createClient(server.port).then((webSocket) { | 350 createClient(server.port).then((webSocket) { |
383 Expect.isFalse(onopenCalled); | 351 Expect.isFalse(onopenCalled); |
384 Expect.equals(0, onmessageCalled); | 352 Expect.equals(0, onmessageCalled); |
385 Expect.isFalse(oncloseCalled); | 353 Expect.isFalse(oncloseCalled); |
386 onopenCalled = true; | 354 onopenCalled = true; |
387 Expect.equals(WebSocket.OPEN, webSocket.readyState); | 355 Expect.equals(WebSocket.OPEN, webSocket.readyState); |
388 webSocket.listen( | 356 webSocket.listen((message) { |
389 (message) { | 357 onmessageCalled++; |
390 onmessageCalled++; | 358 Expect.isTrue(onopenCalled); |
391 Expect.isTrue(onopenCalled); | 359 Expect.isFalse(oncloseCalled); |
392 Expect.isFalse(oncloseCalled); | 360 Expect.equals(WebSocket.OPEN, webSocket.readyState); |
393 Expect.equals(WebSocket.OPEN, webSocket.readyState); | 361 webSocket.add(message); |
394 webSocket.add(message); | 362 }, onDone: () { |
395 }, | 363 Expect.isTrue(onopenCalled); |
396 onDone: () { | 364 Expect.equals(10, onmessageCalled); |
397 Expect.isTrue(onopenCalled); | 365 Expect.isFalse(oncloseCalled); |
398 Expect.equals(10, onmessageCalled); | 366 oncloseCalled = true; |
399 Expect.isFalse(oncloseCalled); | 367 Expect.equals(3002, webSocket.closeCode); |
400 oncloseCalled = true; | 368 Expect.equals("Got tired", webSocket.closeReason); |
401 Expect.equals(3002, webSocket.closeCode); | 369 Expect.equals(WebSocket.CLOSED, webSocket.readyState); |
402 Expect.equals("Got tired", webSocket.closeReason); | 370 }); |
403 Expect.equals(WebSocket.CLOSED, webSocket.readyState); | |
404 }); | |
405 }); | 371 }); |
406 } | 372 } |
407 | 373 |
408 for (int i = 0; i < totalConnections; i++) { | 374 for (int i = 0; i < totalConnections; i++) { |
409 webSocketConnection(); | 375 webSocketConnection(); |
410 } | 376 } |
411 }); | 377 }); |
412 } | 378 } |
413 | 379 |
414 testIndividualUpgrade(int connections) { | 380 testIndividualUpgrade(int connections) { |
415 asyncStart(); | 381 asyncStart(); |
416 createServer().then((server) { | 382 createServer().then((server) { |
417 server.listen((request) { | 383 server.listen((request) { |
418 if (WebSocketTransformer.isUpgradeRequest(request)) { | 384 if (WebSocketTransformer.isUpgradeRequest(request)) { |
419 WebSocketTransformer.upgrade(request).then((webSocket) { | 385 WebSocketTransformer.upgrade(request).then((webSocket) { |
420 webSocket.listen((_) { webSocket.close(); }); | 386 webSocket.listen((_) { |
421 webSocket.add("Hello"); | 387 webSocket.close(); |
422 }); | 388 }); |
423 } else { | 389 webSocket.add("Hello"); |
424 Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request)); | 390 }); |
425 request.response.statusCode = HttpStatus.OK; | 391 } else { |
426 request.response.close(); | 392 Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request)); |
427 } | 393 request.response.statusCode = HttpStatus.OK; |
| 394 request.response.close(); |
| 395 } |
428 }); | 396 }); |
429 | 397 |
430 var futures = []; | 398 var futures = []; |
431 | 399 |
432 var wsProtocol = '${secure ? "wss" : "ws"}'; | 400 var wsProtocol = '${secure ? "wss" : "ws"}'; |
433 var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/'; | 401 var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/'; |
434 var httpProtocol = '${secure ? "https" : "http"}'; | 402 var httpProtocol = '${secure ? "https" : "http"}'; |
435 var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/'; | 403 var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/'; |
436 HttpClient client = new HttpClient(); | 404 HttpClient client = new HttpClient(); |
437 | 405 |
438 for (int i = 0; i < connections; i++) { | 406 for (int i = 0; i < connections; i++) { |
439 var completer = new Completer(); | 407 var completer = new Completer(); |
440 futures.add(completer.future); | 408 futures.add(completer.future); |
441 WebSocket.connect('${baseWsUrl}') | 409 WebSocket.connect('${baseWsUrl}').then((websocket) { |
442 .then((websocket) { | 410 websocket.listen((_) { |
443 websocket.listen((_) { websocket.close(); }, | 411 websocket.close(); |
444 onDone: completer.complete); | 412 }, onDone: completer.complete); |
445 }); | 413 }); |
446 | 414 |
447 futures.add(client.openUrl("GET", Uri.parse('${baseHttpUrl}')) | 415 futures.add(client |
448 .then((request) => request.close()) | 416 .openUrl("GET", Uri.parse('${baseHttpUrl}')) |
449 .then((response) { | 417 .then((request) => request.close()) |
450 response.listen((_) { }); | 418 .then((response) { |
451 Expect.equals(HttpStatus.OK, response.statusCode); | 419 response.listen((_) {}); |
452 })); | 420 Expect.equals(HttpStatus.OK, response.statusCode); |
| 421 })); |
453 } | 422 } |
454 | 423 |
455 Future.wait(futures).then((_) { | 424 Future.wait(futures).then((_) { |
456 server.close(); | 425 server.close(); |
457 client.close(); | 426 client.close(); |
458 asyncEnd(); | 427 asyncEnd(); |
459 }); | 428 }); |
460 }); | 429 }); |
461 } | 430 } |
462 | 431 |
463 testFromUpgradedSocket() { | 432 testFromUpgradedSocket() { |
464 asyncStart(); | 433 asyncStart(); |
465 createServer().then((server) { | 434 createServer().then((server) { |
466 server.listen((request) { | 435 server.listen((request) { |
467 Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION)); | 436 Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION)); |
468 Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE)); | 437 Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE)); |
469 | 438 |
470 var key = request.headers.value('Sec-WebSocket-Key'); | 439 var key = request.headers.value('Sec-WebSocket-Key'); |
471 var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits); | 440 var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits); |
472 var accept = BASE64.encode(digest.bytes); | 441 var accept = BASE64.encode(digest.bytes); |
473 request.response | 442 request.response |
474 ..statusCode = HttpStatus.SWITCHING_PROTOCOLS | 443 ..statusCode = HttpStatus.SWITCHING_PROTOCOLS |
475 ..headers.add(HttpHeaders.CONNECTION, "Upgrade") | 444 ..headers.add(HttpHeaders.CONNECTION, "Upgrade") |
476 ..headers.add(HttpHeaders.UPGRADE, "websocket") | 445 ..headers.add(HttpHeaders.UPGRADE, "websocket") |
477 ..headers.add("Sec-WebSocket-Accept", accept); | 446 ..headers.add("Sec-WebSocket-Accept", accept); |
478 request.response.contentLength = 0; | 447 request.response.contentLength = 0; |
479 request.response.detachSocket().then((socket) { | 448 request.response.detachSocket().then((socket) { |
480 return new WebSocket.fromUpgradedSocket(socket, serverSide: true); | 449 return new WebSocket.fromUpgradedSocket(socket, serverSide: true); |
481 }).then((websocket) { | 450 }).then((websocket) { |
482 websocket.add("Hello"); | 451 websocket.add("Hello"); |
483 websocket.close(); | 452 websocket.close(); |
484 asyncEnd(); | 453 asyncEnd(); |
485 }); | 454 }); |
486 }); | 455 }); |
487 | 456 |
(...skipping 11 matching lines...) Expand all Loading... |
499 void testAdditionalHeaders() { | 468 void testAdditionalHeaders() { |
500 asyncStart(); | 469 asyncStart(); |
501 createServer().then((server) { | 470 createServer().then((server) { |
502 server.listen((request) { | 471 server.listen((request) { |
503 Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 472 Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); |
504 Expect.equals('my-value', request.headers['My-Header'][0]); | 473 Expect.equals('my-value', request.headers['My-Header'][0]); |
505 var header = request.headers['My-Header-Multiple']; | 474 var header = request.headers['My-Header-Multiple']; |
506 Expect.equals(1, header.length); | 475 Expect.equals(1, header.length); |
507 Expect.equals('my-value-1, my-value-2', header[0]); | 476 Expect.equals('my-value-1, my-value-2', header[0]); |
508 WebSocketTransformer.upgrade(request).then((webSocket) { | 477 WebSocketTransformer.upgrade(request).then((webSocket) { |
509 webSocket.listen((_) { webSocket.close(); }); | 478 webSocket.listen((_) { |
| 479 webSocket.close(); |
| 480 }); |
510 webSocket.add("Hello"); | 481 webSocket.add("Hello"); |
511 }); | 482 }); |
512 }); | 483 }); |
513 | 484 |
514 var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; | 485 var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/'; |
515 var headers = {'My-Header': 'my-value', | 486 var headers = { |
516 'My-Header-Multiple': ['my-value-1', 'my-value-2']}; | 487 'My-Header': 'my-value', |
| 488 'My-Header-Multiple': ['my-value-1', 'my-value-2'] |
| 489 }; |
517 WebSocket.connect(url, headers: headers).then((websocket) { | 490 WebSocket.connect(url, headers: headers).then((websocket) { |
518 return websocket.listen((message) { | 491 return websocket.listen((message) { |
519 Expect.equals("Hello", message); | 492 Expect.equals("Hello", message); |
520 websocket.close(); | 493 websocket.close(); |
521 }).asFuture(); | 494 }).asFuture(); |
522 }).then((_) { | 495 }).then((_) { |
523 server.close(); | 496 server.close(); |
524 asyncEnd(); | 497 asyncEnd(); |
525 }); | 498 }); |
526 }); | 499 }); |
527 } | 500 } |
528 | 501 |
529 | |
530 void testBasicAuthentication() { | 502 void testBasicAuthentication() { |
531 var userInfo = 'user:password'; | 503 var userInfo = 'user:password'; |
532 | 504 |
533 asyncStart(); | 505 asyncStart(); |
534 asyncStart(); | 506 asyncStart(); |
535 createServer().then((server) { | 507 createServer().then((server) { |
536 server.listen((request) { | 508 server.listen((request) { |
537 Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); | 509 Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request)); |
538 String auth = | 510 String auth = BASE64.encode(UTF8.encode(userInfo)); |
539 BASE64.encode(UTF8.encode(userInfo)); | |
540 Expect.equals('Basic $auth', request.headers['Authorization'][0]); | 511 Expect.equals('Basic $auth', request.headers['Authorization'][0]); |
541 Expect.equals(1, request.headers['Authorization'].length); | 512 Expect.equals(1, request.headers['Authorization'].length); |
542 WebSocketTransformer.upgrade(request).then((webSocket) { | 513 WebSocketTransformer.upgrade(request).then((webSocket) { |
543 webSocket.listen((_) { throw 'Unexpected'; }, | 514 webSocket.listen((_) { |
544 onDone: () { asyncEnd(); }); | 515 throw 'Unexpected'; |
| 516 }, onDone: () { |
| 517 asyncEnd(); |
| 518 }); |
545 webSocket.add("Hello"); | 519 webSocket.add("Hello"); |
546 }); | 520 }); |
547 }); | 521 }); |
548 | 522 |
549 var url = | 523 var url = |
550 '${secure ? "wss" : "ws"}://$userInfo@$HOST_NAME:${server.port}/'; | 524 '${secure ? "wss" : "ws"}://$userInfo@$HOST_NAME:${server.port}/'; |
551 WebSocket.connect(url).then((websocket) { | 525 WebSocket.connect(url).then((websocket) { |
552 return websocket.listen((message) { | 526 return websocket.listen((message) { |
553 Expect.equals("Hello", message); | 527 Expect.equals("Hello", message); |
554 return websocket.close(); | 528 return websocket.close(); |
(...skipping 29 matching lines...) Expand all Loading... |
584 testNoUpgrade(); | 558 testNoUpgrade(); |
585 testUsePOST(); | 559 testUsePOST(); |
586 testConnections(10, 3002, "Got tired"); | 560 testConnections(10, 3002, "Got tired"); |
587 testIndividualUpgrade(5); | 561 testIndividualUpgrade(5); |
588 testFromUpgradedSocket(); | 562 testFromUpgradedSocket(); |
589 testAdditionalHeaders(); | 563 testAdditionalHeaders(); |
590 testBasicAuthentication(); | 564 testBasicAuthentication(); |
591 } | 565 } |
592 } | 566 } |
593 | 567 |
594 | |
595 main() { | 568 main() { |
596 new SecurityConfiguration(secure: false).runTests(); | 569 new SecurityConfiguration(secure: false).runTests(); |
597 // TODO(whesse): Make WebSocket.connect() take an optional context: parameter. | 570 // TODO(whesse): Make WebSocket.connect() take an optional context: parameter. |
598 // new SecurityConfiguration(secure: true).runTests(); | 571 // new SecurityConfiguration(secure: true).runTests(); |
599 } | 572 } |
OLD | NEW |