Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(538)

Side by Side Diff: pkg/scheduled_test/lib/scheduled_test.dart

Issue 812253002: Delete a bunch of packages that are now on GitHub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Un-delete http Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 // TODO(nweiz): Add support for calling [schedule] while the schedule is already
6 // running.
7 // TODO(nweiz): Port the non-Pub-specific scheduled test libraries from Pub.
8 library scheduled_test;
9
10 import 'dart:async';
11
12 import 'package:stack_trace/stack_trace.dart';
13 import 'package:unittest/unittest.dart' as unittest;
14
15 import 'src/schedule.dart';
16 import 'src/schedule_error.dart';
17
18 export 'package:unittest/unittest.dart' hide
19 test, solo_test, group, setUp, tearDown, completes, completion;
20
21 export 'src/schedule.dart';
22 export 'src/schedule_error.dart';
23 export 'src/scheduled_future_matchers.dart';
24 export 'src/task.dart';
25
26 /// The [Schedule] for the current test. This is used to add new tasks and
27 /// inspect the state of the schedule.
28 ///
29 /// This is `null` when there's no test currently running.
30 Schedule get currentSchedule => _currentSchedule;
31 Schedule _currentSchedule;
32
33 /// The user-provided set-up function for the currently-running test.
34 ///
35 /// This is set for each test during `unittest.setUp`.
36 Function _setUpFn;
37
38 /// The user-provided tear-down function for the currently-running test.
39 ///
40 /// This is set for each test during `unittest.setUp`.
41 Function _tearDownFn;
42
43 /// The user-provided set-up function for the current test scope.
44 Function _setUpForGroup;
45
46 /// The user-provided tear-down function for the current test scope.
47 Function _tearDownForGroup;
48
49 /// Creates a new test case with the given description and body.
50 ///
51 /// This has the same semantics as [unittest.test].
52 ///
53 /// If [body] returns a [Future], that future will automatically be wrapped with
54 /// [wrapFuture].
55 void test(String description, body()) =>
56 _test(description, body, unittest.test);
57
58 /// Creates a new test case with the given description and body that will be the
59 /// only test run in this file.
60 ///
61 /// This has the same semantics as [unittest.solo_test].
62 ///
63 /// If [body] returns a [Future], that future will automatically be wrapped with
64 /// [wrapFuture].
65 void solo_test(String description, body()) =>
66 _test(description, body, unittest.solo_test);
67
68 void _test(String description, body(), Function testFn) {
69 maybeWrapFuture(future, description) {
70 if (future != null) wrapFuture(future, description);
71 }
72
73 unittest.ensureInitialized();
74 _initializeForGroup();
75 testFn(description, () {
76 var completer = new Completer();
77
78 // Capture this in a local variable in case we capture an out-of-band error
79 // after the schedule completes.
80 var errorHandler;
81
82 Chain.capture(() {
83 _currentSchedule = new Schedule();
84 errorHandler = _currentSchedule.signalError;
85 return currentSchedule.run(() {
86 if (_setUpFn != null) maybeWrapFuture(_setUpFn(), "set up");
87 maybeWrapFuture(body(), "test body");
88 if (_tearDownFn != null) maybeWrapFuture(_tearDownFn(), "tear down");
89 }).catchError((error, stackTrace) {
90 if (error is ScheduleError) {
91 assert(error.schedule.errors.contains(error));
92 assert(error.schedule == currentSchedule);
93 unittest.registerException(error.schedule.errorString());
94 } else {
95 unittest.registerException(error, new Chain.forTrace(stackTrace));
96 }
97 }).then(completer.complete);
98 }, onError: (error, stackTrace) => errorHandler(error, stackTrace));
99
100 return completer.future;
101 });
102 }
103
104 /// Whether or not the tests currently being defined are in a group. This is
105 /// only true when defining tests, not when executing them.
106 bool _inGroup = false;
107
108 /// Creates a new named group of tests. This has the same semantics as
109 /// [unittest.group].
110 void group(String description, void body()) {
111 unittest.ensureInitialized();
112 _initializeForGroup();
113 unittest.group(description, () {
114 var oldSetUp = _setUpForGroup;
115 var oldTearDown = _tearDownForGroup;
116 var wasInitializedForGroup = _initializedForGroup;
117 var wasInGroup = _inGroup;
118 _setUpForGroup = null;
119 _tearDownForGroup = null;
120 _initializedForGroup = false;
121 _inGroup = true;
122 body();
123 _setUpForGroup = oldSetUp;
124 _tearDownForGroup = oldTearDown;
125 _initializedForGroup = wasInitializedForGroup;
126 _inGroup = wasInGroup;
127 });
128 }
129
130 /// Schedules a task, [fn], to run asynchronously as part of the main task queue
131 /// of [currentSchedule]. Tasks will be run in the order they're scheduled. If
132 /// [fn] returns a [Future], tasks after it won't be run until that [Future]
133 /// completes.
134 ///
135 /// The return value will be completed once the scheduled task has finished
136 /// running. Its return value is the same as the return value of [fn], or the
137 /// value it completes to if it's a [Future].
138 ///
139 /// If [description] is passed, it's used to describe the task for debugging
140 /// purposes when an error occurs.
141 ///
142 /// If this is called when a task queue is currently running, it will run [fn]
143 /// on the next event loop iteration rather than adding it to a queue. The
144 /// current task will not complete until [fn] (and any [Future] it returns) has
145 /// finished running. Any errors in [fn] will automatically be handled.
146 Future schedule(fn(), [String description]) =>
147 currentSchedule.tasks.schedule(fn, description);
148
149 /// Register a [setUp] function for a test [group].
150 ///
151 /// This has the same semantics as [unittest.setUp]. Tasks may be scheduled
152 /// using [schedule] within [setUpFn], and [currentSchedule] may be accessed as
153 /// well.
154 void setUp(setUpFn()) {
155 _setUpForGroup = setUpFn;
156 }
157
158 /// Register a [tearDown] function for a test [group].
159 ///
160 /// This has the same semantics as [unittest.tearDown]. Tasks may be scheduled
161 /// using [schedule] within [tearDownFn], and [currentSchedule] may be accessed
162 /// as well. Note that [tearDownFn] will be run synchronously after the test
163 /// body finishes running, which means it will run before any scheduled tasks
164 /// have begun.
165 ///
166 /// To run code after the schedule has finished running, use
167 /// `currentSchedule.onComplete.schedule`.
168 void tearDown(tearDownFn()) {
169 _tearDownForGroup = tearDownFn;
170 }
171
172 /// Whether [_initializeForGroup] has been called in this group scope.
173 bool _initializedForGroup = false;
174
175 /// Registers callbacks for [unittest.setUp] and [unittest.tearDown] that set up
176 /// and tear down the scheduled test infrastructure and run the user's [setUp]
177 /// and [tearDown] callbacks.
178 void _initializeForGroup() {
179 if (_initializedForGroup) return;
180 _initializedForGroup = true;
181
182 var setUpFn = _setUpForGroup;
183 var tearDownFn = _tearDownForGroup;
184
185 if (_inGroup) {
186 unittest.setUp(() => _addSetUpTearDown(setUpFn, tearDownFn));
187 return;
188 }
189
190 var oldWrapAsync = unittest.wrapAsync;
191 unittest.setUp(() {
192 if (currentSchedule != null) {
193 throw new StateError('There seems to be another scheduled test '
194 'still running.');
195 }
196
197 unittest.wrapAsync = (f, [description]) {
198 // It's possible that this setup is run before a vanilla unittest test
199 // if [unittest.test] is run in the same context as
200 // [scheduled_test.test]. In that case, [currentSchedule] will never be
201 // set and we should forward to the [unittest.wrapAsync].
202 if (currentSchedule == null) return oldWrapAsync(f, description);
203 return currentSchedule.wrapAsync(f, description);
204 };
205
206 _addSetUpTearDown(setUpFn, tearDownFn);
207 });
208
209 unittest.tearDown(() {
210 unittest.wrapAsync = oldWrapAsync;
211 _currentSchedule = null;
212 _setUpFn = null;
213 _tearDownFn = null;
214 });
215 }
216
217 /// Set [_setUpFn] and [_tearDownFn] appropriately.
218 void _addSetUpTearDown(void setUpFn(), void tearDownFn()) {
219 if (setUpFn != null) {
220 if (_setUpFn != null) {
221 var parentFn = _setUpFn;
222 _setUpFn = () { parentFn(); setUpFn(); };
223 } else {
224 _setUpFn = setUpFn;
225 }
226 }
227
228 if (tearDownFn != null) {
229 if (_tearDownFn != null) {
230 var parentFn = _tearDownFn;
231 _tearDownFn = () { parentFn(); tearDownFn(); };
232 } else {
233 _tearDownFn = tearDownFn;
234 }
235 }
236 }
237
238 /// Like [wrapAsync], this ensures that the current task queue waits for
239 /// out-of-band asynchronous code, and that errors raised in that code are
240 /// handled correctly. However, [wrapFuture] wraps a [Future] chain rather than
241 /// a single callback.
242 ///
243 /// The returned [Future] completes to the same value or error as [future].
244 ///
245 /// [description] provides an optional description of the future, which is
246 /// used when generating error messages.
247 Future wrapFuture(Future future, [String description]) {
248 if (currentSchedule == null) {
249 throw new StateError("Unexpected call to wrapFuture with no current "
250 "schedule.");
251 }
252
253 return currentSchedule.wrapFuture(future, description);
254 }
OLDNEW
« no previous file with comments | « pkg/scheduled_test/lib/scheduled_stream.dart ('k') | pkg/scheduled_test/lib/src/descriptor/async_descriptor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698