| Index: pkg/stack_trace/test/chain_test.dart
|
| diff --git a/pkg/stack_trace/test/chain_test.dart b/pkg/stack_trace/test/chain_test.dart
|
| index beb4721cf558d25e0a6fdb15856da74cf8844ae7..6af3c6b13d7ed2ce9f521016b699680d3922ab9f 100644
|
| --- a/pkg/stack_trace/test/chain_test.dart
|
| +++ b/pkg/stack_trace/test/chain_test.dart
|
| @@ -93,6 +93,37 @@ void main() {
|
| });
|
| });
|
|
|
| + test('thrown in new Future()', () {
|
| + return captureFuture(() => inNewFuture(() => throw 'error'))
|
| + .then((chain) {
|
| + expect(chain.traces, hasLength(3));
|
| + expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
|
| +
|
| + // The second trace is the one captured by
|
| + // [StackZoneSpecification.errorCallback]. Because that runs
|
| + // asynchronously within [new Future], it doesn't actually refer to the
|
| + // source file at all.
|
| + expect(chain.traces[1].frames,
|
| + everyElement(frameLibrary(isNot(contains('chain_test')))));
|
| +
|
| + expect(chain.traces[2].frames,
|
| + contains(frameMember(startsWith('inNewFuture'))));
|
| + });
|
| + });
|
| +
|
| + test('thrown in new Future.sync()', () {
|
| + return captureFuture(() {
|
| + inMicrotask(() => inSyncFuture(() => throw 'error'));
|
| + }).then((chain) {
|
| + expect(chain.traces, hasLength(3));
|
| + expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
|
| + expect(chain.traces[1].frames,
|
| + contains(frameMember(startsWith('inSyncFuture'))));
|
| + expect(chain.traces[2].frames,
|
| + contains(frameMember(startsWith('inMicrotask'))));
|
| + });
|
| + });
|
| +
|
| test('multiple times', () {
|
| var completer = new Completer();
|
| var first = true;
|
| @@ -121,6 +152,73 @@ void main() {
|
| return completer.future;
|
| });
|
|
|
| + test('passed to a completer', () {
|
| + var trace = new Trace.current();
|
| + return captureFuture(() {
|
| + inMicrotask(() => completerErrorFuture(trace));
|
| + }).then((chain) {
|
| + expect(chain.traces, hasLength(3));
|
| +
|
| + // The first trace is the trace that was manually reported for the
|
| + // error.
|
| + expect(chain.traces.first.toString(), equals(trace.toString()));
|
| +
|
| + // The second trace is the trace that was captured when
|
| + // [Completer.addError] was called.
|
| + expect(chain.traces[1].frames,
|
| + contains(frameMember(startsWith('completerErrorFuture'))));
|
| +
|
| + // The third trace is the automatically-captured trace from when the
|
| + // microtask was scheduled.
|
| + expect(chain.traces[2].frames,
|
| + contains(frameMember(startsWith('inMicrotask'))));
|
| + });
|
| + });
|
| +
|
| + test('passed to a completer with no stack trace', () {
|
| + return captureFuture(() {
|
| + inMicrotask(() => completerErrorFuture());
|
| + }).then((chain) {
|
| + expect(chain.traces, hasLength(2));
|
| +
|
| + // The first trace is the one captured when [Completer.addError] was
|
| + // called.
|
| + expect(chain.traces[0].frames,
|
| + contains(frameMember(startsWith('completerErrorFuture'))));
|
| +
|
| + // The second trace is the automatically-captured trace from when the
|
| + // microtask was scheduled.
|
| + expect(chain.traces[1].frames,
|
| + contains(frameMember(startsWith('inMicrotask'))));
|
| + });
|
| + });
|
| +
|
| + test('passed to a stream controller', () {
|
| + var trace = new Trace.current();
|
| + return captureFuture(() {
|
| + inMicrotask(() => controllerErrorStream(trace).listen(null));
|
| + }).then((chain) {
|
| + expect(chain.traces, hasLength(3));
|
| + expect(chain.traces.first.toString(), equals(trace.toString()));
|
| + expect(chain.traces[1].frames,
|
| + contains(frameMember(startsWith('controllerErrorStream'))));
|
| + expect(chain.traces[2].frames,
|
| + contains(frameMember(startsWith('inMicrotask'))));
|
| + });
|
| + });
|
| +
|
| + test('passed to a stream controller with no stack trace', () {
|
| + return captureFuture(() {
|
| + inMicrotask(() => controllerErrorStream().listen(null));
|
| + }).then((chain) {
|
| + expect(chain.traces, hasLength(2));
|
| + expect(chain.traces[0].frames,
|
| + contains(frameMember(startsWith('controllerErrorStream'))));
|
| + expect(chain.traces[1].frames,
|
| + contains(frameMember(startsWith('inMicrotask'))));
|
| + });
|
| + });
|
| +
|
| test('and relays them to the parent zone', () {
|
| var completer = new Completer();
|
|
|
| @@ -526,50 +624,6 @@ void main() {
|
| });
|
|
|
| group('Chain.track(Future)', () {
|
| - test('associates the current chain with a manually-reported exception with '
|
| - 'a stack trace', () {
|
| - var trace = new Trace.current();
|
| - return captureFuture(() {
|
| - inMicrotask(() => trackedErrorFuture(trace));
|
| - }).then((chain) {
|
| - expect(chain.traces, hasLength(3));
|
| -
|
| - // The first trace is the trace that was manually reported for the
|
| - // error.
|
| - expect(chain.traces.first.toString(), equals(trace.toString()));
|
| -
|
| - // The second trace is the trace that was captured when [Chain.track]
|
| - // was called.
|
| - expect(chain.traces[1].frames.first,
|
| - frameMember(startsWith('trackedErrorFuture')));
|
| -
|
| - // The third trace is the automatically-captured trace from when the
|
| - // microtask was scheduled.
|
| - expect(chain.traces[2].frames,
|
| - contains(frameMember(startsWith('inMicrotask'))));
|
| - });
|
| - });
|
| -
|
| - test('associates the current chain with a manually-reported exception with '
|
| - 'no stack trace', () {
|
| - return captureFuture(() {
|
| - inMicrotask(() => trackedErrorFuture());
|
| - }).then((chain) {
|
| - expect(chain.traces, hasLength(3));
|
| -
|
| - // The first trace is the one captured by
|
| - // [StackZoneSpecification.trackFuture], which should contain only
|
| - // stack_trace and dart: frames.
|
| - expect(chain.traces.first.frames,
|
| - everyElement(frameLibrary(isNot(contains('chain_test')))));
|
| -
|
| - expect(chain.traces[1].frames.first,
|
| - frameMember(startsWith('trackedErrorFuture')));
|
| - expect(chain.traces[2].frames,
|
| - contains(frameMember(startsWith('inMicrotask'))));
|
| - });
|
| - });
|
| -
|
| test('forwards the future value within Chain.capture()', () {
|
| Chain.capture(() {
|
| expect(Chain.track(new Future.value('value')),
|
| @@ -598,36 +652,6 @@ void main() {
|
| });
|
|
|
| group('Chain.track(Stream)', () {
|
| - test('associates the current chain with a manually-reported exception with '
|
| - 'a stack trace', () {
|
| - var trace = new Trace.current();
|
| - return captureFuture(() {
|
| - inMicrotask(() => trackedErrorStream(trace).listen(null));
|
| - }).then((chain) {
|
| - expect(chain.traces, hasLength(3));
|
| - expect(chain.traces.first.toString(), equals(trace.toString()));
|
| - expect(chain.traces[1].frames.first,
|
| - frameMember(startsWith('trackedErrorStream')));
|
| - expect(chain.traces[2].frames,
|
| - contains(frameMember(startsWith('inMicrotask'))));
|
| - });
|
| - });
|
| -
|
| - test('associates the current chain with a manually-reported exception with '
|
| - 'no stack trace', () {
|
| - return captureFuture(() {
|
| - inMicrotask(() => trackedErrorStream().listen(null));
|
| - }).then((chain) {
|
| - expect(chain.traces, hasLength(3));
|
| - expect(chain.traces.first.frames,
|
| - everyElement(frameLibrary(isNot(contains('chain_test')))));
|
| - expect(chain.traces[1].frames.first,
|
| - frameMember(startsWith('trackedErrorStream')));
|
| - expect(chain.traces[2].frames,
|
| - contains(frameMember(startsWith('inMicrotask'))));
|
| - });
|
| - });
|
| -
|
| test('forwards stream values within Chain.capture()', () {
|
| Chain.capture(() {
|
| var controller = new StreamController()
|
| @@ -692,22 +716,30 @@ void inFutureChain(callback()) {
|
| .then((_) => new Future(() {}));
|
| }
|
|
|
| -/// Returns a Future that completes to an error and is wrapped in [Chain.track].
|
| +void inNewFuture(callback()) {
|
| + new Future(callback);
|
| +}
|
| +
|
| +void inSyncFuture(callback()) {
|
| + new Future.sync(callback);
|
| +}
|
| +
|
| +/// Returns a Future that completes to an error using a completer.
|
| ///
|
| /// If [trace] is passed, it's used as the stack trace for the error.
|
| -Future trackedErrorFuture([StackTrace trace]) {
|
| +Future completerErrorFuture([StackTrace trace]) {
|
| var completer = new Completer();
|
| completer.completeError('error', trace);
|
| - return Chain.track(completer.future);
|
| + return completer.future;
|
| }
|
|
|
| -/// Returns a Stream that emits an error and is wrapped in [Chain.track].
|
| +/// Returns a Stream that emits an error using a controller.
|
| ///
|
| /// If [trace] is passed, it's used as the stack trace for the error.
|
| -Stream trackedErrorStream([StackTrace trace]) {
|
| +Stream controllerErrorStream([StackTrace trace]) {
|
| var controller = new StreamController();
|
| controller.addError('error', trace);
|
| - return Chain.track(controller.stream);
|
| + return controller.stream;
|
| }
|
|
|
| /// Runs [callback] within [asyncFn], then converts any errors raised into a
|
|
|