OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, 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 /// This library is used for testing asynchronous tests. | |
6 /// If a test is asynchronous, it needs to notify the testing driver | |
7 /// about this (otherwise tests may get reported as passing [after main() | |
8 /// finished] even if the asynchronous operations fail). | |
9 /// Tests which can't use the unittest framework should use the helper functions | |
10 /// in this library. | |
11 /// This library provides four methods | |
12 /// - asyncStart(): Needs to be called before an asynchronous operation is | |
13 /// scheduled. | |
14 /// - asyncEnd(): Needs to be called as soon as the asynchronous operation | |
15 /// ended. | |
16 /// - asyncSuccess(_): Variant of asyncEnd useful together with Future.then. | |
17 /// - asyncTest(f()): Helper method that wraps a computation that returns a | |
18 /// Future with matching calls to asyncStart() and | |
19 /// asyncSuccess(_). | |
20 /// After the last asyncStart() called was matched with a corresponding | |
21 /// asyncEnd() or asyncSuccess(_) call, the testing driver will be notified that | |
22 /// the tests is done. | |
23 | |
24 library async_helper; | |
25 | |
26 // TODO(kustermann): This is problematic because we rely on a working | |
27 // 'dart:isolate' (i.e. it is in particular problematic with dart2js). | |
28 // It would be nice if we could use a different mechanism for different | |
29 // runtimes. | |
30 import 'dart:isolate'; | |
31 | |
32 bool _initialized = false; | |
33 ReceivePort _port = null; | |
34 int _asyncLevel = 0; | |
35 | |
36 Exception _buildException(String msg) { | |
37 return new Exception('Fatal: $msg. This is most likely a bug in your test.'); | |
38 } | |
39 | |
40 /// Call this method before an asynchronous test is created. | |
41 void asyncStart() { | |
42 if (_initialized && _asyncLevel == 0) { | |
43 throw _buildException('asyncStart() was called even though we are done ' | |
44 'with testing.'); | |
45 } | |
46 if (!_initialized) { | |
47 print('unittest-suite-wait-for-done'); | |
48 _initialized = true; | |
49 _port = new ReceivePort(); | |
50 } | |
51 _asyncLevel++; | |
52 } | |
53 | |
54 /// Call this after an asynchronous test has ended successfully. | |
55 void asyncEnd() { | |
56 if (_asyncLevel <= 0) { | |
57 if (!_initialized) { | |
58 throw _buildException('asyncEnd() was called before asyncStart().'); | |
59 } else { | |
60 throw _buildException('asyncEnd() was called more often than ' | |
61 'asyncStart().'); | |
62 } | |
63 } | |
64 _asyncLevel--; | |
65 if (_asyncLevel == 0) { | |
66 _port.close(); | |
67 _port = null; | |
68 print('unittest-suite-success'); | |
69 } | |
70 } | |
71 | |
72 /** | |
73 * Call this after an asynchronous test has ended successfully. This is a helper | |
74 * for calling [asyncEnd]. | |
75 * | |
76 * This method intentionally has a signature that matches [:Future.then:] as a | |
77 * convenience for calling [asyncEnd] when a [:Future:] completes without error, | |
78 * like this: | |
79 * | |
80 * asyncStart(); | |
81 * Future result = test(); | |
82 * result.then(asyncSuccess); | |
83 */ | |
84 void asyncSuccess(_) => asyncEnd(); | |
85 | |
86 /** | |
87 * Helper method for performing asynchronous tests involving [:Future:]. | |
88 * | |
89 * [f] must return a [:Future:] for the test computation. | |
90 */ | |
91 void asyncTest(f()) { | |
92 asyncStart(); | |
93 f().then(asyncSuccess); | |
94 } | |
OLD | NEW |