]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | #![deny(clippy::all, clippy::pedantic)] |
2 | ||
3 | use std::fmt::Display; | |
4 | use thiserror::Error; | |
5 | ||
6 | fn assert<T: Display>(expected: &str, value: T) { | |
7 | assert_eq!(expected, value.to_string()); | |
8 | } | |
9 | ||
10 | #[test] | |
11 | fn test_braced() { | |
12 | #[derive(Error, Debug)] | |
13 | #[error("braced error: {msg}")] | |
14 | struct Error { | |
15 | msg: String, | |
16 | } | |
17 | ||
18 | let msg = "T".to_owned(); | |
19 | assert("braced error: T", Error { msg }); | |
20 | } | |
21 | ||
22 | #[test] | |
23 | fn test_braced_unused() { | |
24 | #[derive(Error, Debug)] | |
25 | #[error("braced error")] | |
26 | struct Error { | |
27 | extra: usize, | |
28 | } | |
29 | ||
30 | assert("braced error", Error { extra: 0 }); | |
31 | } | |
32 | ||
33 | #[test] | |
34 | fn test_tuple() { | |
35 | #[derive(Error, Debug)] | |
36 | #[error("tuple error: {0}")] | |
37 | struct Error(usize); | |
38 | ||
39 | assert("tuple error: 0", Error(0)); | |
40 | } | |
41 | ||
42 | #[test] | |
43 | fn test_unit() { | |
44 | #[derive(Error, Debug)] | |
45 | #[error("unit error")] | |
46 | struct Error; | |
47 | ||
48 | assert("unit error", Error); | |
49 | } | |
50 | ||
51 | #[test] | |
52 | fn test_enum() { | |
53 | #[derive(Error, Debug)] | |
54 | enum Error { | |
55 | #[error("braced error: {id}")] | |
56 | Braced { id: usize }, | |
57 | #[error("tuple error: {0}")] | |
58 | Tuple(usize), | |
59 | #[error("unit error")] | |
60 | Unit, | |
61 | } | |
62 | ||
63 | assert("braced error: 0", Error::Braced { id: 0 }); | |
64 | assert("tuple error: 0", Error::Tuple(0)); | |
65 | assert("unit error", Error::Unit); | |
66 | } | |
67 | ||
68 | #[test] | |
69 | fn test_constants() { | |
70 | #[derive(Error, Debug)] | |
71 | #[error("{MSG}: {id:?} (code {CODE:?})")] | |
72 | struct Error { | |
73 | id: &'static str, | |
74 | } | |
75 | ||
76 | const MSG: &str = "failed to do"; | |
77 | const CODE: usize = 9; | |
78 | ||
79 | assert("failed to do: \"\" (code 9)", Error { id: "" }); | |
80 | } | |
81 | ||
82 | #[test] | |
83 | fn test_inherit() { | |
84 | #[derive(Error, Debug)] | |
85 | #[error("{0}")] | |
86 | enum Error { | |
87 | Some(&'static str), | |
88 | #[error("other error")] | |
89 | Other(&'static str), | |
90 | } | |
91 | ||
92 | assert("some error", Error::Some("some error")); | |
93 | assert("other error", Error::Other("...")); | |
94 | } | |
95 | ||
96 | #[test] | |
97 | fn test_brace_escape() { | |
98 | #[derive(Error, Debug)] | |
99 | #[error("fn main() {{}}")] | |
100 | struct Error; | |
101 | ||
102 | assert("fn main() {}", Error); | |
103 | } | |
104 | ||
105 | #[test] | |
106 | fn test_expr() { | |
107 | #[derive(Error, Debug)] | |
108 | #[error("1 + 1 = {}", 1 + 1)] | |
109 | struct Error; | |
110 | assert("1 + 1 = 2", Error); | |
111 | } | |
112 | ||
113 | #[test] | |
114 | fn test_nested() { | |
115 | #[derive(Error, Debug)] | |
116 | #[error("!bool = {}", not(.0))] | |
117 | struct Error(bool); | |
118 | ||
119 | #[allow(clippy::trivially_copy_pass_by_ref)] | |
120 | fn not(bool: &bool) -> bool { | |
121 | !*bool | |
122 | } | |
123 | ||
124 | assert("!bool = false", Error(true)); | |
125 | } | |
126 | ||
127 | #[test] | |
128 | fn test_match() { | |
129 | #[derive(Error, Debug)] | |
130 | #[error("{}: {0}", match .1 { | |
131 | Some(n) => format!("error occurred with {}", n), | |
132 | None => "there was an empty error".to_owned(), | |
133 | })] | |
134 | struct Error(String, Option<usize>); | |
135 | ||
136 | assert( | |
137 | "error occurred with 1: ...", | |
138 | Error("...".to_owned(), Some(1)), | |
139 | ); | |
140 | assert( | |
141 | "there was an empty error: ...", | |
142 | Error("...".to_owned(), None), | |
143 | ); | |
144 | } | |
145 | ||
146 | #[test] | |
147 | fn test_void() { | |
148 | #[allow(clippy::empty_enum)] | |
149 | #[derive(Error, Debug)] | |
150 | #[error("...")] | |
151 | pub enum Error {} | |
152 | ||
153 | let _: Error; | |
154 | } | |
155 | ||
156 | #[test] | |
157 | fn test_mixed() { | |
158 | #[derive(Error, Debug)] | |
159 | #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)] | |
160 | struct Error { | |
161 | a: usize, | |
162 | d: usize, | |
163 | } | |
164 | ||
165 | assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 }); | |
166 | } | |
167 | ||
168 | #[test] | |
169 | fn test_ints() { | |
170 | #[derive(Error, Debug)] | |
171 | enum Error { | |
172 | #[error("error {0}")] | |
173 | Tuple(usize, usize), | |
174 | #[error("error {0}", '?')] | |
175 | Struct { v: usize }, | |
176 | } | |
177 | ||
178 | assert("error 9", Error::Tuple(9, 0)); | |
179 | assert("error ?", Error::Struct { v: 0 }); | |
180 | } | |
181 | ||
182 | #[test] | |
183 | fn test_trailing_comma() { | |
184 | #[derive(Error, Debug)] | |
185 | #[error( | |
186 | "error {0}", | |
187 | )] | |
188 | #[rustfmt::skip] | |
189 | struct Error(char); | |
190 | ||
191 | assert("error ?", Error('?')); | |
192 | } | |
193 | ||
194 | #[test] | |
195 | fn test_field() { | |
196 | #[derive(Debug)] | |
197 | struct Inner { | |
198 | data: usize, | |
199 | } | |
200 | ||
201 | #[derive(Error, Debug)] | |
202 | #[error("{}", .0.data)] | |
203 | struct Error(Inner); | |
204 | ||
205 | assert("0", Error(Inner { data: 0 })); | |
206 | } | |
207 | ||
208 | #[test] | |
209 | fn test_macro_rules() { | |
210 | // Regression test for https://github.com/dtolnay/thiserror/issues/86 | |
211 | ||
212 | macro_rules! decl_error { | |
213 | ($variant:ident($value:ident)) => { | |
214 | #[derive(Debug, Error)] | |
215 | pub enum Error0 { | |
216 | #[error("{0:?}")] | |
217 | $variant($value), | |
218 | } | |
219 | ||
220 | #[derive(Debug, Error)] | |
221 | #[error("{0:?}")] | |
222 | pub enum Error1 { | |
223 | $variant($value), | |
224 | } | |
225 | }; | |
226 | } | |
227 | ||
228 | decl_error!(Repro(u8)); | |
229 | ||
230 | assert("0", Error0::Repro(0)); | |
231 | assert("0", Error1::Repro(0)); | |
232 | } | |
233 | ||
234 | #[test] | |
235 | fn test_raw() { | |
236 | #[derive(Error, Debug)] | |
237 | #[error("braced raw error: {r#fn}")] | |
238 | struct Error { | |
239 | r#fn: &'static str, | |
240 | } | |
241 | ||
242 | assert("braced raw error: T", Error { r#fn: "T" }); | |
243 | } | |
244 | ||
245 | #[test] | |
246 | fn test_raw_enum() { | |
247 | #[derive(Error, Debug)] | |
248 | enum Error { | |
249 | #[error("braced raw error: {r#fn}")] | |
250 | Braced { r#fn: &'static str }, | |
251 | } | |
252 | ||
253 | assert("braced raw error: T", Error::Braced { r#fn: "T" }); | |
254 | } | |
255 | ||
256 | #[test] | |
257 | fn test_raw_conflict() { | |
258 | #[derive(Error, Debug)] | |
259 | enum Error { | |
260 | #[error("braced raw error: {r#func}, {func}", func = "U")] | |
261 | Braced { r#func: &'static str }, | |
262 | } | |
263 | ||
264 | assert("braced raw error: T, U", Error::Braced { r#func: "T" }); | |
265 | } | |
266 | ||
267 | #[test] | |
268 | fn test_keyword() { | |
269 | #[derive(Error, Debug)] | |
270 | #[error("error: {type}", type = 1)] | |
271 | struct Error; | |
272 | ||
273 | assert("error: 1", Error); | |
274 | } |