| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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 library scheduled_test.scheduled_process; | 5 library scheduled_test.scheduled_process; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 | 10 |
| 11 import 'package:stack_trace/stack_trace.dart'; | 11 import 'package:stack_trace/stack_trace.dart'; |
| 12 | 12 |
| 13 import 'scheduled_stream.dart'; |
| 13 import 'scheduled_test.dart'; | 14 import 'scheduled_test.dart'; |
| 14 import 'src/utils.dart'; | 15 import 'src/utils.dart'; |
| 15 import 'src/value_future.dart'; | 16 import 'src/value_future.dart'; |
| 16 | 17 |
| 17 /// A class representing a [Process] that is scheduled to run in the course of | 18 /// A class representing a [Process] that is scheduled to run in the course of |
| 18 /// the test. This class allows actions on the process to be scheduled | 19 /// the test. This class allows actions on the process to be scheduled |
| 19 /// synchronously. All operations on this class are scheduled. | 20 /// synchronously. All operations on this class are scheduled. |
| 20 /// | 21 /// |
| 21 /// Before running the test, either [shouldExit] or [kill] must be called on | 22 /// Before running the test, either [shouldExit] or [kill] must be called on |
| 22 /// this to ensure that the process terminates when expected. Note that [kill] | 23 /// this to ensure that the process terminates when expected. Note that [kill] |
| (...skipping 14 matching lines...) Expand all Loading... |
| 37 final Encoding _encoding; | 38 final Encoding _encoding; |
| 38 | 39 |
| 39 /// The process that's scheduled to run. | 40 /// The process that's scheduled to run. |
| 40 ValueFuture<Process> _process; | 41 ValueFuture<Process> _process; |
| 41 | 42 |
| 42 /// A fork of [_stdout] that records the standard output of the process. Used | 43 /// A fork of [_stdout] that records the standard output of the process. Used |
| 43 /// for debugging information. | 44 /// for debugging information. |
| 44 Stream<String> _stdoutLog; | 45 Stream<String> _stdoutLog; |
| 45 | 46 |
| 46 /// A line-by-line view of the standard output stream of the process. | 47 /// A line-by-line view of the standard output stream of the process. |
| 47 StreamIterator<String> _stdout; | 48 ScheduledStream<String> get stdout => _stdout; |
| 49 ScheduledStream<String> _stdout; |
| 48 | 50 |
| 49 /// A canceller that controls both [_stdout] and [_stdoutLog]. | 51 /// A canceller that controls both [_stdout] and [_stdoutLog]. |
| 50 StreamCanceller _stdoutCanceller; | 52 StreamCanceller _stdoutCanceller; |
| 51 | 53 |
| 52 /// A fork of [_stderr] that records the standard error of the process. Used | 54 /// A fork of [_stderr] that records the standard error of the process. Used |
| 53 /// for debugging information. | 55 /// for debugging information. |
| 54 Stream<String> _stderrLog; | 56 Stream<String> _stderrLog; |
| 55 | 57 |
| 56 /// A line-by-line view of the standard error stream of the process. | 58 /// A line-by-line view of the standard error stream of the process. |
| 57 StreamIterator<String> _stderr; | 59 ScheduledStream<String> get stderr => _stderr; |
| 60 ScheduledStream<String> _stderr; |
| 58 | 61 |
| 59 /// A canceller that controls both [_stderr] and [_stderrLog]. | 62 /// A canceller that controls both [_stderr] and [_stderrLog]. |
| 60 StreamCanceller _stderrCanceller; | 63 StreamCanceller _stderrCanceller; |
| 61 | 64 |
| 62 /// The exit code of the process that's scheduled to run. This will naturally | 65 /// The exit code of the process that's scheduled to run. This will naturally |
| 63 /// only complete once the process has terminated. | 66 /// only complete once the process has terminated. |
| 64 ValueFuture<int> _exitCode; | 67 ValueFuture<int> _exitCode; |
| 65 | 68 |
| 66 /// Whether the user has scheduled the end of this process by calling either | 69 /// Whether the user has scheduled the end of this process by calling either |
| 67 /// [shouldExit] or [kill]. | 70 /// [shouldExit] or [kill]. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 var stdoutWithCanceller = _lineStreamWithCanceller( | 108 var stdoutWithCanceller = _lineStreamWithCanceller( |
| 106 _process.then((p) => Chain.track(p.stdout))); | 109 _process.then((p) => Chain.track(p.stdout))); |
| 107 _stdoutCanceller = stdoutWithCanceller.last; | 110 _stdoutCanceller = stdoutWithCanceller.last; |
| 108 _stdoutLog = stdoutWithCanceller.first; | 111 _stdoutLog = stdoutWithCanceller.first; |
| 109 | 112 |
| 110 var stderrWithCanceller = _lineStreamWithCanceller( | 113 var stderrWithCanceller = _lineStreamWithCanceller( |
| 111 _process.then((p) => Chain.track(p.stderr))); | 114 _process.then((p) => Chain.track(p.stderr))); |
| 112 _stderrCanceller = stderrWithCanceller.last; | 115 _stderrCanceller = stderrWithCanceller.last; |
| 113 _stderrLog = stderrWithCanceller.first; | 116 _stderrLog = stderrWithCanceller.first; |
| 114 | 117 |
| 115 _stdout = new StreamIterator<String>(stdoutStream()); | 118 _stdout = new ScheduledStream<String>(stdoutStream()); |
| 116 _stderr = new StreamIterator<String>(stderrStream()); | 119 _stderr = new ScheduledStream<String>(stderrStream()); |
| 117 } | 120 } |
| 118 | 121 |
| 119 /// Updates [_description] to reflect [executable] and [arguments], which are | 122 /// Updates [_description] to reflect [executable] and [arguments], which are |
| 120 /// the same values as in [start]. | 123 /// the same values as in [start]. |
| 121 void _updateDescription(executable, arguments) { | 124 void _updateDescription(executable, arguments) { |
| 122 if (_explicitDescription) return; | 125 if (_explicitDescription) return; |
| 123 if (executable is Future) { | 126 if (executable is Future) { |
| 124 _description = "future process"; | 127 _description = "future process"; |
| 125 } else if (arguments is Future || arguments.any((e) => e is Future)) { | 128 } else if (arguments is Future || arguments.any((e) => e is Future)) { |
| 126 _description = executable; | 129 _description = executable; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 "Results of running '$description':\n" | 247 "Results of running '$description':\n" |
| 245 "$exitDescription\n" | 248 "$exitDescription\n" |
| 246 "Standard output:\n" | 249 "Standard output:\n" |
| 247 "${prefixLines(stdout)}\n" | 250 "${prefixLines(stdout)}\n" |
| 248 "Standard error:\n" | 251 "Standard error:\n" |
| 249 "${prefixLines(stderr)}"); | 252 "${prefixLines(stderr)}"); |
| 250 }); | 253 }); |
| 251 }, "cleaning up process '$description'"); | 254 }, "cleaning up process '$description'"); |
| 252 } | 255 } |
| 253 | 256 |
| 254 /// Reads the next line of stdout from the process. | |
| 255 Future<String> nextLine() => schedule(() => streamIteratorFirst(_stdout), | |
| 256 "reading the next stdout line from process '$description'"); | |
| 257 | |
| 258 /// Reads the next line of stderr from the process. | |
| 259 Future<String> nextErrLine() => schedule(() => streamIteratorFirst(_stderr), | |
| 260 "reading the next stderr line from process '$description'"); | |
| 261 | |
| 262 /// Reads the remaining stdout from the process. This should only be called | |
| 263 /// after kill() or shouldExit(). | |
| 264 Future<String> remainingStdout() { | |
| 265 if (!_endScheduled) { | |
| 266 throw new StateError("remainingStdout() should only be called after " | |
| 267 "kill() or shouldExit()."); | |
| 268 } | |
| 269 return schedule(() => concatRest(_stdout), | |
| 270 "reading the remaining stdout from process '$description'"); | |
| 271 } | |
| 272 | |
| 273 /// Reads the remaining stderr from the process. This should only be called | |
| 274 /// after kill() or shouldExit(). | |
| 275 Future<String> remainingStderr() { | |
| 276 if (!_endScheduled) { | |
| 277 throw new StateError("remainingStderr() should only be called after " | |
| 278 "kill() or shouldExit()."); | |
| 279 } | |
| 280 | |
| 281 return schedule(() => concatRest(_stderr), | |
| 282 "reading the remaining stderr from process '$description'"); | |
| 283 } | |
| 284 | |
| 285 /// Returns a stream that will emit anything the process emits via the | 257 /// Returns a stream that will emit anything the process emits via the |
| 286 /// process's standard output from now on. | 258 /// process's standard output from now on. |
| 287 /// | 259 /// |
| 288 /// This stream will be independent from any other methods that deal with | 260 /// This stream will be independent from any other methods that deal with |
| 289 /// standard output, including other calls to [stdoutStream]. | 261 /// standard output, including other calls to [stdoutStream]. |
| 290 /// | 262 /// |
| 291 /// This can be overridden by subclasses to return a derived standard output | 263 /// This can be overridden by subclasses to return a derived standard output |
| 292 /// stream. This stream will then be used for [nextLine], [nextErrLine], | 264 /// stream. This stream will then be used for [stdout] and [stderr]. |
| 293 /// [remainingStdout], and [remainingStderr]. | |
| 294 Stream<String> stdoutStream() { | 265 Stream<String> stdoutStream() { |
| 295 var pair = tee(_stdoutLog); | 266 var pair = tee(_stdoutLog); |
| 296 _stdoutLog = pair.first; | 267 _stdoutLog = pair.first; |
| 297 return pair.last; | 268 return pair.last; |
| 298 } | 269 } |
| 299 | 270 |
| 300 /// Returns a stream that will emit anything the process emits via the | 271 /// Returns a stream that will emit anything the process emits via the |
| 301 /// process's standard error from now on. | 272 /// process's standard error from now on. |
| 302 /// | 273 /// |
| 303 /// This stream will be independent from any other methods that deal with | 274 /// This stream will be independent from any other methods that deal with |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 schedule(() { | 316 schedule(() { |
| 346 return _exitCode.then((exitCode) { | 317 return _exitCode.then((exitCode) { |
| 347 if (expectedExitCode != null) { | 318 if (expectedExitCode != null) { |
| 348 expect(exitCode, equals(expectedExitCode)); | 319 expect(exitCode, equals(expectedExitCode)); |
| 349 } | 320 } |
| 350 }); | 321 }); |
| 351 }, "waiting for process '$description' to exit"); | 322 }, "waiting for process '$description' to exit"); |
| 352 _scheduledExitTask = currentSchedule.tasks.contents.last; | 323 _scheduledExitTask = currentSchedule.tasks.contents.last; |
| 353 } | 324 } |
| 354 } | 325 } |
| OLD | NEW |