1 use super::*;
2
3 use rustc_ast::attr;
4 use rustc_ast::Path;
5 use rustc_span::create_default_session_globals_then;
6 use rustc_span::symbol::{Ident, Symbol};
7 use rustc_span::DUMMY_SP;
8
word_cfg(s: &str) -> Cfg9 fn word_cfg(s: &str) -> Cfg {
10 Cfg::Cfg(Symbol::intern(s), None)
11 }
12
name_value_cfg(name: &str, value: &str) -> Cfg13 fn name_value_cfg(name: &str, value: &str) -> Cfg {
14 Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value)))
15 }
16
dummy_meta_item_word(name: &str) -> MetaItem17 fn dummy_meta_item_word(name: &str) -> MetaItem {
18 MetaItem {
19 path: Path::from_ident(Ident::from_str(name)),
20 kind: MetaItemKind::Word,
21 span: DUMMY_SP,
22 }
23 }
24
25 macro_rules! dummy_meta_item_list {
26 ($name:ident, [$($list:ident),* $(,)?]) => {
27 MetaItem {
28 path: Path::from_ident(Ident::from_str(stringify!($name))),
29 kind: MetaItemKind::List(vec![
30 $(
31 NestedMetaItem::MetaItem(
32 dummy_meta_item_word(stringify!($list)),
33 ),
34 )*
35 ]),
36 span: DUMMY_SP,
37 }
38 };
39
40 ($name:ident, [$($list:expr),* $(,)?]) => {
41 MetaItem {
42 path: Path::from_ident(Ident::from_str(stringify!($name))),
43 kind: MetaItemKind::List(vec![
44 $(
45 NestedMetaItem::MetaItem($list),
46 )*
47 ]),
48 span: DUMMY_SP,
49 }
50 };
51 }
52
53 #[test]
test_cfg_not()54 fn test_cfg_not() {
55 create_default_session_globals_then(|| {
56 assert_eq!(!Cfg::False, Cfg::True);
57 assert_eq!(!Cfg::True, Cfg::False);
58 assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test"))));
59 assert_eq!(
60 !Cfg::All(vec![word_cfg("a"), word_cfg("b")]),
61 Cfg::Not(Box::new(Cfg::All(vec![word_cfg("a"), word_cfg("b")])))
62 );
63 assert_eq!(
64 !Cfg::Any(vec![word_cfg("a"), word_cfg("b")]),
65 Cfg::Not(Box::new(Cfg::Any(vec![word_cfg("a"), word_cfg("b")])))
66 );
67 assert_eq!(!Cfg::Not(Box::new(word_cfg("test"))), word_cfg("test"));
68 })
69 }
70
71 #[test]
test_cfg_and()72 fn test_cfg_and() {
73 create_default_session_globals_then(|| {
74 let mut x = Cfg::False;
75 x &= Cfg::True;
76 assert_eq!(x, Cfg::False);
77
78 x = word_cfg("test");
79 x &= Cfg::False;
80 assert_eq!(x, Cfg::False);
81
82 x = word_cfg("test2");
83 x &= Cfg::True;
84 assert_eq!(x, word_cfg("test2"));
85
86 x = Cfg::True;
87 x &= word_cfg("test3");
88 assert_eq!(x, word_cfg("test3"));
89
90 x &= word_cfg("test3");
91 assert_eq!(x, word_cfg("test3"));
92
93 x &= word_cfg("test4");
94 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
95
96 x &= word_cfg("test4");
97 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
98
99 x &= word_cfg("test5");
100 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
101
102 x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
103 assert_eq!(
104 x,
105 Cfg::All(vec![
106 word_cfg("test3"),
107 word_cfg("test4"),
108 word_cfg("test5"),
109 word_cfg("test6"),
110 word_cfg("test7"),
111 ])
112 );
113
114 x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
115 assert_eq!(
116 x,
117 Cfg::All(vec![
118 word_cfg("test3"),
119 word_cfg("test4"),
120 word_cfg("test5"),
121 word_cfg("test6"),
122 word_cfg("test7"),
123 ])
124 );
125
126 let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]);
127 y &= x;
128 assert_eq!(
129 y,
130 Cfg::All(vec![
131 word_cfg("test3"),
132 word_cfg("test4"),
133 word_cfg("test5"),
134 word_cfg("test6"),
135 word_cfg("test7"),
136 Cfg::Any(vec![word_cfg("a"), word_cfg("b")]),
137 ])
138 );
139
140 let mut z = word_cfg("test8");
141 z &= Cfg::All(vec![word_cfg("test9"), word_cfg("test10")]);
142 assert_eq!(z, Cfg::All(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
143
144 let mut z = word_cfg("test11");
145 z &= Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]);
146 assert_eq!(z, Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]));
147
148 assert_eq!(
149 word_cfg("a") & word_cfg("b") & word_cfg("c"),
150 Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
151 );
152 })
153 }
154
155 #[test]
test_cfg_or()156 fn test_cfg_or() {
157 create_default_session_globals_then(|| {
158 let mut x = Cfg::True;
159 x |= Cfg::False;
160 assert_eq!(x, Cfg::True);
161
162 x = word_cfg("test");
163 x |= Cfg::True;
164 assert_eq!(x, Cfg::True);
165
166 x = word_cfg("test2");
167 x |= Cfg::False;
168 assert_eq!(x, word_cfg("test2"));
169
170 x = Cfg::False;
171 x |= word_cfg("test3");
172 assert_eq!(x, word_cfg("test3"));
173
174 x |= word_cfg("test3");
175 assert_eq!(x, word_cfg("test3"));
176
177 x |= word_cfg("test4");
178 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
179
180 x |= word_cfg("test4");
181 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
182
183 x |= word_cfg("test5");
184 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
185
186 x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
187 assert_eq!(
188 x,
189 Cfg::Any(vec![
190 word_cfg("test3"),
191 word_cfg("test4"),
192 word_cfg("test5"),
193 word_cfg("test6"),
194 word_cfg("test7"),
195 ])
196 );
197
198 x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
199 assert_eq!(
200 x,
201 Cfg::Any(vec![
202 word_cfg("test3"),
203 word_cfg("test4"),
204 word_cfg("test5"),
205 word_cfg("test6"),
206 word_cfg("test7"),
207 ])
208 );
209
210 let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]);
211 y |= x;
212 assert_eq!(
213 y,
214 Cfg::Any(vec![
215 word_cfg("test3"),
216 word_cfg("test4"),
217 word_cfg("test5"),
218 word_cfg("test6"),
219 word_cfg("test7"),
220 Cfg::All(vec![word_cfg("a"), word_cfg("b")]),
221 ])
222 );
223
224 let mut z = word_cfg("test8");
225 z |= Cfg::Any(vec![word_cfg("test9"), word_cfg("test10")]);
226 assert_eq!(z, Cfg::Any(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
227
228 let mut z = word_cfg("test11");
229 z |= Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]);
230 assert_eq!(z, Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]));
231
232 assert_eq!(
233 word_cfg("a") | word_cfg("b") | word_cfg("c"),
234 Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
235 );
236 })
237 }
238
239 #[test]
test_parse_ok()240 fn test_parse_ok() {
241 create_default_session_globals_then(|| {
242 let mi = dummy_meta_item_word("all");
243 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
244
245 let mi =
246 attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP);
247 assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
248
249 let mi = dummy_meta_item_list!(all, [a, b]);
250 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b")));
251
252 let mi = dummy_meta_item_list!(any, [a, b]);
253 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b")));
254
255 let mi = dummy_meta_item_list!(not, [a]);
256 assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a")));
257
258 let mi = dummy_meta_item_list!(
259 not,
260 [dummy_meta_item_list!(
261 any,
262 [dummy_meta_item_word("a"), dummy_meta_item_list!(all, [b, c]),]
263 ),]
264 );
265 assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
266
267 let mi = dummy_meta_item_list!(all, [a, b, c]);
268 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c")));
269 })
270 }
271
272 #[test]
test_parse_err()273 fn test_parse_err() {
274 create_default_session_globals_then(|| {
275 let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
276 assert!(Cfg::parse(&mi).is_err());
277
278 let mi = dummy_meta_item_list!(not, [a, b]);
279 assert!(Cfg::parse(&mi).is_err());
280
281 let mi = dummy_meta_item_list!(not, []);
282 assert!(Cfg::parse(&mi).is_err());
283
284 let mi = dummy_meta_item_list!(foo, []);
285 assert!(Cfg::parse(&mi).is_err());
286
287 let mi = dummy_meta_item_list!(
288 all,
289 [dummy_meta_item_list!(foo, []), dummy_meta_item_word("b"),]
290 );
291 assert!(Cfg::parse(&mi).is_err());
292
293 let mi = dummy_meta_item_list!(
294 any,
295 [dummy_meta_item_word("a"), dummy_meta_item_list!(foo, []),]
296 );
297 assert!(Cfg::parse(&mi).is_err());
298
299 let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]);
300 assert!(Cfg::parse(&mi).is_err());
301 })
302 }
303
304 #[test]
test_render_short_html()305 fn test_render_short_html() {
306 create_default_session_globals_then(|| {
307 assert_eq!(word_cfg("unix").render_short_html(), "Unix");
308 assert_eq!(name_value_cfg("target_os", "macos").render_short_html(), "macOS");
309 assert_eq!(name_value_cfg("target_pointer_width", "16").render_short_html(), "16-bit");
310 assert_eq!(name_value_cfg("target_endian", "little").render_short_html(), "Little-endian");
311 assert_eq!((!word_cfg("windows")).render_short_html(), "Non-Windows");
312 assert_eq!(
313 (word_cfg("unix") & word_cfg("windows")).render_short_html(),
314 "Unix and Windows"
315 );
316 assert_eq!((word_cfg("unix") | word_cfg("windows")).render_short_html(), "Unix or Windows");
317 assert_eq!(
318 (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
319 .render_short_html(),
320 "Unix and Windows and debug-assertions enabled"
321 );
322 assert_eq!(
323 (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
324 .render_short_html(),
325 "Unix or Windows or debug-assertions enabled"
326 );
327 assert_eq!(
328 (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
329 .render_short_html(),
330 "Neither Unix nor Windows nor debug-assertions enabled"
331 );
332 assert_eq!(
333 ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
334 | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
335 .render_short_html(),
336 "Unix and x86-64, or Windows and 64-bit"
337 );
338 assert_eq!(
339 (!(word_cfg("unix") & word_cfg("windows"))).render_short_html(),
340 "Not (Unix and Windows)"
341 );
342 assert_eq!(
343 ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
344 .render_short_html(),
345 "(Debug-assertions enabled or Windows) and Unix"
346 );
347 assert_eq!(
348 name_value_cfg("target_feature", "sse2").render_short_html(),
349 "<code>sse2</code>"
350 );
351 assert_eq!(
352 (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
353 .render_short_html(),
354 "x86-64 and <code>sse2</code>"
355 );
356 })
357 }
358
359 #[test]
test_render_long_html()360 fn test_render_long_html() {
361 create_default_session_globals_then(|| {
362 assert_eq!(
363 word_cfg("unix").render_long_html(),
364 "This is supported on <strong>Unix</strong> only."
365 );
366 assert_eq!(
367 name_value_cfg("target_os", "macos").render_long_html(),
368 "This is supported on <strong>macOS</strong> only."
369 );
370 assert_eq!(
371 name_value_cfg("target_os", "wasi").render_long_html(),
372 "This is supported on <strong>WASI</strong> only."
373 );
374 assert_eq!(
375 name_value_cfg("target_pointer_width", "16").render_long_html(),
376 "This is supported on <strong>16-bit</strong> only."
377 );
378 assert_eq!(
379 name_value_cfg("target_endian", "little").render_long_html(),
380 "This is supported on <strong>little-endian</strong> only."
381 );
382 assert_eq!(
383 (!word_cfg("windows")).render_long_html(),
384 "This is supported on <strong>non-Windows</strong> only."
385 );
386 assert_eq!(
387 (word_cfg("unix") & word_cfg("windows")).render_long_html(),
388 "This is supported on <strong>Unix and Windows</strong> only."
389 );
390 assert_eq!(
391 (word_cfg("unix") | word_cfg("windows")).render_long_html(),
392 "This is supported on <strong>Unix or Windows</strong> only."
393 );
394 assert_eq!(
395 (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
396 .render_long_html(),
397 "This is supported on <strong>Unix and Windows and debug-assertions enabled\
398 </strong> only."
399 );
400 assert_eq!(
401 (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
402 .render_long_html(),
403 "This is supported on <strong>Unix or Windows or debug-assertions enabled\
404 </strong> only."
405 );
406 assert_eq!(
407 (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
408 .render_long_html(),
409 "This is supported on <strong>neither Unix nor Windows nor debug-assertions \
410 enabled</strong>."
411 );
412 assert_eq!(
413 ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
414 | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
415 .render_long_html(),
416 "This is supported on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
417 );
418 assert_eq!(
419 (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(),
420 "This is supported on <strong>not (Unix and Windows)</strong>."
421 );
422 assert_eq!(
423 ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
424 .render_long_html(),
425 "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
426 </strong> only."
427 );
428 assert_eq!(
429 name_value_cfg("target_feature", "sse2").render_long_html(),
430 "This is supported with <strong>target feature <code>sse2</code></strong> only."
431 );
432 assert_eq!(
433 (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
434 .render_long_html(),
435 "This is supported on <strong>x86-64 and target feature \
436 <code>sse2</code></strong> only."
437 );
438 })
439 }
440
441 #[test]
test_simplify_with()442 fn test_simplify_with() {
443 // This is a tiny subset of things that could be simplified, but it likely covers 90% of
444 // real world usecases well.
445 create_default_session_globals_then(|| {
446 let foo = word_cfg("foo");
447 let bar = word_cfg("bar");
448 let baz = word_cfg("baz");
449 let quux = word_cfg("quux");
450
451 let foobar = Cfg::All(vec![foo.clone(), bar.clone()]);
452 let barbaz = Cfg::All(vec![bar.clone(), baz.clone()]);
453 let foobarbaz = Cfg::All(vec![foo.clone(), bar.clone(), baz.clone()]);
454 let bazquux = Cfg::All(vec![baz.clone(), quux.clone()]);
455
456 // Unrelated cfgs don't affect each other
457 assert_eq!(foo.simplify_with(&bar).as_ref(), Some(&foo));
458 assert_eq!(foobar.simplify_with(&bazquux).as_ref(), Some(&foobar));
459
460 // Identical cfgs are eliminated
461 assert_eq!(foo.simplify_with(&foo), None);
462 assert_eq!(foobar.simplify_with(&foobar), None);
463
464 // Multiple cfgs eliminate a single assumed cfg
465 assert_eq!(foobar.simplify_with(&foo).as_ref(), Some(&bar));
466 assert_eq!(foobar.simplify_with(&bar).as_ref(), Some(&foo));
467
468 // A single cfg is eliminated by multiple assumed cfg containing it
469 assert_eq!(foo.simplify_with(&foobar), None);
470
471 // Multiple cfgs eliminate the matching subset of multiple assumed cfg
472 assert_eq!(foobar.simplify_with(&barbaz).as_ref(), Some(&foo));
473 assert_eq!(foobar.simplify_with(&foobarbaz), None);
474 });
475 }
476