|
1 | 1 | use std::io::{self, BufRead, Read, Result, Write};
|
2 |
| -#[cfg(feature = "test")] |
3 |
| -use std::{ |
4 |
| - io::Cursor, |
5 |
| - sync::{Arc, Mutex, MutexGuard}, |
6 |
| -}; |
7 | 2 |
|
8 | 3 | use enum_dispatch::enum_dispatch;
|
9 | 4 |
|
| 5 | +#[cfg(feature = "test")] |
| 6 | +pub(crate) use self::tests::*; |
10 | 7 | use super::terminalsource::{ColorableTerminal, StreamSelector};
|
11 | 8 | use crate::currentprocess::process;
|
12 | 9 |
|
@@ -45,58 +42,6 @@ impl StdinSource for super::OSProcess {
|
45 | 42 | }
|
46 | 43 | }
|
47 | 44 |
|
48 |
| -// ----------------------- test support for stdin ------------------ |
49 |
| - |
50 |
| -#[cfg(feature = "test")] |
51 |
| -struct TestStdinLock<'a> { |
52 |
| - inner: MutexGuard<'a, Cursor<String>>, |
53 |
| -} |
54 |
| - |
55 |
| -#[cfg(feature = "test")] |
56 |
| -impl StdinLock for TestStdinLock<'_> {} |
57 |
| - |
58 |
| -#[cfg(feature = "test")] |
59 |
| -impl Read for TestStdinLock<'_> { |
60 |
| - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
61 |
| - self.inner.read(buf) |
62 |
| - } |
63 |
| -} |
64 |
| - |
65 |
| -#[cfg(feature = "test")] |
66 |
| -impl BufRead for TestStdinLock<'_> { |
67 |
| - fn fill_buf(&mut self) -> io::Result<&[u8]> { |
68 |
| - self.inner.fill_buf() |
69 |
| - } |
70 |
| - fn consume(&mut self, n: usize) { |
71 |
| - self.inner.consume(n) |
72 |
| - } |
73 |
| -} |
74 |
| - |
75 |
| -#[cfg(feature = "test")] |
76 |
| -pub(crate) type TestStdinInner = Arc<Mutex<Cursor<String>>>; |
77 |
| - |
78 |
| -#[cfg(feature = "test")] |
79 |
| -struct TestStdin(TestStdinInner); |
80 |
| - |
81 |
| -#[cfg(feature = "test")] |
82 |
| -impl Stdin for TestStdin { |
83 |
| - fn lock(&self) -> Box<dyn StdinLock + '_> { |
84 |
| - Box::new(TestStdinLock { |
85 |
| - inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
86 |
| - }) |
87 |
| - } |
88 |
| - fn read_line(&self, buf: &mut String) -> Result<usize> { |
89 |
| - self.lock().read_line(buf) |
90 |
| - } |
91 |
| -} |
92 |
| - |
93 |
| -#[cfg(feature = "test")] |
94 |
| -impl StdinSource for super::TestProcess { |
95 |
| - fn stdin(&self) -> Box<dyn Stdin> { |
96 |
| - Box::new(TestStdin(self.stdin.clone())) |
97 |
| - } |
98 |
| -} |
99 |
| - |
100 | 45 | // -------------- stdout -------------------------------
|
101 | 46 |
|
102 | 47 | /// This is a stand-in for [`std::io::StdoutLock`] and [`std::io::StderrLock`].
|
@@ -187,81 +132,126 @@ impl StderrSource for super::OSProcess {
|
187 | 132 | }
|
188 | 133 | }
|
189 | 134 |
|
190 |
| -// ----------------------- test support for writers ------------------ |
191 |
| - |
192 | 135 | #[cfg(feature = "test")]
|
193 |
| -pub(super) struct TestWriterLock<'a> { |
194 |
| - inner: MutexGuard<'a, Vec<u8>>, |
195 |
| -} |
| 136 | +mod tests { |
| 137 | + use std::{ |
| 138 | + io::Cursor, |
| 139 | + sync::{Arc, Mutex, MutexGuard}, |
| 140 | + }; |
196 | 141 |
|
197 |
| -#[cfg(feature = "test")] |
198 |
| -impl WriterLock for TestWriterLock<'_> {} |
| 142 | + use super::{super::TestProcess, *}; |
199 | 143 |
|
200 |
| -#[cfg(feature = "test")] |
201 |
| -impl Write for TestWriterLock<'_> { |
202 |
| - fn write(&mut self, buf: &[u8]) -> Result<usize> { |
203 |
| - self.inner.write(buf) |
| 144 | + // ----------------------- test support for stdin ------------------ |
| 145 | + |
| 146 | + struct TestStdinLock<'a> { |
| 147 | + inner: MutexGuard<'a, Cursor<String>>, |
204 | 148 | }
|
205 | 149 |
|
206 |
| - fn flush(&mut self) -> Result<()> { |
207 |
| - Ok(()) |
| 150 | + impl StdinLock for TestStdinLock<'_> {} |
| 151 | + |
| 152 | + impl Read for TestStdinLock<'_> { |
| 153 | + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 154 | + self.inner.read(buf) |
| 155 | + } |
208 | 156 | }
|
209 |
| -} |
210 | 157 |
|
211 |
| -#[cfg(feature = "test")] |
212 |
| -pub(super) type TestWriterInner = Arc<Mutex<Vec<u8>>>; |
213 |
| -/// A thread-safe test file handle that pretends to be e.g. stdout. |
214 |
| -#[derive(Clone, Default)] |
215 |
| -#[cfg(feature = "test")] |
216 |
| -pub(super) struct TestWriter(TestWriterInner); |
| 158 | + impl BufRead for TestStdinLock<'_> { |
| 159 | + fn fill_buf(&mut self) -> io::Result<&[u8]> { |
| 160 | + self.inner.fill_buf() |
| 161 | + } |
| 162 | + fn consume(&mut self, n: usize) { |
| 163 | + self.inner.consume(n) |
| 164 | + } |
| 165 | + } |
217 | 166 |
|
218 |
| -#[cfg(feature = "test")] |
219 |
| -impl TestWriter { |
220 |
| - pub(super) fn lock(&self) -> TestWriterLock<'_> { |
221 |
| - // The stream can be locked even if a test thread panicked: its state |
222 |
| - // will be ok |
223 |
| - TestWriterLock { |
224 |
| - inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
| 167 | + pub(crate) type TestStdinInner = Arc<Mutex<Cursor<String>>>; |
| 168 | + |
| 169 | + struct TestStdin(TestStdinInner); |
| 170 | + |
| 171 | + impl Stdin for TestStdin { |
| 172 | + fn lock(&self) -> Box<dyn StdinLock + '_> { |
| 173 | + Box::new(TestStdinLock { |
| 174 | + inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
| 175 | + }) |
| 176 | + } |
| 177 | + fn read_line(&self, buf: &mut String) -> Result<usize> { |
| 178 | + self.lock().read_line(buf) |
225 | 179 | }
|
226 | 180 | }
|
227 |
| -} |
228 | 181 |
|
229 |
| -#[cfg(feature = "test")] |
230 |
| -impl Writer for TestWriter { |
231 |
| - fn is_a_tty(&self) -> bool { |
232 |
| - false |
| 182 | + impl StdinSource for TestProcess { |
| 183 | + fn stdin(&self) -> Box<dyn Stdin> { |
| 184 | + Box::new(TestStdin(self.stdin.clone())) |
| 185 | + } |
233 | 186 | }
|
234 | 187 |
|
235 |
| - fn lock(&self) -> Box<dyn WriterLock + '_> { |
236 |
| - Box::new(self.lock()) |
| 188 | + // ----------------------- test support for writers ------------------ |
| 189 | + |
| 190 | + pub(in super::super) struct TestWriterLock<'a> { |
| 191 | + inner: MutexGuard<'a, Vec<u8>>, |
237 | 192 | }
|
238 | 193 |
|
239 |
| - fn terminal(&self) -> ColorableTerminal { |
240 |
| - ColorableTerminal::new(StreamSelector::TestWriter(self.clone())) |
| 194 | + impl WriterLock for TestWriterLock<'_> {} |
| 195 | + |
| 196 | + impl Write for TestWriterLock<'_> { |
| 197 | + fn write(&mut self, buf: &[u8]) -> Result<usize> { |
| 198 | + self.inner.write(buf) |
| 199 | + } |
| 200 | + |
| 201 | + fn flush(&mut self) -> Result<()> { |
| 202 | + Ok(()) |
| 203 | + } |
241 | 204 | }
|
242 |
| -} |
243 | 205 |
|
244 |
| -#[cfg(feature = "test")] |
245 |
| -impl Write for TestWriter { |
246 |
| - fn write(&mut self, buf: &[u8]) -> Result<usize> { |
247 |
| - self.lock().write(buf) |
| 206 | + pub(in super::super) type TestWriterInner = Arc<Mutex<Vec<u8>>>; |
| 207 | + |
| 208 | + /// A thread-safe test file handle that pretends to be e.g. stdout. |
| 209 | + #[derive(Clone, Default)] |
| 210 | + pub(in super::super) struct TestWriter(TestWriterInner); |
| 211 | + |
| 212 | + impl TestWriter { |
| 213 | + pub(in super::super) fn lock(&self) -> TestWriterLock<'_> { |
| 214 | + // The stream can be locked even if a test thread panicked: its state |
| 215 | + // will be ok |
| 216 | + TestWriterLock { |
| 217 | + inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
| 218 | + } |
| 219 | + } |
248 | 220 | }
|
249 | 221 |
|
250 |
| - fn flush(&mut self) -> Result<()> { |
251 |
| - Ok(()) |
| 222 | + impl Writer for TestWriter { |
| 223 | + fn is_a_tty(&self) -> bool { |
| 224 | + false |
| 225 | + } |
| 226 | + |
| 227 | + fn lock(&self) -> Box<dyn WriterLock + '_> { |
| 228 | + Box::new(self.lock()) |
| 229 | + } |
| 230 | + |
| 231 | + fn terminal(&self) -> ColorableTerminal { |
| 232 | + ColorableTerminal::new(StreamSelector::TestWriter(self.clone())) |
| 233 | + } |
252 | 234 | }
|
253 |
| -} |
254 | 235 |
|
255 |
| -#[cfg(feature = "test")] |
256 |
| -impl StdoutSource for super::TestProcess { |
257 |
| - fn stdout(&self) -> Box<dyn Writer> { |
258 |
| - Box::new(TestWriter(self.stdout.clone())) |
| 236 | + impl Write for TestWriter { |
| 237 | + fn write(&mut self, buf: &[u8]) -> Result<usize> { |
| 238 | + self.lock().write(buf) |
| 239 | + } |
| 240 | + |
| 241 | + fn flush(&mut self) -> Result<()> { |
| 242 | + Ok(()) |
| 243 | + } |
259 | 244 | }
|
260 |
| -} |
261 | 245 |
|
262 |
| -#[cfg(feature = "test")] |
263 |
| -impl StderrSource for super::TestProcess { |
264 |
| - fn stderr(&self) -> Box<dyn Writer> { |
265 |
| - Box::new(TestWriter(self.stderr.clone())) |
| 246 | + impl StdoutSource for TestProcess { |
| 247 | + fn stdout(&self) -> Box<dyn Writer> { |
| 248 | + Box::new(TestWriter(self.stdout.clone())) |
| 249 | + } |
| 250 | + } |
| 251 | + |
| 252 | + impl StderrSource for TestProcess { |
| 253 | + fn stderr(&self) -> Box<dyn Writer> { |
| 254 | + Box::new(TestWriter(self.stderr.clone())) |
| 255 | + } |
266 | 256 | }
|
267 | 257 | }
|
0 commit comments