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 |