1use std::borrow::Cow;
4use std::fmt;
5use std::sync::Arc;
6use std::sync::mpsc::Sender;
7
8pub use NamePadding::*;
9pub use TestFn::*;
10pub use TestName::*;
11
12use super::bench::Bencher;
13use super::event::CompletedTest;
14use super::{__rust_begin_short_backtrace, options};
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
19pub enum TestType {
20 UnitTest,
22 IntegrationTest,
24 DocTest,
26 Unknown,
29}
30
31#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
32pub enum NamePadding {
33 PadNone,
34 PadOnRight,
35}
36
37#[derive(Clone, PartialEq, Eq, Hash, Debug)]
42pub enum TestName {
43 StaticTestName(&'static str),
44 DynTestName(String),
45 AlignedTestName(Cow<'static, str>, NamePadding),
46}
47
48impl TestName {
49 pub fn as_slice(&self) -> &str {
50 match *self {
51 StaticTestName(s) => s,
52 DynTestName(ref s) => s,
53 AlignedTestName(ref s, _) => s,
54 }
55 }
56
57 pub fn padding(&self) -> NamePadding {
58 match self {
59 &AlignedTestName(_, p) => p,
60 _ => PadNone,
61 }
62 }
63
64 pub fn with_padding(&self, padding: NamePadding) -> TestName {
65 let name = match *self {
66 TestName::StaticTestName(name) => Cow::Borrowed(name),
67 TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
68 TestName::AlignedTestName(ref name, _) => name.clone(),
69 };
70
71 TestName::AlignedTestName(name, padding)
72 }
73}
74impl fmt::Display for TestName {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 fmt::Display::fmt(self.as_slice(), f)
77 }
78}
79
80#[derive(Clone)]
86pub enum TestFn {
87 StaticTestFn(fn() -> Result<(), String>),
88 StaticBenchFn(fn(&mut Bencher) -> Result<(), String>),
89 StaticBenchAsTestFn(fn(&mut Bencher) -> Result<(), String>),
90 DynTestFn(Arc<dyn Fn() -> Result<(), String> + Send + Sync>),
91 DynBenchFn(Arc<dyn Fn(&mut Bencher) -> Result<(), String> + Send + Sync>),
92 DynBenchAsTestFn(Arc<dyn Fn(&mut Bencher) -> Result<(), String> + Send + Sync>),
93}
94
95impl TestFn {
96 pub fn padding(&self) -> NamePadding {
97 match *self {
98 StaticTestFn(..) => PadNone,
99 StaticBenchFn(..) => PadOnRight,
100 StaticBenchAsTestFn(..) => PadNone,
101 DynTestFn(..) => PadNone,
102 DynBenchFn(..) => PadOnRight,
103 DynBenchAsTestFn(..) => PadNone,
104 }
105 }
106
107 pub(crate) fn into_runnable(self) -> Runnable {
108 match self {
109 StaticTestFn(f) => Runnable::Test(RunnableTest::Static(f)),
110 StaticBenchFn(f) => Runnable::Bench(RunnableBench::Static(f)),
111 StaticBenchAsTestFn(f) => Runnable::Test(RunnableTest::StaticBenchAsTest(f)),
112 DynTestFn(f) => Runnable::Test(RunnableTest::Dynamic(f)),
113 DynBenchFn(f) => Runnable::Bench(RunnableBench::Dynamic(f)),
114 DynBenchAsTestFn(f) => Runnable::Test(RunnableTest::DynamicBenchAsTest(f)),
115 }
116 }
117}
118
119impl fmt::Debug for TestFn {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str(match *self {
122 StaticTestFn(..) => "StaticTestFn(..)",
123 StaticBenchFn(..) => "StaticBenchFn(..)",
124 StaticBenchAsTestFn(..) => "StaticBenchAsTestFn(..)",
125 DynTestFn(..) => "DynTestFn(..)",
126 DynBenchFn(..) => "DynBenchFn(..)",
127 DynBenchAsTestFn(..) => "DynBenchAsTestFn(..)",
128 })
129 }
130}
131
132pub(crate) enum Runnable {
133 Test(RunnableTest),
134 Bench(RunnableBench),
135}
136
137pub(crate) enum RunnableTest {
138 Static(fn() -> Result<(), String>),
139 Dynamic(Arc<dyn Fn() -> Result<(), String> + Send + Sync>),
140 StaticBenchAsTest(fn(&mut Bencher) -> Result<(), String>),
141 DynamicBenchAsTest(Arc<dyn Fn(&mut Bencher) -> Result<(), String> + Send + Sync>),
142}
143
144impl RunnableTest {
145 pub(crate) fn run(self) -> Result<(), String> {
146 match self {
147 RunnableTest::Static(f) => __rust_begin_short_backtrace(f),
148 RunnableTest::Dynamic(f) => __rust_begin_short_backtrace(|| f()),
149 RunnableTest::StaticBenchAsTest(f) => {
150 crate::bench::run_once(|b| __rust_begin_short_backtrace(|| f(b)))
151 }
152 RunnableTest::DynamicBenchAsTest(f) => {
153 crate::bench::run_once(|b| __rust_begin_short_backtrace(|| f(b)))
154 }
155 }
156 }
157
158 pub(crate) fn is_dynamic(&self) -> bool {
159 match self {
160 RunnableTest::Static(_) => false,
161 RunnableTest::StaticBenchAsTest(_) => false,
162 RunnableTest::Dynamic(_) => true,
163 RunnableTest::DynamicBenchAsTest(_) => true,
164 }
165 }
166}
167
168pub(crate) enum RunnableBench {
169 Static(fn(&mut Bencher) -> Result<(), String>),
170 Dynamic(Arc<dyn Fn(&mut Bencher) -> Result<(), String> + Send + Sync>),
171}
172
173impl RunnableBench {
174 pub(crate) fn run(
175 self,
176 id: TestId,
177 desc: &TestDesc,
178 monitor_ch: &Sender<CompletedTest>,
179 nocapture: bool,
180 ) {
181 match self {
182 RunnableBench::Static(f) => {
183 crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, f)
184 }
185 RunnableBench::Dynamic(f) => {
186 crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, |b| f(b))
187 }
188 }
189 }
190}
191
192#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
194pub struct TestId(pub usize);
195
196#[derive(Clone, Debug)]
199pub struct TestDesc {
200 pub name: TestName,
201 pub ignore: bool,
202 pub ignore_message: Option<&'static str>,
203 pub source_file: &'static str,
204 pub start_line: usize,
205 pub start_col: usize,
206 pub end_line: usize,
207 pub end_col: usize,
208 pub should_panic: options::ShouldPanic,
209 pub compile_fail: bool,
210 pub no_run: bool,
211 pub test_type: TestType,
212}
213
214impl TestDesc {
215 pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
216 let mut name = String::from(self.name.as_slice());
217 let fill = column_count.saturating_sub(name.len());
218 let pad = " ".repeat(fill);
219 match align {
220 PadNone => name,
221 PadOnRight => {
222 name.push_str(&pad);
223 name
224 }
225 }
226 }
227
228 pub fn test_mode(&self) -> Option<&'static str> {
231 if self.ignore {
232 return None;
233 }
234 match self.should_panic {
235 options::ShouldPanic::Yes | options::ShouldPanic::YesWithMessage(_) => {
236 return Some("should panic");
237 }
238 options::ShouldPanic::No => {}
239 }
240 if self.compile_fail {
241 return Some("compile fail");
242 }
243 if self.no_run {
244 return Some("compile");
245 }
246 None
247 }
248}
249
250#[derive(Clone, Debug)]
251pub struct TestDescAndFn {
252 pub desc: TestDesc,
253 pub testfn: TestFn,
254}
255
256impl TestDescAndFn {
257 pub const fn new_doctest(
258 test_name: &'static str,
259 ignore: bool,
260 source_file: &'static str,
261 start_line: usize,
262 no_run: bool,
263 should_panic: bool,
264 testfn: TestFn,
265 ) -> Self {
266 Self {
267 desc: TestDesc {
268 name: StaticTestName(test_name),
269 ignore,
270 ignore_message: None,
271 source_file,
272 start_line,
273 start_col: 0,
274 end_line: 0,
275 end_col: 0,
276 compile_fail: false,
277 no_run,
278 should_panic: if should_panic {
279 options::ShouldPanic::Yes
280 } else {
281 options::ShouldPanic::No
282 },
283 test_type: TestType::DocTest,
284 },
285 testfn,
286 }
287 }
288}
289
290#[derive(Clone, Copy, Debug, PartialEq, Eq)]
295pub enum TestListOrder {
296 Sorted,
300 Unsorted,
302}
303
304#[derive(Debug)]
306pub struct TestList<'a> {
307 pub tests: &'a [&'a TestDescAndFn],
308 pub order: TestListOrder,
309}
310
311impl<'a> TestList<'a> {
312 pub fn new(tests: &'a [&'a TestDescAndFn], order: TestListOrder) -> Self {
313 Self { tests, order }
314 }
315}