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