]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | //! Common types used by `libtest`. |
2 | ||
3 | use std::borrow::Cow; | |
4 | use std::fmt; | |
5 | ||
6 | use super::bench::Bencher; | |
7 | use super::options; | |
8 | ||
9 | pub use NamePadding::*; | |
10 | pub use TestFn::*; | |
11 | pub use TestName::*; | |
12 | ||
13 | /// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) | |
14 | /// conventions. | |
15 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | |
16 | pub enum TestType { | |
17 | /// Unit-tests are expected to be in the `src` folder of the crate. | |
18 | UnitTest, | |
19 | /// Integration-style tests are expected to be in the `tests` folder of the crate. | |
20 | IntegrationTest, | |
21 | /// Doctests are created by the `librustdoc` manually, so it's a different type of test. | |
22 | DocTest, | |
23 | /// Tests for the sources that don't follow the project layout convention | |
24 | /// (e.g. tests in raw `main.rs` compiled by calling `rustc --test` directly). | |
25 | Unknown, | |
26 | } | |
27 | ||
28 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
29 | pub enum NamePadding { | |
30 | PadNone, | |
31 | PadOnRight, | |
32 | } | |
33 | ||
34 | // The name of a test. By convention this follows the rules for rust | |
35 | // paths; i.e., it should be a series of identifiers separated by double | |
36 | // colons. This way if some test runner wants to arrange the tests | |
37 | // hierarchically it may. | |
38 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
39 | pub enum TestName { | |
40 | StaticTestName(&'static str), | |
41 | DynTestName(String), | |
42 | AlignedTestName(Cow<'static, str>, NamePadding), | |
43 | } | |
44 | ||
45 | impl TestName { | |
46 | pub fn as_slice(&self) -> &str { | |
47 | match *self { | |
48 | StaticTestName(s) => s, | |
49 | DynTestName(ref s) => s, | |
50 | AlignedTestName(ref s, _) => &*s, | |
51 | } | |
52 | } | |
53 | ||
54 | pub fn padding(&self) -> NamePadding { | |
55 | match self { | |
56 | &AlignedTestName(_, p) => p, | |
57 | _ => PadNone, | |
58 | } | |
59 | } | |
60 | ||
61 | pub fn with_padding(&self, padding: NamePadding) -> TestName { | |
62 | let name = match *self { | |
63 | TestName::StaticTestName(name) => Cow::Borrowed(name), | |
64 | TestName::DynTestName(ref name) => Cow::Owned(name.clone()), | |
65 | TestName::AlignedTestName(ref name, _) => name.clone(), | |
66 | }; | |
67 | ||
68 | TestName::AlignedTestName(name, padding) | |
69 | } | |
70 | } | |
71 | impl fmt::Display for TestName { | |
72 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
73 | fmt::Display::fmt(self.as_slice(), f) | |
74 | } | |
75 | } | |
76 | ||
77 | /// Represents a benchmark function. | |
78 | pub trait TDynBenchFn: Send { | |
79 | fn run(&self, harness: &mut Bencher); | |
80 | } | |
81 | ||
82 | // A function that runs a test. If the function returns successfully, | |
83 | // the test succeeds; if the function panics then the test fails. We | |
84 | // may need to come up with a more clever definition of test in order | |
85 | // to support isolation of tests into threads. | |
86 | pub enum TestFn { | |
87 | StaticTestFn(fn()), | |
88 | StaticBenchFn(fn(&mut Bencher)), | |
89 | DynTestFn(Box<dyn FnOnce() + Send>), | |
90 | DynBenchFn(Box<dyn TDynBenchFn + 'static>), | |
91 | } | |
92 | ||
93 | impl TestFn { | |
94 | pub fn padding(&self) -> NamePadding { | |
95 | match *self { | |
96 | StaticTestFn(..) => PadNone, | |
97 | StaticBenchFn(..) => PadOnRight, | |
98 | DynTestFn(..) => PadNone, | |
99 | DynBenchFn(..) => PadOnRight, | |
100 | } | |
101 | } | |
102 | } | |
103 | ||
104 | impl fmt::Debug for TestFn { | |
105 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
106 | f.write_str(match *self { | |
107 | StaticTestFn(..) => "StaticTestFn(..)", | |
108 | StaticBenchFn(..) => "StaticBenchFn(..)", | |
109 | DynTestFn(..) => "DynTestFn(..)", | |
110 | DynBenchFn(..) => "DynBenchFn(..)", | |
111 | }) | |
112 | } | |
113 | } | |
114 | ||
115 | // The definition of a single test. A test runner will run a list of | |
116 | // these. | |
117 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | |
118 | pub struct TestDesc { | |
119 | pub name: TestName, | |
120 | pub ignore: bool, | |
121 | pub should_panic: options::ShouldPanic, | |
122 | pub allow_fail: bool, | |
123 | pub test_type: TestType, | |
124 | } | |
125 | ||
126 | impl TestDesc { | |
127 | pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String { | |
128 | let mut name = String::from(self.name.as_slice()); | |
129 | let fill = column_count.saturating_sub(name.len()); | |
130 | let pad = " ".repeat(fill); | |
131 | match align { | |
132 | PadNone => name, | |
133 | PadOnRight => { | |
134 | name.push_str(&pad); | |
135 | name | |
136 | } | |
137 | } | |
138 | } | |
139 | } | |
140 | ||
141 | #[derive(Debug)] | |
142 | pub struct TestDescAndFn { | |
143 | pub desc: TestDesc, | |
144 | pub testfn: TestFn, | |
145 | } |