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:io'; | 10 import 'dart:io'; |
11 import 'dart:isolate'; | 11 import 'dart:isolate'; |
12 import 'dart:convert'; | 12 import 'dart:convert'; |
13 import 'package:expect/expect.dart'; | 13 import 'package:expect/expect.dart'; |
14 import '../chat_server_lib.dart'; | 14 import '../chat_server_lib.dart'; |
15 | 15 |
16 // Message to start chat test client running in an isolate. | 16 // Message to start chat test client running in an isolate. |
17 class ChatTestClientStart { | 17 class ChatTestClientStart { |
18 ChatTestClientStart(int this.totalClients, | 18 ChatTestClientStart(int this.totalClients, |
19 int this.messagesToSend, | 19 int this.messagesToSend, |
20 int this.messagesToReceive, | 20 int this.messagesToReceive, |
21 int this.port); | 21 int this.port); |
22 | 22 |
23 int totalClients; | 23 int totalClients; |
24 int messagesToSend; | 24 int messagesToSend; |
25 int messagesToReceive; | 25 int messagesToReceive; |
26 int port; | 26 int port; |
27 } | 27 } |
28 | 28 |
| 29 Future<SendPort> spawnChatTestClient() { |
| 30 var response = new ReceivePort(); |
| 31 return Isolate.spawn(startChatTestClient, response.sendPort) |
| 32 .then((remoteIsolate) => response.first) |
| 33 .whenComplete(() { response.close(); }); // Make sure the port is closed. |
| 34 } |
29 | 35 |
30 void startChatTestClient() { | 36 void startChatTestClient(SendPort replyTo) { |
31 var client = new ChatTestClient(); | 37 var client = new ChatTestClient(); |
32 port.receive(client.dispatch); | 38 replyTo.send(client.dispatchSendPort); |
33 } | 39 } |
34 | 40 |
35 | 41 |
36 // Chat server test client for running in a separate isolate. When | 42 // Chat server test client for running in a separate isolate. When |
37 // this test client is started it will join the chat topic, send a | 43 // this test client is started it will join the chat topic, send a |
38 // number of messages, receive the expected number of messages and | 44 // number of messages, receive the expected number of messages and |
39 // leave the topic. | 45 // leave the topic. |
40 class ChatTestClient { | 46 class ChatTestClient { |
| 47 ReceivePort _dispatchReceivePort; // Port that is linked to dispatch. |
41 SendPort statusPort; // Port to reply to when test has finished. | 48 SendPort statusPort; // Port to reply to when test has finished. |
42 HttpClient httpClient; // HTTP client connection factory. | 49 HttpClient httpClient; // HTTP client connection factory. |
43 | 50 |
44 int totalClients; // Total number of clients in the test. | 51 int totalClients; // Total number of clients in the test. |
45 int messagesToSend; // Number of messages to send. | 52 int messagesToSend; // Number of messages to send. |
46 int messagesToReceive; // Numbe rof messages expected to be received. | 53 int messagesToReceive; // Numbe rof messages expected to be received. |
47 int port; // TCP/IP port for server. | 54 int port; // TCP/IP port for server. |
48 | 55 |
49 String sessionId; // Session id when connected. | 56 String sessionId; // Session id when connected. |
50 int sendMessageNumber; // Number of messages sent. | 57 int sendMessageNumber; // Number of messages sent. |
51 int joinCount; | 58 int joinCount; |
52 int messageCount; | 59 int messageCount; |
53 int receiveMessageNumber; // Number of messages received. | 60 int receiveMessageNumber; // Number of messages received. |
54 | 61 |
| 62 ChatTestClient() : _dispatchReceivePort = new ReceivePort() { |
| 63 _dispatchReceivePort.listen(dispatch); |
| 64 } |
| 65 |
| 66 SendPort get dispatchSendPort => _dispatchReceivePort.sendPort; |
| 67 |
| 68 void close() { |
| 69 _dispatchReceivePort.close(); |
| 70 } |
| 71 |
55 void leave() { | 72 void leave() { |
56 void leaveResponseHandler(response, String data) { | 73 void leaveResponseHandler(response, String data) { |
57 Expect.equals(HttpStatus.OK, response.statusCode); | 74 Expect.equals(HttpStatus.OK, response.statusCode); |
58 var responseData = JSON.decode(data); | 75 var responseData = JSON.decode(data); |
59 Expect.equals("leave", responseData["response"]); | 76 Expect.equals("leave", responseData["response"]); |
60 | 77 |
61 // Test done. | 78 // Test done. |
62 statusPort.send("Test succeeded", null); | 79 statusPort.send("Test succeeded"); |
| 80 close(); |
63 } | 81 } |
64 | 82 |
65 Map leaveRequest = new Map(); | 83 Map leaveRequest = new Map(); |
66 leaveRequest["request"] = "leave"; | 84 leaveRequest["request"] = "leave"; |
67 leaveRequest["sessionId"] = sessionId; | 85 leaveRequest["sessionId"] = sessionId; |
68 httpClient.post("127.0.0.1", port, "/leave") | 86 httpClient.post("127.0.0.1", port, "/leave") |
69 .then((HttpClientRequest request) { | 87 .then((HttpClientRequest request) { |
70 request.write(JSON.encode(leaveRequest)); | 88 request.write(JSON.encode(leaveRequest)); |
71 return request.close(); | 89 return request.close(); |
72 }) | 90 }) |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 return request.close(); | 206 return request.close(); |
189 }) | 207 }) |
190 .then((HttpClientResponse response) { | 208 .then((HttpClientResponse response) { |
191 StringBuffer body = new StringBuffer(); | 209 StringBuffer body = new StringBuffer(); |
192 response.listen( | 210 response.listen( |
193 (data) => body.write(new String.fromCharCodes(data)), | 211 (data) => body.write(new String.fromCharCodes(data)), |
194 onDone: () => joinResponseHandler(response, body.toString())); | 212 onDone: () => joinResponseHandler(response, body.toString())); |
195 }); | 213 }); |
196 } | 214 } |
197 | 215 |
198 void dispatch(message, replyTo) { | 216 void dispatch(message) { |
199 totalClients = message.totalClients; | 217 var chatMessage = message[0]; |
200 messagesToSend = message.messagesToSend; | 218 var replyTo = message[1]; |
201 messagesToReceive = message.messagesToReceive; | 219 totalClients = chatMessage.totalClients; |
202 port = message.port; | 220 messagesToSend = chatMessage.messagesToSend; |
| 221 messagesToReceive = chatMessage.messagesToReceive; |
| 222 port = chatMessage.port; |
203 statusPort = replyTo; | 223 statusPort = replyTo; |
204 | 224 |
205 // Create a HTTP client factory. | 225 // Create a HTTP client factory. |
206 httpClient = new HttpClient(); | 226 httpClient = new HttpClient(); |
207 | 227 |
208 // Start the client by joining the chat topic. | 228 // Start the client by joining the chat topic. |
209 join(); | 229 join(); |
210 } | 230 } |
211 } | 231 } |
212 | 232 |
213 | 233 |
214 class TestMain { | 234 class TestMain { |
215 TestMain.run(int this.clientCount, int this.messageCount) | 235 TestMain.run(int this.clientCount, int this.messageCount) |
216 : serverStatusPort = new ReceivePort(), | 236 : serverStatusPort = new ReceivePort(), |
217 serverPort = null, | 237 serverPort = null, |
218 finishedClients = 0 { | 238 finishedClients = 0 { |
219 serverPort = spawnFunction(startChatServer); | 239 spawnChatServer().then((serverPort) { |
220 start(); | 240 this.serverPort = serverPort; |
| 241 start(); |
| 242 }); |
221 } | 243 } |
222 | 244 |
223 void start() { | 245 void start() { |
224 // Handle status messages from the server. | 246 // Handle status messages from the server. |
225 serverStatusPort.receive( | 247 serverStatusPort.listen((var message) { |
226 (var message, SendPort replyTo) { | |
227 if (message.isStarted) { | 248 if (message.isStarted) { |
228 // When the server is started start all test clients. | 249 // When the server is started start all test clients. |
229 for (int i = 0; i < clientCount; i++) { | 250 for (int i = 0; i < clientCount; i++) { |
230 ChatTestClientStart command = | 251 ChatTestClientStart command = |
231 new ChatTestClientStart(clientCount, | 252 new ChatTestClientStart(clientCount, |
232 messageCount, | 253 messageCount, |
233 messageCount * this.clientCount, | 254 messageCount * this.clientCount, |
234 message.port); | 255 message.port); |
235 clientPorts[i].send(command, clientStatusPorts[i].toSendPort()); | 256 clientPorts[i].send([command, clientStatusPorts[i].sendPort]); |
236 } | 257 } |
237 } else if (message.isError) { | 258 } else if (message.isError) { |
238 print("Could not start server - probably error \"Address already in
use\" from bind."); | 259 print("Could not start server - probably error \"Address already in
use\" from bind."); |
239 serverStatusPort.close(); | 260 serverStatusPort.close(); |
240 } | 261 } |
241 }); | 262 }); |
242 | 263 |
243 // Prepare the requested number of clients. | 264 // Prepare the requested number of clients. |
244 clientPorts = new List<SendPort>(clientCount); | 265 clientPorts = new List<SendPort>(clientCount); |
245 int liveClientsCount = 0; | 266 int liveClientsCount = 0; |
246 clientStatusPorts = new List<ReceivePort>(clientCount); | 267 clientStatusPorts = new List<ReceivePort>(clientCount); |
247 for (int i = 0; i < clientCount; i++) { | 268 for (int i = 0; i < clientCount; i++) { |
248 ReceivePort statusPort = new ReceivePort(); | 269 ReceivePort statusPort = new ReceivePort(); |
249 statusPort.receive((var message, SendPort replyTo) { | 270 statusPort.listen((var message) { |
250 // First and only message from the client indicates that | 271 // First and only message from the client indicates that |
251 // the test is done. | 272 // the test is done. |
252 Expect.equals("Test succeeded", message); | 273 Expect.equals("Test succeeded", message); |
253 statusPort.close(); | 274 statusPort.close(); |
254 finishedClients++; | 275 finishedClients++; |
255 | 276 |
256 // If all clients are finished shutdown the server. | 277 // If all clients are finished shutdown the server. |
257 if (finishedClients == clientCount) { | 278 if (finishedClients == clientCount) { |
258 // Send server stop message to the server. | 279 // Send server stop message to the server. |
259 serverPort.send(new ChatServerCommand.stop(), | 280 serverPort.send([new ChatServerCommand.stop(), |
260 serverStatusPort.toSendPort()); | 281 serverStatusPort.sendPort]); |
261 | 282 |
262 // Close the last port to terminate the test. | 283 // Close the last port to terminate the test. |
263 serverStatusPort.close(); | 284 serverStatusPort.close(); |
264 } | 285 } |
265 }); | 286 }); |
266 | 287 |
267 clientStatusPorts[i] = statusPort; | 288 clientStatusPorts[i] = statusPort; |
268 clientPorts[i] = spawnFunction(startChatTestClient); | 289 spawnChatTestClient().then((clientPort) { |
269 liveClientsCount++; | 290 clientPorts[i] = clientPort; |
270 if (liveClientsCount == clientCount) { | 291 liveClientsCount++; |
271 // Once all clients are running send server start message to | 292 if (liveClientsCount == clientCount) { |
272 // the server. Use port 0 for an ephemeral port. The actual | 293 // Once all clients are running send server start message to |
273 // port will be returned with the server started | 294 // the server. Use port 0 for an ephemeral port. The actual |
274 // message. Use a backlog equal to the client count to avoid | 295 // port will be returned with the server started |
275 // connection issues. | 296 // message. Use a backlog equal to the client count to avoid |
276 serverPort.send(new ChatServerCommand.start("127.0.0.1", 0), | 297 // connection issues. |
277 serverStatusPort.toSendPort()); | 298 serverPort.send([new ChatServerCommand.start("127.0.0.1", 0), |
278 } | 299 serverStatusPort.sendPort]); |
| 300 } |
| 301 }); |
279 } | 302 } |
280 } | 303 } |
281 | 304 |
282 int clientCount; // Number of clients to run. | 305 int clientCount; // Number of clients to run. |
283 int messageCount; // Number of messages per clients to send. | 306 int messageCount; // Number of messages per clients to send. |
284 int finishedClients; // Number of clients finished. | 307 int finishedClients; // Number of clients finished. |
285 | 308 |
286 // Ports for communicating with the server. | 309 // Ports for communicating with the server. |
287 SendPort serverPort; | 310 SendPort serverPort; |
288 ReceivePort serverStatusPort; | 311 ReceivePort serverStatusPort; |
(...skipping 22 matching lines...) Expand all Loading... |
311 TestMain testMain = new TestMain.run(10, 2); | 334 TestMain testMain = new TestMain.run(10, 2); |
312 } | 335 } |
313 | 336 |
314 | 337 |
315 void main() { | 338 void main() { |
316 testOneClient(); | 339 testOneClient(); |
317 testTwoClients(); | 340 testTwoClients(); |
318 testTwoClientsMoreMessages(); | 341 testTwoClientsMoreMessages(); |
319 testTenClients(); | 342 testTenClients(); |
320 } | 343 } |
OLD | NEW |