| Index: tests/lib_strong/async/zone_error_callback_test.dart
|
| diff --git a/tests/lib_strong/async/zone_error_callback_test.dart b/tests/lib_strong/async/zone_error_callback_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fcf0ba7c3798ed778c2cd31c9f0b4fd4539c834f
|
| --- /dev/null
|
| +++ b/tests/lib_strong/async/zone_error_callback_test.dart
|
| @@ -0,0 +1,327 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'package:expect/expect.dart';
|
| +import 'package:async_helper/async_helper.dart';
|
| +import 'dart:async';
|
| +
|
| +main() {
|
| + asyncStart();
|
| + testNoChange();
|
| + testWithReplacement();
|
| + asyncEnd();
|
| +}
|
| +
|
| +class MockStack implements StackTrace {
|
| + final int id;
|
| + const MockStack(this.id);
|
| + String toString() => "MocKStack($id)";
|
| +}
|
| +const stack1 = const MockStack(1);
|
| +const stack2 = const MockStack(2);
|
| +
|
| +class SomeError implements Error {
|
| + final int id;
|
| + const SomeError(this.id);
|
| + StackTrace get stackTrace => stack2;
|
| + String toString() => "SomeError($id)";
|
| +}
|
| +
|
| +const error1 = const SomeError(1);
|
| +const error2 = const SomeError(2);
|
| +
|
| +void expectError(e, s) {
|
| + // Remember one asyncStart per use of this callback.
|
| + Expect.identical(error1, e);
|
| + Expect.identical(stack1, s);
|
| + asyncEnd();
|
| +}
|
| +
|
| +void expectErrorOnly(e, s) {
|
| + // Remember one asyncStart per use of this callback.
|
| + Expect.identical(error1, e);
|
| + asyncEnd();
|
| +}
|
| +
|
| +AsyncError replace(self, parent, zone, e, s) {
|
| + if (e == "ignore") return null; // For testing handleError throwing.
|
| + Expect.identical(error1, e); // Ensure replacement only called once
|
| + return new AsyncError(error2, stack2);
|
| +}
|
| +
|
| +var replaceZoneSpec = new ZoneSpecification(errorCallback: replace);
|
| +
|
| +// Expectation after replacing.
|
| +void expectReplaced(e, s) {
|
| + Expect.identical(error2, e);
|
| + Expect.identical(stack2, s);
|
| + asyncEnd();
|
| +}
|
| +
|
| +
|
| +void testProgrammaticErrors(expectError) {
|
| + {
|
| + asyncStart();
|
| + Completer c = new Completer();
|
| + c.future.catchError(expectError);
|
| + c.completeError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.listen(null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController(sync: true);
|
| + controller.stream.listen(null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController.broadcast();
|
| + controller.stream.listen(null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController.broadcast(sync: true);
|
| + controller.stream.listen(null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.asBroadcastStream().listen(
|
| + null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController(sync: true);
|
| + controller.stream.asBroadcastStream().listen(
|
| + null, onError: expectError, cancelOnError: true);
|
| + controller.addError(error1, stack1);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + Future f = new Future.error(error1, stack1);
|
| + f.catchError(expectError);
|
| + }
|
| +}
|
| +
|
| +void testThrownErrors(expectErrorOnly) {
|
| + // Throw error in non-registered callback.
|
| + {
|
| + asyncStart();
|
| + Future f = new Future(() => throw error1);
|
| + f.catchError(expectErrorOnly);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + Future f = new Future.microtask(() => throw error1);
|
| + f.catchError(expectErrorOnly);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + Future f = new Future.sync(() => throw error1);
|
| + f.catchError(expectErrorOnly);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.map((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.where((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.forEach((x) => throw error1).catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.expand((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.asyncMap((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.asyncExpand((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.handleError((e, s) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.addError("ignore", null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.skipWhile((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.takeWhile((x) => throw error1).listen(
|
| + null, onError: expectErrorOnly, cancelOnError: true);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.every((x) => throw error1).catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.any((x) => throw error1).catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.firstWhere((x) => throw error1)
|
| + .catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.lastWhere((x) => throw error1)
|
| + .catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.singleWhere((x) => throw error1)
|
| + .catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.reduce((x, y) => throw error1)
|
| + .catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + controller.add(null);
|
| + }
|
| +
|
| + {
|
| + asyncStart();
|
| + StreamController controller = new StreamController();
|
| + controller.stream.fold(null, (x, y) => throw error1)
|
| + .catchError(expectErrorOnly);
|
| + controller.add(null);
|
| + }
|
| +}
|
| +
|
| +
|
| +testNoChange() {
|
| + void testTransparent() {
|
| + testProgrammaticErrors(expectError);
|
| + testThrownErrors(expectErrorOnly);
|
| + }
|
| +
|
| + // Run directly.
|
| + testTransparent();
|
| +
|
| + // Run in a zone that doesn't change callback.
|
| + runZoned(testTransparent,
|
| + zoneSpecification:
|
| + new ZoneSpecification(handleUncaughtError: (s,p,z,e,t){}));
|
| +
|
| + // Run in zone that delegates to root zone
|
| + runZoned(testTransparent,
|
| + zoneSpecification: new ZoneSpecification(
|
| + errorCallback: (s,p,z,e,t) => p.errorCallback(z, e, t)));
|
| +
|
| + // Run in a zone that returns null from the callback.
|
| + runZoned(testTransparent,
|
| + zoneSpecification:
|
| + new ZoneSpecification(errorCallback: (s,p,z,e,t) => null));
|
| +
|
| + // Run in zone that returns same values.
|
| + runZoned(testTransparent,
|
| + zoneSpecification: new ZoneSpecification(
|
| + errorCallback: (s,p,z,e,t) => new AsyncError(e, t)));
|
| +
|
| + // Run in zone that returns null, inside zone that does replacement.
|
| + runZoned(() {
|
| + runZoned(testTransparent,
|
| + zoneSpecification:
|
| + new ZoneSpecification(errorCallback: (s,p,z,e,t)=>null));
|
| + }, zoneSpecification: replaceZoneSpec);
|
| +}
|
| +
|
| +
|
| +void testWithReplacement() {
|
| + void testReplaced() {
|
| + testProgrammaticErrors(expectReplaced);
|
| + testThrownErrors(expectReplaced);
|
| + }
|
| + // Zone which replaces errors.
|
| + runZoned(testReplaced, zoneSpecification: replaceZoneSpec);
|
| +
|
| + // Nested zone, only innermost gets to act.
|
| + runZoned(() {
|
| + runZoned(testReplaced, zoneSpecification: replaceZoneSpec);
|
| + }, zoneSpecification: replaceZoneSpec);
|
| +
|
| + // Use delegation to parent which replaces.
|
| + runZoned(() {
|
| + runZoned(testReplaced,
|
| + zoneSpecification: new ZoneSpecification(
|
| + errorCallback: (s,p,z,e,t) => p.errorCallback(z,e,t)));
|
| + }, zoneSpecification: replaceZoneSpec);
|
| +}
|
|
|