OLD | NEW |
---|---|
(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 library scheduled_process_test; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:io'; | |
9 | |
10 import 'package:pathos/path.dart' as path; | |
11 import 'package:scheduled_test/scheduled_process.dart'; | |
12 import 'package:scheduled_test/scheduled_test.dart'; | |
13 import 'package:scheduled_test/src/mock_clock.dart' as mock_clock; | |
14 | |
15 import 'metatest.dart'; | |
16 import 'utils.dart'; | |
17 | |
18 ServerSocket backChannel; | |
19 | |
20 void main() { | |
21 expectTestsPass("a process must have kill() or shouldExit() called", () { | |
22 var errors; | |
23 test('test 1', () { | |
24 currentSchedule.onException.schedule(() { | |
25 errors = currentSchedule.errors; | |
26 }); | |
27 | |
28 startDartProcess('print("hello!");'); | |
29 }); | |
30 | |
31 test('test 2', () { | |
32 expect(errors, everyElement(new isInstanceOf<ScheduleError>())); | |
33 expect(errors.length, equals(1)); | |
34 expect(errors.first.error, isStateError); | |
35 expect(errors.first.error.message, matches(r"^Scheduled process " | |
36 r"'[^']+[\\/]dart' must have shouldExit\(\) or kill\(\) called " | |
37 r"before the test is run\.$")); | |
38 }); | |
39 }, passing: ['test 2']); | |
40 | |
41 expectTestsPass("a process exits with the expected exit code", () { | |
42 test('exit code 0', () { | |
43 var process = startDartProcess('exitCode = 0;'); | |
44 process.shouldExit(0); | |
45 }); | |
46 | |
47 test('exit code 42', () { | |
48 var process = startDartProcess('exitCode = 42;'); | |
49 process.shouldExit(42); | |
50 }); | |
51 }); | |
52 | |
53 expectTestsPass("a process exiting with an unexpected exit code should cause " | |
54 "an error", () { | |
55 var errors; | |
56 test('test 1', () { | |
57 currentSchedule.onException.schedule(() { | |
58 errors = currentSchedule.errors; | |
59 }); | |
60 | |
61 var process = startDartProcess('exitCode = 1;'); | |
62 process.shouldExit(0); | |
63 }); | |
64 | |
65 test('test 2', () { | |
66 expect(errors, everyElement(new isInstanceOf<ScheduleError>())); | |
67 expect(errors.length, equals(1)); | |
68 expect(errors.first.error, new isInstanceOf<TestFailure>()); | |
69 }); | |
70 }, passing: ['test 2']); | |
71 | |
72 expectTestsPass("a killed process doesn't care about its exit code", () { | |
73 test('exit code 0', () { | |
74 var process = startDartProcess('exitCode = 0;'); | |
75 process.kill(); | |
76 }); | |
77 | |
78 test('exit code 1', () { | |
79 var process = startDartProcess('exitCode = 1;'); | |
80 process.kill(); | |
81 }); | |
82 }); | |
83 | |
84 expectTestsPass("a killed process stops running", () { | |
85 test('test', () { | |
86 var process = startDartProcess('while (true);'); | |
87 process.kill(); | |
88 }); | |
89 }); | |
90 | |
91 expectTestsPass("kill can't be called twice", () { | |
92 test('test', () { | |
93 var process = startDartProcess(''); | |
94 process.kill(); | |
95 expect(process.kill, throwsA(isStateError)); | |
96 }); | |
97 }); | |
98 | |
99 expectTestsPass("kill can't be called after shouldExit", () { | |
100 test('test', () { | |
101 var process = startDartProcess(''); | |
102 process.shouldExit(0); | |
103 expect(process.kill, throwsA(isStateError)); | |
104 }); | |
105 }); | |
106 | |
107 expectTestsPass("shouldExit can't be called twice", () { | |
108 test('test', () { | |
109 var process = startDartProcess(''); | |
110 process.shouldExit(0); | |
111 expect(() => process.shouldExit(0), throwsA(isStateError)); | |
112 }); | |
113 }); | |
114 | |
115 expectTestsPass("shouldExit can't be called after kill", () { | |
116 test('test', () { | |
117 var process = startDartProcess(''); | |
118 process.kill(); | |
119 expect(() => process.shouldExit(0), throwsA(isStateError)); | |
120 }); | |
121 }); | |
122 | |
123 expectTestsPass("a process that ends while waiting for stdout shouldn't " | |
124 "block the test", () { | |
125 var errors; | |
126 test('test 1', () { | |
127 currentSchedule.onException.schedule(() { | |
128 errors = currentSchedule.errors; | |
129 }); | |
130 | |
131 var process = startDartProcess(''); | |
132 expect(process.nextLine(), completion(equals('hello'))); | |
133 expect(process.nextLine(), completion(equals('world'))); | |
134 process.shouldExit(0); | |
135 }); | |
136 | |
137 test('test 2', () { | |
138 expect(errors, everyElement(new isInstanceOf<ScheduleError>())); | |
139 expect(errors.length, equals(2)); | |
140 expect(errors[0].error, isStateError); | |
141 expect(errors[0].error.message, equals("No elements")); | |
142 expect(errors[1].error, matches(r"^Process '[^']+[\\/]dart [^']+' ended " | |
143 r"earlier than scheduled with exit code 0\.")); | |
144 }); | |
145 }, passing: ['test 2']); | |
146 | |
147 expectTestsPass("a process that ends during the task immediately before it's " | |
148 "scheduled to end shouldn't cause an error", () { | |
149 test('test', () { | |
150 var process = startDartProcess('stdin.toList();'); | |
151 process.closeStdin(); | |
152 // Unfortunately, sleeping for a second seems like the best way of | |
153 // guaranteeing that the process ends during this task. | |
154 schedule(() => new Future.delayed(new Duration(seconds: 1))); | |
155 process.shouldExit(0); | |
156 }); | |
157 }); | |
158 | |
159 expectTestsPass("nextLine returns the next line of stdout from the process", | |
160 () { | |
161 test('test', () { | |
162 var process = startDartProcess(r'print("hello\n\nworld"); print("hi");'); | |
163 expect(process.nextLine(), completion(equals('hello'))); | |
164 expect(process.nextLine(), completion(equals(''))); | |
165 expect(process.nextLine(), completion(equals('world'))); | |
166 expect(process.nextLine(), completion(equals('hi'))); | |
167 process.shouldExit(0); | |
168 }); | |
169 }); | |
170 | |
171 expectTestsPass("nextLine throws an error if there's no more stdout", () { | |
172 var errors; | |
173 test('test 1', () { | |
174 currentSchedule.onException.schedule(() { | |
175 errors = currentSchedule.errors; | |
176 }); | |
177 | |
178 var process = startDartProcess('print("hello");'); | |
179 expect(process.nextLine(), completion(equals('hello'))); | |
180 expect(process.nextLine(), completion(equals('world'))); | |
181 process.shouldExit(0); | |
182 }); | |
183 | |
184 test('test 2', () { | |
185 expect(errors, everyElement(new isInstanceOf<ScheduleError>())); | |
186 expect(errors.length, equals(2)); | |
187 expect(errors[0].error, isStateError); | |
188 expect(errors[0].error.message, equals("No elements")); | |
189 expect(errors[1].error, matches(r"^Process '[^']+[\\/]dart [^']+' ended " | |
190 r"earlier than scheduled with exit code 0\.")); | |
191 }); | |
192 }, passing: ['test 2']); | |
193 | |
194 expectTestsPass("nextErrLine returns the next line of stderr from the " | |
195 "process", () { | |
196 test('test', () { | |
197 var process = startDartProcess(r''' | |
198 stderr.addString("hello\n\nworld\n"); | |
199 stderr.addString("hi"); | |
200 '''); | |
201 expect(process.nextErrLine(), completion(equals('hello'))); | |
202 expect(process.nextErrLine(), completion(equals(''))); | |
203 expect(process.nextErrLine(), completion(equals('world'))); | |
204 expect(process.nextErrLine(), completion(equals('hi'))); | |
205 process.shouldExit(0); | |
206 }); | |
207 }); | |
208 | |
209 expectTestsPass("nextErrLine throws an error if there's no more stderr", () { | |
210 var errors; | |
211 test('test 1', () { | |
212 currentSchedule.onException.schedule(() { | |
213 errors = currentSchedule.errors; | |
214 }); | |
215 | |
216 var process = startDartProcess(r'stderr.addString("hello\n");'); | |
217 expect(process.nextErrLine(), completion(equals('hello'))); | |
218 expect(process.nextErrLine(), completion(equals('world'))); | |
219 process.shouldExit(0); | |
220 }); | |
221 | |
222 test('test 2', () { | |
223 expect(errors, everyElement(new isInstanceOf<ScheduleError>())); | |
224 expect(errors.length, equals(2)); | |
225 expect(errors[0].error, isStateError); | |
226 expect(errors[0].error.message, equals("No elements")); | |
227 expect(errors[1].error, matches(r"^Process '[^']+[\\/]dart [^']+' ended " | |
228 r"earlier than scheduled with exit code 0\.")); | |
229 }); | |
230 }, passing: ['test 2']); | |
231 | |
232 expectTestsPass("remainingStdout returns all the stdout if it's not consumed " | |
233 "any other way", () { | |
234 test('test', () { | |
235 var process = startDartProcess(r'print("hello\n\nworld"); print("hi");'); | |
236 process.shouldExit(0); | |
237 expect(process.remainingStdout(), | |
238 completion(equals("hello\n\nworld\nhi"))); | |
239 }); | |
240 }); | |
241 | |
242 expectTestsPass("remainingStdout returns the empty string if there's no " | |
243 "stdout", () { | |
244 test('test', () { | |
245 var process = startDartProcess(r''); | |
246 process.shouldExit(0); | |
247 expect(process.remainingStdout(), completion(isEmpty)); | |
248 }); | |
249 }); | |
250 | |
251 expectTestsPass("remainingStdout returns the remaining stdout after the " | |
252 "lines consumed by nextLine", () { | |
253 test('test', () { | |
254 var process = startDartProcess(r'print("hello\n\nworld"); print("hi");'); | |
255 expect(process.nextLine(), completion(equals("hello"))); | |
256 expect(process.nextLine(), completion(equals(""))); | |
257 process.shouldExit(0); | |
258 expect(process.remainingStdout(), completion(equals("world\nhi"))); | |
259 }); | |
260 }); | |
261 | |
262 expectTestsPass("remainingStdout can't be called before the process is " | |
263 "scheduled to end", () { | |
264 test('test', () { | |
265 var process = startDartProcess(r''); | |
266 expect(process.remainingStdout, throwsA(isStateError)); | |
267 process.shouldExit(0); | |
268 }); | |
269 }); | |
270 | |
271 expectTestsPass("remainingStderr returns all the stderr if it's not consumed " | |
272 "any other way", () { | |
273 test('test', () { | |
274 var process = startDartProcess(r''' | |
275 stderr.addString("hello\n\nworld\n"); | |
276 stderr.addString("hi\n"); | |
277 '''); | |
278 process.shouldExit(0); | |
279 expect(process.remainingStderr(), | |
280 completion(equals("hello\n\nworld\nhi"))); | |
281 }); | |
282 }); | |
283 | |
284 expectTestsPass("remainingStderr returns the empty string if there's no " | |
285 "stderr", () { | |
286 test('test', () { | |
287 var process = startDartProcess(r''); | |
288 process.shouldExit(0); | |
289 expect(process.remainingStderr(), completion(isEmpty)); | |
290 }); | |
291 }); | |
292 | |
293 expectTestsPass("remainingStderr returns the remaining stderr after the " | |
294 "lines consumed by nextLine", () { | |
295 test('test', () { | |
296 var process = startDartProcess(r''' | |
297 stderr.addString("hello\n\nworld\n"); | |
298 stderr.addString("hi\n"); | |
299 '''); | |
300 expect(process.nextErrLine(), completion(equals("hello"))); | |
301 expect(process.nextErrLine(), completion(equals(""))); | |
302 process.shouldExit(0); | |
303 expect(process.remainingStderr(), completion(equals("world\nhi"))); | |
304 }); | |
305 }); | |
306 | |
307 expectTestsPass("remainingStderr can't be called before the process is " | |
308 "scheduled to end", () { | |
309 test('test', () { | |
310 var process = startDartProcess(r''); | |
311 expect(process.remainingStderr, throwsA(isStateError)); | |
312 process.shouldExit(0); | |
313 }); | |
314 }); | |
315 | |
316 expectTestsPass("writeLine schedules a line to be written to the process", | |
317 () { | |
318 test('test', () { | |
319 var process = startDartProcess(r''' | |
320 stdinLines.listen((line) => print("> $line")); | |
321 '''); | |
322 process.writeLine("hello"); | |
323 expect(process.nextLine(), completion(equals("> hello"))); | |
324 process.writeLine("world"); | |
325 expect(process.nextLine(), completion(equals("> world"))); | |
326 process.kill(); | |
327 }); | |
328 }); | |
329 | |
330 expectTestsPass("closeStdin closes the process's stdin stream", () { | |
331 test('test', () { | |
332 currentSchedule.timeout = new Duration(seconds: 1); | |
333 var process = startDartProcess(r''' | |
334 stdin.listen((line) => print("> $line"), | |
335 onDone: () => print("stdin closed")); | |
336 '''); | |
337 process.closeStdin(); | |
338 process.shouldExit(0); | |
339 expect(process.nextLine(), completion(equals('stdin closed'))); | |
340 }); | |
341 }); | |
342 } | |
343 | |
344 ScheduledProcess startDartProcess(String script) { | |
345 var tempDir = schedule(() { | |
346 return new Directory('').createTemp().then((dir) => dir.path); | |
Bob Nystrom
2013/03/04 23:52:00
Create this synchronously.
nweiz
2013/03/05 02:16:09
Why? It wouldn't clean up the code at all.
Bob Nystrom
2013/03/05 17:35:06
Couldn't you save a schedule() step here and creat
nweiz
2013/03/08 22:38:09
No, we need to access it from multiple schedule bl
| |
347 }, 'create temp dir'); | |
348 | |
349 var dartPath = schedule(() { | |
350 return tempDir.then((dir) { | |
351 var utilsPath = path.absolute(path.join( | |
352 new Options().script, 'utils.dart')); | |
353 return new File(path.join(dir, 'test.dart')).writeAsString(''' | |
354 import 'dart:async'; | |
355 import 'dart:io'; | |
356 | |
357 var stdinLines = stdin | |
358 .transform(new StringDecoder()) | |
359 .transform(new LineTransformer()); | |
360 | |
361 void main() { | |
362 $script | |
363 } | |
364 ''').then((file) => file.path); | |
365 }); | |
366 }, 'write script file'); | |
367 | |
368 currentSchedule.onComplete.schedule(() { | |
369 return tempDir.catchError((_) => null).then((dir) { | |
370 if (dir == null) return; | |
371 return new Directory(dir).delete(recursive: true); | |
372 }); | |
373 }, 'clean up temp dir'); | |
374 | |
375 return new ScheduledProcess.start(dartExecutable, ['--checked', dartPath]); | |
376 } | |
OLD | NEW |