]> git.lizzy.rs Git - rust.git/blob - library/test/src/types.rs
Add 'library/portable-simd/' from commit '1ce1c645cf27c4acdefe6ec8a11d1f0491954a99'
[rust.git] / library / test / src / types.rs
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 // A unique integer associated with each test.
116 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
117 pub struct TestId(pub usize);
118
119 // The definition of a single test. A test runner will run a list of
120 // these.
121 #[derive(Clone, Debug)]
122 pub struct TestDesc {
123     pub name: TestName,
124     pub ignore: bool,
125     pub should_panic: options::ShouldPanic,
126     pub allow_fail: bool,
127     pub compile_fail: bool,
128     pub no_run: bool,
129     pub test_type: TestType,
130 }
131
132 impl TestDesc {
133     pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
134         let mut name = String::from(self.name.as_slice());
135         let fill = column_count.saturating_sub(name.len());
136         let pad = " ".repeat(fill);
137         match align {
138             PadNone => name,
139             PadOnRight => {
140                 name.push_str(&pad);
141                 name
142             }
143         }
144     }
145
146     /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test.
147     /// Descriptions include "should panic", "compile fail" and "compile".
148     pub fn test_mode(&self) -> Option<&'static str> {
149         if self.ignore {
150             return None;
151         }
152         match self.should_panic {
153             options::ShouldPanic::Yes | options::ShouldPanic::YesWithMessage(_) => {
154                 return Some("should panic");
155             }
156             options::ShouldPanic::No => {}
157         }
158         if self.allow_fail {
159             return Some("allow fail");
160         }
161         if self.compile_fail {
162             return Some("compile fail");
163         }
164         if self.no_run {
165             return Some("compile");
166         }
167         None
168     }
169 }
170
171 #[derive(Debug)]
172 pub struct TestDescAndFn {
173     pub desc: TestDesc,
174     pub testfn: TestFn,
175 }