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

Side by Side Diff: test/chain/dart2js_test.dart

Issue 1218903003: Add tests for stack chains in the browser. (Closed) Base URL: git@github.com:dart-lang/stack_trace@master
Patch Set: Created 5 years, 5 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 | « test/chain/chain_test.dart ('k') | test/chain/utils.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 // dart2js chain tests are separated out because dart2js stack traces are
6 // inconsistent due to inlining and browser differences. These tests don't
7 // assert anything about the content of the traces, just the number of traces in
8 // a chain.
9 @TestOn('js')
10
11 import 'dart:async';
12
13 import 'package:stack_trace/stack_trace.dart';
14 import 'package:test/test.dart';
15
16 import 'utils.dart';
17
18 void main() {
19 group('capture() with onError catches exceptions', () {
20 test('thrown synchronously', () async {
21 var chain = await captureFuture(() => throw 'error');
22 expect(chain.traces, hasLength(1));
23 });
24
25 test('thrown in a microtask', () async {
26 var chain = await captureFuture(() => inMicrotask(() => throw 'error'));
27 expect(chain.traces, hasLength(2));
28 });
29
30 test('thrown in a one-shot timer', () async {
31 var chain = await captureFuture(
32 () => inOneShotTimer(() => throw 'error'));
33 expect(chain.traces, hasLength(2));
34 });
35
36 test('thrown in a periodic timer', () async {
37 var chain = await captureFuture(
38 () => inPeriodicTimer(() => throw 'error'));
39 expect(chain.traces, hasLength(2));
40 });
41
42 test('thrown in a nested series of asynchronous operations', () async {
43 var chain = await captureFuture(() {
44 inPeriodicTimer(() {
45 inOneShotTimer(() => inMicrotask(() => throw 'error'));
46 });
47 });
48
49 expect(chain.traces, hasLength(4));
50 });
51
52 test('thrown in a long future chain', () async {
53 var chain = await captureFuture(() => inFutureChain(() => throw 'error'));
54
55 // Despite many asynchronous operations, there's only one level of
56 // nested calls, so there should be only two traces in the chain. This
57 // is important; programmers expect stack trace memory consumption to be
58 // O(depth of program), not O(length of program).
59 expect(chain.traces, hasLength(2));
60 });
61
62 test('thrown in new Future()', () async {
63 var chain = await captureFuture(() => inNewFuture(() => throw 'error'));
64 expect(chain.traces, hasLength(3));
65 });
66
67 test('thrown in new Future.sync()', () async {
68 var chain = await captureFuture(() {
69 inMicrotask(() => inSyncFuture(() => throw 'error'));
70 });
71
72 expect(chain.traces, hasLength(3));
73 });
74
75 test('multiple times', () {
76 var completer = new Completer();
77 var first = true;
78
79 Chain.capture(() {
80 inMicrotask(() => throw 'first error');
81 inPeriodicTimer(() => throw 'second error');
82 }, onError: (error, chain) {
83 try {
84 if (first) {
85 expect(error, equals('first error'));
86 expect(chain.traces, hasLength(2));
87 first = false;
88 } else {
89 expect(error, equals('second error'));
90 expect(chain.traces, hasLength(2));
91 completer.complete();
92 }
93 } catch (error, stackTrace) {
94 completer.completeError(error, stackTrace);
95 }
96 });
97
98 return completer.future;
99 });
100
101 test('passed to a completer', () async {
102 var trace = new Trace.current();
103 var chain = await captureFuture(() {
104 inMicrotask(() => completerErrorFuture(trace));
105 });
106
107 expect(chain.traces, hasLength(3));
108
109 // The first trace is the trace that was manually reported for the
110 // error.
111 expect(chain.traces.first.toString(), equals(trace.toString()));
112 });
113
114 test('passed to a completer with no stack trace', () async {
115 var chain = await captureFuture(() {
116 inMicrotask(() => completerErrorFuture());
117 });
118
119 expect(chain.traces, hasLength(2));
120 });
121
122 test('passed to a stream controller', () async {
123 var trace = new Trace.current();
124 var chain = await captureFuture(() {
125 inMicrotask(() => controllerErrorStream(trace).listen(null));
126 });
127
128 expect(chain.traces, hasLength(3));
129 expect(chain.traces.first.toString(), equals(trace.toString()));
130 });
131
132 test('passed to a stream controller with no stack trace', () async {
133 var chain = await captureFuture(() {
134 inMicrotask(() => controllerErrorStream().listen(null));
135 });
136
137 expect(chain.traces, hasLength(2));
138 });
139
140 test('and relays them to the parent zone', () {
141 var completer = new Completer();
142
143 runZoned(() {
144 Chain.capture(() {
145 inMicrotask(() => throw 'error');
146 }, onError: (error, chain) {
147 expect(error, equals('error'));
148 expect(chain.traces, hasLength(2));
149 throw error;
150 });
151 }, onError: (error, chain) {
152 try {
153 expect(error, equals('error'));
154 expect(chain, new isInstanceOf<Chain>());
155 expect(chain.traces, hasLength(2));
156 completer.complete();
157 } catch (error, stackTrace) {
158 completer.completeError(error, stackTrace);
159 }
160 });
161
162 return completer.future;
163 });
164 });
165
166 test('capture() without onError passes exceptions to parent zone', () {
167 var completer = new Completer();
168
169 runZoned(() {
170 Chain.capture(() => inMicrotask(() => throw 'error'));
171 }, onError: (error, chain) {
172 try {
173 expect(error, equals('error'));
174 expect(chain, new isInstanceOf<Chain>());
175 expect(chain.traces, hasLength(2));
176 completer.complete();
177 } catch (error, stackTrace) {
178 completer.completeError(error, stackTrace);
179 }
180 });
181
182 return completer.future;
183 });
184
185 group('current() within capture()', () {
186 test('called in a microtask', () async {
187 var completer = new Completer();
188 Chain.capture(() {
189 inMicrotask(() => completer.complete(new Chain.current()));
190 });
191
192 var chain = await completer.future;
193 expect(chain.traces, hasLength(2));
194 });
195
196 test('called in a one-shot timer', () async {
197 var completer = new Completer();
198 Chain.capture(() {
199 inOneShotTimer(() => completer.complete(new Chain.current()));
200 });
201
202 var chain = await completer.future;
203 expect(chain.traces, hasLength(2));
204 });
205
206 test('called in a periodic timer', () async {
207 var completer = new Completer();
208 Chain.capture(() {
209 inPeriodicTimer(() => completer.complete(new Chain.current()));
210 });
211
212 var chain = await completer.future;
213 expect(chain.traces, hasLength(2));
214 });
215
216 test('called in a nested series of asynchronous operations', () async {
217 var completer = new Completer();
218 Chain.capture(() {
219 inPeriodicTimer(() {
220 inOneShotTimer(() {
221 inMicrotask(() => completer.complete(new Chain.current()));
222 });
223 });
224 });
225
226 var chain = await completer.future;
227 expect(chain.traces, hasLength(4));
228 });
229
230 test('called in a long future chain', () async {
231 var completer = new Completer();
232 Chain.capture(() {
233 inFutureChain(() => completer.complete(new Chain.current()));
234 });
235
236 var chain = await completer.future;
237 expect(chain.traces, hasLength(2));
238 });
239 });
240
241 test('current() outside of capture() returns a chain wrapping the current '
242 'trace', () {
243 // The test runner runs all tests with chains enabled, so to test without we
244 // have to do some zone munging.
245 return runZoned(() async {
246 var completer = new Completer();
247 inMicrotask(() => completer.complete(new Chain.current()));
248
249 var chain = await completer.future;
250 // Since the chain wasn't loaded within [Chain.capture], the full stack
251 // chain isn't available and it just returns the current stack when
252 // called.
253 expect(chain.traces, hasLength(1));
254 }, zoneValues: {#stack_trace.stack_zone.spec: null});
255 });
256
257 group('forTrace() within capture()', () {
258 test('called for a stack trace from a microtask', () async {
259 var chain = await Chain.capture(() {
260 return chainForTrace(inMicrotask, () => throw 'error');
261 });
262
263 // Because [chainForTrace] has to set up a future chain to capture the
264 // stack trace while still showing it to the zone specification, it adds
265 // an additional level of async nesting and so an additional trace.
266 expect(chain.traces, hasLength(3));
267 });
268
269 test('called for a stack trace from a one-shot timer', () async {
270 var chain = await Chain.capture(() {
271 return chainForTrace(inOneShotTimer, () => throw 'error');
272 });
273
274 expect(chain.traces, hasLength(3));
275 });
276
277 test('called for a stack trace from a periodic timer', () async {
278 var chain = await Chain.capture(() {
279 return chainForTrace(inPeriodicTimer, () => throw 'error');
280 });
281
282 expect(chain.traces, hasLength(3));
283 });
284
285 test('called for a stack trace from a nested series of asynchronous '
286 'operations', () async {
287 var chain = await Chain.capture(() {
288 return chainForTrace((callback) {
289 inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback)));
290 }, () => throw 'error');
291 });
292
293 expect(chain.traces, hasLength(5));
294 });
295
296 test('called for a stack trace from a long future chain', () async {
297 var chain = await Chain.capture(() {
298 return chainForTrace(inFutureChain, () => throw 'error');
299 });
300
301 expect(chain.traces, hasLength(3));
302 });
303
304 test('called for an unregistered stack trace returns a chain wrapping that '
305 'trace', () {
306 var trace;
307 var chain = Chain.capture(() {
308 try {
309 throw 'error';
310 } catch (_, stackTrace) {
311 trace = stackTrace;
312 return new Chain.forTrace(stackTrace);
313 }
314 });
315
316 expect(chain.traces, hasLength(1));
317 expect(chain.traces.first.toString(),
318 equals(new Trace.from(trace).toString()));
319 });
320 });
321
322 test('forTrace() outside of capture() returns a chain wrapping the given '
323 'trace', () {
324 var trace;
325 var chain = Chain.capture(() {
326 try {
327 throw 'error';
328 } catch (_, stackTrace) {
329 trace = stackTrace;
330 return new Chain.forTrace(stackTrace);
331 }
332 });
333
334 expect(chain.traces, hasLength(1));
335 expect(chain.traces.first.toString(),
336 equals(new Trace.from(trace).toString()));
337 });
338 }
OLDNEW
« no previous file with comments | « test/chain/chain_test.dart ('k') | test/chain/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698