| // Copyright (c) 2013, 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:path/path.dart' as path; | |
| import 'package:stack_trace/stack_trace.dart'; | |
| import 'package:test/test.dart'; | |
| void main() { | |
| // This just shouldn't crash. | |
| test('a native stack trace is parseable', Trace.current); | |
| group('.parse', () { | |
| test('.parse parses a V8 stack trace with eval statment correctly', () { | |
| var trace = Trace.parse(r'''Error | |
| at Object.eval (eval at Foo (main.dart.js:588), <anonymous>:3:47)'''); | |
| expect(trace.frames[0].uri, Uri.parse('main.dart.js')); | |
| expect(trace.frames[0].member, equals('Object.eval')); | |
| expect(trace.frames[0].line, equals(588)); | |
| expect(trace.frames[0].column, isNull); | |
| }); | |
| test('.parse parses a VM stack trace correctly', () { | |
| var trace = Trace.parse( | |
| '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' | |
| '#1 zip.<anonymous closure>.zap (dart:async/future.dart:0:2)\n' | |
| '#2 zip.<anonymous closure>.zap (https://pub.dev/thing.dart:1:100)', | |
| ); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); | |
| expect(trace.frames[1].uri, equals(Uri.parse('dart:async/future.dart'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.dart'))); | |
| }); | |
| test('parses a V8 stack trace correctly', () { | |
| var trace = Trace.parse('Error\n' | |
| ' at Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| ' at https://example.com/stuff.js:0:2\n' | |
| ' at zip.<anonymous>.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('Exception: foo\n' | |
| ' at Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| ' at https://example.com/stuff.js:0:2\n' | |
| ' at zip.<anonymous>.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('Exception: foo\n' | |
| ' bar\n' | |
| ' at Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| ' at https://example.com/stuff.js:0:2\n' | |
| ' at zip.<anonymous>.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('Exception: foo\n' | |
| ' bar\n' | |
| ' at Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| ' at https://example.com/stuff.js:0:2\n' | |
| ' at (anonymous function).zip.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].member, equals('<fn>')); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| expect(trace.frames[2].member, equals('<fn>.zip.zap')); | |
| // Missing description line | |
| trace = | |
| Trace.parse(' at Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| ' at https://example.com/stuff.js:0:2\n' | |
| ' at (anonymous function).zip.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].member, equals('<fn>')); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| expect(trace.frames[2].member, equals('<fn>.zip.zap')); | |
| }); | |
| // JavaScriptCore traces are just like V8, except that it doesn't have a | |
| // header and it starts with a tab rather than spaces. | |
| test('parses a JavaScriptCore stack trace correctly', () { | |
| var trace = | |
| Trace.parse('\tat Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| '\tat https://example.com/stuff.js:0:2\n' | |
| '\tat zip.<anonymous>.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('\tat Foo._bar (https://example.com/stuff.js:42:21)\n' | |
| '\tat \n' | |
| '\tat zip.<anonymous>.zap ' | |
| '(https://pub.dev/thing.js:1:100)'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[1].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| }); | |
| test('parses a Firefox/Safari stack trace correctly', () { | |
| var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('zip/<@https://example.com/stuff.js:0\n' | |
| 'Foo._bar@https://example.com/stuff.js:42\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| trace = Trace.parse('zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'Foo._bar@https://example.com/stuff.js:42'); | |
| expect( | |
| trace.frames[0].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[2].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| }); | |
| test('parses a Firefox/Safari stack trace containing native code correctly', | |
| () { | |
| var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1\n' | |
| '[native code]'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| expect(trace.frames.length, equals(3)); | |
| }); | |
| test('parses a Firefox/Safari stack trace without a method name correctly', | |
| () { | |
| var trace = Trace.parse('https://example.com/stuff.js:42\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[0].member, equals('<fn>')); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| }); | |
| test('parses a Firefox/Safari stack trace with an empty line correctly', | |
| () { | |
| var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' | |
| '\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| }); | |
| test('parses a Firefox/Safari stack trace with a column number correctly', | |
| () { | |
| var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42:2\n' | |
| 'zip/<@https://example.com/stuff.js:0\n' | |
| 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect(trace.frames[0].line, equals(42)); | |
| expect(trace.frames[0].column, equals(2)); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://example.com/stuff.js'))); | |
| expect( | |
| trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); | |
| }); | |
| test('parses a package:stack_trace stack trace correctly', () { | |
| var trace = | |
| Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/baz.dart Foo.<fn>.bar'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://dart.dev/foo/bar.dart'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://dart.dev/foo/baz.dart'))); | |
| }); | |
| test('parses a package:stack_trace stack chain correctly', () { | |
| var trace = | |
| Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/baz.dart Foo.<fn>.bar\n' | |
| '===== asynchronous gap ===========================\n' | |
| 'https://dart.dev/foo/bang.dart 10:11 Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/quux.dart Foo.<fn>.bar'); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://dart.dev/foo/bar.dart'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://dart.dev/foo/baz.dart'))); | |
| expect(trace.frames[2].uri, | |
| equals(Uri.parse('https://dart.dev/foo/bang.dart'))); | |
| expect(trace.frames[3].uri, | |
| equals(Uri.parse('https://dart.dev/foo/quux.dart'))); | |
| }); | |
| test('parses a package:stack_trace stack chain with end gap correctly', () { | |
| var trace = Trace.parse( | |
| 'https://dart.dev/foo/bar.dart 10:11 Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/baz.dart Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/bang.dart 10:11 Foo.<fn>.bar\n' | |
| 'https://dart.dev/foo/quux.dart Foo.<fn>.bar===== asynchronous gap ===========================\n', | |
| ); | |
| expect(trace.frames.length, 4); | |
| expect(trace.frames[0].uri, | |
| equals(Uri.parse('https://dart.dev/foo/bar.dart'))); | |
| expect(trace.frames[1].uri, | |
| equals(Uri.parse('https://dart.dev/foo/baz.dart'))); | |
| expect(trace.frames[2].uri, | |
| equals(Uri.parse('https://dart.dev/foo/bang.dart'))); | |
| expect(trace.frames[3].uri, | |
| equals(Uri.parse('https://dart.dev/foo/quux.dart'))); | |
| }); | |
| test('parses a real package:stack_trace stack trace correctly', () { | |
| var traceString = Trace.current().toString(); | |
| expect(Trace.parse(traceString).toString(), equals(traceString)); | |
| }); | |
| test('parses an empty string correctly', () { | |
| var trace = Trace.parse(''); | |
| expect(trace.frames, isEmpty); | |
| expect(trace.toString(), equals('')); | |
| }); | |
| test('parses trace with async gap correctly', () { | |
| var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' | |
| '<asynchronous suspension>\n' | |
| '#1 twist (dart:the/future.dart:0:2)\n' | |
| '#2 main (dart:my/file.dart:4:6)\n'); | |
| expect(trace.frames.length, 3); | |
| expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); | |
| expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); | |
| expect(trace.frames[2].uri, equals(Uri.parse('dart:my/file.dart'))); | |
| }); | |
| test('parses trace with async gap at end correctly', () { | |
| var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' | |
| '#1 twist (dart:the/future.dart:0:2)\n' | |
| '<asynchronous suspension>\n'); | |
| expect(trace.frames.length, 2); | |
| expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); | |
| expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); | |
| }); | |
| test('parses a V8 stack frace with Wasm frames correctly', () { | |
| var trace = Trace.parse( | |
| '\tat Error._throwWithCurrentStackTrace (wasm://wasm/0006d892:wasm-function[119]:0xbaf8)\n' | |
| '\tat main (wasm://wasm/0006d892:wasm-function[792]:0x14378)\n' | |
| '\tat main tear-off trampoline (wasm://wasm/0006d892:wasm-function[794]:0x14387)\n' | |
| '\tat _invokeMain (wasm://wasm/0006d892:wasm-function[70]:0xa56c)\n' | |
| '\tat InstantiatedApp.invokeMain (/home/user/test.mjs:361:37)\n' | |
| '\tat main (/home/user/run_wasm.js:416:21)\n' | |
| '\tat async action (/home/user/run_wasm.js:353:38)\n' | |
| '\tat async eventLoop (/home/user/run_wasm.js:329:9)'); | |
| expect(trace.frames.length, 8); | |
| for (final frame in trace.frames) { | |
| expect(frame is UnparsedFrame, false); | |
| } | |
| expect(trace.frames[0].uri, Uri.parse('wasm://wasm/0006d892')); | |
| expect(trace.frames[0].line, 1); | |
| expect(trace.frames[0].column, 0xbaf8 + 1); | |
| expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); | |
| expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); | |
| expect(trace.frames[4].line, 361); | |
| expect(trace.frames[4].column, 37); | |
| expect(trace.frames[4].member, 'InstantiatedApp.invokeMain'); | |
| expect(trace.frames[5].uri, Uri.parse('file:///home/user/run_wasm.js')); | |
| expect(trace.frames[5].line, 416); | |
| expect(trace.frames[5].column, 21); | |
| expect(trace.frames[5].member, 'main'); | |
| }); | |
| test('parses Firefox stack frace with Wasm frames correctly', () { | |
| var trace = Trace.parse( | |
| 'Error._throwWithCurrentStackTrace@http://localhost:8080/test.wasm:wasm-function[119]:0xbaf8\n' | |
| 'main@http://localhost:8080/test.wasm:wasm-function[792]:0x14378\n' | |
| 'main tear-off trampoline@http://localhost:8080/test.wasm:wasm-function[794]:0x14387\n' | |
| '_invokeMain@http://localhost:8080/test.wasm:wasm-function[70]:0xa56c\n' | |
| 'invoke@http://localhost:8080/test.mjs:48:26'); | |
| expect(trace.frames.length, 5); | |
| for (final frame in trace.frames) { | |
| expect(frame is UnparsedFrame, false); | |
| } | |
| expect(trace.frames[0].uri, Uri.parse('http://localhost:8080/test.wasm')); | |
| expect(trace.frames[0].line, 1); | |
| expect(trace.frames[0].column, 0xbaf8 + 1); | |
| expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); | |
| expect(trace.frames[4].uri, Uri.parse('http://localhost:8080/test.mjs')); | |
| expect(trace.frames[4].line, 48); | |
| expect(trace.frames[4].column, 26); | |
| expect(trace.frames[4].member, 'invoke'); | |
| }); | |
| test('parses JSShell stack frace with Wasm frames correctly', () { | |
| var trace = Trace.parse( | |
| 'Error._throwWithCurrentStackTrace@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[119]:0xbaf8\n' | |
| 'main@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[792]:0x14378\n' | |
| 'main tear-off trampoline@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[794]:0x14387\n' | |
| '_invokeMain@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[70]:0xa56c\n' | |
| 'invokeMain@/home/user/test.mjs:361:37\n' | |
| 'main@/home/user/run_wasm.js:416:21\n' | |
| 'async*action@/home/user/run_wasm.js:353:44\n' | |
| 'eventLoop@/home/user/run_wasm.js:329:15\n' | |
| 'self.dartMainRunner@/home/user/run_wasm.js:354:14\n' | |
| '@/home/user/run_wasm.js:419:15'); | |
| expect(trace.frames.length, 10); | |
| for (final frame in trace.frames) { | |
| expect(frame is UnparsedFrame, false); | |
| } | |
| expect(trace.frames[0].uri, Uri.parse('file:///home/user/test.mjs')); | |
| expect(trace.frames[0].line, 1); | |
| expect(trace.frames[0].column, 0xbaf8 + 1); | |
| expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); | |
| expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); | |
| expect(trace.frames[4].line, 361); | |
| expect(trace.frames[4].column, 37); | |
| expect(trace.frames[4].member, 'invokeMain'); | |
| expect(trace.frames[9].uri, Uri.parse('file:///home/user/run_wasm.js')); | |
| expect(trace.frames[9].line, 419); | |
| expect(trace.frames[9].column, 15); | |
| expect(trace.frames[9].member, '<fn>'); | |
| }); | |
| test('parses Safari stack frace with Wasm frames correctly', () { | |
| var trace = Trace.parse( | |
| '<?>.wasm-function[Error._throwWithCurrentStackTrace]@[wasm code]\n' | |
| '<?>.wasm-function[main]@[wasm code]\n' | |
| '<?>.wasm-function[main tear-off trampoline]@[wasm code]\n' | |
| '<?>.wasm-function[_invokeMain]@[wasm code]\n' | |
| 'invokeMain@/home/user/test.mjs:361:48\n' | |
| '@/home/user/run_wasm.js:416:31'); | |
| expect(trace.frames.length, 6); | |
| for (final frame in trace.frames) { | |
| expect(frame is UnparsedFrame, false); | |
| } | |
| expect(trace.frames[0].uri, Uri.parse('wasm code')); | |
| expect(trace.frames[0].line, null); | |
| expect(trace.frames[0].column, null); | |
| expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); | |
| expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); | |
| expect(trace.frames[4].line, 361); | |
| expect(trace.frames[4].column, 48); | |
| expect(trace.frames[4].member, 'invokeMain'); | |
| expect(trace.frames[5].uri, Uri.parse('file:///home/user/run_wasm.js')); | |
| expect(trace.frames[5].line, 416); | |
| expect(trace.frames[5].column, 31); | |
| expect(trace.frames[5].member, '<fn>'); | |
| }); | |
| }); | |
| test('.toString() nicely formats the stack trace', () { | |
| var trace = Trace.parse(''' | |
| #0 Foo._bar (foo/bar.dart:42:21) | |
| #1 zip.<anonymous closure>.zap (dart:async/future.dart:0:2) | |
| #2 zip.<anonymous closure>.zap (https://pub.dev/thing.dart:1:100) | |
| '''); | |
| expect(trace.toString(), equals(''' | |
| ${path.join('foo', 'bar.dart')} 42:21 Foo._bar | |
| dart:async/future.dart 0:2 zip.<fn>.zap | |
| https://pub.dev/thing.dart 1:100 zip.<fn>.zap | |
| ''')); | |
| }); | |
| test('.vmTrace returns a native-style trace', () { | |
| var uri = path.toUri(path.absolute('foo')); | |
| var trace = Trace([ | |
| Frame(uri, 10, 20, 'Foo.<fn>'), | |
| Frame(Uri.parse('https://dart.dev/foo.dart'), null, null, 'bar'), | |
| Frame(Uri.parse('dart:async'), 15, null, 'baz'), | |
| ]); | |
| expect( | |
| trace.vmTrace.toString(), | |
| equals('#1 Foo.<anonymous closure> ($uri:10:20)\n' | |
| '#2 bar (https://dart.dev/foo.dart:0:0)\n' | |
| '#3 baz (dart:async:15:0)\n')); | |
| }); | |
| group('folding', () { | |
| group('.terse', () { | |
| test('folds core frames together bottom-up', () { | |
| var trace = Trace.parse(''' | |
| #1 top (dart:async/future.dart:0:2) | |
| #2 bottom (dart:core/uri.dart:1:100) | |
| #0 notCore (foo.dart:42:21) | |
| #3 top (dart:io:5:10) | |
| #4 bottom (dart:async-patch/future.dart:9:11) | |
| #5 alsoNotCore (bar.dart:10:20) | |
| '''); | |
| expect(trace.terse.toString(), equals(''' | |
| dart:core bottom | |
| foo.dart 42:21 notCore | |
| dart:async bottom | |
| bar.dart 10:20 alsoNotCore | |
| ''')); | |
| }); | |
| test('folds empty async frames', () { | |
| var trace = Trace.parse(''' | |
| #0 top (dart:async/future.dart:0:2) | |
| #1 empty.<<anonymous closure>_async_body> (bar.dart) | |
| #2 bottom (dart:async-patch/future.dart:9:11) | |
| #3 notCore (foo.dart:42:21) | |
| '''); | |
| expect(trace.terse.toString(), equals(''' | |
| dart:async bottom | |
| foo.dart 42:21 notCore | |
| ''')); | |
| }); | |
| test('removes the bottom-most async frame', () { | |
| var trace = Trace.parse(''' | |
| #0 notCore (foo.dart:42:21) | |
| #1 top (dart:async/future.dart:0:2) | |
| #2 bottom (dart:core/uri.dart:1:100) | |
| #3 top (dart:io:5:10) | |
| #4 bottom (dart:async-patch/future.dart:9:11) | |
| '''); | |
| expect(trace.terse.toString(), equals(''' | |
| foo.dart 42:21 notCore | |
| ''')); | |
| }); | |
| test("won't make a trace empty", () { | |
| var trace = Trace.parse(''' | |
| #1 top (dart:async/future.dart:0:2) | |
| #2 bottom (dart:core/uri.dart:1:100) | |
| '''); | |
| expect(trace.terse.toString(), equals(''' | |
| dart:core bottom | |
| ''')); | |
| }); | |
| test("won't panic on an empty trace", () { | |
| expect(Trace.parse('').terse.toString(), equals('')); | |
| }); | |
| }); | |
| group('.foldFrames', () { | |
| test('folds frames together bottom-up', () { | |
| var trace = Trace.parse(''' | |
| #0 notFoo (foo.dart:42:21) | |
| #1 fooTop (bar.dart:0:2) | |
| #2 fooBottom (foo.dart:1:100) | |
| #3 alsoNotFoo (bar.dart:10:20) | |
| #4 fooTop (dart:io/socket.dart:5:10) | |
| #5 fooBottom (dart:async-patch/future.dart:9:11) | |
| '''); | |
| var folded = | |
| trace.foldFrames((frame) => frame.member!.startsWith('foo')); | |
| expect(folded.toString(), equals(''' | |
| foo.dart 42:21 notFoo | |
| foo.dart 1:100 fooBottom | |
| bar.dart 10:20 alsoNotFoo | |
| dart:async-patch/future.dart 9:11 fooBottom | |
| ''')); | |
| }); | |
| test('will never fold unparsed frames', () { | |
| var trace = Trace.parse(r''' | |
| .g"cs$#:b";a#>sw{*{ul$"$xqwr`p | |
| %+j-?uppx<([j@#nu{{>*+$%x-={`{ | |
| !e($b{nj)zs?cgr%!;bmw.+$j+pfj~ | |
| '''); | |
| expect(trace.foldFrames((frame) => true).toString(), equals(r''' | |
| .g"cs$#:b";a#>sw{*{ul$"$xqwr`p | |
| %+j-?uppx<([j@#nu{{>*+$%x-={`{ | |
| !e($b{nj)zs?cgr%!;bmw.+$j+pfj~ | |
| ''')); | |
| }); | |
| group('with terse: true', () { | |
| test('folds core frames as well', () { | |
| var trace = Trace.parse(''' | |
| #0 notFoo (foo.dart:42:21) | |
| #1 fooTop (bar.dart:0:2) | |
| #2 coreBottom (dart:async/future.dart:0:2) | |
| #3 alsoNotFoo (bar.dart:10:20) | |
| #4 fooTop (foo.dart:9:11) | |
| #5 coreBottom (dart:async-patch/future.dart:9:11) | |
| '''); | |
| var folded = trace.foldFrames( | |
| (frame) => frame.member!.startsWith('foo'), | |
| terse: true); | |
| expect(folded.toString(), equals(''' | |
| foo.dart 42:21 notFoo | |
| dart:async coreBottom | |
| bar.dart 10:20 alsoNotFoo | |
| ''')); | |
| }); | |
| test('shortens folded frames', () { | |
| var trace = Trace.parse(''' | |
| #0 notFoo (foo.dart:42:21) | |
| #1 fooTop (bar.dart:0:2) | |
| #2 fooBottom (package:foo/bar.dart:0:2) | |
| #3 alsoNotFoo (bar.dart:10:20) | |
| #4 fooTop (foo.dart:9:11) | |
| #5 fooBottom (foo/bar.dart:9:11) | |
| #6 againNotFoo (bar.dart:20:20) | |
| '''); | |
| var folded = trace.foldFrames( | |
| (frame) => frame.member!.startsWith('foo'), | |
| terse: true); | |
| expect(folded.toString(), equals(''' | |
| foo.dart 42:21 notFoo | |
| package:foo fooBottom | |
| bar.dart 10:20 alsoNotFoo | |
| foo fooBottom | |
| bar.dart 20:20 againNotFoo | |
| ''')); | |
| }); | |
| test('removes the bottom-most folded frame', () { | |
| var trace = Trace.parse(''' | |
| #2 fooTop (package:foo/bar.dart:0:2) | |
| #3 notFoo (bar.dart:10:20) | |
| #5 fooBottom (foo/bar.dart:9:11) | |
| '''); | |
| var folded = trace.foldFrames( | |
| (frame) => frame.member!.startsWith('foo'), | |
| terse: true); | |
| expect(folded.toString(), equals(''' | |
| package:foo fooTop | |
| bar.dart 10:20 notFoo | |
| ''')); | |
| }); | |
| }); | |
| }); | |
| }); | |
| } |