OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // VM chain tests can rely on stronger guarantees about the contents of the | 5 // VM chain tests can rely on stronger guarantees about the contents of the |
6 // stack traces than dart2js. | 6 // stack traces than dart2js. |
7 @TestOn('dart-vm') | 7 @TestOn('dart-vm') |
8 | 8 |
9 import 'dart:async'; | 9 import 'dart:async'; |
10 | 10 |
11 import 'package:stack_trace/stack_trace.dart'; | 11 import 'package:stack_trace/stack_trace.dart'; |
12 import 'package:test/test.dart'; | 12 import 'package:test/test.dart'; |
13 | 13 |
14 import '../utils.dart'; | 14 import '../utils.dart'; |
15 import 'utils.dart'; | 15 import 'utils.dart'; |
16 | 16 |
17 void main() { | 17 void main() { |
18 group('capture() with onError catches exceptions', () { | 18 group('capture() with onError catches exceptions', () { |
19 test('thrown synchronously', () { | 19 test('thrown synchronously', () { |
20 return captureFuture(() => throw 'error') | 20 return captureFuture(() => throw 'error').then((chain) { |
21 .then((chain) { | |
22 expect(chain.traces, hasLength(1)); | 21 expect(chain.traces, hasLength(1)); |
23 expect(chain.traces.single.frames.first, | 22 expect( |
24 frameMember(startsWith('main'))); | 23 chain.traces.single.frames.first, frameMember(startsWith('main'))); |
25 }); | 24 }); |
26 }); | 25 }); |
27 | 26 |
28 test('thrown in a microtask', () { | 27 test('thrown in a microtask', () { |
29 return captureFuture(() => inMicrotask(() => throw 'error')) | 28 return captureFuture(() => inMicrotask(() => throw 'error')) |
30 .then((chain) { | 29 .then((chain) { |
31 // Since there was only one asynchronous operation, there should be only | 30 // Since there was only one asynchronous operation, there should be only |
32 // two traces in the chain. | 31 // two traces in the chain. |
33 expect(chain.traces, hasLength(2)); | 32 expect(chain.traces, hasLength(2)); |
34 | 33 |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 | 341 |
343 return completer.future.then((chain) { | 342 return completer.future.then((chain) { |
344 expect(chain.traces, hasLength(2)); | 343 expect(chain.traces, hasLength(2)); |
345 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); | 344 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); |
346 expect(chain.traces[1].frames, | 345 expect(chain.traces[1].frames, |
347 contains(frameMember(startsWith('inFutureChain')))); | 346 contains(frameMember(startsWith('inFutureChain')))); |
348 }); | 347 }); |
349 }); | 348 }); |
350 }); | 349 }); |
351 | 350 |
352 test('current() outside of capture() returns a chain wrapping the current ' | 351 test( |
| 352 'current() outside of capture() returns a chain wrapping the current ' |
353 'trace', () { | 353 'trace', () { |
354 // The test runner runs all tests with chains enabled, so to test without we | 354 // The test runner runs all tests with chains enabled. |
355 // have to do some zone munging. | 355 return Chain.disable(() { |
356 return runZoned(() { | |
357 var completer = new Completer(); | 356 var completer = new Completer(); |
358 inMicrotask(() => completer.complete(new Chain.current())); | 357 inMicrotask(() => completer.complete(new Chain.current())); |
359 | 358 |
360 return completer.future.then((chain) { | 359 return completer.future.then((chain) { |
361 // Since the chain wasn't loaded within [Chain.capture], the full stack | 360 // Since the chain wasn't loaded within [Chain.capture], the full stack |
362 // chain isn't available and it just returns the current stack when | 361 // chain isn't available and it just returns the current stack when |
363 // called. | 362 // called. |
364 expect(chain.traces, hasLength(1)); | 363 expect(chain.traces, hasLength(1)); |
365 expect(chain.traces.first.frames.first, | 364 expect( |
366 frameMember(startsWith('main'))); | 365 chain.traces.first.frames.first, frameMember(startsWith('main'))); |
367 }); | 366 }); |
368 }, zoneValues: {#stack_trace.stack_zone.spec: null}); | 367 }); |
369 }); | 368 }); |
370 | 369 |
371 group('forTrace() within capture()', () { | 370 group('forTrace() within capture()', () { |
372 test('called for a stack trace from a microtask', () { | 371 test('called for a stack trace from a microtask', () { |
373 return Chain.capture(() { | 372 return Chain.capture(() { |
374 return chainForTrace(inMicrotask, () => throw 'error'); | 373 return chainForTrace(inMicrotask, () => throw 'error'); |
375 }).then((chain) { | 374 }).then((chain) { |
376 // Because [chainForTrace] has to set up a future chain to capture the | 375 // Because [chainForTrace] has to set up a future chain to capture the |
377 // stack trace while still showing it to the zone specification, it adds | 376 // stack trace while still showing it to the zone specification, it adds |
378 // an additional level of async nesting and so an additional trace. | 377 // an additional level of async nesting and so an additional trace. |
(...skipping 25 matching lines...) Expand all Loading... |
404 }).then((chain) { | 403 }).then((chain) { |
405 expect(chain.traces, hasLength(3)); | 404 expect(chain.traces, hasLength(3)); |
406 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); | 405 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); |
407 expect(chain.traces[1].frames, | 406 expect(chain.traces[1].frames, |
408 contains(frameMember(startsWith('chainForTrace')))); | 407 contains(frameMember(startsWith('chainForTrace')))); |
409 expect(chain.traces[2].frames, | 408 expect(chain.traces[2].frames, |
410 contains(frameMember(startsWith('inPeriodicTimer')))); | 409 contains(frameMember(startsWith('inPeriodicTimer')))); |
411 }); | 410 }); |
412 }); | 411 }); |
413 | 412 |
414 test('called for a stack trace from a nested series of asynchronous ' | 413 test( |
| 414 'called for a stack trace from a nested series of asynchronous ' |
415 'operations', () { | 415 'operations', () { |
416 return Chain.capture(() { | 416 return Chain.capture(() { |
417 return chainForTrace((callback) { | 417 return chainForTrace((callback) { |
418 inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); | 418 inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); |
419 }, () => throw 'error'); | 419 }, () => throw 'error'); |
420 }).then((chain) { | 420 }).then((chain) { |
421 expect(chain.traces, hasLength(5)); | 421 expect(chain.traces, hasLength(5)); |
422 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); | 422 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); |
423 expect(chain.traces[1].frames, | 423 expect(chain.traces[1].frames, |
424 contains(frameMember(startsWith('chainForTrace')))); | 424 contains(frameMember(startsWith('chainForTrace')))); |
(...skipping 12 matching lines...) Expand all Loading... |
437 }).then((chain) { | 437 }).then((chain) { |
438 expect(chain.traces, hasLength(3)); | 438 expect(chain.traces, hasLength(3)); |
439 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); | 439 expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); |
440 expect(chain.traces[1].frames, | 440 expect(chain.traces[1].frames, |
441 contains(frameMember(startsWith('chainForTrace')))); | 441 contains(frameMember(startsWith('chainForTrace')))); |
442 expect(chain.traces[2].frames, | 442 expect(chain.traces[2].frames, |
443 contains(frameMember(startsWith('inFutureChain')))); | 443 contains(frameMember(startsWith('inFutureChain')))); |
444 }); | 444 }); |
445 }); | 445 }); |
446 | 446 |
447 test('called for an unregistered stack trace returns a chain wrapping that ' | 447 test( |
| 448 'called for an unregistered stack trace returns a chain wrapping that ' |
448 'trace', () { | 449 'trace', () { |
449 var trace; | 450 var trace; |
450 var chain = Chain.capture(() { | 451 var chain = Chain.capture(() { |
451 try { | 452 try { |
452 throw 'error'; | 453 throw 'error'; |
453 } catch (_, stackTrace) { | 454 } catch (_, stackTrace) { |
454 trace = stackTrace; | 455 trace = stackTrace; |
455 return new Chain.forTrace(stackTrace); | 456 return new Chain.forTrace(stackTrace); |
456 } | 457 } |
457 }); | 458 }); |
458 | 459 |
459 expect(chain.traces, hasLength(1)); | 460 expect(chain.traces, hasLength(1)); |
460 expect(chain.traces.first.toString(), | 461 expect(chain.traces.first.toString(), |
461 equals(new Trace.from(trace).toString())); | 462 equals(new Trace.from(trace).toString())); |
462 }); | 463 }); |
463 }); | 464 }); |
464 | 465 |
465 test('forTrace() outside of capture() returns a chain wrapping the given ' | 466 test( |
| 467 'forTrace() outside of capture() returns a chain wrapping the given ' |
466 'trace', () { | 468 'trace', () { |
467 var trace; | 469 var trace; |
468 var chain = Chain.capture(() { | 470 var chain = Chain.capture(() { |
469 try { | 471 try { |
470 throw 'error'; | 472 throw 'error'; |
471 } catch (_, stackTrace) { | 473 } catch (_, stackTrace) { |
472 trace = stackTrace; | 474 trace = stackTrace; |
473 return new Chain.forTrace(stackTrace); | 475 return new Chain.forTrace(stackTrace); |
474 } | 476 } |
475 }); | 477 }); |
476 | 478 |
477 expect(chain.traces, hasLength(1)); | 479 expect(chain.traces, hasLength(1)); |
478 expect(chain.traces.first.toString(), | 480 expect(chain.traces.first.toString(), |
479 equals(new Trace.from(trace).toString())); | 481 equals(new Trace.from(trace).toString())); |
480 }); | 482 }); |
481 } | 483 } |
OLD | NEW |