]> git.lizzy.rs Git - rust.git/blob - library/test/src/test_result.rs
Merge commit '61667dedf55e3e5aa584f7ae2bd0471336b92ce9' into sync_cg_clif-2021-09-19
[rust.git] / library / test / src / test_result.rs
1 use std::any::Any;
2
3 use super::bench::BenchSamples;
4 use super::options::ShouldPanic;
5 use super::time;
6 use super::types::TestDesc;
7
8 pub use self::TestResult::*;
9
10 // Return codes for secondary process.
11 // Start somewhere other than 0 so we know the return code means what we think
12 // it means.
13 pub const TR_OK: i32 = 50;
14 pub const TR_FAILED: i32 = 51;
15
16 #[derive(Debug, Clone, PartialEq)]
17 pub enum TestResult {
18     TrOk,
19     TrFailed,
20     TrFailedMsg(String),
21     TrIgnored,
22     TrAllowedFail,
23     TrBench(BenchSamples),
24     TrTimedFail,
25 }
26
27 /// Creates a `TestResult` depending on the raw result of test execution
28 /// and associated data.
29 pub fn calc_result<'a>(
30     desc: &TestDesc,
31     task_result: Result<(), &'a (dyn Any + 'static + Send)>,
32     time_opts: &Option<time::TestTimeOptions>,
33     exec_time: &Option<time::TestExecTime>,
34 ) -> TestResult {
35     let result = match (&desc.should_panic, task_result) {
36         (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
37         (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
38             let maybe_panic_str = err
39                 .downcast_ref::<String>()
40                 .map(|e| &**e)
41                 .or_else(|| err.downcast_ref::<&'static str>().copied());
42
43             if maybe_panic_str.map(|e| e.contains(msg)).unwrap_or(false) {
44                 TestResult::TrOk
45             } else if desc.allow_fail {
46                 TestResult::TrAllowedFail
47             } else if let Some(panic_str) = maybe_panic_str {
48                 TestResult::TrFailedMsg(format!(
49                     r#"panic did not contain expected string
50       panic message: `{:?}`,
51  expected substring: `{:?}`"#,
52                     panic_str, msg
53                 ))
54             } else {
55                 TestResult::TrFailedMsg(format!(
56                     r#"expected panic with string value,
57  found non-string value: `{:?}`
58      expected substring: `{:?}`"#,
59                     (**err).type_id(),
60                     msg
61                 ))
62             }
63         }
64         (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => {
65             TestResult::TrFailedMsg("test did not panic as expected".to_string())
66         }
67         _ if desc.allow_fail => TestResult::TrAllowedFail,
68         _ => TestResult::TrFailed,
69     };
70
71     // If test is already failed (or allowed to fail), do not change the result.
72     if result != TestResult::TrOk {
73         return result;
74     }
75
76     // Check if test is failed due to timeout.
77     if let (Some(opts), Some(time)) = (time_opts, exec_time) {
78         if opts.error_on_excess && opts.is_critical(desc, time) {
79             return TestResult::TrTimedFail;
80         }
81     }
82
83     result
84 }
85
86 /// Creates a `TestResult` depending on the exit code of test subprocess.
87 pub fn get_result_from_exit_code(
88     desc: &TestDesc,
89     code: i32,
90     time_opts: &Option<time::TestTimeOptions>,
91     exec_time: &Option<time::TestExecTime>,
92 ) -> TestResult {
93     let result = match (desc.allow_fail, code) {
94         (_, TR_OK) => TestResult::TrOk,
95         (true, TR_FAILED) => TestResult::TrAllowedFail,
96         (false, TR_FAILED) => TestResult::TrFailed,
97         (_, _) => TestResult::TrFailedMsg(format!("got unexpected return code {}", code)),
98     };
99
100     // If test is already failed (or allowed to fail), do not change the result.
101     if result != TestResult::TrOk {
102         return result;
103     }
104
105     // Check if test is failed due to timeout.
106     if let (Some(opts), Some(time)) = (time_opts, exec_time) {
107         if opts.error_on_excess && opts.is_critical(desc, time) {
108             return TestResult::TrTimedFail;
109         }
110     }
111
112     result
113 }