Skip to content

Commit bea4e60

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#42219 - pwoolcoc:add-allow-fail-to-libtest, r=GuillaumeGomez
add `allow_fail` test attribute This change allows the user to add an `#[allow_fail]` attribute to tests that will cause the test to compile & run, but if the test fails it will not cause the entire test run to fail. The test output will show the failure, but in yellow instead of red, and also indicate that it was an allowed failure. Here is an example of the output: http://imgur.com/a/wt7ga
2 parents dc2003b + 4154f89 commit bea4e60

File tree

8 files changed

+140
-30
lines changed

8 files changed

+140
-30
lines changed

src/librustdoc/html/markdown.rs

+27-18
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position
769769
block_info.should_panic, block_info.no_run,
770770
block_info.ignore, block_info.test_harness,
771771
block_info.compile_fail, block_info.error_codes,
772-
line, filename);
772+
line, filename, block_info.allow_fail);
773773
} else {
774774
tests.add_old_test(text, filename);
775775
}
@@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
859859
block_info.should_panic, block_info.no_run,
860860
block_info.ignore, block_info.test_harness,
861861
block_info.compile_fail, block_info.error_codes,
862-
line, filename);
862+
line, filename, block_info.allow_fail);
863863
prev_offset = offset;
864864
}
865865
Event::Start(Tag::Header(level)) => {
@@ -889,6 +889,7 @@ struct LangString {
889889
test_harness: bool,
890890
compile_fail: bool,
891891
error_codes: Vec<String>,
892+
allow_fail: bool,
892893
}
893894

894895
impl LangString {
@@ -902,6 +903,7 @@ impl LangString {
902903
test_harness: false,
903904
compile_fail: false,
904905
error_codes: Vec::new(),
906+
allow_fail: false,
905907
}
906908
}
907909

@@ -930,6 +932,7 @@ impl LangString {
930932
}
931933
"no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
932934
"ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
935+
"allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
933936
"rust" => { data.rust = true; seen_rust_tags = true; }
934937
"test_harness" => {
935938
data.test_harness = true;
@@ -1118,7 +1121,7 @@ mod tests {
11181121
fn test_lang_string_parse() {
11191122
fn t(s: &str,
11201123
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
1121-
compile_fail: bool, error_codes: Vec<String>) {
1124+
compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
11221125
assert_eq!(LangString::parse(s), LangString {
11231126
should_panic: should_panic,
11241127
no_run: no_run,
@@ -1128,25 +1131,31 @@ mod tests {
11281131
compile_fail: compile_fail,
11291132
error_codes: error_codes,
11301133
original: s.to_owned(),
1134+
allow_fail: allow_fail,
11311135
})
11321136
}
11331137

1138+
fn v() -> Vec<String> {
1139+
Vec::new()
1140+
}
1141+
11341142
// marker | should_panic| no_run| ignore| rust | test_harness| compile_fail
1135-
// | error_codes
1136-
t("", false, false, false, true, false, false, Vec::new());
1137-
t("rust", false, false, false, true, false, false, Vec::new());
1138-
t("sh", false, false, false, false, false, false, Vec::new());
1139-
t("ignore", false, false, true, true, false, false, Vec::new());
1140-
t("should_panic", true, false, false, true, false, false, Vec::new());
1141-
t("no_run", false, true, false, true, false, false, Vec::new());
1142-
t("test_harness", false, false, false, true, true, false, Vec::new());
1143-
t("compile_fail", false, true, false, true, false, true, Vec::new());
1144-
t("{.no_run .example}", false, true, false, true, false, false, Vec::new());
1145-
t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new());
1146-
t("{.example .rust}", false, false, false, true, false, false, Vec::new());
1147-
t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new());
1148-
t("text, no_run", false, true, false, false, false, false, Vec::new());
1149-
t("text,no_run", false, true, false, false, false, false, Vec::new());
1143+
// | allow_fail | error_codes
1144+
t("", false, false, false, true, false, false, false, v());
1145+
t("rust", false, false, false, true, false, false, false, v());
1146+
t("sh", false, false, false, false, false, false, false, v());
1147+
t("ignore", false, false, true, true, false, false, false, v());
1148+
t("should_panic", true, false, false, true, false, false, false, v());
1149+
t("no_run", false, true, false, true, false, false, false, v());
1150+
t("test_harness", false, false, false, true, true, false, false, v());
1151+
t("compile_fail", false, true, false, true, false, true, false, v());
1152+
t("allow_fail", false, false, false, true, false, false, true, v());
1153+
t("{.no_run .example}", false, true, false, true, false, false, false, v());
1154+
t("{.sh .should_panic}", true, false, false, false, false, false, false, v());
1155+
t("{.example .rust}", false, false, false, true, false, false, false, v());
1156+
t("{.test_harness .rust}", false, false, false, true, true, false, false, v());
1157+
t("text, no_run", false, true, false, false, false, false, false, v());
1158+
t("text,no_run", false, true, false, false, false, false, false, v());
11501159
}
11511160

11521161
#[test]

src/librustdoc/test.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ impl Collector {
467467
pub fn add_test(&mut self, test: String,
468468
should_panic: bool, no_run: bool, should_ignore: bool,
469469
as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
470-
line: usize, filename: String) {
470+
line: usize, filename: String, allow_fail: bool) {
471471
let name = self.generate_name(line, &filename);
472472
// to be removed when hoedown is removed
473473
if self.render_type == RenderType::Pulldown {
@@ -499,6 +499,7 @@ impl Collector {
499499
ignore: should_ignore,
500500
// compiler failures are test failures
501501
should_panic: testing::ShouldPanic::No,
502+
allow_fail: allow_fail,
502503
},
503504
testfn: testing::DynTestFn(box move |()| {
504505
let panic = io::set_panic(None);

src/libsyntax/feature_gate.rs

+8
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ declare_features! (
354354

355355
// rustc internal
356356
(active, abi_thiscall, "1.19.0", None),
357+
358+
// Allows a test to fail without failing the whole suite
359+
(active, allow_fail, "1.19.0", Some(42219)),
357360
);
358361

359362
declare_features! (
@@ -812,6 +815,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
812815
"used internally by rustc",
813816
cfg_fn!(rustc_attrs))),
814817

818+
("allow_fail", Normal, Gated(Stability::Unstable,
819+
"allow_fail",
820+
"allow_fail attribute is currently unstable",
821+
cfg_fn!(allow_fail))),
822+
815823
// Crate level attributes
816824
("crate_name", CrateLevel, Ungated),
817825
("crate_type", CrateLevel, Ungated),

src/libsyntax/test.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ struct Test {
5252
path: Vec<Ident> ,
5353
bench: bool,
5454
ignore: bool,
55-
should_panic: ShouldPanic
55+
should_panic: ShouldPanic,
56+
allow_fail: bool,
5657
}
5758

5859
struct TestCtxt<'a> {
@@ -133,7 +134,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
133134
path: self.cx.path.clone(),
134135
bench: is_bench_fn(&self.cx, &i),
135136
ignore: is_ignored(&i),
136-
should_panic: should_panic(&i, &self.cx)
137+
should_panic: should_panic(&i, &self.cx),
138+
allow_fail: is_allowed_fail(&i),
137139
};
138140
self.cx.testfns.push(test);
139141
self.tests.push(i.ident);
@@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool {
383385
i.attrs.iter().any(|attr| attr.check_name("ignore"))
384386
}
385387

388+
fn is_allowed_fail(i: &ast::Item) -> bool {
389+
i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
390+
}
391+
386392
fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
387393
match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
388394
Some(attr) => {
@@ -668,14 +674,16 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
668674
}
669675
}
670676
};
677+
let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
671678

672679
// self::test::TestDesc { ... }
673680
let desc_expr = ecx.expr_struct(
674681
span,
675682
test_path("TestDesc"),
676683
vec![field("name", name_expr),
677684
field("ignore", ignore_expr),
678-
field("should_panic", fail_expr)]);
685+
field("should_panic", fail_expr),
686+
field("allow_fail", allow_fail_expr)]);
679687

680688

681689
let mut visible_path = match cx.toplevel_reexport {

0 commit comments

Comments
 (0)