OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub | 6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub |
7 * tests are integration tests that stage some stuff on the file system, run | 7 * tests are integration tests that stage some stuff on the file system, run |
8 * pub, and then validate the results. This library provides an API to build | 8 * pub, and then validate the results. This library provides an API to build |
9 * tests like that. | 9 * tests like that. |
10 */ | 10 */ |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 } | 1392 } |
1393 } | 1393 } |
1394 | 1394 |
1395 /// A class representing an [HttpServer] that's scheduled to run in the course | 1395 /// A class representing an [HttpServer] that's scheduled to run in the course |
1396 /// of the test. This class allows the server's request handling to be scheduled | 1396 /// of the test. This class allows the server's request handling to be scheduled |
1397 /// synchronously. All operations on this class are scheduled. | 1397 /// synchronously. All operations on this class are scheduled. |
1398 class ScheduledServer { | 1398 class ScheduledServer { |
1399 /// The wrapped server. | 1399 /// The wrapped server. |
1400 final Future<HttpServer> _server; | 1400 final Future<HttpServer> _server; |
1401 | 1401 |
| 1402 /// The queue of handlers to run for upcoming requests. |
| 1403 final _handlers = new Queue<Future>(); |
| 1404 |
1402 ScheduledServer._(this._server); | 1405 ScheduledServer._(this._server); |
1403 | 1406 |
1404 /// Creates a new server listening on an automatically-allocated port on | 1407 /// Creates a new server listening on an automatically-allocated port on |
1405 /// localhost. | 1408 /// localhost. |
1406 factory ScheduledServer() { | 1409 factory ScheduledServer() { |
1407 return new ScheduledServer._(_scheduleValue((_) { | 1410 var scheduledServer; |
| 1411 scheduledServer = new ScheduledServer._(_scheduleValue((_) { |
1408 var server = new HttpServer(); | 1412 var server = new HttpServer(); |
1409 server.defaultRequestHandler = _unexpectedRequest; | 1413 server.defaultRequestHandler = scheduledServer._awaitHandle; |
1410 server.listen("127.0.0.1", 0); | 1414 server.listen("127.0.0.1", 0); |
1411 _scheduleCleanup((_) => server.close()); | 1415 _scheduleCleanup((_) => server.close()); |
1412 return new Future.immediate(server); | 1416 return new Future.immediate(server); |
1413 })); | 1417 })); |
| 1418 return scheduledServer; |
1414 } | 1419 } |
1415 | 1420 |
1416 /// The port on which the server is listening. | 1421 /// The port on which the server is listening. |
1417 Future<int> get port => _server.transform((s) => s.port); | 1422 Future<int> get port => _server.transform((s) => s.port); |
1418 | 1423 |
1419 /// The base URL of the server, including its port. | 1424 /// The base URL of the server, including its port. |
1420 Future<Uri> get url => | 1425 Future<Uri> get url => |
1421 port.transform((p) => new Uri.fromString("http://localhost:$p")); | 1426 port.transform((p) => new Uri.fromString("http://localhost:$p")); |
1422 | 1427 |
1423 /// Assert that the next request has the given [method] and [path], and pass | 1428 /// Assert that the next request has the given [method] and [path], and pass |
1424 /// it to [handler] to handle. If [handler] returns a [Future], wait until | 1429 /// it to [handler] to handle. If [handler] returns a [Future], wait until |
1425 /// it's completed to continue the schedule. | 1430 /// it's completed to continue the schedule. |
1426 void handle(String method, String path, | 1431 void handle(String method, String path, |
1427 Future handler(HttpRequest request, HttpResponse response)) { | 1432 Future handler(HttpRequest request, HttpResponse response)) { |
1428 _schedule((_) => timeout(_server.chain((server) { | 1433 var handlerCompleter = new Completer<Function>(); |
1429 var completer = new Completer(); | 1434 _scheduleValue((_) { |
1430 server.defaultRequestHandler = (request, response) { | 1435 var requestCompleteCompleter = new Completer(); |
1431 server.defaultRequestHandler = _unexpectedRequest; | 1436 handlerCompleter.complete((request, response) { |
1432 expect(request.method, equals(method)); | 1437 expect(request.method, equals(method)); |
1433 expect(request.path, equals(path)); | 1438 expect(request.path, equals(path)); |
1434 | 1439 |
1435 var future = handler(request, response); | 1440 var future = handler(request, response); |
1436 if (future == null) future = new Future.immediate(null); | 1441 if (future == null) future = new Future.immediate(null); |
1437 chainToCompleter(future, completer); | 1442 chainToCompleter(future, requestCompleteCompleter); |
1438 }; | 1443 }); |
1439 return completer.future; | 1444 return timeout(requestCompleteCompleter.future, |
1440 }), 5000, "waiting for $method $path")); | 1445 5000, "waiting for $method $path"); |
| 1446 }); |
| 1447 _handlers.add(handlerCompleter.future); |
1441 } | 1448 } |
1442 | 1449 |
1443 /// Raises an error complaining of an unexpected request. | 1450 /// Raises an error complaining of an unexpected request. |
1444 static void _unexpectedRequest(HttpRequest request, HttpResponse response) { | 1451 void _awaitHandle(HttpRequest request, HttpResponse response) { |
1445 fail('Unexpected ${request.method} request to ${request.path}.'); | 1452 var future = timeout(new Future.immediate(null).chain((_) { |
| 1453 var handlerFuture = _handlers.removeFirst(); |
| 1454 if (handlerFuture == null) { |
| 1455 fail('Unexpected ${request.method} request to ${request.path}.'); |
| 1456 } |
| 1457 return handlerFuture; |
| 1458 }).transform((handler) { |
| 1459 handler(request, response); |
| 1460 }), 5000, "waiting for a handler for ${request.method} ${request.path}"); |
| 1461 expect(future, completes); |
1446 } | 1462 } |
1447 } | 1463 } |
1448 | 1464 |
1449 /** | 1465 /** |
1450 * Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, | 1466 * Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, |
1451 * and [Future]s) and recursively resolves all the [Future]s contained within. | 1467 * and [Future]s) and recursively resolves all the [Future]s contained within. |
1452 * Completes with the fully resolved structure. | 1468 * Completes with the fully resolved structure. |
1453 */ | 1469 */ |
1454 Future _awaitObject(object) { | 1470 Future _awaitObject(object) { |
1455 // Unroll nested futures. | 1471 // Unroll nested futures. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 if (_scheduledOnException == null) _scheduledOnException = []; | 1519 if (_scheduledOnException == null) _scheduledOnException = []; |
1504 _scheduledOnException.add(event); | 1520 _scheduledOnException.add(event); |
1505 } | 1521 } |
1506 | 1522 |
1507 /// Like [expect], but for [Future]s that complete as part of the scheduled | 1523 /// Like [expect], but for [Future]s that complete as part of the scheduled |
1508 /// test. This is necessary to ensure that the exception thrown by the | 1524 /// test. This is necessary to ensure that the exception thrown by the |
1509 /// expectation failing is handled by the scheduler. | 1525 /// expectation failing is handled by the scheduler. |
1510 /// | 1526 /// |
1511 /// Note that [matcher] matches against the completed value of [actual], so | 1527 /// Note that [matcher] matches against the completed value of [actual], so |
1512 /// calling [completion] is unnecessary. | 1528 /// calling [completion] is unnecessary. |
1513 Matcher expectLater(Future actual, matcher, {String reason, | 1529 void expectLater(Future actual, matcher, {String reason, |
1514 FailureHandler failureHandler, bool verbose: false}) { | 1530 FailureHandler failureHandler, bool verbose: false}) { |
1515 _schedule((_) { | 1531 _schedule((_) { |
1516 return actual.transform((value) { | 1532 return actual.transform((value) { |
1517 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1533 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
1518 verbose: false); | 1534 verbose: false); |
1519 }); | 1535 }); |
1520 }); | 1536 }); |
1521 } | 1537 } |
OLD | NEW |