| 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 library test.utils; | 5 library test.utils; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:math' as math; | 9 import 'dart:math' as math; |
| 10 | 10 |
| 11 import 'package:async/async.dart' hide StreamQueue; |
| 11 import 'package:crypto/crypto.dart'; | 12 import 'package:crypto/crypto.dart'; |
| 12 import 'package:path/path.dart' as p; | 13 import 'package:path/path.dart' as p; |
| 13 import 'package:shelf/shelf.dart' as shelf; | 14 import 'package:shelf/shelf.dart' as shelf; |
| 14 import 'package:stack_trace/stack_trace.dart'; | 15 import 'package:stack_trace/stack_trace.dart'; |
| 15 | 16 |
| 16 import 'backend/operating_system.dart'; | 17 import 'backend/operating_system.dart'; |
| 17 import 'util/cancelable_future.dart'; | |
| 18 import 'util/path_handler.dart'; | 18 import 'util/path_handler.dart'; |
| 19 import 'util/stream_queue.dart'; | 19 import 'util/stream_queue.dart'; |
| 20 | 20 |
| 21 /// The maximum console line length. | 21 /// The maximum console line length. |
| 22 const _lineLength = 100; | 22 const _lineLength = 100; |
| 23 | 23 |
| 24 /// A typedef for a possibly-asynchronous function. | 24 /// A typedef for a possibly-asynchronous function. |
| 25 /// | 25 /// |
| 26 /// The return type should only ever by [Future] or void. | 26 /// The return type should only ever by [Future] or void. |
| 27 typedef AsyncFunction(); | 27 typedef AsyncFunction(); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 }, onError: (error, stackTrace) { | 316 }, onError: (error, stackTrace) { |
| 317 completer.completeError(error, stackTrace); | 317 completer.completeError(error, stackTrace); |
| 318 subscription.cancel(); | 318 subscription.cancel(); |
| 319 }, onDone: () { | 319 }, onDone: () { |
| 320 completer.complete(); | 320 completer.complete(); |
| 321 }); | 321 }); |
| 322 | 322 |
| 323 return completer.future; | 323 return completer.future; |
| 324 } | 324 } |
| 325 | 325 |
| 326 /// Returns a [CancelableFuture] that returns the next value of [queue] unless | 326 /// Returns a [CancelableOperation] that returns the next value of [queue] |
| 327 /// it's canceled. | 327 /// unless it's canceled. |
| 328 /// | 328 /// |
| 329 /// If the future is canceled, [queue] is not moved forward at all. Note that | 329 /// If the operation is canceled, [queue] is not moved forward at all. Note that |
| 330 /// it's not safe to call further methods on [queue] until this future has | 330 /// it's not safe to call further methods on [queue] until this operation has |
| 331 /// either completed or been canceled. | 331 /// either completed or been canceled. |
| 332 CancelableFuture cancelableNext(StreamQueue queue) { | 332 CancelableOperation cancelableNext(StreamQueue queue) { |
| 333 var fork = queue.fork(); | 333 var fork = queue.fork(); |
| 334 var completer = new CancelableCompleter(() => fork.cancel(immediate: true)); | 334 var completer = new CancelableCompleter( |
| 335 onCancel: () => fork.cancel(immediate: true)); |
| 335 completer.complete(fork.next.then((_) { | 336 completer.complete(fork.next.then((_) { |
| 336 fork.cancel(); | 337 fork.cancel(); |
| 337 return queue.next; | 338 return queue.next; |
| 338 })); | 339 })); |
| 339 return completer.future; | 340 return completer.operation; |
| 340 } | 341 } |
| 341 | 342 |
| 342 /// Returns a single-subscription stream that emits the results of [futures] in | 343 /// Returns a single-subscription stream that emits the results of [operations] |
| 343 /// the order they complete. | 344 /// in the order they complete. |
| 344 /// | 345 /// |
| 345 /// If any futures in [futures] are [CancelableFuture]s, this will cancel them | 346 /// If the subscription is canceled, any pending operations are canceled as |
| 346 /// if the subscription is canceled. | 347 /// well. |
| 347 Stream inCompletionOrder(Iterable<Future> futures) { | 348 Stream inCompletionOrder(Iterable<CancelableOperation> operations) { |
| 348 var futureSet = futures.toSet(); | 349 var operationSet = operations.toSet(); |
| 349 var controller = new StreamController(sync: true, onCancel: () { | 350 var controller = new StreamController(sync: true, onCancel: () { |
| 350 return Future.wait(futureSet.map((future) { | 351 return Future.wait(operationSet.map((operation) => operation.cancel())); |
| 351 return future is CancelableFuture ? future.cancel() : null; | |
| 352 }).where((future) => future != null)); | |
| 353 }); | 352 }); |
| 354 | 353 |
| 355 for (var future in futureSet) { | 354 for (var operation in operationSet) { |
| 356 future.then(controller.add).catchError(controller.addError) | 355 operation.value.then(controller.add).catchError(controller.addError) |
| 357 .whenComplete(() { | 356 .whenComplete(() { |
| 358 futureSet.remove(future); | 357 operationSet.remove(operation); |
| 359 if (futureSet.isEmpty) controller.close(); | 358 if (operationSet.isEmpty) controller.close(); |
| 360 }); | 359 }); |
| 361 } | 360 } |
| 362 | 361 |
| 363 return controller.stream; | 362 return controller.stream; |
| 364 } | 363 } |
| 365 | 364 |
| 366 /// Returns a stream that emits [error] and [stackTrace], then closes. | 365 /// Returns a stream that emits [error] and [stackTrace], then closes. |
| 367 /// | 366 /// |
| 368 /// This is useful for adding errors to streams defined via `async*`. | 367 /// This is useful for adding errors to streams defined via `async*`. |
| 369 Stream errorStream(error, StackTrace stackTrace) { | 368 Stream errorStream(error, StackTrace stackTrace) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 396 urlSafe: urlSafe, addLineSeparator: addLineSeparator); | 395 urlSafe: urlSafe, addLineSeparator: addLineSeparator); |
| 397 } | 396 } |
| 398 | 397 |
| 399 /// Returns middleware that nests all requests beneath the URL prefix [beneath]. | 398 /// Returns middleware that nests all requests beneath the URL prefix [beneath]. |
| 400 shelf.Middleware nestingMiddleware(String beneath) { | 399 shelf.Middleware nestingMiddleware(String beneath) { |
| 401 return (handler) { | 400 return (handler) { |
| 402 var pathHandler = new PathHandler()..add(beneath, handler); | 401 var pathHandler = new PathHandler()..add(beneath, handler); |
| 403 return pathHandler.handler; | 402 return pathHandler.handler; |
| 404 }; | 403 }; |
| 405 } | 404 } |
| OLD | NEW |