1 //! Test runner emitted events.
2 //!
3 //! Required feature: `test_unstable` since the format parsed is unstable.
4 
5 use serde::Deserialize;
6 
7 // See https://github.com/rust-lang/rust/tree/master/src/libtest/formatters/json.rs
8 
9 /// Test-runner event.
10 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
11 #[serde(rename_all = "snake_case")]
12 #[serde(tag = "type")]
13 pub enum Event {
14     /// Suite event.
15     Suite(Suite),
16     /// Test case event.
17     Test(Test),
18     /// Benchmark event.
19     Bench(Bench),
20     #[cfg(not(feature = "strict_unstable"))]
21     #[doc(hidden)]
22     #[serde(other)]
23     Unknown,
24 }
25 
26 /// Suite event.
27 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
28 #[serde(rename_all = "snake_case")]
29 #[serde(tag = "event")]
30 pub enum Suite {
31     /// Suite-started event.
32     Started(SuiteStarted),
33     /// Suite-finished successfully event.
34     Ok(SuiteOk),
35     /// Suite-finished with failure event.
36     Failed(SuiteFailed),
37     #[cfg(not(feature = "strict_unstable"))]
38     #[doc(hidden)]
39     #[serde(other)]
40     Unknown,
41 }
42 
43 /// Suite-started event.
44 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
45 #[non_exhaustive]
46 pub struct SuiteStarted {
47     /// Number of test cases in the suite.
48     pub test_count: usize,
49 }
50 
51 /// Suite-finished successfully event.
52 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
53 #[non_exhaustive]
54 pub struct SuiteOk {
55     /// Cases that passed.
56     pub passed: usize,
57     /// Cases that failed.
58     pub failed: usize,
59     /// Cases that were allowed to fail.
60     pub allowed_fail: usize,
61     /// Ignored cases.
62     pub ignored: usize,
63     /// Benchmarks
64     pub measured: usize,
65     /// Cases filtered out by caller.
66     pub filtered_out: usize,
67 }
68 
69 /// Suite-finished with failure event.
70 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
71 #[non_exhaustive]
72 pub struct SuiteFailed {
73     /// Cases that passed.
74     pub passed: usize,
75     /// Cases that failed.
76     pub failed: usize,
77     /// Cases that were allowed to fail.
78     pub allowed_fail: usize,
79     /// Ignored cases.
80     pub ignored: usize,
81     /// Benchmarks
82     pub measured: usize,
83     /// Cases filtered out by caller.
84     pub filtered_out: usize,
85 }
86 
87 /// Test case event.
88 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
89 #[serde(rename_all = "snake_case")]
90 #[serde(tag = "event")]
91 pub enum Test {
92     /// Case-started event.
93     Started(TestStarted),
94     /// Case-finished successfully event.
95     Ok(TestOk),
96     /// Case-finished with failure event.
97     Failed(TestFailed),
98     /// Case-ignored event.
99     Ignored(TestIgnored),
100     /// Case-allowed-failure event.
101     AllowedFailure(TestAllowedFailured),
102     /// Case-timeout event.
103     Timeout(TestTimeout),
104     #[cfg(not(feature = "strict_unstable"))]
105     #[doc(hidden)]
106     #[serde(other)]
107     Unknown,
108 }
109 
110 /// Case-started event.
111 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
112 #[non_exhaustive]
113 pub struct TestStarted {
114     /// Test case name.
115     pub name: String,
116 }
117 
118 /// Case-finished successfully event.
119 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
120 #[non_exhaustive]
121 pub struct TestOk {
122     /// Test case name.
123     pub name: String,
124 }
125 
126 /// Case-finished with failure event.
127 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
128 #[non_exhaustive]
129 pub struct TestFailed {
130     /// Test case name.
131     pub name: String,
132     /// Test's stdout
133     pub stdout: Option<String>,
134     /// Test failure mssage
135     pub message: Option<String>,
136 }
137 
138 /// Case-ignored event.
139 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
140 #[non_exhaustive]
141 pub struct TestIgnored {
142     /// Test case name.
143     pub name: String,
144 }
145 
146 /// Case-allowed-failure event.
147 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
148 #[non_exhaustive]
149 pub struct TestAllowedFailured {
150     /// Test case name.
151     pub name: String,
152 }
153 
154 /// Case-timeout event.
155 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
156 #[non_exhaustive]
157 pub struct TestTimeout {
158     /// Test case name.
159     pub name: String,
160 }
161 
162 /// Benchmark event.
163 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
164 #[non_exhaustive]
165 pub struct Bench {
166     /// Benchmark name.
167     pub name: String,
168     /// Median performance.
169     pub median: usize,
170     /// Deviation from median.
171     pub deviation: usize,
172     /// Mb/s
173     pub mib_per_second: Option<usize>,
174 }
175 
176 #[cfg(test)]
177 mod tests {
178     use super::*;
179 
180     #[test]
suite_started()181     fn suite_started() {
182         let input = r#"{ "type": "suite", "event": "started", "test_count": 10 }"#;
183         let _data: Event = serde_json::from_str(input).unwrap();
184     }
185 
186     #[test]
suite_ok()187     fn suite_ok() {
188         let input = "{ \"type\": \"suite\", \
189                      \"event\": \"ok\", \
190                      \"passed\": 6, \
191                      \"failed\": 5, \
192                      \"allowed_fail\": 4, \
193                      \"ignored\": 3, \
194                      \"measured\": 2, \
195                      \"filtered_out\": 1 }";
196         let _data: Event = serde_json::from_str(input).unwrap();
197     }
198 
199     #[test]
suite_failed()200     fn suite_failed() {
201         let input = "{ \"type\": \"suite\", \
202                      \"event\": \"failed\", \
203                      \"passed\": 6, \
204                      \"failed\": 5, \
205                      \"allowed_fail\": 4, \
206                      \"ignored\": 3, \
207                      \"measured\": 2, \
208                      \"filtered_out\": 1 }";
209         let _data: Event = serde_json::from_str(input).unwrap();
210     }
211 
212     #[test]
test_started()213     fn test_started() {
214         let input = r#"{ "type": "test", "event": "started", "name": "foo" }"#;
215         let _data: Event = serde_json::from_str(input).unwrap();
216     }
217 
218     #[test]
test_timeout()219     fn test_timeout() {
220         let input = r#"{ "type": "test", "event": "timeout", "name": "foo" }"#;
221         let _data: Event = serde_json::from_str(input).unwrap();
222     }
223 
224     #[test]
bench()225     fn bench() {
226         let input = "{ \"type\": \"bench\", \
227                      \"name\": \"foo\", \
228                      \"median\": 10, \
229                      \"deviation\": 2 }";
230         let _data: Event = serde_json::from_str(input).unwrap();
231     }
232 
233     #[test]
bench_full()234     fn bench_full() {
235         let input = "{ \"type\": \"bench\", \
236                      \"name\": \"foo\", \
237                      \"median\": 10, \
238                      \"deviation\": 2, \
239                      \"mib_per_second\": 1 }";
240         let _data: Event = serde_json::from_str(input).unwrap();
241     }
242 }
243