Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: tests/standalone/io/raw_synchronous_socket_test.dart

Issue 2803543006: Added synchronous socket implementation to dart:io. (Closed)
Patch Set: Small fix for MacOS Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« sdk/lib/io/sync_socket.dart ('K') | « sdk/lib/io/sync_socket.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
zra 2017/04/07 16:29:42 2017
bkonyi 2017/04/10 19:20:06 Done.
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 // VMOptions=
zra 2017/04/07 16:29:41 Remove this if there aren't any.
bkonyi 2017/04/10 19:20:06 Done.
6
7 import "dart:async";
8 import "dart:io";
9 import "dart:isolate";
10 import "dart:math";
11
12 import "package:async_helper/async_helper.dart";
13 import "package:expect/expect.dart";
14
15 const String LOOPBACK_IP_V4_STRING = "127.0.0.1";
16
17 void testArguments() {
zra 2017/04/07 16:29:42 How about null?
bkonyi 2017/04/10 19:20:07 Done.
18 Expect.throws(
19 () => RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, 65536));
20 Expect.throws(
21 () => RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, -1));
22 Expect.throws(() =>
23 RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, 0, backlog: -1));
zra 2017/04/07 16:29:42 what is backlog?
bkonyi 2017/04/10 19:20:06 Something that came from the RawSocket tests. I co
24 }
zra 2017/04/07 16:29:42 We should probably have more tests with bogus argu
bkonyi 2017/04/10 19:20:07 Done.
25
26 void testInvalidConnect() {
27 // Connect to an unknown DNS name.
28 try {
29 var socket = RawSynchronousSocket.connectSync("ko.faar.__hest__", 0);
30 Expect.fail("Failure expected");
31 } catch (e) {
32 Expect.isTrue(e is SocketException);
33 }
34
35 // Connect to an unavaliable IP-address.
36 try {
37 var socket = RawSynchronousSocket.connectSync("1.2.3.4", 0);
38 Expect.fail("Failure expected");
39 } catch (e) {
40 Expect.isTrue(e is SocketException);
41 }
42 ;
43 }
44
45 void testSimpleConnect() {
46 asyncStart();
47 RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
48 var socket =
49 RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, server.port);
50 server.listen((serverSocket) {
51 Expect.equals(socket.address, serverSocket.remoteAddress);
52 Expect.equals(socket.port, serverSocket.remotePort);
53 Expect.equals(socket.remoteAddress, server.address);
54 Expect.equals(socket.remotePort, server.port);
55 socket.closeSync();
56 server.close();
57 asyncEnd();
58 });
59 });
60 }
61
62 void testServerListenAfterConnect() {
63 asyncStart();
64 RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
65 Expect.isTrue(server.port > 0);
66 var client =
67 RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, server.port);
68 server.listen((socket) {
69 client.closeSync();
70 server.close();
71 socket.close();
72 asyncEnd();
73 });
74 });
75 }
76
77 const messageSize = 1000;
78 // Configuration fields for the EchoServer.
79 enum EchoServerTypes {
80 // Max accumulated connections to server before close. Defaults to 1.
81 CONNECTION_COUNT,
82 // Sets the range of the fields to check in the list generated by
83 // createTestData().
84 OFFSET_END,
85 OFFSET_START,
86 // The port used to communicate with an isolate.
87 ISOLATE_SEND_PORT,
88 // The port of the newly created echo server.
89 SERVER_PORT
90 }
91
92 List<int> createTestData() {
93 return new List<int>.generate(messageSize, (index) => index & 0xff);
94 }
95
96 // Consumes data generated by a test and compares it against the original test
97 // data. The optional fields, start and end, are used to compare against
98 // segments of the original test data list. In other words, data.length == (end
99 // - start).
100 void verifyTestData(List<int> data, [int start = 0, int end]) {
101 assert(data != null);
102 List<int> expected = createTestData();
103 if (end == null) {
104 end = data.length;
105 }
106 end = min(messageSize, end);
107 Expect.equals(end - start, data.length);
108 for (int i = 0; i < (end - start); i++) {
109 Expect.equals(expected[start + i], data[i]);
110 }
111 }
112
113 // The echo server is spawned in a new isolate and is used to test various
114 // synchronous read/write operations by echoing any data received back to the
115 // sender. The server should shutdown automatically after a specified number of
116 // socket disconnections (default: 1).
117 Future echoServer(var sendPort) async {
118 RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) async {
119 ReceivePort receivePort = new ReceivePort();
120 Map response = {
121 EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
122 EchoServerTypes.SERVER_PORT: server.port
123 };
124 sendPort.send(response);
125 Map limits = await receivePort.first;
126 int start = limits[EchoServerTypes.OFFSET_START];
127 int end = limits[EchoServerTypes.OFFSET_END];
128 int length = end - start;
129 int connection_count = limits[EchoServerTypes.CONNECTION_COUNT] ?? 1;
130 int connections = 0;
131 sendPort = limits[EchoServerTypes.ISOLATE_SEND_PORT];
132 server.listen((client) {
133 int bytesRead = 0;
134 int bytesWritten = 0;
135 bool closedEventReceived = false;
136 List<int> data = new List<int>(length);
137 client.writeEventsEnabled = false;
138 client.listen((event) {
139 switch (event) {
140 case RawSocketEvent.READ:
141 Expect.isTrue(bytesWritten == 0);
142 Expect.isTrue(client.available() > 0);
143 var buffer = client.read(client.available());
144 data.setRange(bytesRead, bytesRead + buffer.length, buffer);
145 bytesRead += buffer.length;
146 // Once we've read all the data, we can echo it back. Otherwise,
147 // keep waiting for more bytes.
148 if (bytesRead >= length) {
149 verifyTestData(data, start, end);
150 client.writeEventsEnabled = true;
151 }
152 break;
153 case RawSocketEvent.WRITE:
154 Expect.isFalse(client.writeEventsEnabled);
155 bytesWritten +=
156 client.write(data, bytesWritten, data.length - bytesWritten);
157 if (bytesWritten < length) {
158 client.writeEventsEnabled = true;
159 } else if (bytesWritten == length) {
160 // Close the socket for writing from the server since we're done
161 // writing to this socket. The connection is closed completely
162 // after the client closes the socket for reading from the server.
163 client.shutdown(SocketDirection.SEND);
164 }
165 break;
166 case RawSocketEvent.READ_CLOSED:
167 client.close();
168 break;
169 case RawSocketEvent.CLOSED:
170 Expect.isFalse(closedEventReceived);
171 closedEventReceived = true;
172 break;
173 default:
174 throw "Unexpected event $event";
175 }
176 }, onDone: () {
177 Expect.isTrue(closedEventReceived);
178 connections++;
179 if (connections >= connection_count) {
180 server.close();
181 }
182 });
183 }, onDone: () {
184 // Let the client know we're shutting down then kill the isolate.
185 sendPort.send(null);
186 kill();
187 });
188 });
189 }
190
191 Future testSimpleReadWrite({bool dropReads}) async {
192 asyncStart();
193 // This test creates an server and a client connects. The client writes data
194 // to the socket and the server echos it back. The client confirms the data it
195 // reads is the same as the data sent, then closes the socket, resulting in
196 // the closing of the server, which responds on receivePort with null to
197 // specify the echo server isolate is about to be killed. If an error occurs
198 // in the echo server, the exception and stack trace are sent to receivePort,
199 // which prints the exception and stack trace before eventually throwing an
200 // error.
201 ReceivePort receivePort = new ReceivePort();
202 Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
203
204 Map response = await receivePort.first;
205 SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
206 int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
207
208 receivePort = new ReceivePort();
209 echo.addErrorListener(receivePort.sendPort);
210
211 Map limits = {
212 EchoServerTypes.OFFSET_START: 0,
213 EchoServerTypes.OFFSET_END: messageSize,
214 EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
215 };
216 sendPort.send(limits);
217
218 try {
219 var socket = RawSynchronousSocket.connectSync(
220 LOOPBACK_IP_V4_STRING, serverInternetPort);
221 List<int> data = createTestData();
222 socket.writeFromSync(data);
223 List<int> result = socket.readSync(data.length);
224 verifyTestData(result);
225 socket.shutdown(SocketDirection.SEND);
226 socket.closeSync();
227 } catch (e, stack) {
zra 2017/04/07 16:29:42 print("Echo test failed in the client"); rethrow;
bkonyi 2017/04/10 19:20:06 Done.
228 throw "Echo test failed in client!\nError: ${e}\nStack trace: ${stack}";
229 }
230 // Wait for the server to shutdown before finishing the test.
231 var result = await receivePort.first;
232 if (result != null) {
233 throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
234 " ${result[1]}";
235 }
236 asyncEnd();
237 }
238
239 Future testPartialRead() async {
240 asyncStart();
241 // This test creates an server and a client connects. The client writes data
242 // to the socket and the server echos it back. The client confirms the data it
243 // reads is the same as the data sent, then closes the socket, resulting in
244 // the closing of the server, which responds on receivePort with null to
245 // specify the echo server isolate is about to be killed. If an error occurs
246 // in the echo server, the exception and stack trace are sent to receivePort,
247 // which prints the exception and stack trace before eventually throwing an
248 // error.
249
250 ReceivePort receivePort = new ReceivePort();
251 Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
252
253 Map response = await receivePort.first;
254 SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
255 int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
256 List<int> data = createTestData();
257
258 receivePort = new ReceivePort();
259 echo.addErrorListener(receivePort.sendPort);
260
261 Map limits = {
262 EchoServerTypes.OFFSET_START: 0,
263 EchoServerTypes.OFFSET_END: 1000,
264 EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
265 };
266 sendPort.send(limits);
267
268 try {
269 var socket = RawSynchronousSocket.connectSync(
270 LOOPBACK_IP_V4_STRING, serverInternetPort);
271 int half_length = (data.length / 2).toInt();
272
273 // Send the full data list to the server.
274 socket.writeFromSync(data);
275 List<int> result = new List<int>(data.length);
276
277 // Read half at a time and check that there's still more bytes available.
278 socket.readIntoSync(result, 0, half_length);
279 verifyTestData(result.sublist(0, half_length), 0, half_length);
280 Expect.isTrue(socket.available() == (data.length - half_length));
281
282 // Read the second half and verify again.
283 socket.readIntoSync(result, half_length);
284 verifyTestData(result);
285 Expect.isTrue(socket.available() == 0);
286
287 socket.closeSync();
288 } catch (e, stack) {
289 throw "Echo test failed in client!\nError: ${e}\nStack trace: ${stack}";
290 }
291 // Wait for the server to shutdown before finishing the test.
292 var result = await receivePort.first;
293 if (result != null) {
294 throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
295 " ${result[1]}";
296 }
297 asyncEnd();
298 }
299
300 Future testPartialWrite() async {
301 asyncStart();
302 // This test creates an server and a client connects. The client writes data
303 // to the socket and the server echos it back. The client confirms the data it
304 // reads is the same as the data sent, then closes the socket, resulting in
305 // the closing of the server, which responds on receivePort with null to
306 // specify the echo server isolate is about to be killed. If an error occurs
307 // in the echo server, the exception and stack trace are sent to receivePort,
308 // which prints the exception and stack trace before eventually throwing an
309 // error.
310
311 ReceivePort receivePort = new ReceivePort();
312 Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
313
314 Map response = await receivePort.first;
315 List<int> data = createTestData();
316 SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
317 int startOffset = 32;
318 int endOffset = (data.length / 2).toInt();
319 int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
320
321 receivePort = new ReceivePort();
322 echo.addErrorListener(receivePort.sendPort);
323
324 Map limits = {
325 EchoServerTypes.OFFSET_START: startOffset,
326 EchoServerTypes.OFFSET_END: endOffset,
327 EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
328 };
329 sendPort.send(limits);
330 try {
331 var socket = RawSynchronousSocket.connectSync(
332 LOOPBACK_IP_V4_STRING, serverInternetPort);
333 List<int> data = createTestData();
334
335 // Write a subset of data to the server.
336 socket.writeFromSync(data, startOffset, endOffset);
337
338 // Grab the response and verify it's correct.
339 List<int> result = new List<int>(endOffset - startOffset);
340 socket.readIntoSync(result);
341
342 Expect.equals(result.length, endOffset - startOffset);
343 verifyTestData(result, startOffset, endOffset);
344 socket.closeSync();
345 } catch (e, stack) {
346 throw "Echo test failed in client!\nError: ${e}\nStack trace: ${stack}";
347 }
348
349 // Wait for the server to shutdown before finishing the test.
350 var result = await receivePort.first;
351 if (result != null) {
352 throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
353 " ${result[1]}";
354 }
355 asyncEnd();
356 }
357
358 Future testShutdown() async {
359 asyncStart();
360 // This test creates an server and a client connects. The client writes data
361 // to the socket and the server echos it back. The client confirms the data it
362 // reads is the same as the data sent, then closes the socket, resulting in
363 // the closing of the server, which responds on receivePort with null to
364 // specify the echo server isolate is about to be killed. If an error occurs
365 // in the echo server, the exception and stack trace are sent to receivePort,
366 // which prints the exception and stack trace before eventually throwing an
367 // error.
368
369 ReceivePort receivePort = new ReceivePort();
370 Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
371
372 Map response = await receivePort.first;
373 SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
374 int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
375 List<int> data = createTestData();
376
377 receivePort = new ReceivePort();
378 echo.addErrorListener(receivePort.sendPort);
379
380 Map limits = {
381 EchoServerTypes.OFFSET_START: 0,
382 EchoServerTypes.OFFSET_END: data.length,
383 EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
384 // Tell the server to shutdown after 3 sockets disconnect.
385 EchoServerTypes.CONNECTION_COUNT: 3
386 };
387 sendPort.send(limits);
388
389 try {
390 var socket = RawSynchronousSocket.connectSync(
391 LOOPBACK_IP_V4_STRING, serverInternetPort);
392
393 // Close from both directions. Shouldn't be able to read/write to the
394 // socket.
395 socket.shutdown(SocketDirection.BOTH);
396 socket.writeFromSync(data); // Should this work?
zra 2017/04/07 16:29:41 It's weird that this doesn't throw when closed in
bkonyi 2017/04/10 19:20:07 I've gone ahead and changed all the read/write ope
397 Expect.isTrue(socket.readSync(data.length) == null);
398 socket.closeSync();
399
400 // Close the socket for reading, do a write, and see if we can get any
401 // response from the server (we shouldn't be able to).
402 socket = RawSynchronousSocket.connectSync(
403 LOOPBACK_IP_V4_STRING, serverInternetPort);
404 socket.shutdown(SocketDirection.RECEIVE);
405 socket.writeFromSync(data);
406 // Returns null when the socket is closed for RECEIVE.
407 Expect.isTrue(socket.readSync(data.length) == null);
408 Expect.isTrue(socket.available() == 0);
409 socket.closeSync();
410
411 // Close the socket for writing and try to do a write. This should cause an
412 // OSError to be throw as the pipe is closed for writing.
413 socket = RawSynchronousSocket.connectSync(
414 LOOPBACK_IP_V4_STRING, serverInternetPort);
415 socket.shutdown(SocketDirection.SEND);
416 Expect.throws(() => socket.writeFromSync(data), (e) => e is OSError);
417 socket.closeSync();
418 } catch (e, stack) {
419 throw "Echo test failed in client!\nError: ${e}\nStack trace: ${stack}";
420 }
421 // Wait for the server to shutdown before finishing the test.
422 var result = await receivePort.first;
423 if (result != null) {
424 throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
425 " ${result[1]}";
426 }
427 asyncEnd();
428 }
429
430 void testClosedError() {
431 asyncStart();
432 RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
433 server.listen((socket) {
434 socket.close();
435 });
436 var socket =
437 RawSynchronousSocket.connectSync(LOOPBACK_IP_V4_STRING, server.port);
438 server.close();
439 socket.closeSync();
440 Expect.throws(() => socket.remotePort, (e) => e is SocketException);
441 Expect.throws(() => socket.remoteAddress, (e) => e is SocketException);
442 asyncEnd();
443 });
444 }
445
446 main() async {
447 asyncStart();
448 testArguments();
449 testInvalidConnect();
450 await testShutdown();
451 testSimpleConnect();
452 testServerListenAfterConnect();
453 await testSimpleReadWrite();
454 await testPartialRead();
455 await testPartialWrite();
456 testClosedError();
457 asyncEnd();
458 }
OLDNEW
« sdk/lib/io/sync_socket.dart ('K') | « sdk/lib/io/sync_socket.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698