Chromium Code Reviews| 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 |