提交 11bdeea7 编写于 作者: H Huon Wilson

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).
上级 a17b0421
......@@ -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 @@ fn all_false() -> LangString {
no_run: false,
ignore: false,
notrust: false,
test_harness: false,
}
}
......@@ -401,6 +403,7 @@ fn parse(string: &str) -> 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 @@ pub fn new(cratename: String, libs: HashSet<Path>,
}
}
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 @@ pub fn add_test(&mut self, test: String, should_fail: bool, no_run: bool, should
cratename.as_slice(),
libs,
should_fail,
no_run);
no_run,
as_test_harness);
}),
});
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册