Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: packages/stack_trace/test/chain/vm_test.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packages/stack_trace/test/chain/utils.dart ('k') | packages/stack_trace/test/frame_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 // VM chain tests can rely on stronger guarantees about the contents of the
6 // stack traces than dart2js.
7 @TestOn('dart-vm')
8
9 import 'dart:async';
10
11 import 'package:stack_trace/stack_trace.dart';
12 import 'package:test/test.dart';
13
14 import '../utils.dart';
15 import 'utils.dart';
16
17 void main() {
18 group('capture() with onError catches exceptions', () {
19 test('thrown synchronously', () {
20 return captureFuture(() => throw 'error')
21 .then((chain) {
22 expect(chain.traces, hasLength(1));
23 expect(chain.traces.single.frames.first,
24 frameMember(startsWith('main')));
25 });
26 });
27
28 test('thrown in a microtask', () {
29 return captureFuture(() => inMicrotask(() => throw 'error'))
30 .then((chain) {
31 // Since there was only one asynchronous operation, there should be only
32 // two traces in the chain.
33 expect(chain.traces, hasLength(2));
34
35 // The first frame of the first trace should be the line on which the
36 // actual error was thrown.
37 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
38
39 // The second trace should describe the stack when the error callback
40 // was scheduled.
41 expect(chain.traces[1].frames,
42 contains(frameMember(startsWith('inMicrotask'))));
43 });
44 });
45
46 test('thrown in a one-shot timer', () {
47 return captureFuture(() => inOneShotTimer(() => throw 'error'))
48 .then((chain) {
49 expect(chain.traces, hasLength(2));
50 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
51 expect(chain.traces[1].frames,
52 contains(frameMember(startsWith('inOneShotTimer'))));
53 });
54 });
55
56 test('thrown in a periodic timer', () {
57 return captureFuture(() => inPeriodicTimer(() => throw 'error'))
58 .then((chain) {
59 expect(chain.traces, hasLength(2));
60 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
61 expect(chain.traces[1].frames,
62 contains(frameMember(startsWith('inPeriodicTimer'))));
63 });
64 });
65
66 test('thrown in a nested series of asynchronous operations', () {
67 return captureFuture(() {
68 inPeriodicTimer(() {
69 inOneShotTimer(() => inMicrotask(() => throw 'error'));
70 });
71 }).then((chain) {
72 expect(chain.traces, hasLength(4));
73 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
74 expect(chain.traces[1].frames,
75 contains(frameMember(startsWith('inMicrotask'))));
76 expect(chain.traces[2].frames,
77 contains(frameMember(startsWith('inOneShotTimer'))));
78 expect(chain.traces[3].frames,
79 contains(frameMember(startsWith('inPeriodicTimer'))));
80 });
81 });
82
83 test('thrown in a long future chain', () {
84 return captureFuture(() => inFutureChain(() => throw 'error'))
85 .then((chain) {
86 // Despite many asynchronous operations, there's only one level of
87 // nested calls, so there should be only two traces in the chain. This
88 // is important; programmers expect stack trace memory consumption to be
89 // O(depth of program), not O(length of program).
90 expect(chain.traces, hasLength(2));
91
92 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
93 expect(chain.traces[1].frames,
94 contains(frameMember(startsWith('inFutureChain'))));
95 });
96 });
97
98 test('thrown in new Future()', () {
99 return captureFuture(() => inNewFuture(() => throw 'error'))
100 .then((chain) {
101 expect(chain.traces, hasLength(3));
102 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
103
104 // The second trace is the one captured by
105 // [StackZoneSpecification.errorCallback]. Because that runs
106 // asynchronously within [new Future], it doesn't actually refer to the
107 // source file at all.
108 expect(chain.traces[1].frames,
109 everyElement(frameLibrary(isNot(contains('chain_test')))));
110
111 expect(chain.traces[2].frames,
112 contains(frameMember(startsWith('inNewFuture'))));
113 });
114 });
115
116 test('thrown in new Future.sync()', () {
117 return captureFuture(() {
118 inMicrotask(() => inSyncFuture(() => throw 'error'));
119 }).then((chain) {
120 expect(chain.traces, hasLength(3));
121 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
122 expect(chain.traces[1].frames,
123 contains(frameMember(startsWith('inSyncFuture'))));
124 expect(chain.traces[2].frames,
125 contains(frameMember(startsWith('inMicrotask'))));
126 });
127 });
128
129 test('multiple times', () {
130 var completer = new Completer();
131 var first = true;
132
133 Chain.capture(() {
134 inMicrotask(() => throw 'first error');
135 inPeriodicTimer(() => throw 'second error');
136 }, onError: (error, chain) {
137 try {
138 if (first) {
139 expect(error, equals('first error'));
140 expect(chain.traces[1].frames,
141 contains(frameMember(startsWith('inMicrotask'))));
142 first = false;
143 } else {
144 expect(error, equals('second error'));
145 expect(chain.traces[1].frames,
146 contains(frameMember(startsWith('inPeriodicTimer'))));
147 completer.complete();
148 }
149 } catch (error, stackTrace) {
150 completer.completeError(error, stackTrace);
151 }
152 });
153
154 return completer.future;
155 });
156
157 test('passed to a completer', () {
158 var trace = new Trace.current();
159 return captureFuture(() {
160 inMicrotask(() => completerErrorFuture(trace));
161 }).then((chain) {
162 expect(chain.traces, hasLength(3));
163
164 // The first trace is the trace that was manually reported for the
165 // error.
166 expect(chain.traces.first.toString(), equals(trace.toString()));
167
168 // The second trace is the trace that was captured when
169 // [Completer.addError] was called.
170 expect(chain.traces[1].frames,
171 contains(frameMember(startsWith('completerErrorFuture'))));
172
173 // The third trace is the automatically-captured trace from when the
174 // microtask was scheduled.
175 expect(chain.traces[2].frames,
176 contains(frameMember(startsWith('inMicrotask'))));
177 });
178 });
179
180 test('passed to a completer with no stack trace', () {
181 return captureFuture(() {
182 inMicrotask(() => completerErrorFuture());
183 }).then((chain) {
184 expect(chain.traces, hasLength(2));
185
186 // The first trace is the one captured when [Completer.addError] was
187 // called.
188 expect(chain.traces[0].frames,
189 contains(frameMember(startsWith('completerErrorFuture'))));
190
191 // The second trace is the automatically-captured trace from when the
192 // microtask was scheduled.
193 expect(chain.traces[1].frames,
194 contains(frameMember(startsWith('inMicrotask'))));
195 });
196 });
197
198 test('passed to a stream controller', () {
199 var trace = new Trace.current();
200 return captureFuture(() {
201 inMicrotask(() => controllerErrorStream(trace).listen(null));
202 }).then((chain) {
203 expect(chain.traces, hasLength(3));
204 expect(chain.traces.first.toString(), equals(trace.toString()));
205 expect(chain.traces[1].frames,
206 contains(frameMember(startsWith('controllerErrorStream'))));
207 expect(chain.traces[2].frames,
208 contains(frameMember(startsWith('inMicrotask'))));
209 });
210 });
211
212 test('passed to a stream controller with no stack trace', () {
213 return captureFuture(() {
214 inMicrotask(() => controllerErrorStream().listen(null));
215 }).then((chain) {
216 expect(chain.traces, hasLength(2));
217 expect(chain.traces[0].frames,
218 contains(frameMember(startsWith('controllerErrorStream'))));
219 expect(chain.traces[1].frames,
220 contains(frameMember(startsWith('inMicrotask'))));
221 });
222 });
223
224 test('and relays them to the parent zone', () {
225 var completer = new Completer();
226
227 runZoned(() {
228 Chain.capture(() {
229 inMicrotask(() => throw 'error');
230 }, onError: (error, chain) {
231 expect(error, equals('error'));
232 expect(chain.traces[1].frames,
233 contains(frameMember(startsWith('inMicrotask'))));
234 throw error;
235 });
236 }, onError: (error, chain) {
237 try {
238 expect(error, equals('error'));
239 expect(chain, new isInstanceOf<Chain>());
240 expect(chain.traces[1].frames,
241 contains(frameMember(startsWith('inMicrotask'))));
242 completer.complete();
243 } catch (error, stackTrace) {
244 completer.completeError(error, stackTrace);
245 }
246 });
247
248 return completer.future;
249 });
250 });
251
252 test('capture() without onError passes exceptions to parent zone', () {
253 var completer = new Completer();
254
255 runZoned(() {
256 Chain.capture(() => inMicrotask(() => throw 'error'));
257 }, onError: (error, chain) {
258 try {
259 expect(error, equals('error'));
260 expect(chain, new isInstanceOf<Chain>());
261 expect(chain.traces[1].frames,
262 contains(frameMember(startsWith('inMicrotask'))));
263 completer.complete();
264 } catch (error, stackTrace) {
265 completer.completeError(error, stackTrace);
266 }
267 });
268
269 return completer.future;
270 });
271
272 group('current() within capture()', () {
273 test('called in a microtask', () {
274 var completer = new Completer();
275 Chain.capture(() {
276 inMicrotask(() => completer.complete(new Chain.current()));
277 });
278
279 return completer.future.then((chain) {
280 expect(chain.traces, hasLength(2));
281 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
282 expect(chain.traces[1].frames,
283 contains(frameMember(startsWith('inMicrotask'))));
284 });
285 });
286
287 test('called in a one-shot timer', () {
288 var completer = new Completer();
289 Chain.capture(() {
290 inOneShotTimer(() => completer.complete(new Chain.current()));
291 });
292
293 return completer.future.then((chain) {
294 expect(chain.traces, hasLength(2));
295 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
296 expect(chain.traces[1].frames,
297 contains(frameMember(startsWith('inOneShotTimer'))));
298 });
299 });
300
301 test('called in a periodic timer', () {
302 var completer = new Completer();
303 Chain.capture(() {
304 inPeriodicTimer(() => completer.complete(new Chain.current()));
305 });
306
307 return completer.future.then((chain) {
308 expect(chain.traces, hasLength(2));
309 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
310 expect(chain.traces[1].frames,
311 contains(frameMember(startsWith('inPeriodicTimer'))));
312 });
313 });
314
315 test('called in a nested series of asynchronous operations', () {
316 var completer = new Completer();
317 Chain.capture(() {
318 inPeriodicTimer(() {
319 inOneShotTimer(() {
320 inMicrotask(() => completer.complete(new Chain.current()));
321 });
322 });
323 });
324
325 return completer.future.then((chain) {
326 expect(chain.traces, hasLength(4));
327 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
328 expect(chain.traces[1].frames,
329 contains(frameMember(startsWith('inMicrotask'))));
330 expect(chain.traces[2].frames,
331 contains(frameMember(startsWith('inOneShotTimer'))));
332 expect(chain.traces[3].frames,
333 contains(frameMember(startsWith('inPeriodicTimer'))));
334 });
335 });
336
337 test('called in a long future chain', () {
338 var completer = new Completer();
339 Chain.capture(() {
340 inFutureChain(() => completer.complete(new Chain.current()));
341 });
342
343 return completer.future.then((chain) {
344 expect(chain.traces, hasLength(2));
345 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
346 expect(chain.traces[1].frames,
347 contains(frameMember(startsWith('inFutureChain'))));
348 });
349 });
350 });
351
352 test('current() outside of capture() returns a chain wrapping the current '
353 'trace', () {
354 // The test runner runs all tests with chains enabled, so to test without we
355 // have to do some zone munging.
356 return runZoned(() {
357 var completer = new Completer();
358 inMicrotask(() => completer.complete(new Chain.current()));
359
360 return completer.future.then((chain) {
361 // 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
363 // called.
364 expect(chain.traces, hasLength(1));
365 expect(chain.traces.first.frames.first,
366 frameMember(startsWith('main')));
367 });
368 }, zoneValues: {#stack_trace.stack_zone.spec: null});
369 });
370
371 group('forTrace() within capture()', () {
372 test('called for a stack trace from a microtask', () {
373 return Chain.capture(() {
374 return chainForTrace(inMicrotask, () => throw 'error');
375 }).then((chain) {
376 // 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
378 // an additional level of async nesting and so an additional trace.
379 expect(chain.traces, hasLength(3));
380 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
381 expect(chain.traces[1].frames,
382 contains(frameMember(startsWith('chainForTrace'))));
383 expect(chain.traces[2].frames,
384 contains(frameMember(startsWith('inMicrotask'))));
385 });
386 });
387
388 test('called for a stack trace from a one-shot timer', () {
389 return Chain.capture(() {
390 return chainForTrace(inOneShotTimer, () => throw 'error');
391 }).then((chain) {
392 expect(chain.traces, hasLength(3));
393 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
394 expect(chain.traces[1].frames,
395 contains(frameMember(startsWith('chainForTrace'))));
396 expect(chain.traces[2].frames,
397 contains(frameMember(startsWith('inOneShotTimer'))));
398 });
399 });
400
401 test('called for a stack trace from a periodic timer', () {
402 return Chain.capture(() {
403 return chainForTrace(inPeriodicTimer, () => throw 'error');
404 }).then((chain) {
405 expect(chain.traces, hasLength(3));
406 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
407 expect(chain.traces[1].frames,
408 contains(frameMember(startsWith('chainForTrace'))));
409 expect(chain.traces[2].frames,
410 contains(frameMember(startsWith('inPeriodicTimer'))));
411 });
412 });
413
414 test('called for a stack trace from a nested series of asynchronous '
415 'operations', () {
416 return Chain.capture(() {
417 return chainForTrace((callback) {
418 inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback)));
419 }, () => throw 'error');
420 }).then((chain) {
421 expect(chain.traces, hasLength(5));
422 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
423 expect(chain.traces[1].frames,
424 contains(frameMember(startsWith('chainForTrace'))));
425 expect(chain.traces[2].frames,
426 contains(frameMember(startsWith('inMicrotask'))));
427 expect(chain.traces[3].frames,
428 contains(frameMember(startsWith('inOneShotTimer'))));
429 expect(chain.traces[4].frames,
430 contains(frameMember(startsWith('inPeriodicTimer'))));
431 });
432 });
433
434 test('called for a stack trace from a long future chain', () {
435 return Chain.capture(() {
436 return chainForTrace(inFutureChain, () => throw 'error');
437 }).then((chain) {
438 expect(chain.traces, hasLength(3));
439 expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
440 expect(chain.traces[1].frames,
441 contains(frameMember(startsWith('chainForTrace'))));
442 expect(chain.traces[2].frames,
443 contains(frameMember(startsWith('inFutureChain'))));
444 });
445 });
446
447 test('called for an unregistered stack trace returns a chain wrapping that '
448 'trace', () {
449 var trace;
450 var chain = Chain.capture(() {
451 try {
452 throw 'error';
453 } catch (_, stackTrace) {
454 trace = stackTrace;
455 return new Chain.forTrace(stackTrace);
456 }
457 });
458
459 expect(chain.traces, hasLength(1));
460 expect(chain.traces.first.toString(),
461 equals(new Trace.from(trace).toString()));
462 });
463 });
464
465 test('forTrace() outside of capture() returns a chain wrapping the given '
466 'trace', () {
467 var trace;
468 var chain = Chain.capture(() {
469 try {
470 throw 'error';
471 } catch (_, stackTrace) {
472 trace = stackTrace;
473 return new Chain.forTrace(stackTrace);
474 }
475 });
476
477 expect(chain.traces, hasLength(1));
478 expect(chain.traces.first.toString(),
479 equals(new Trace.from(trace).toString()));
480 });
481 }
OLDNEW
« no previous file with comments | « packages/stack_trace/test/chain/utils.dart ('k') | packages/stack_trace/test/frame_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698