Added ability to crosscompile doctests
This commit is contained in:
@@ -77,6 +77,10 @@ pub struct Options {
|
||||
/// Optional path to persist the doctest executables to, defaults to a
|
||||
/// temporary directory if not set.
|
||||
pub persist_doctests: Option<PathBuf>,
|
||||
/// Runtool to run doctests with
|
||||
pub runtool: Option<String>,
|
||||
/// Arguments to pass to the runtool
|
||||
pub runtool_args: Vec<String>,
|
||||
|
||||
// Options that affect the documentation process
|
||||
|
||||
@@ -140,6 +144,8 @@ impl fmt::Debug for Options {
|
||||
.field("show_coverage", &self.show_coverage)
|
||||
.field("crate_version", &self.crate_version)
|
||||
.field("render_options", &self.render_options)
|
||||
.field("runtool", &self.runtool)
|
||||
.field("runtool_args", &self.runtool_args)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@@ -466,6 +472,8 @@ impl Options {
|
||||
let codegen_options_strs = matches.opt_strs("C");
|
||||
let lib_strs = matches.opt_strs("L");
|
||||
let extern_strs = matches.opt_strs("extern");
|
||||
let runtool = matches.opt_str("runtool");
|
||||
let runtool_args = matches.opt_strs("runtool-arg");
|
||||
|
||||
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
|
||||
|
||||
@@ -496,6 +504,8 @@ impl Options {
|
||||
show_coverage,
|
||||
crate_version,
|
||||
persist_doctests,
|
||||
runtool,
|
||||
runtool_args,
|
||||
render_options: RenderOptions {
|
||||
output,
|
||||
external_html,
|
||||
|
||||
@@ -272,7 +272,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
))
|
||||
});
|
||||
|
||||
let tooltip = if ignore {
|
||||
let tooltip = if ignore != Ignore::None {
|
||||
Some(("This example is not tested".to_owned(), "ignore"))
|
||||
} else if compile_fail {
|
||||
Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
|
||||
@@ -286,7 +286,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
s.push_str(&highlight::render_with_highlighting(
|
||||
&text,
|
||||
Some(&format!("rust-example-rendered{}",
|
||||
if ignore { " ignore" }
|
||||
if ignore != Ignore::None { " ignore" }
|
||||
else if compile_fail { " compile_fail" }
|
||||
else if explicit_edition { " edition " }
|
||||
else { "" })),
|
||||
@@ -297,7 +297,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
s.push_str(&highlight::render_with_highlighting(
|
||||
&text,
|
||||
Some(&format!("rust-example-rendered{}",
|
||||
if ignore { " ignore" }
|
||||
if ignore != Ignore::None { " ignore" }
|
||||
else if compile_fail { " compile_fail" }
|
||||
else if explicit_edition { " edition " }
|
||||
else { "" })),
|
||||
@@ -607,7 +607,7 @@ pub struct LangString {
|
||||
original: String,
|
||||
pub should_panic: bool,
|
||||
pub no_run: bool,
|
||||
pub ignore: bool,
|
||||
pub ignore: Ignore,
|
||||
pub rust: bool,
|
||||
pub test_harness: bool,
|
||||
pub compile_fail: bool,
|
||||
@@ -616,13 +616,20 @@ pub struct LangString {
|
||||
pub edition: Option<Edition>
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||
pub enum Ignore {
|
||||
All,
|
||||
None,
|
||||
Some(Vec<String>),
|
||||
}
|
||||
|
||||
impl LangString {
|
||||
fn all_false() -> LangString {
|
||||
LangString {
|
||||
original: String::new(),
|
||||
should_panic: false,
|
||||
no_run: false,
|
||||
ignore: false,
|
||||
ignore: Ignore::None,
|
||||
rust: true, // NB This used to be `notrust = false`
|
||||
test_harness: false,
|
||||
compile_fail: false,
|
||||
@@ -637,6 +644,7 @@ impl LangString {
|
||||
let mut seen_rust_tags = false;
|
||||
let mut seen_other_tags = false;
|
||||
let mut data = LangString::all_false();
|
||||
let mut ignores = vec![];
|
||||
|
||||
data.original = string.to_owned();
|
||||
let tokens = string.split(|c: char|
|
||||
@@ -651,7 +659,11 @@ impl LangString {
|
||||
seen_rust_tags = seen_other_tags == false;
|
||||
}
|
||||
"no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
|
||||
"ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
|
||||
"ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; }
|
||||
x if x.starts_with("ignore-") => {
|
||||
ignores.push(x.trim_start_matches("ignore-").to_owned());
|
||||
seen_rust_tags = !seen_other_tags;
|
||||
}
|
||||
"allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
|
||||
"rust" => { data.rust = true; seen_rust_tags = true; }
|
||||
"test_harness" => {
|
||||
@@ -680,6 +692,16 @@ impl LangString {
|
||||
}
|
||||
}
|
||||
|
||||
match data.ignore {
|
||||
Ignore::All => {},
|
||||
Ignore::None => {
|
||||
if !ignores.is_empty() {
|
||||
data.ignore = Ignore::Some(ignores);
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
data.rust &= !seen_other_tags || seen_rust_tags;
|
||||
|
||||
data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
|
||||
use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap, Ignore};
|
||||
use super::plain_summary_line;
|
||||
use std::cell::RefCell;
|
||||
use syntax::edition::{Edition, DEFAULT_EDITION};
|
||||
@@ -26,10 +26,10 @@ fn test_unique_id() {
|
||||
#[test]
|
||||
fn test_lang_string_parse() {
|
||||
fn t(s: &str,
|
||||
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
|
||||
should_panic: bool, no_run: bool, ignore: Ignore, rust: bool, test_harness: bool,
|
||||
compile_fail: bool, allow_fail: bool, error_codes: Vec<String>,
|
||||
edition: Option<Edition>) {
|
||||
assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
|
||||
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true), LangString {
|
||||
should_panic,
|
||||
no_run,
|
||||
ignore,
|
||||
@@ -42,6 +42,7 @@ fn test_lang_string_parse() {
|
||||
edition,
|
||||
})
|
||||
}
|
||||
let ignore_foo = Ignore::Some(vec!("foo".to_string()));
|
||||
|
||||
fn v() -> Vec<String> {
|
||||
Vec::new()
|
||||
@@ -50,23 +51,24 @@ fn test_lang_string_parse() {
|
||||
// ignore-tidy-linelength
|
||||
// marker | should_panic | no_run | ignore | rust | test_harness
|
||||
// | compile_fail | allow_fail | error_codes | edition
|
||||
t("", false, false, false, true, false, false, false, v(), None);
|
||||
t("rust", false, false, false, true, false, false, false, v(), None);
|
||||
t("sh", false, false, false, false, false, false, false, v(), None);
|
||||
t("ignore", false, false, true, true, false, false, false, v(), None);
|
||||
t("should_panic", true, false, false, true, false, false, false, v(), None);
|
||||
t("no_run", false, true, false, true, false, false, false, v(), None);
|
||||
t("test_harness", false, false, false, true, true, false, false, v(), None);
|
||||
t("compile_fail", false, true, false, true, false, true, false, v(), None);
|
||||
t("allow_fail", false, false, false, true, false, false, true, v(), None);
|
||||
t("{.no_run .example}", false, true, false, true, false, false, false, v(), None);
|
||||
t("{.sh .should_panic}", true, false, false, false, false, false, false, v(), None);
|
||||
t("{.example .rust}", false, false, false, true, false, false, false, v(), None);
|
||||
t("{.test_harness .rust}", false, false, false, true, true, false, false, v(), None);
|
||||
t("text, no_run", false, true, false, false, false, false, false, v(), None);
|
||||
t("text,no_run", false, true, false, false, false, false, false, v(), None);
|
||||
t("edition2015", false, false, false, true, false, false, false, v(), Some(Edition::Edition2015));
|
||||
t("edition2018", false, false, false, true, false, false, false, v(), Some(Edition::Edition2018));
|
||||
t("", false, false, Ignore::None, true, false, false, false, v(), None);
|
||||
t("rust", false, false, Ignore::None, true, false, false, false, v(), None);
|
||||
t("sh", false, false, Ignore::None, false, false, false, false, v(), None);
|
||||
t("ignore", false, false, Ignore::All, true, false, false, false, v(), None);
|
||||
t("ignore-foo", false, false, ignore_foo, true, false, false, false, v(), None);
|
||||
t("should_panic", true, false, Ignore::None, true, false, false, false, v(), None);
|
||||
t("no_run", false, true, Ignore::None, true, false, false, false, v(), None);
|
||||
t("test_harness", false, false, Ignore::None, true, true, false, false, v(), None);
|
||||
t("compile_fail", false, true, Ignore::None, true, false, true, false, v(), None);
|
||||
t("allow_fail", false, false, Ignore::None, true, false, false, true, v(), None);
|
||||
t("{.no_run .example}", false, true, Ignore::None, true, false, false, false, v(), None);
|
||||
t("{.sh .should_panic}", true, false, Ignore::None, false, false, false, false, v(), None);
|
||||
t("{.example .rust}", false, false, Ignore::None, true, false, false, false, v(), None);
|
||||
t("{.test_harness .rust}", false, false, Ignore::None, true, true, false, false, v(), None);
|
||||
t("text, no_run", false, true, Ignore::None, false, false, false, false, v(), None);
|
||||
t("text,no_run", false, true, Ignore::None, false, false, false, false, v(), None);
|
||||
t("edition2015", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2015));
|
||||
t("edition2018", false, false, Ignore::None, true, false, false, false, v(), Some(Edition::Edition2018));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -355,6 +355,18 @@ fn opts() -> Vec<RustcOptGroup> {
|
||||
"show-coverage",
|
||||
"calculate percentage of public items with documentation")
|
||||
}),
|
||||
unstable("runtool", |o| {
|
||||
o.optopt("",
|
||||
"runtool",
|
||||
"",
|
||||
"The tool to run tests with when building for a different target than host")
|
||||
}),
|
||||
unstable("runtool-arg", |o| {
|
||||
o.optmulti("",
|
||||
"runtool-arg",
|
||||
"",
|
||||
"One (of possibly many) arguments to pass to the runtool")
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_interface::interface;
|
||||
use rustc_target::spec::TargetTriple;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit;
|
||||
use rustc::session::{self, config, DiagnosticOutput};
|
||||
@@ -22,7 +23,7 @@ use testing;
|
||||
|
||||
use crate::clean::Attributes;
|
||||
use crate::config::Options;
|
||||
use crate::html::markdown::{self, ErrorCodes, LangString};
|
||||
use crate::html::markdown::{self, ErrorCodes, LangString, Ignore};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct TestOptions {
|
||||
@@ -44,7 +45,7 @@ pub fn run(options: Options) -> i32 {
|
||||
vec![config::CrateType::Dylib]
|
||||
};
|
||||
|
||||
let sessopts = config::Options {
|
||||
let mut sessopts = config::Options {
|
||||
maybe_sysroot: options.maybe_sysroot.clone(),
|
||||
search_paths: options.libs.clone(),
|
||||
crate_types,
|
||||
@@ -59,7 +60,7 @@ pub fn run(options: Options) -> i32 {
|
||||
edition: options.edition,
|
||||
..config::Options::default()
|
||||
};
|
||||
|
||||
options.target.as_ref().map(|t| { sessopts.target_triple = t.clone() });
|
||||
let config = interface::Config {
|
||||
opts: sessopts,
|
||||
crate_cfg: config::parse_cfgspecs(options.cfgs.clone()),
|
||||
@@ -181,6 +182,9 @@ fn run_test(
|
||||
should_panic: bool,
|
||||
no_run: bool,
|
||||
as_test_harness: bool,
|
||||
runtool: Option<String>,
|
||||
runtool_args: Vec<String>,
|
||||
target: Option<TargetTriple>,
|
||||
compile_fail: bool,
|
||||
mut error_codes: Vec<String>,
|
||||
opts: &TestOptions,
|
||||
@@ -315,7 +319,15 @@ fn run_test(
|
||||
}
|
||||
|
||||
// Run the code!
|
||||
let mut cmd = Command::new(output_file);
|
||||
let mut cmd;
|
||||
|
||||
if let Some(tool) = runtool {
|
||||
cmd = Command::new(tool);
|
||||
cmd.arg(output_file);
|
||||
cmd.args(runtool_args);
|
||||
}else{
|
||||
cmd = Command::new(output_file);
|
||||
}
|
||||
|
||||
match cmd.output() {
|
||||
Err(e) => return Err(TestFailure::ExecutionError(e)),
|
||||
@@ -661,12 +673,27 @@ impl Tester for Collector {
|
||||
let opts = self.opts.clone();
|
||||
let edition = config.edition.unwrap_or(self.options.edition.clone());
|
||||
let options = self.options.clone();
|
||||
let maybe_sysroot = self.maybe_sysroot.clone();
|
||||
let linker = self.linker.clone();
|
||||
let edition = config.edition.unwrap_or(self.edition);
|
||||
let persist_doctests = self.persist_doctests.clone();
|
||||
let runtool = self.runtool.clone();
|
||||
let runtool_args = self.runtool_args.clone();
|
||||
let target = self.target.clone();
|
||||
let target_str = target.as_ref().map(|t| t.to_string());
|
||||
|
||||
debug!("creating test {}: {}", name, test);
|
||||
self.tests.push(testing::TestDescAndFn {
|
||||
desc: testing::TestDesc {
|
||||
name: testing::DynTestName(name),
|
||||
ignore: config.ignore,
|
||||
name: testing::DynTestName(name.clone()),
|
||||
ignore: match config.ignore {
|
||||
Ignore::All => true,
|
||||
Ignore::None => false,
|
||||
Ignore::Some(ref ignores) => {
|
||||
target_str.map_or(false,
|
||||
|s| ignores.iter().any(|t| s.contains(t)))
|
||||
},
|
||||
},
|
||||
// compiler failures are test failures
|
||||
should_panic: testing::ShouldPanic::No,
|
||||
allow_fail: config.allow_fail,
|
||||
@@ -681,6 +708,9 @@ impl Tester for Collector {
|
||||
config.should_panic,
|
||||
config.no_run,
|
||||
config.test_harness,
|
||||
runtool,
|
||||
runtool_args,
|
||||
target,
|
||||
config.compile_fail,
|
||||
config.error_codes,
|
||||
&opts,
|
||||
|
||||
Reference in New Issue
Block a user