]> git.proxmox.com Git - rustc.git/blob - library/test/src/types.rs
New upstream version 1.61.0+dfsg1
[rustc.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 // A function that runs a test. If the function returns successfully,
78 // the test succeeds; if the function panics then the test fails. We
79 // may need to come up with a more clever definition of test in order
80 // to support isolation of tests into threads.
81 pub enum TestFn {
82 StaticTestFn(fn()),
83 StaticBenchFn(fn(&mut Bencher)),
84 DynTestFn(Box<dyn FnOnce() + Send>),
85 DynBenchFn(Box<dyn Fn(&mut Bencher) + Send>),
86 }
87
88 impl TestFn {
89 pub fn padding(&self) -> NamePadding {
90 match *self {
91 StaticTestFn(..) => PadNone,
92 StaticBenchFn(..) => PadOnRight,
93 DynTestFn(..) => PadNone,
94 DynBenchFn(..) => PadOnRight,
95 }
96 }
97 }
98
99 impl fmt::Debug for TestFn {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 f.write_str(match *self {
102 StaticTestFn(..) => "StaticTestFn(..)",
103 StaticBenchFn(..) => "StaticBenchFn(..)",
104 DynTestFn(..) => "DynTestFn(..)",
105 DynBenchFn(..) => "DynBenchFn(..)",
106 })
107 }
108 }
109
110 // A unique integer associated with each test.
111 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
112 pub struct TestId(pub usize);
113
114 // The definition of a single test. A test runner will run a list of
115 // these.
116 #[derive(Clone, Debug)]
117 pub struct TestDesc {
118 pub name: TestName,
119 pub ignore: bool,
120 #[cfg(not(bootstrap))]
121 pub ignore_message: Option<&'static str>,
122 pub should_panic: options::ShouldPanic,
123 pub compile_fail: bool,
124 pub no_run: bool,
125 pub test_type: TestType,
126 }
127
128 impl TestDesc {
129 pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
130 let mut name = String::from(self.name.as_slice());
131 let fill = column_count.saturating_sub(name.len());
132 let pad = " ".repeat(fill);
133 match align {
134 PadNone => name,
135 PadOnRight => {
136 name.push_str(&pad);
137 name
138 }
139 }
140 }
141
142 /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test.
143 /// Descriptions include "should panic", "compile fail" and "compile".
144 pub fn test_mode(&self) -> Option<&'static str> {
145 if self.ignore {
146 return None;
147 }
148 match self.should_panic {
149 options::ShouldPanic::Yes | options::ShouldPanic::YesWithMessage(_) => {
150 return Some("should panic");
151 }
152 options::ShouldPanic::No => {}
153 }
154 if self.compile_fail {
155 return Some("compile fail");
156 }
157 if self.no_run {
158 return Some("compile");
159 }
160 None
161 }
162 }
163
164 #[derive(Debug)]
165 pub struct TestDescAndFn {
166 pub desc: TestDesc,
167 pub testfn: TestFn,
168 }