|
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 |
|
@@ -45,58 +40,6 @@ impl StdinSource for super::OSProcess { |
45 | 40 | } |
46 | 41 | } |
47 | 42 |
|
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 | 43 | // -------------- stdout ------------------------------- |
101 | 44 |
|
102 | 45 | /// This is a stand-in for [`std::io::StdoutLock`] and [`std::io::StderrLock`]. |
@@ -187,81 +130,129 @@ impl StderrSource for super::OSProcess { |
187 | 130 | } |
188 | 131 | } |
189 | 132 |
|
190 | | -// ----------------------- test support for writers ------------------ |
191 | | - |
192 | 133 | #[cfg(feature = "test")] |
193 | | -pub(super) struct TestWriterLock<'a> { |
194 | | - inner: MutexGuard<'a, Vec<u8>>, |
195 | | -} |
| 134 | +pub(crate) use self::test_support::*; |
196 | 135 |
|
197 | 136 | #[cfg(feature = "test")] |
198 | | -impl WriterLock for TestWriterLock<'_> {} |
| 137 | +mod test_support { |
| 138 | + use std::{ |
| 139 | + io::Cursor, |
| 140 | + sync::{Arc, Mutex, MutexGuard}, |
| 141 | + }; |
199 | 142 |
|
200 | | -#[cfg(feature = "test")] |
201 | | -impl Write for TestWriterLock<'_> { |
202 | | - fn write(&mut self, buf: &[u8]) -> Result<usize> { |
203 | | - self.inner.write(buf) |
| 143 | + use super::{super::TestProcess, *}; |
| 144 | + |
| 145 | + // ----------------------- test support for stdin ------------------ |
| 146 | + |
| 147 | + struct TestStdinLock<'a> { |
| 148 | + inner: MutexGuard<'a, Cursor<String>>, |
204 | 149 | } |
205 | 150 |
|
206 | | - fn flush(&mut self) -> Result<()> { |
207 | | - Ok(()) |
| 151 | + impl StdinLock for TestStdinLock<'_> {} |
| 152 | + |
| 153 | + impl Read for TestStdinLock<'_> { |
| 154 | + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 155 | + self.inner.read(buf) |
| 156 | + } |
208 | 157 | } |
209 | | -} |
210 | 158 |
|
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); |
| 159 | + impl BufRead for TestStdinLock<'_> { |
| 160 | + fn fill_buf(&mut self) -> io::Result<&[u8]> { |
| 161 | + self.inner.fill_buf() |
| 162 | + } |
| 163 | + fn consume(&mut self, n: usize) { |
| 164 | + self.inner.consume(n) |
| 165 | + } |
| 166 | + } |
217 | 167 |
|
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()), |
| 168 | + pub(crate) type TestStdinInner = Arc<Mutex<Cursor<String>>>; |
| 169 | + |
| 170 | + struct TestStdin(TestStdinInner); |
| 171 | + |
| 172 | + impl Stdin for TestStdin { |
| 173 | + fn lock(&self) -> Box<dyn StdinLock + '_> { |
| 174 | + Box::new(TestStdinLock { |
| 175 | + inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
| 176 | + }) |
| 177 | + } |
| 178 | + fn read_line(&self, buf: &mut String) -> Result<usize> { |
| 179 | + self.lock().read_line(buf) |
225 | 180 | } |
226 | 181 | } |
227 | | -} |
228 | 182 |
|
229 | | -#[cfg(feature = "test")] |
230 | | -impl Writer for TestWriter { |
231 | | - fn is_a_tty(&self) -> bool { |
232 | | - false |
| 183 | + impl StdinSource for TestProcess { |
| 184 | + fn stdin(&self) -> Box<dyn Stdin> { |
| 185 | + Box::new(TestStdin(self.stdin.clone())) |
| 186 | + } |
233 | 187 | } |
234 | 188 |
|
235 | | - fn lock(&self) -> Box<dyn WriterLock + '_> { |
236 | | - Box::new(self.lock()) |
| 189 | + // ----------------------- test support for writers ------------------ |
| 190 | + |
| 191 | + pub(in super::super) struct TestWriterLock<'a> { |
| 192 | + inner: MutexGuard<'a, Vec<u8>>, |
237 | 193 | } |
238 | 194 |
|
239 | | - fn terminal(&self) -> ColorableTerminal { |
240 | | - ColorableTerminal::new(StreamSelector::TestWriter(self.clone())) |
| 195 | + impl WriterLock for TestWriterLock<'_> {} |
| 196 | + |
| 197 | + impl Write for TestWriterLock<'_> { |
| 198 | + fn write(&mut self, buf: &[u8]) -> Result<usize> { |
| 199 | + self.inner.write(buf) |
| 200 | + } |
| 201 | + |
| 202 | + fn flush(&mut self) -> Result<()> { |
| 203 | + Ok(()) |
| 204 | + } |
241 | 205 | } |
242 | | -} |
243 | 206 |
|
244 | | -#[cfg(feature = "test")] |
245 | | -impl Write for TestWriter { |
246 | | - fn write(&mut self, buf: &[u8]) -> Result<usize> { |
247 | | - self.lock().write(buf) |
| 207 | + pub(in super::super) type TestWriterInner = Arc<Mutex<Vec<u8>>>; |
| 208 | + |
| 209 | + /// A thread-safe test file handle that pretends to be e.g. stdout. |
| 210 | + #[derive(Clone, Default)] |
| 211 | + pub(in super::super) struct TestWriter(TestWriterInner); |
| 212 | + |
| 213 | + impl TestWriter { |
| 214 | + pub(in super::super) fn lock(&self) -> TestWriterLock<'_> { |
| 215 | + // The stream can be locked even if a test thread panicked: its state |
| 216 | + // will be ok |
| 217 | + TestWriterLock { |
| 218 | + inner: self.0.lock().unwrap_or_else(|e| e.into_inner()), |
| 219 | + } |
| 220 | + } |
248 | 221 | } |
249 | 222 |
|
250 | | - fn flush(&mut self) -> Result<()> { |
251 | | - Ok(()) |
| 223 | + impl Writer for TestWriter { |
| 224 | + fn is_a_tty(&self) -> bool { |
| 225 | + false |
| 226 | + } |
| 227 | + |
| 228 | + fn lock(&self) -> Box<dyn WriterLock + '_> { |
| 229 | + Box::new(self.lock()) |
| 230 | + } |
| 231 | + |
| 232 | + fn terminal(&self) -> ColorableTerminal { |
| 233 | + ColorableTerminal::new(StreamSelector::TestWriter(self.clone())) |
| 234 | + } |
252 | 235 | } |
253 | | -} |
254 | 236 |
|
255 | | -#[cfg(feature = "test")] |
256 | | -impl StdoutSource for super::TestProcess { |
257 | | - fn stdout(&self) -> Box<dyn Writer> { |
258 | | - Box::new(TestWriter(self.stdout.clone())) |
| 237 | + impl Write for TestWriter { |
| 238 | + fn write(&mut self, buf: &[u8]) -> Result<usize> { |
| 239 | + self.lock().write(buf) |
| 240 | + } |
| 241 | + |
| 242 | + fn flush(&mut self) -> Result<()> { |
| 243 | + Ok(()) |
| 244 | + } |
259 | 245 | } |
260 | | -} |
261 | 246 |
|
262 | | -#[cfg(feature = "test")] |
263 | | -impl StderrSource for super::TestProcess { |
264 | | - fn stderr(&self) -> Box<dyn Writer> { |
265 | | - Box::new(TestWriter(self.stderr.clone())) |
| 247 | + impl StdoutSource for TestProcess { |
| 248 | + fn stdout(&self) -> Box<dyn Writer> { |
| 249 | + Box::new(TestWriter(self.stdout.clone())) |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + impl StderrSource for TestProcess { |
| 254 | + fn stderr(&self) -> Box<dyn Writer> { |
| 255 | + Box::new(TestWriter(self.stderr.clone())) |
| 256 | + } |
266 | 257 | } |
267 | 258 | } |
0 commit comments