| 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 /// A test library for testing test libraries? We must go deeper. | 5 /// A test library for testing test libraries? We must go deeper. |
| 6 /// | 6 /// |
| 7 /// Since unit testing code tends to use a lot of global state, it can be tough | 7 /// Since unit testing code tends to use a lot of global state, it can be tough |
| 8 /// to test. This library manages it by running each test case in a child | 8 /// to test. This library manages it by running each test case in a child |
| 9 /// isolate, then reporting the results back to the parent isolate. | 9 /// isolate, then reporting the results back to the parent isolate. |
| 10 library metatest; | 10 library metatest; |
| 11 | 11 |
| 12 import 'dart:async'; | 12 import 'dart:async'; |
| 13 import 'dart:isolate'; | 13 import 'dart:isolate'; |
| 14 | 14 |
| 15 import 'package:pathos/path.dart' as path; | 15 import 'package:pathos/path.dart' as path; |
| 16 import 'package:unittest/unittest.dart'; | 16 import 'package:unittest/unittest.dart'; |
| 17 | 17 |
| 18 import 'utils.dart'; | 18 import 'utils.dart'; |
| 19 | 19 |
| 20 // TODO(nweiz): get rid of this once issue 8863 is fixed. |
| 21 /// The path to the Dart executable. This is only set in a child isolate. |
| 22 String get dartExecutable => _executable; |
| 23 String _executable; |
| 24 |
| 20 /// Declares a test with the given [description] and [body]. [body] corresponds | 25 /// Declares a test with the given [description] and [body]. [body] corresponds |
| 21 /// to the `main` method of a test file, and will be run in an isolate. By | 26 /// to the `main` method of a test file, and will be run in an isolate. By |
| 22 /// default, this expects that all tests defined in [body] pass, but if | 27 /// default, this expects that all tests defined in [body] pass, but if |
| 23 /// [passing] is passed, only tests listed there are expected to pass. | 28 /// [passing] is passed, only tests listed there are expected to pass. |
| 24 void expectTestsPass(String description, void body(), {List<String> passing}) { | 29 void expectTestsPass(String description, void body(), {List<String> passing}) { |
| 25 _setUpTest(description, body, (results) { | 30 _setUpTest(description, body, (results) { |
| 26 if (_hasError(results)) { | 31 if (_hasError(results)) { |
| 27 throw 'Expected all tests to pass, but got error(s):\n' | 32 throw 'Expected all tests to pass, but got error(s):\n' |
| 28 '${_summarizeTests(results)}'; | 33 '${_summarizeTests(results)}'; |
| 29 } else if (passing == null) { | 34 } else if (passing == null) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 /// The cached [Future] for [_inChildIsolate]. | 97 /// The cached [Future] for [_inChildIsolate]. |
| 93 Future<bool> _inChildIsolateFuture; | 98 Future<bool> _inChildIsolateFuture; |
| 94 | 99 |
| 95 /// Returns whether or not we're running in a child isolate that's supposed to | 100 /// Returns whether or not we're running in a child isolate that's supposed to |
| 96 /// run a test. | 101 /// run a test. |
| 97 Future<bool> get _inChildIsolate { | 102 Future<bool> get _inChildIsolate { |
| 98 if (_inChildIsolateFuture != null) return _inChildIsolateFuture; | 103 if (_inChildIsolateFuture != null) return _inChildIsolateFuture; |
| 99 | 104 |
| 100 var completer = new Completer(); | 105 var completer = new Completer(); |
| 101 port.receive((message, replyTo) { | 106 port.receive((message, replyTo) { |
| 102 _testToRun = message; | 107 _testToRun = message['testToRun']; |
| 108 _executable = message['executable']; |
| 103 _replyTo = replyTo; | 109 _replyTo = replyTo; |
| 104 port.close(); | 110 port.close(); |
| 105 completer.complete(true); | 111 completer.complete(true); |
| 106 }); | 112 }); |
| 107 | 113 |
| 108 // TODO(nweiz): don't use a timeout here once issue 8416 is fixed. | 114 // TODO(nweiz): don't use a timeout here once issue 8416 is fixed. |
| 109 _inChildIsolateFuture = timeout(completer.future, 500, () { | 115 _inChildIsolateFuture = timeout(completer.future, 500, () { |
| 110 port.close(); | 116 port.close(); |
| 111 return false; | 117 return false; |
| 112 }); | 118 }); |
| 113 return _inChildIsolateFuture; | 119 return _inChildIsolateFuture; |
| 114 } | 120 } |
| 115 | 121 |
| 116 /// Runs the test described by [description] in its own isolate. Returns a map | 122 /// Runs the test described by [description] in its own isolate. Returns a map |
| 117 /// describing the results of that test run. | 123 /// describing the results of that test run. |
| 118 Future<Map> _runInIsolate(String description) { | 124 Future<Map> _runInIsolate(String description) { |
| 119 // TODO(nweiz): Don't use path here once issue 8440 is fixed. | 125 // TODO(nweiz): Don't use path here once issue 8440 is fixed. |
| 120 var future = spawnUri(path.join(path.current, new Options().script)) | 126 var future = spawnUri(path.join(path.current, new Options().script)).call({ |
| 121 .call(description); | 127 'testToRun': description, |
| 128 'executable': new Options().executable |
| 129 }); |
| 122 // TODO(nweiz): Remove this timeout once issue 8417 is fixed and we can | 130 // TODO(nweiz): Remove this timeout once issue 8417 is fixed and we can |
| 123 // capture top-level exceptions. | 131 // capture top-level exceptions. |
| 124 return timeout(future, 30 * 1000, () { | 132 return timeout(future, 30 * 1000, () { |
| 125 throw 'Timed out waiting for test to complete.'; | 133 throw 'Timed out waiting for test to complete.'; |
| 126 }); | 134 }); |
| 127 } | 135 } |
| 128 | 136 |
| 129 /// Returns whether [results] (a test result map) describes a test run in which | 137 /// Returns whether [results] (a test result map) describes a test run in which |
| 130 /// an error occurred. | 138 /// an error occurred. |
| 131 bool _hasError(Map results) { | 139 bool _hasError(Map results) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 "message": testCase.message, | 205 "message": testCase.message, |
| 198 "result": testCase.result, | 206 "result": testCase.result, |
| 199 "stackTrace": testCase.stackTrace | 207 "stackTrace": testCase.stackTrace |
| 200 }).toList() | 208 }).toList() |
| 201 }); | 209 }); |
| 202 } | 210 } |
| 203 | 211 |
| 204 void onInit() {} | 212 void onInit() {} |
| 205 void onDone(bool success) {} | 213 void onDone(bool success) {} |
| 206 } | 214 } |
| OLD | NEW |