1 use super::*;
2
3 use crate::{parser::*, Flags};
4
5 #[test]
6 #[cfg(not(miri))] // Very slow in miri
roundtrip()7 fn roundtrip() {
8 let mut s = String::new();
9
10 for a in 0u8..=255 {
11 for b in 0u8..=255 {
12 let f = TestFlags::from_bits_retain(a | b);
13
14 s.clear();
15 to_writer(&f, &mut s).unwrap();
16
17 assert_eq!(f, from_str::<TestFlags>(&s).unwrap());
18 }
19 }
20 }
21
22 #[test]
23 #[cfg(not(miri))] // Very slow in miri
roundtrip_truncate()24 fn roundtrip_truncate() {
25 let mut s = String::new();
26
27 for a in 0u8..=255 {
28 for b in 0u8..=255 {
29 let f = TestFlags::from_bits_retain(a | b);
30
31 s.clear();
32 to_writer_truncate(&f, &mut s).unwrap();
33
34 assert_eq!(
35 TestFlags::from_bits_truncate(f.bits()),
36 from_str_truncate::<TestFlags>(&s).unwrap()
37 );
38 }
39 }
40 }
41
42 #[test]
43 #[cfg(not(miri))] // Very slow in miri
roundtrip_strict()44 fn roundtrip_strict() {
45 let mut s = String::new();
46
47 for a in 0u8..=255 {
48 for b in 0u8..=255 {
49 let f = TestFlags::from_bits_retain(a | b);
50
51 s.clear();
52 to_writer_strict(&f, &mut s).unwrap();
53
54 let mut strict = TestFlags::empty();
55 for (_, flag) in f.iter_names() {
56 strict |= flag;
57 }
58 let f = strict;
59
60 if let Ok(s) = from_str_strict::<TestFlags>(&s) {
61 assert_eq!(f, s);
62 }
63 }
64 }
65 }
66
67 mod from_str {
68 use super::*;
69
70 #[test]
valid()71 fn valid() {
72 assert_eq!(0, from_str::<TestFlags>("").unwrap().bits());
73
74 assert_eq!(1, from_str::<TestFlags>("A").unwrap().bits());
75 assert_eq!(1, from_str::<TestFlags>(" A ").unwrap().bits());
76 assert_eq!(
77 1 | 1 << 1 | 1 << 2,
78 from_str::<TestFlags>("A | B | C").unwrap().bits()
79 );
80 assert_eq!(
81 1 | 1 << 1 | 1 << 2,
82 from_str::<TestFlags>("A\n|\tB\r\n| C ").unwrap().bits()
83 );
84 assert_eq!(
85 1 | 1 << 1 | 1 << 2,
86 from_str::<TestFlags>("A|B|C").unwrap().bits()
87 );
88
89 assert_eq!(1 << 3, from_str::<TestFlags>("0x8").unwrap().bits());
90 assert_eq!(1 | 1 << 3, from_str::<TestFlags>("A | 0x8").unwrap().bits());
91 assert_eq!(
92 1 | 1 << 1 | 1 << 3,
93 from_str::<TestFlags>("0x1 | 0x8 | B").unwrap().bits()
94 );
95
96 assert_eq!(
97 1 | 1 << 1,
98 from_str::<TestUnicode>("一 | 二").unwrap().bits()
99 );
100 }
101
102 #[test]
invalid()103 fn invalid() {
104 assert!(from_str::<TestFlags>("a")
105 .unwrap_err()
106 .to_string()
107 .starts_with("unrecognized named flag"));
108 assert!(from_str::<TestFlags>("A & B")
109 .unwrap_err()
110 .to_string()
111 .starts_with("unrecognized named flag"));
112
113 assert!(from_str::<TestFlags>("0xg")
114 .unwrap_err()
115 .to_string()
116 .starts_with("invalid hex flag"));
117 assert!(from_str::<TestFlags>("0xffffffffffff")
118 .unwrap_err()
119 .to_string()
120 .starts_with("invalid hex flag"));
121 }
122 }
123
124 mod to_writer {
125 use super::*;
126
127 #[test]
cases()128 fn cases() {
129 assert_eq!("", write(TestFlags::empty()));
130 assert_eq!("A", write(TestFlags::A));
131 assert_eq!("A | B | C", write(TestFlags::all()));
132 assert_eq!("0x8", write(TestFlags::from_bits_retain(1 << 3)));
133 assert_eq!(
134 "A | 0x8",
135 write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
136 );
137
138 assert_eq!("", write(TestZero::ZERO));
139
140 assert_eq!("ABC", write(TestFlagsInvert::all()));
141
142 assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
143
144 assert_eq!("A", write(TestOverlappingFull::C));
145 assert_eq!(
146 "A | D",
147 write(TestOverlappingFull::C | TestOverlappingFull::D)
148 );
149 }
150
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,151 fn write<F: Flags>(value: F) -> String
152 where
153 F::Bits: crate::parser::WriteHex,
154 {
155 let mut s = String::new();
156
157 to_writer(&value, &mut s).unwrap();
158 s
159 }
160 }
161
162 mod from_str_truncate {
163 use super::*;
164
165 #[test]
valid()166 fn valid() {
167 assert_eq!(0, from_str_truncate::<TestFlags>("").unwrap().bits());
168
169 assert_eq!(1, from_str_truncate::<TestFlags>("A").unwrap().bits());
170 assert_eq!(1, from_str_truncate::<TestFlags>(" A ").unwrap().bits());
171 assert_eq!(
172 1 | 1 << 1 | 1 << 2,
173 from_str_truncate::<TestFlags>("A | B | C").unwrap().bits()
174 );
175 assert_eq!(
176 1 | 1 << 1 | 1 << 2,
177 from_str_truncate::<TestFlags>("A\n|\tB\r\n| C ")
178 .unwrap()
179 .bits()
180 );
181 assert_eq!(
182 1 | 1 << 1 | 1 << 2,
183 from_str_truncate::<TestFlags>("A|B|C").unwrap().bits()
184 );
185
186 assert_eq!(0, from_str_truncate::<TestFlags>("0x8").unwrap().bits());
187 assert_eq!(1, from_str_truncate::<TestFlags>("A | 0x8").unwrap().bits());
188 assert_eq!(
189 1 | 1 << 1,
190 from_str_truncate::<TestFlags>("0x1 | 0x8 | B")
191 .unwrap()
192 .bits()
193 );
194
195 assert_eq!(
196 1 | 1 << 1,
197 from_str_truncate::<TestUnicode>("一 | 二").unwrap().bits()
198 );
199 }
200 }
201
202 mod to_writer_truncate {
203 use super::*;
204
205 #[test]
cases()206 fn cases() {
207 assert_eq!("", write(TestFlags::empty()));
208 assert_eq!("A", write(TestFlags::A));
209 assert_eq!("A | B | C", write(TestFlags::all()));
210 assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
211 assert_eq!(
212 "A",
213 write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
214 );
215
216 assert_eq!("", write(TestZero::ZERO));
217
218 assert_eq!("ABC", write(TestFlagsInvert::all()));
219
220 assert_eq!("0x1", write(TestOverlapping::from_bits_retain(1)));
221
222 assert_eq!("A", write(TestOverlappingFull::C));
223 assert_eq!(
224 "A | D",
225 write(TestOverlappingFull::C | TestOverlappingFull::D)
226 );
227 }
228
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,229 fn write<F: Flags>(value: F) -> String
230 where
231 F::Bits: crate::parser::WriteHex,
232 {
233 let mut s = String::new();
234
235 to_writer_truncate(&value, &mut s).unwrap();
236 s
237 }
238 }
239
240 mod from_str_strict {
241 use super::*;
242
243 #[test]
valid()244 fn valid() {
245 assert_eq!(0, from_str_strict::<TestFlags>("").unwrap().bits());
246
247 assert_eq!(1, from_str_strict::<TestFlags>("A").unwrap().bits());
248 assert_eq!(1, from_str_strict::<TestFlags>(" A ").unwrap().bits());
249 assert_eq!(
250 1 | 1 << 1 | 1 << 2,
251 from_str_strict::<TestFlags>("A | B | C").unwrap().bits()
252 );
253 assert_eq!(
254 1 | 1 << 1 | 1 << 2,
255 from_str_strict::<TestFlags>("A\n|\tB\r\n| C ")
256 .unwrap()
257 .bits()
258 );
259 assert_eq!(
260 1 | 1 << 1 | 1 << 2,
261 from_str_strict::<TestFlags>("A|B|C").unwrap().bits()
262 );
263
264 assert_eq!(
265 1 | 1 << 1,
266 from_str_strict::<TestUnicode>("一 | 二").unwrap().bits()
267 );
268 }
269
270 #[test]
invalid()271 fn invalid() {
272 assert!(from_str_strict::<TestFlags>("a")
273 .unwrap_err()
274 .to_string()
275 .starts_with("unrecognized named flag"));
276 assert!(from_str_strict::<TestFlags>("A & B")
277 .unwrap_err()
278 .to_string()
279 .starts_with("unrecognized named flag"));
280
281 assert!(from_str_strict::<TestFlags>("0x1")
282 .unwrap_err()
283 .to_string()
284 .starts_with("invalid hex flag"));
285 assert!(from_str_strict::<TestFlags>("0xg")
286 .unwrap_err()
287 .to_string()
288 .starts_with("invalid hex flag"));
289 assert!(from_str_strict::<TestFlags>("0xffffffffffff")
290 .unwrap_err()
291 .to_string()
292 .starts_with("invalid hex flag"));
293 }
294 }
295
296 mod to_writer_strict {
297 use super::*;
298
299 #[test]
cases()300 fn cases() {
301 assert_eq!("", write(TestFlags::empty()));
302 assert_eq!("A", write(TestFlags::A));
303 assert_eq!("A | B | C", write(TestFlags::all()));
304 assert_eq!("", write(TestFlags::from_bits_retain(1 << 3)));
305 assert_eq!(
306 "A",
307 write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
308 );
309
310 assert_eq!("", write(TestZero::ZERO));
311
312 assert_eq!("ABC", write(TestFlagsInvert::all()));
313
314 assert_eq!("", write(TestOverlapping::from_bits_retain(1)));
315
316 assert_eq!("A", write(TestOverlappingFull::C));
317 assert_eq!(
318 "A | D",
319 write(TestOverlappingFull::C | TestOverlappingFull::D)
320 );
321 }
322
write<F: Flags>(value: F) -> String where F::Bits: crate::parser::WriteHex,323 fn write<F: Flags>(value: F) -> String
324 where
325 F::Bits: crate::parser::WriteHex,
326 {
327 let mut s = String::new();
328
329 to_writer_strict(&value, &mut s).unwrap();
330 s
331 }
332 }
333