| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:isolate'; | 6 import 'dart:isolate'; |
| 7 | 7 |
| 8 import 'package:unittest/src/declarer.dart'; | |
| 9 import 'package:unittest/src/invoker.dart'; | 8 import 'package:unittest/src/invoker.dart'; |
| 10 import 'package:unittest/src/isolate_test.dart'; | 9 import 'package:unittest/src/isolate_test.dart'; |
| 11 import 'package:unittest/src/live_test.dart'; | 10 import 'package:unittest/src/live_test.dart'; |
| 11 import 'package:unittest/src/remote_exception.dart'; |
| 12 import 'package:unittest/src/state.dart'; | 12 import 'package:unittest/src/state.dart'; |
| 13 import 'package:unittest/src/suite.dart'; | 13 import 'package:unittest/src/suite.dart'; |
| 14 import 'package:unittest/src/vm_listener.dart'; | 14 import 'package:unittest/src/vm_listener.dart'; |
| 15 import 'package:unittest/unittest.dart'; | 15 import 'package:unittest/unittest.dart'; |
| 16 | 16 |
| 17 import 'utils.dart'; | 17 import 'utils.dart'; |
| 18 | 18 |
| 19 /// The current declarer. | |
| 20 Declarer get _declarer => Zone.current[#unittest.declarer]; | |
| 21 | |
| 22 /// An isolate that's been spun up for the current test. | 19 /// An isolate that's been spun up for the current test. |
| 23 /// | 20 /// |
| 24 /// This is tracked so that it can be killed once the test is done. | 21 /// This is tracked so that it can be killed once the test is done. |
| 25 Isolate _isolate; | 22 Isolate _isolate; |
| 26 | 23 |
| 27 /// A live test that's running for the current test. | 24 /// A live test that's running for the current test. |
| 28 /// | 25 /// |
| 29 /// This is tracked so that it can be closed once the test is done. | 26 /// This is tracked so that it can be closed once the test is done. |
| 30 LiveTest _liveTest; | 27 LiveTest _liveTest; |
| 31 | 28 |
| 32 void main() { | 29 void main() { |
| 33 tearDown(() { | 30 tearDown(() { |
| 34 if (_isolate != null) _isolate.kill(Isolate.IMMEDIATE); | 31 if (_isolate != null) _isolate.kill(Isolate.IMMEDIATE); |
| 35 _isolate = null; | 32 _isolate = null; |
| 36 | 33 |
| 37 if (_liveTest != null) _liveTest.close(); | 34 if (_liveTest != null) _liveTest.close(); |
| 38 _liveTest = null; | 35 _liveTest = null; |
| 39 }); | 36 }); |
| 40 | 37 |
| 41 test("sends a list of available tests on startup", () { | 38 test("sends a list of available tests on startup", () { |
| 42 return _spawnIsolate(_successfulTests).then((receivePort) { | 39 return _spawnIsolate(_successfulTests).then((receivePort) { |
| 43 return receivePort.first; | 40 return receivePort.first; |
| 44 }).then((tests) { | 41 }).then((response) { |
| 42 expect(response, containsPair("type", "success")); |
| 43 expect(response, contains("tests")); |
| 44 |
| 45 var tests = response["tests"]; |
| 45 expect(tests, hasLength(3)); | 46 expect(tests, hasLength(3)); |
| 46 expect(tests[0], containsPair("name", "successful 1")); | 47 expect(tests[0], containsPair("name", "successful 1")); |
| 47 expect(tests[1], containsPair("name", "successful 2")); | 48 expect(tests[1], containsPair("name", "successful 2")); |
| 48 expect(tests[2], containsPair("name", "successful 3")); | 49 expect(tests[2], containsPair("name", "successful 3")); |
| 49 }); | 50 }); |
| 50 }); | 51 }); |
| 51 | 52 |
| 53 test("sends an error response if loading fails", () { |
| 54 return _spawnIsolate(_loadError).then((receivePort) { |
| 55 return receivePort.first; |
| 56 }).then((response) { |
| 57 expect(response, containsPair("type", "error")); |
| 58 expect(response, contains("error")); |
| 59 |
| 60 var error = RemoteException.deserialize(response["error"]).error; |
| 61 expect(error.message, equals("oh no")); |
| 62 expect(error.type, equals("String")); |
| 63 }); |
| 64 }); |
| 65 |
| 66 test("sends an error response on a NoSuchMethodError", () { |
| 67 return _spawnIsolate(_noSuchMethodError).then((receivePort) { |
| 68 return receivePort.first; |
| 69 }).then((response) { |
| 70 expect(response, containsPair("type", "loadException")); |
| 71 expect(response, |
| 72 containsPair("message", "No top-level main() function defined.")); |
| 73 }); |
| 74 }); |
| 75 |
| 76 test("sends an error response on non-function main", () { |
| 77 return _spawnIsolate(_nonFunction).then((receivePort) { |
| 78 return receivePort.first; |
| 79 }).then((response) { |
| 80 expect(response, containsPair("type", "loadException")); |
| 81 expect(response, |
| 82 containsPair("message", "Top-level main getter is not a function.")); |
| 83 }); |
| 84 }); |
| 85 |
| 86 test("sends an error response on wrong-arity main", () { |
| 87 return _spawnIsolate(_wrongArity).then((receivePort) { |
| 88 return receivePort.first; |
| 89 }).then((response) { |
| 90 expect(response, containsPair("type", "loadException")); |
| 91 expect( |
| 92 response, |
| 93 containsPair( |
| 94 "message", |
| 95 "Top-level main() function takes arguments.")); |
| 96 }); |
| 97 }); |
| 98 |
| 52 group("in a successful test", () { | 99 group("in a successful test", () { |
| 53 test("the state changes from pending to running to complete", () { | 100 test("the state changes from pending to running to complete", () { |
| 54 return _isolateTest(_successfulTests).then((liveTest) { | 101 return _isolateTest(_successfulTests).then((liveTest) { |
| 55 liveTest.onError.listen(expectAsync((_) {}, count: 0)); | 102 liveTest.onError.listen(expectAsync((_) {}, count: 0)); |
| 56 | 103 |
| 57 expect(liveTest.state, | 104 expect(liveTest.state, |
| 58 equals(const State(Status.pending, Result.success))); | 105 equals(const State(Status.pending, Result.success))); |
| 59 | 106 |
| 60 var future = liveTest.run(); | 107 var future = liveTest.run(); |
| 61 | 108 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 }); | 258 }); |
| 212 } | 259 } |
| 213 | 260 |
| 214 /// Loads the first test defined in [entryPoint] in another isolate. | 261 /// Loads the first test defined in [entryPoint] in another isolate. |
| 215 /// | 262 /// |
| 216 /// This test will be automatically closed when the test is finished. | 263 /// This test will be automatically closed when the test is finished. |
| 217 Future<LiveTest> _isolateTest(void entryPoint(SendPort sendPort)) { | 264 Future<LiveTest> _isolateTest(void entryPoint(SendPort sendPort)) { |
| 218 return _spawnIsolate(entryPoint).then((receivePort) { | 265 return _spawnIsolate(entryPoint).then((receivePort) { |
| 219 return receivePort.first; | 266 return receivePort.first; |
| 220 }).then((response) { | 267 }).then((response) { |
| 221 var testMap = response.first; | 268 expect(response, containsPair("type", "success")); |
| 269 |
| 270 var testMap = response["tests"].first; |
| 222 var test = new IsolateTest(testMap["name"], testMap["sendPort"]); | 271 var test = new IsolateTest(testMap["name"], testMap["sendPort"]); |
| 223 var suite = new Suite("suite", [test]); | 272 var suite = new Suite("suite", [test]); |
| 224 _liveTest = test.load(suite); | 273 _liveTest = test.load(suite); |
| 225 return _liveTest; | 274 return _liveTest; |
| 226 }); | 275 }); |
| 227 } | 276 } |
| 228 | 277 |
| 229 /// Spawns an isolate from [entryPoint], sends it a new [SendPort], and returns | 278 /// Spawns an isolate from [entryPoint], sends it a new [SendPort], and returns |
| 230 /// the corresponding [ReceivePort]. | 279 /// the corresponding [ReceivePort]. |
| 231 /// | 280 /// |
| 232 /// This isolate will be automatically killed when the test is finished. | 281 /// This isolate will be automatically killed when the test is finished. |
| 233 Future<ReceivePort> _spawnIsolate(void entryPoint(SendPort sendPort)) { | 282 Future<ReceivePort> _spawnIsolate(void entryPoint(SendPort sendPort)) { |
| 234 var receivePort = new ReceivePort(); | 283 var receivePort = new ReceivePort(); |
| 235 return Isolate.spawn(entryPoint, receivePort.sendPort).then((isolate) { | 284 return Isolate.spawn(entryPoint, receivePort.sendPort).then((isolate) { |
| 236 _isolate = isolate; | 285 _isolate = isolate; |
| 237 return receivePort; | 286 return receivePort; |
| 238 }); | 287 }); |
| 239 } | 288 } |
| 240 | 289 |
| 290 /// An isolate entrypoint that throws immediately. |
| 291 void _loadError(SendPort sendPort) => |
| 292 VmListener.start(sendPort, () => () => throw 'oh no'); |
| 293 |
| 294 /// An isolate entrypoint that throws a NoSuchMethodError. |
| 295 void _noSuchMethodError(SendPort sendPort) { |
| 296 return VmListener.start(sendPort, () => |
| 297 throw new NoSuchMethodError(null, #main, [], {})); |
| 298 } |
| 299 |
| 300 /// An isolate entrypoint that returns a non-function. |
| 301 void _nonFunction(SendPort sendPort) => |
| 302 VmListener.start(sendPort, () => null); |
| 303 |
| 304 /// An isolate entrypoint that returns a function with the wrong arity. |
| 305 void _wrongArity(SendPort sendPort) => |
| 306 VmListener.start(sendPort, () => (_) {}); |
| 307 |
| 241 /// An isolate entrypoint that defines three tests that succeed. | 308 /// An isolate entrypoint that defines three tests that succeed. |
| 242 void _successfulTests(SendPort sendPort) { | 309 void _successfulTests(SendPort sendPort) { |
| 243 VmListener.start(sendPort, () { | 310 VmListener.start(sendPort, () => () { |
| 244 _declarer.test("successful 1", () {}); | 311 test("successful 1", () {}); |
| 245 _declarer.test("successful 2", () {}); | 312 test("successful 2", () {}); |
| 246 _declarer.test("successful 3", () {}); | 313 test("successful 3", () {}); |
| 247 }); | 314 }); |
| 248 } | 315 } |
| 249 | 316 |
| 250 /// An isolate entrypoint that defines a test that fails. | 317 /// An isolate entrypoint that defines a test that fails. |
| 251 void _failingTest(SendPort sendPort) { | 318 void _failingTest(SendPort sendPort) { |
| 252 VmListener.start(sendPort, () { | 319 VmListener.start(sendPort, () => () { |
| 253 _declarer.test("failure", () => throw new TestFailure('oh no')); | 320 test("failure", () => throw new TestFailure('oh no')); |
| 254 }); | 321 }); |
| 255 } | 322 } |
| 256 | 323 |
| 257 /// An isolate entrypoint that defines a test that fails after succeeding. | 324 /// An isolate entrypoint that defines a test that fails after succeeding. |
| 258 void _failAfterSucceedTest(SendPort sendPort) { | 325 void _failAfterSucceedTest(SendPort sendPort) { |
| 259 VmListener.start(sendPort, () { | 326 VmListener.start(sendPort, () => () { |
| 260 _declarer.test("fail after succeed", () { | 327 test("fail after succeed", () { |
| 261 pumpEventQueue().then((_) { | 328 pumpEventQueue().then((_) { |
| 262 throw new TestFailure('oh no'); | 329 throw new TestFailure('oh no'); |
| 263 }); | 330 }); |
| 264 }); | 331 }); |
| 265 }); | 332 }); |
| 266 } | 333 } |
| 267 | 334 |
| 268 /// An isolate entrypoint that defines a test that fails multiple times. | 335 /// An isolate entrypoint that defines a test that fails multiple times. |
| 269 void _multiFailTest(SendPort sendPort) { | 336 void _multiFailTest(SendPort sendPort) { |
| 270 VmListener.start(sendPort, () { | 337 VmListener.start(sendPort, () => () { |
| 271 _declarer.test("multiple failures", () { | 338 test("multiple failures", () { |
| 272 Invoker.current.addOutstandingCallback(); | 339 Invoker.current.addOutstandingCallback(); |
| 273 new Future(() => throw new TestFailure("one")); | 340 new Future(() => throw new TestFailure("one")); |
| 274 new Future(() => throw new TestFailure("two")); | 341 new Future(() => throw new TestFailure("two")); |
| 275 new Future(() => throw new TestFailure("three")); | 342 new Future(() => throw new TestFailure("three")); |
| 276 new Future(() => throw new TestFailure("four")); | 343 new Future(() => throw new TestFailure("four")); |
| 277 }); | 344 }); |
| 278 }); | 345 }); |
| 279 } | 346 } |
| 280 | 347 |
| 281 /// An isolate entrypoint that defines a test that errors. | 348 /// An isolate entrypoint that defines a test that errors. |
| 282 void _errorTest(SendPort sendPort) { | 349 void _errorTest(SendPort sendPort) { |
| 283 VmListener.start(sendPort, () { | 350 VmListener.start(sendPort, () => () { |
| 284 _declarer.test("error", () => throw 'oh no'); | 351 test("error", () => throw 'oh no'); |
| 285 }); | 352 }); |
| 286 } | 353 } |
| 287 | 354 |
| 288 /// An isolate entrypoint that defines a test that errors after succeeding. | 355 /// An isolate entrypoint that defines a test that errors after succeeding. |
| 289 void _errorAfterSucceedTest(SendPort sendPort) { | 356 void _errorAfterSucceedTest(SendPort sendPort) { |
| 290 VmListener.start(sendPort, () { | 357 VmListener.start(sendPort, () => () { |
| 291 _declarer.test("error after succeed", () { | 358 test("error after succeed", () { |
| 292 pumpEventQueue().then((_) => throw 'oh no'); | 359 pumpEventQueue().then((_) => throw 'oh no'); |
| 293 }); | 360 }); |
| 294 }); | 361 }); |
| 295 } | 362 } |
| 296 | 363 |
| 297 /// An isolate entrypoint that defines a test that errors multiple times. | 364 /// An isolate entrypoint that defines a test that errors multiple times. |
| 298 void _multiErrorTest(SendPort sendPort) { | 365 void _multiErrorTest(SendPort sendPort) { |
| 299 VmListener.start(sendPort, () { | 366 VmListener.start(sendPort, () => () { |
| 300 _declarer.test("multiple errors", () { | 367 test("multiple errors", () { |
| 301 Invoker.current.addOutstandingCallback(); | 368 Invoker.current.addOutstandingCallback(); |
| 302 new Future(() => throw "one"); | 369 new Future(() => throw "one"); |
| 303 new Future(() => throw "two"); | 370 new Future(() => throw "two"); |
| 304 new Future(() => throw "three"); | 371 new Future(() => throw "three"); |
| 305 new Future(() => throw "four"); | 372 new Future(() => throw "four"); |
| 306 }); | 373 }); |
| 307 }); | 374 }); |
| 308 } | 375 } |
| OLD | NEW |