2024-04-22 16:47:48 -05:00
|
|
|
//! This checks the output of `--print=check-cfg`
|
|
|
|
|
|
|
|
extern crate run_make_support;
|
|
|
|
|
|
|
|
use std::collections::HashSet;
|
|
|
|
use std::iter::FromIterator;
|
|
|
|
use std::ops::Deref;
|
|
|
|
|
|
|
|
use run_make_support::rustc;
|
|
|
|
|
2024-05-31 10:02:27 -05:00
|
|
|
struct CheckCfg {
|
|
|
|
args: &'static [&'static str],
|
|
|
|
contains: Contains,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Contains {
|
|
|
|
Some { contains: &'static [&'static str], doesnt_contain: &'static [&'static str] },
|
|
|
|
Only(&'static str),
|
|
|
|
}
|
|
|
|
|
2024-04-22 16:47:48 -05:00
|
|
|
fn main() {
|
2024-05-31 10:02:27 -05:00
|
|
|
check(CheckCfg { args: &[], contains: Contains::Only("any()=any()") });
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &["--check-cfg=cfg()"],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["unix", "miri"],
|
|
|
|
doesnt_contain: &["any()", "any()=any()"],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &["--check-cfg=cfg(any())"],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["any()", "unix", r#"target_feature="crt-static""#],
|
|
|
|
doesnt_contain: &["any()=any()"],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &["--check-cfg=cfg(feature)"],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["unix", "miri", "feature"],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
|
|
|
|
},
|
|
|
|
});
|
2024-05-31 08:39:10 -05:00
|
|
|
check(CheckCfg {
|
|
|
|
args: &["--check-cfg=cfg(feature, values())"],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["feature="],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature"],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &["--check-cfg=cfg(feature, values())", "--check-cfg=cfg(feature, values(none()))"],
|
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["feature"],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
|
|
|
|
},
|
|
|
|
});
|
2024-05-31 10:02:27 -05:00
|
|
|
check(CheckCfg {
|
|
|
|
args: &[
|
2024-04-22 16:47:48 -05:00
|
|
|
r#"--check-cfg=cfg(feature, values(any()))"#,
|
2024-05-29 00:01:33 -05:00
|
|
|
r#"--check-cfg=cfg(feature, values("tmp"))"#,
|
2024-04-22 16:47:48 -05:00
|
|
|
],
|
2024-05-31 10:02:27 -05:00
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["unix", "miri", "feature=any()"],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature", "feature=", "feature=\"tmp\""],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
check(CheckCfg {
|
|
|
|
args: &[
|
2024-04-22 16:47:48 -05:00
|
|
|
r#"--check-cfg=cfg(has_foo, has_bar)"#,
|
|
|
|
r#"--check-cfg=cfg(feature, values("tmp"))"#,
|
2024-05-29 00:01:33 -05:00
|
|
|
r#"--check-cfg=cfg(feature, values("tmp"))"#,
|
2024-04-22 16:47:48 -05:00
|
|
|
],
|
2024-05-31 10:02:27 -05:00
|
|
|
contains: Contains::Some {
|
|
|
|
contains: &["has_foo", "has_bar", "feature=\"tmp\""],
|
|
|
|
doesnt_contain: &["any()", "any()=any()", "feature"],
|
|
|
|
},
|
|
|
|
});
|
2024-04-22 16:47:48 -05:00
|
|
|
}
|
|
|
|
|
2024-05-31 10:02:27 -05:00
|
|
|
fn check(CheckCfg { args, contains }: CheckCfg) {
|
2024-04-22 16:47:48 -05:00
|
|
|
let output = rustc()
|
|
|
|
.input("lib.rs")
|
|
|
|
.arg("-Zunstable-options")
|
|
|
|
.arg("--print=check-cfg")
|
|
|
|
.args(&*args)
|
|
|
|
.run();
|
|
|
|
|
2024-06-07 08:23:10 -05:00
|
|
|
let stdout = output.stdout_utf8();
|
2024-04-22 16:47:48 -05:00
|
|
|
|
|
|
|
let mut found = HashSet::<String>::new();
|
|
|
|
|
|
|
|
for l in stdout.lines() {
|
|
|
|
assert!(l == l.trim());
|
2024-05-31 10:02:27 -05:00
|
|
|
if let Some((left, right)) = l.split_once('=') {
|
2024-04-22 16:47:48 -05:00
|
|
|
if right != "any()" && right != "" {
|
|
|
|
assert!(right.starts_with("\""));
|
|
|
|
assert!(right.ends_with("\""));
|
|
|
|
}
|
|
|
|
assert!(!left.contains("\""));
|
|
|
|
} else {
|
|
|
|
assert!(!l.contains("\""));
|
|
|
|
}
|
2024-05-31 10:02:27 -05:00
|
|
|
assert!(found.insert(l.to_string()), "{}", &l);
|
2024-04-22 16:47:48 -05:00
|
|
|
}
|
|
|
|
|
2024-05-31 10:02:27 -05:00
|
|
|
match contains {
|
|
|
|
Contains::Some { contains, doesnt_contain } => {
|
|
|
|
{
|
|
|
|
let should_found =
|
|
|
|
HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
|
|
|
|
let diff: Vec<_> = should_found.difference(&found).collect();
|
|
|
|
assert!(
|
|
|
|
diff.is_empty(),
|
|
|
|
"should found: {:?}, didn't found {:?}",
|
|
|
|
&should_found,
|
|
|
|
&diff
|
|
|
|
);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let should_not_find =
|
|
|
|
HashSet::<String>::from_iter(doesnt_contain.iter().map(|s| s.to_string()));
|
|
|
|
let diff: Vec<_> = should_not_find.intersection(&found).collect();
|
|
|
|
assert!(
|
|
|
|
diff.is_empty(),
|
|
|
|
"should not find {:?}, did found {:?}",
|
|
|
|
&should_not_find,
|
|
|
|
&diff
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Contains::Only(only) => {
|
|
|
|
assert!(found.contains(&only.to_string()), "{:?} != {:?}", &only, &found);
|
|
|
|
assert!(found.len() == 1, "len: {}, instead of 1", found.len());
|
|
|
|
}
|
|
|
|
}
|
2024-04-22 16:47:48 -05:00
|
|
|
}
|