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