rustdoc: add the ability to run tests with --test.
This adds the `test_harness` directive that runs a code block using the test runner, to allow for `#[test]` items to be demonstrated and still tested (currently they are just stripped and not even compiled, let alone run).
This commit is contained in:
parent
a17b0421d3
commit
11bdeea767
@ -171,6 +171,18 @@ You can specify that the code block should be compiled but not run with the
|
||||
```
|
||||
~~~
|
||||
|
||||
Lastly, you can specify that a code block be compiled as if `--test`
|
||||
were passed to the compiler using the `test_harness` directive.
|
||||
|
||||
~~~md
|
||||
```test_harness
|
||||
#[test]
|
||||
fn foo() {
|
||||
fail!("oops! (will run & register as failure)")
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
Rustdoc also supplies some extra sugar for helping with some tedious
|
||||
documentation examples. If a line is prefixed with `# `, then the line
|
||||
will not show up in the HTML documentation, but it will be used when
|
||||
|
@ -195,7 +195,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
|
||||
stripped_filtered_line(l).unwrap_or(l)
|
||||
}).collect::<Vec<&str>>().connect("\n");
|
||||
let krate = krate.as_ref().map(|s| s.as_slice());
|
||||
let test = test::maketest(test.as_slice(), krate, false);
|
||||
let test = test::maketest(test.as_slice(), krate, false, false);
|
||||
s.push_str(format!("<span id='rust-example-raw-{}' \
|
||||
class='rusttest'>{}</span>",
|
||||
i, Escape(test.as_slice())).as_slice());
|
||||
@ -328,7 +328,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
|
||||
let text = lines.collect::<Vec<&str>>().connect("\n");
|
||||
tests.add_test(text.to_string(),
|
||||
block_info.should_fail, block_info.no_run,
|
||||
block_info.ignore);
|
||||
block_info.ignore, block_info.test_harness);
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -372,6 +372,7 @@ struct LangString {
|
||||
no_run: bool,
|
||||
ignore: bool,
|
||||
notrust: bool,
|
||||
test_harness: bool,
|
||||
}
|
||||
|
||||
impl LangString {
|
||||
@ -381,6 +382,7 @@ impl LangString {
|
||||
no_run: false,
|
||||
ignore: false,
|
||||
notrust: false,
|
||||
test_harness: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,6 +403,7 @@ impl LangString {
|
||||
"ignore" => { data.ignore = true; seen_rust_tags = true; },
|
||||
"notrust" => { data.notrust = true; seen_rust_tags = true; },
|
||||
"rust" => { data.notrust = false; seen_rust_tags = true; },
|
||||
"test_harness" => { data.test_harness = true; seen_rust_tags = true; }
|
||||
_ => { seen_other_tags = true }
|
||||
}
|
||||
}
|
||||
@ -446,24 +449,28 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_lang_string_parse() {
|
||||
fn t(s: &str, should_fail: bool, no_run: bool, ignore: bool, notrust: bool) {
|
||||
fn t(s: &str,
|
||||
should_fail: bool, no_run: bool, ignore: bool, notrust: bool, test_harness: bool) {
|
||||
assert_eq!(LangString::parse(s), LangString {
|
||||
should_fail: should_fail,
|
||||
no_run: no_run,
|
||||
ignore: ignore,
|
||||
notrust: notrust,
|
||||
test_harness: test_harness,
|
||||
})
|
||||
}
|
||||
|
||||
t("", false,false,false,false);
|
||||
t("rust", false,false,false,false);
|
||||
t("sh", false,false,false,true);
|
||||
t("notrust", false,false,false,true);
|
||||
t("ignore", false,false,true,false);
|
||||
t("should_fail", true,false,false,false);
|
||||
t("no_run", false,true,false,false);
|
||||
t("{.no_run .example}", false,true,false,false);
|
||||
t("{.sh .should_fail}", true,false,false,false);
|
||||
t("{.example .rust}", false,false,false,false);
|
||||
t("", false,false,false,false,false);
|
||||
t("rust", false,false,false,false,false);
|
||||
t("sh", false,false,false,true,false);
|
||||
t("notrust", false,false,false,true,false);
|
||||
t("ignore", false,false,true,false,false);
|
||||
t("should_fail", true,false,false,false,false);
|
||||
t("no_run", false,true,false,false,false);
|
||||
t("test_harness", false,false,false,false,true);
|
||||
t("{.no_run .example}", false,true,false,false,false);
|
||||
t("{.sh .should_fail}", true,false,false,false,false);
|
||||
t("{.example .rust}", false,false,false,false,false);
|
||||
t("{.test_harness .rust}", false,false,false,false,true);
|
||||
}
|
||||
}
|
||||
|
@ -102,8 +102,10 @@ pub fn run(input: &str,
|
||||
}
|
||||
|
||||
fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||
no_run: bool) {
|
||||
let test = maketest(test, Some(cratename), true);
|
||||
no_run: bool, as_test_harness: bool) {
|
||||
// the test harness wants its own `main` & top level functions, so
|
||||
// never wrap the test in `fn main() { ... }`
|
||||
let test = maketest(test, Some(cratename), true, as_test_harness);
|
||||
let input = driver::StrInput(test.to_string());
|
||||
|
||||
let sessopts = config::Options {
|
||||
@ -116,6 +118,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||
prefer_dynamic: true,
|
||||
.. config::basic_codegen_options()
|
||||
},
|
||||
test: as_test_harness,
|
||||
..config::basic_options().clone()
|
||||
};
|
||||
|
||||
@ -200,7 +203,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maketest(s: &str, cratename: Option<&str>, lints: bool) -> String {
|
||||
pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String {
|
||||
let mut prog = String::new();
|
||||
if lints {
|
||||
prog.push_str(r"
|
||||
@ -220,7 +223,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool) -> String {
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
if s.contains("fn main") {
|
||||
if dont_insert_main || s.contains("fn main") {
|
||||
prog.push_str(s);
|
||||
} else {
|
||||
prog.push_str("fn main() {\n ");
|
||||
@ -255,7 +258,8 @@ impl Collector {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_test(&mut self, test: String, should_fail: bool, no_run: bool, should_ignore: bool) {
|
||||
pub fn add_test(&mut self, test: String,
|
||||
should_fail: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) {
|
||||
let name = if self.use_headers {
|
||||
let s = self.current_header.as_ref().map(|s| s.as_slice()).unwrap_or("");
|
||||
format!("{}_{}", s, self.cnt)
|
||||
@ -277,7 +281,8 @@ impl Collector {
|
||||
cratename.as_slice(),
|
||||
libs,
|
||||
should_fail,
|
||||
no_run);
|
||||
no_run,
|
||||
as_test_harness);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user