| 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_process; | 5 library scheduled_process; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'scheduled_test.dart'; | 10 import 'scheduled_test.dart'; |
| 11 import 'src/utils.dart'; | 11 import 'src/utils.dart'; |
| 12 import 'src/value_future.dart'; | 12 import 'src/value_future.dart'; |
| 13 | 13 |
| 14 /// A class representing a [Process] that is scheduled to run in the course of | 14 /// A class representing a [Process] that is scheduled to run in the course of |
| 15 /// the test. This class allows actions on the process to be scheduled | 15 /// the test. This class allows actions on the process to be scheduled |
| 16 /// synchronously. All operations on this class are scheduled. | 16 /// synchronously. All operations on this class are scheduled. |
| 17 /// | 17 /// |
| 18 /// Before running the test, either [shouldExit] or [kill] must be called on | 18 /// Before running the test, either [shouldExit] or [kill] must be called on |
| 19 /// this to ensure that the process terminates when expected. | 19 /// this to ensure that the process terminates when expected. |
| 20 /// | 20 /// |
| 21 /// If the test fails, this will automatically print out any stdout and stderr | 21 /// If the test fails, this will automatically print out any stdout and stderr |
| 22 /// from the process to aid debugging. | 22 /// from the process to aid debugging. |
| 23 class ScheduledProcess { | 23 class ScheduledProcess { |
| 24 // A description of the process. Used for error reporting. | 24 /// A description of the process. Used for error reporting. |
| 25 String get description => _description; | 25 String get description => _description; |
| 26 String _description; | 26 String _description; |
| 27 | 27 |
| 28 /// Whether a description was passed explicitly by the user. |
| 29 bool _explicitDescription; |
| 30 |
| 28 /// The encoding used for the process's input and output streams. | 31 /// The encoding used for the process's input and output streams. |
| 29 final Encoding _encoding; | 32 final Encoding _encoding; |
| 30 | 33 |
| 31 /// The process that's scheduled to run. | 34 /// The process that's scheduled to run. |
| 32 ValueFuture<Process> _process; | 35 ValueFuture<Process> _process; |
| 33 | 36 |
| 34 /// A fork of [_stdout] that records the standard output of the process. Used | 37 /// A fork of [_stdout] that records the standard output of the process. Used |
| 35 /// for debugging information. | 38 /// for debugging information. |
| 36 Stream<String> _stdoutLog; | 39 Stream<String> _stdoutLog; |
| 37 | 40 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 /// description of this process; it defaults to the command-line invocation. | 74 /// description of this process; it defaults to the command-line invocation. |
| 72 /// [encoding] is the [Encoding] that will be used for the process's input and | 75 /// [encoding] is the [Encoding] that will be used for the process's input and |
| 73 /// output. | 76 /// output. |
| 74 /// | 77 /// |
| 75 /// [executable], [arguments], and [options] may be either a [Future] or a | 78 /// [executable], [arguments], and [options] may be either a [Future] or a |
| 76 /// concrete value. If any are [Future]s, the process won't start until the | 79 /// concrete value. If any are [Future]s, the process won't start until the |
| 77 /// [Future]s have completed. In addition, [arguments] may be a [List] | 80 /// [Future]s have completed. In addition, [arguments] may be a [List] |
| 78 /// containing a mix of strings and [Future]s. | 81 /// containing a mix of strings and [Future]s. |
| 79 ScheduledProcess.start(executable, arguments, | 82 ScheduledProcess.start(executable, arguments, |
| 80 {options, String description, Encoding encoding: Encoding.UTF_8}) | 83 {options, String description, Encoding encoding: Encoding.UTF_8}) |
| 81 : _encoding = encoding { | 84 : _encoding = encoding, |
| 85 _explicitDescription = description != null, |
| 86 _description = description { |
| 82 assert(currentSchedule.state == ScheduleState.SET_UP); | 87 assert(currentSchedule.state == ScheduleState.SET_UP); |
| 83 | 88 |
| 84 _updateDescription(executable, arguments); | 89 _updateDescription(executable, arguments); |
| 85 | 90 |
| 86 _scheduleStartProcess(executable, arguments, options); | 91 _scheduleStartProcess(executable, arguments, options); |
| 87 | 92 |
| 88 _scheduleExceptionCleanup(); | 93 _scheduleExceptionCleanup(); |
| 89 | 94 |
| 90 var stdoutWithCanceller = _lineStreamWithCanceller( | 95 var stdoutWithCanceller = _lineStreamWithCanceller( |
| 91 _process.then((p) => p.stdout)); | 96 _process.then((p) => p.stdout)); |
| 92 _stdoutCanceller = stdoutWithCanceller.last; | 97 _stdoutCanceller = stdoutWithCanceller.last; |
| 93 var stdoutTee = tee(stdoutWithCanceller.first); | 98 var stdoutTee = tee(stdoutWithCanceller.first); |
| 94 _stdout = stdoutTee.first; | 99 _stdout = stdoutTee.first; |
| 95 _stdoutLog = stdoutTee.last; | 100 _stdoutLog = stdoutTee.last; |
| 96 | 101 |
| 97 var stderrWithCanceller = _lineStreamWithCanceller( | 102 var stderrWithCanceller = _lineStreamWithCanceller( |
| 98 _process.then((p) => p.stderr)); | 103 _process.then((p) => p.stderr)); |
| 99 _stderrCanceller = stderrWithCanceller.last; | 104 _stderrCanceller = stderrWithCanceller.last; |
| 100 var stderrTee = tee(stderrWithCanceller.first); | 105 var stderrTee = tee(stderrWithCanceller.first); |
| 101 _stderr = stderrTee.first; | 106 _stderr = stderrTee.first; |
| 102 _stderrLog = stderrTee.last; | 107 _stderrLog = stderrTee.last; |
| 103 } | 108 } |
| 104 | 109 |
| 105 /// Updates [_description] to reflect [executable] and [arguments], which are | 110 /// Updates [_description] to reflect [executable] and [arguments], which are |
| 106 /// the same values as in [start]. | 111 /// the same values as in [start]. |
| 107 void _updateDescription(executable, arguments) { | 112 void _updateDescription(executable, arguments) { |
| 113 if (_explicitDescription) return; |
| 108 if (executable is Future) { | 114 if (executable is Future) { |
| 109 _description = "future process"; | 115 _description = "future process"; |
| 110 } else if (arguments is Future || arguments.any((e) => e is Future)) { | 116 } else if (arguments is Future || arguments.any((e) => e is Future)) { |
| 111 _description = executable; | 117 _description = executable; |
| 112 } else { | 118 } else { |
| 113 _description = "$executable ${arguments.map((a) => '"$a"').join(' ')}"; | 119 _description = "$executable ${arguments.map((a) => '"$a"').join(' ')}"; |
| 114 } | 120 } |
| 115 } | 121 } |
| 116 | 122 |
| 117 /// Schedules the process to start and sets [_process]. | 123 /// Schedules the process to start and sets [_process]. |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 schedule(() { | 305 schedule(() { |
| 300 _endExpected = true; | 306 _endExpected = true; |
| 301 return _exitCode.then((exitCode) { | 307 return _exitCode.then((exitCode) { |
| 302 if (expectedExitCode != null) { | 308 if (expectedExitCode != null) { |
| 303 expect(exitCode, equals(expectedExitCode)); | 309 expect(exitCode, equals(expectedExitCode)); |
| 304 } | 310 } |
| 305 }); | 311 }); |
| 306 }, "waiting for process '$description' to exit"); | 312 }, "waiting for process '$description' to exit"); |
| 307 } | 313 } |
| 308 } | 314 } |
| OLD | NEW |