OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library test.runner.load_suite; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:stack_trace/stack_trace.dart'; | |
10 | |
11 import '../../test.dart'; | |
12 import '../backend/invoker.dart'; | |
13 import '../backend/metadata.dart'; | |
14 import '../backend/suite.dart'; | |
15 import '../utils.dart'; | |
16 import 'load_exception.dart'; | |
17 | |
18 /// A [Suite] emitted by a [Loader] that provides a test-like interface for | |
19 /// loading a test file. | |
20 /// | |
21 /// This is used to expose the current status of test loading to the user. It's | |
kevmoo
2015/06/23 00:48:06
Avoid starting doc sentences with 'This...'
inste
nweiz
2015/06/23 19:38:54
Why? This isn't mentioned in the doc comment guide
| |
22 /// important to provide users visibility into what's taking a long time and | |
23 /// where failures occur. And since some tests may be loaded at the same time as | |
24 /// others are run, it's useful to provide that visibility in the form of a test | |
25 /// suite so that it can integrate well into the existing reporting interface | |
26 /// without too much extra logic. | |
kevmoo
2015/06/23 00:48:06
This paragraph feels like a justification for the
nweiz
2015/06/23 19:38:54
It's important that users of a class understand wh
| |
27 /// | |
28 /// A suite is constructed with logic necessary to produce a test suite. As with | |
29 /// a normal test body, this logic isn't run until [LiveTest.run] is called. The | |
30 /// suite itself is returned by [suite] once it's avaialble, but any errors or | |
31 /// prints will be emitted through the running [LiveTest]. | |
32 class LoadSuite extends Suite { | |
33 /// A future that completes to the loaded suite once the suite's test has been | |
34 /// run and completed successfully. | |
35 /// | |
36 /// This will return `null` if the suite is unavailable for some reason (for | |
37 /// example if an error occurred while loading it). | |
38 final Future<Suite> suite; | |
39 | |
40 /// Creates a load suite named [name] on [platform]. | |
41 /// | |
42 /// [body] may return either a [Suite] or a [Future] that completes to a | |
43 /// [Suite]. Its return value is forwarded through [suite], although if it | |
44 /// throws an error that will be forwarded through the suite's test. | |
45 factory LoadSuite(String name, body(), {String platform}) { | |
46 var completer = new Completer.sync(); | |
47 return new LoadSuite._(name, () { | |
48 var invoker = Invoker.current; | |
49 invoker.addOutstandingCallback(); | |
50 | |
51 invoke(() async { | |
52 try { | |
53 var suite = await body(); | |
54 if (completer.isCompleted) return; | |
55 completer.complete(suite); | |
56 invoker.removeOutstandingCallback(); | |
57 } catch (error, stackTrace) { | |
58 registerException(error, stackTrace); | |
59 if (!completer.isCompleted) completer.complete(); | |
60 } | |
61 }); | |
62 | |
63 // If the test is forcibly closed, exit immediately. It doesn't have any | |
64 // cleanup to do that won't be handled by Loader.close. | |
65 invoker.onClose.then((_) { | |
66 if (completer.isCompleted) return; | |
67 completer.complete(); | |
68 invoker.removeOutstandingCallback(); | |
69 }); | |
70 }, completer.future, platform: platform); | |
71 } | |
72 | |
73 /// A utility constructor for a load suite that just throws [exception]. | |
74 /// | |
75 /// The suite's name will be based on [exception]'s path. | |
76 factory LoadSuite.forLoadException(LoadException exception, | |
77 {StackTrace stackTrace, String platform}) { | |
78 if (stackTrace == null) stackTrace = new Trace.current(); | |
79 | |
80 return new LoadSuite("loading ${exception.path}", () { | |
81 return new Future.error(exception, stackTrace); | |
82 }, platform: platform); | |
83 } | |
84 | |
85 /// A utility constructor for a load suite that just emits [suite]. | |
86 factory LoadSuite.forSuite(Suite suite) { | |
87 return new LoadSuite("loading ${suite.path}", () => suite, | |
88 platform: suite.platform); | |
89 } | |
90 | |
91 LoadSuite._(String name, void body(), this.suite, {String platform}) | |
92 : super([ | |
93 new LocalTest(name, | |
94 new Metadata(timeout: new Timeout(new Duration(minutes: 5))), | |
95 body) | |
96 ], platform: platform); | |
97 | |
98 /// Runs the test and returns the suite. | |
99 /// | |
100 /// Rather than emitting errors through a [LiveTest], this just pipes them | |
101 /// through the return value. | |
102 Future<Suite> getSuite() async { | |
103 var liveTest = await tests.single.load(this); | |
104 liveTest.onPrint.listen(print); | |
105 await liveTest.run(); | |
106 | |
107 if (liveTest.errors.isEmpty) return await suite; | |
108 | |
109 var error = liveTest.errors.first; | |
110 await new Future.error(error.error, error.stackTrace); | |
111 throw 'unreachable'; | |
112 } | |
113 } | |
OLD | NEW |