diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 61e53f53e9797..2e9df48d00002 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1327,661 +1327,4 @@ impl<'a> Builder<'a> { } #[cfg(test)] -mod __test { - use super::*; - use crate::config::Config; - use std::thread; - - use pretty_assertions::assert_eq; - - fn configure(host: &[&str], target: &[&str]) -> Config { - let mut config = Config::default_opts(); - // don't save toolstates - config.save_toolstates = None; - config.skip_only_host_steps = false; - config.dry_run = true; - // try to avoid spurious failures in dist where we create/delete each others file - let dir = config.out.join("tmp-rustbuild-tests").join( - &thread::current() - .name() - .unwrap_or("unknown") - .replace(":", "-"), - ); - t!(fs::create_dir_all(&dir)); - config.out = dir; - config.build = INTERNER.intern_str("A"); - config.hosts = vec![config.build] - .clone() - .into_iter() - .chain(host.iter().map(|s| INTERNER.intern_str(s))) - .collect::>(); - config.targets = config - .hosts - .clone() - .into_iter() - .chain(target.iter().map(|s| INTERNER.intern_str(s))) - .collect::>(); - config - } - - fn first(v: Vec<(A, B)>) -> Vec { - v.into_iter().map(|(a, _)| a).collect::>() - } - - #[test] - fn dist_baseline() { - let build = Build::new(configure(&[], &[])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - - assert_eq!( - first(builder.cache.all::()), - &[dist::Docs { host: a },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - },] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_targets() { - let build = Build::new(configure(&[], &["B"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_hosts() { - let build = Build::new(configure(&["B"], &[])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_only_cross_host() { - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let mut build = Build::new(configure(&["B"], &[])); - build.config.docs = false; - build.config.extended = true; - build.hosts = vec![b]; - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - } - - #[test] - fn dist_with_targets_and_hosts() { - let build = Build::new(configure(&["B"], &["C"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - dist::Docs { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.skip_only_host_steps = true; // as-if --target=C was passed - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - dist::Docs { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[]); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[]); - } - - #[test] - fn dist_with_same_targets_and_hosts() { - let build = Build::new(configure(&["B"], &["B"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Std { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { - target_compiler: Compiler { host: a, stage: 0 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 1 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 2 }, - }, - compile::Assemble { - target_compiler: Compiler { host: b, stage: 2 }, - }, - ] - ); - } - - #[test] - fn build_default() { - let build = Build::new(configure(&["B"], &["C"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); - assert!(!builder.cache.all::().is_empty()); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); - } - - #[test] - fn build_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.skip_only_host_steps = true; - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { - target_compiler: Compiler { host: a, stage: 0 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 1 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 2 }, - }, - compile::Assemble { - target_compiler: Compiler { host: b, stage: 2 }, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); - } - - #[test] - fn test_with_no_doc_stage0() { - let mut config = configure(&[], &[]); - config.stage = Some(0); - config.cmd = Subcommand::Test { - paths: vec!["src/libstd".into()], - test_args: vec![], - rustc_args: vec![], - fail_fast: true, - doc_tests: DocTests::No, - bless: false, - compare_mode: None, - rustfix_coverage: false, - }; - - let build = Build::new(config); - let mut builder = Builder::new(&build); - - let host = INTERNER.intern_str("A"); - - builder.run_step_descriptions( - &[StepDescription::from::()], - &["src/libstd".into()], - ); - - // Ensure we don't build any compiler artifacts. - assert!(!builder.cache.contains::()); - assert_eq!( - first(builder.cache.all::()), - &[test::Crate { - compiler: Compiler { host, stage: 0 }, - target: host, - mode: Mode::Std, - test_kind: test::TestKind::Test, - krate: INTERNER.intern_str("std"), - },] - ); - } - - #[test] - fn test_exclude() { - let mut config = configure(&[], &[]); - config.exclude = vec![ - "src/test/run-pass".into(), - "src/tools/tidy".into(), - ]; - config.cmd = Subcommand::Test { - paths: Vec::new(), - test_args: Vec::new(), - rustc_args: Vec::new(), - fail_fast: true, - doc_tests: DocTests::No, - bless: false, - compare_mode: None, - rustfix_coverage: false, - }; - - let build = Build::new(config); - let builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); - - // Ensure we have really excluded run-pass & tidy - assert!(!builder.cache.contains::()); - assert!(!builder.cache.contains::()); - - // Ensure other tests are not affected. - assert!(builder.cache.contains::()); - assert!(builder.cache.contains::()); - } -} +mod tests; diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs new file mode 100644 index 0000000000000..46c58d118f743 --- /dev/null +++ b/src/bootstrap/builder/tests.rs @@ -0,0 +1,656 @@ +use super::*; +use crate::config::Config; +use std::thread; + +use pretty_assertions::assert_eq; + +fn configure(host: &[&str], target: &[&str]) -> Config { + let mut config = Config::default_opts(); + // don't save toolstates + config.save_toolstates = None; + config.skip_only_host_steps = false; + config.dry_run = true; + // try to avoid spurious failures in dist where we create/delete each others file + let dir = config.out.join("tmp-rustbuild-tests").join( + &thread::current() + .name() + .unwrap_or("unknown") + .replace(":", "-"), + ); + t!(fs::create_dir_all(&dir)); + config.out = dir; + config.build = INTERNER.intern_str("A"); + config.hosts = vec![config.build] + .clone() + .into_iter() + .chain(host.iter().map(|s| INTERNER.intern_str(s))) + .collect::>(); + config.targets = config + .hosts + .clone() + .into_iter() + .chain(target.iter().map(|s| INTERNER.intern_str(s))) + .collect::>(); + config +} + +fn first(v: Vec<(A, B)>) -> Vec { + v.into_iter().map(|(a, _)| a).collect::>() +} + +#[test] +fn dist_baseline() { + let build = Build::new(configure(&[], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + + assert_eq!( + first(builder.cache.all::()), + &[dist::Docs { host: a },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + },] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_targets() { + let build = Build::new(configure(&[], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_hosts() { + let build = Build::new(configure(&["B"], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_only_cross_host() { + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let mut build = Build::new(configure(&["B"], &[])); + build.config.docs = false; + build.config.extended = true; + build.hosts = vec![b]; + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); +} + +#[test] +fn dist_with_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; // as-if --target=C was passed + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[]); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[]); +} + +#[test] +fn dist_with_same_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Std { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ] + ); +} + +#[test] +fn build_default() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + ] + ); + + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); +} + +#[test] +fn build_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); +} + +#[test] +fn test_with_no_doc_stage0() { + let mut config = configure(&[], &[]); + config.stage = Some(0); + config.cmd = Subcommand::Test { + paths: vec!["src/libstd".into()], + test_args: vec![], + rustc_args: vec![], + fail_fast: true, + doc_tests: DocTests::No, + bless: false, + compare_mode: None, + rustfix_coverage: false, + }; + + let build = Build::new(config); + let mut builder = Builder::new(&build); + + let host = INTERNER.intern_str("A"); + + builder.run_step_descriptions( + &[StepDescription::from::()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(!builder.cache.contains::()); + assert_eq!( + first(builder.cache.all::()), + &[test::Crate { + compiler: Compiler { host, stage: 0 }, + target: host, + mode: Mode::Std, + test_kind: test::TestKind::Test, + krate: INTERNER.intern_str("std"), + },] + ); +} + +#[test] +fn test_exclude() { + let mut config = configure(&[], &[]); + config.exclude = vec![ + "src/test/run-pass".into(), + "src/tools/tidy".into(), + ]; + config.cmd = Subcommand::Test { + paths: Vec::new(), + test_args: Vec::new(), + rustc_args: Vec::new(), + fail_fast: true, + doc_tests: DocTests::No, + bless: false, + compare_mode: None, + rustfix_coverage: false, + }; + + let build = Build::new(config); + let builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); + + // Ensure we have really excluded run-pass & tidy + assert!(!builder.cache.contains::()); + assert!(!builder.cache.contains::()); + + // Ensure other tests are not affected. + assert!(builder.cache.contains::()); + assert!(builder.cache.contains::()); +} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index c530ac24275c2..5fc58c8ab5a7b 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -141,7 +141,7 @@ mod boxed { pub use std::boxed::Box; } #[cfg(test)] -mod boxed_test; +mod tests; pub mod collections; #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub mod sync; diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/tests.rs similarity index 100% rename from src/liballoc/boxed_test.rs rename to src/liballoc/tests.rs diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 1739b2236e89d..e2a249c8e61c0 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -617,218 +617,4 @@ impl SyncDroplessArena { } #[cfg(test)] -mod tests { - extern crate test; - use test::Bencher; - use super::TypedArena; - use std::cell::Cell; - - #[allow(dead_code)] - #[derive(Debug, Eq, PartialEq)] - struct Point { - x: i32, - y: i32, - z: i32, - } - - #[test] - pub fn test_unused() { - let arena: TypedArena = TypedArena::default(); - assert!(arena.chunks.borrow().is_empty()); - } - - #[test] - fn test_arena_alloc_nested() { - struct Inner { - value: u8, - } - struct Outer<'a> { - inner: &'a Inner, - } - enum EI<'e> { - I(Inner), - O(Outer<'e>), - } - - struct Wrap<'a>(TypedArena>); - - impl<'a> Wrap<'a> { - fn alloc_inner Inner>(&self, f: F) -> &Inner { - let r: &EI<'_> = self.0.alloc(EI::I(f())); - if let &EI::I(ref i) = r { - i - } else { - panic!("mismatch"); - } - } - fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> { - let r: &EI<'_> = self.0.alloc(EI::O(f())); - if let &EI::O(ref o) = r { - o - } else { - panic!("mismatch"); - } - } - } - - let arena = Wrap(TypedArena::default()); - - let result = arena.alloc_outer(|| Outer { - inner: arena.alloc_inner(|| Inner { value: 10 }), - }); - - assert_eq!(result.inner.value, 10); - } - - #[test] - pub fn test_copy() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - } - } - - #[bench] - pub fn bench_copy(b: &mut Bencher) { - let arena = TypedArena::default(); - b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) - } - - #[bench] - pub fn bench_copy_nonarena(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); - }) - } - - #[allow(dead_code)] - struct Noncopy { - string: String, - array: Vec, - } - - #[test] - pub fn test_noncopy() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }); - } - } - - #[test] - pub fn test_typed_arena_zero_sized() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(()); - } - } - - #[test] - pub fn test_typed_arena_clear() { - let mut arena = TypedArena::default(); - for _ in 0..10 { - arena.clear(); - for _ in 0..10000 { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - } - } - } - - #[bench] - pub fn bench_typed_arena_clear(b: &mut Bencher) { - let mut arena = TypedArena::default(); - b.iter(|| { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - arena.clear(); - }) - } - - // Drop tests - - struct DropCounter<'a> { - count: &'a Cell, - } - - impl Drop for DropCounter<'_> { - fn drop(&mut self) { - self.count.set(self.count.get() + 1); - } - } - - #[test] - fn test_typed_arena_drop_count() { - let counter = Cell::new(0); - { - let arena: TypedArena> = TypedArena::default(); - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(DropCounter { count: &counter }); - } - }; - assert_eq!(counter.get(), 100); - } - - #[test] - fn test_typed_arena_drop_on_clear() { - let counter = Cell::new(0); - let mut arena: TypedArena> = TypedArena::default(); - for i in 0..10 { - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(DropCounter { count: &counter }); - } - arena.clear(); - assert_eq!(counter.get(), i * 100 + 100); - } - } - - thread_local! { - static DROP_COUNTER: Cell = Cell::new(0) - } - - struct SmallDroppable; - - impl Drop for SmallDroppable { - fn drop(&mut self) { - DROP_COUNTER.with(|c| c.set(c.get() + 1)); - } - } - - #[test] - fn test_typed_arena_drop_small_count() { - DROP_COUNTER.with(|c| c.set(0)); - { - let arena: TypedArena = TypedArena::default(); - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(SmallDroppable); - } - // dropping - }; - assert_eq!(DROP_COUNTER.with(|c| c.get()), 100); - } - - #[bench] - pub fn bench_noncopy(b: &mut Bencher) { - let arena = TypedArena::default(); - b.iter(|| { - arena.alloc(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }) - }) - } - - #[bench] - pub fn bench_noncopy_nonarena(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = Box::new(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }); - }) - } -} +mod tests; diff --git a/src/libarena/tests.rs b/src/libarena/tests.rs new file mode 100644 index 0000000000000..fa4189409d0e8 --- /dev/null +++ b/src/libarena/tests.rs @@ -0,0 +1,213 @@ +extern crate test; +use test::Bencher; +use super::TypedArena; +use std::cell::Cell; + +#[allow(dead_code)] +#[derive(Debug, Eq, PartialEq)] +struct Point { + x: i32, + y: i32, + z: i32, +} + +#[test] +pub fn test_unused() { + let arena: TypedArena = TypedArena::default(); + assert!(arena.chunks.borrow().is_empty()); +} + +#[test] +fn test_arena_alloc_nested() { + struct Inner { + value: u8, + } + struct Outer<'a> { + inner: &'a Inner, + } + enum EI<'e> { + I(Inner), + O(Outer<'e>), + } + + struct Wrap<'a>(TypedArena>); + + impl<'a> Wrap<'a> { + fn alloc_inner Inner>(&self, f: F) -> &Inner { + let r: &EI<'_> = self.0.alloc(EI::I(f())); + if let &EI::I(ref i) = r { + i + } else { + panic!("mismatch"); + } + } + fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> { + let r: &EI<'_> = self.0.alloc(EI::O(f())); + if let &EI::O(ref o) = r { + o + } else { + panic!("mismatch"); + } + } + } + + let arena = Wrap(TypedArena::default()); + + let result = arena.alloc_outer(|| Outer { + inner: arena.alloc_inner(|| Inner { value: 10 }), + }); + + assert_eq!(result.inner.value, 10); +} + +#[test] +pub fn test_copy() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + } +} + +#[bench] +pub fn bench_copy(b: &mut Bencher) { + let arena = TypedArena::default(); + b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) +} + +#[bench] +pub fn bench_copy_nonarena(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); + }) +} + +#[allow(dead_code)] +struct Noncopy { + string: String, + array: Vec, +} + +#[test] +pub fn test_noncopy() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }); + } +} + +#[test] +pub fn test_typed_arena_zero_sized() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(()); + } +} + +#[test] +pub fn test_typed_arena_clear() { + let mut arena = TypedArena::default(); + for _ in 0..10 { + arena.clear(); + for _ in 0..10000 { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + } + } +} + +#[bench] +pub fn bench_typed_arena_clear(b: &mut Bencher) { + let mut arena = TypedArena::default(); + b.iter(|| { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + arena.clear(); + }) +} + +// Drop tests + +struct DropCounter<'a> { + count: &'a Cell, +} + +impl Drop for DropCounter<'_> { + fn drop(&mut self) { + self.count.set(self.count.get() + 1); + } +} + +#[test] +fn test_typed_arena_drop_count() { + let counter = Cell::new(0); + { + let arena: TypedArena> = TypedArena::default(); + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(DropCounter { count: &counter }); + } + }; + assert_eq!(counter.get(), 100); +} + +#[test] +fn test_typed_arena_drop_on_clear() { + let counter = Cell::new(0); + let mut arena: TypedArena> = TypedArena::default(); + for i in 0..10 { + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(DropCounter { count: &counter }); + } + arena.clear(); + assert_eq!(counter.get(), i * 100 + 100); + } +} + +thread_local! { + static DROP_COUNTER: Cell = Cell::new(0) +} + +struct SmallDroppable; + +impl Drop for SmallDroppable { + fn drop(&mut self) { + DROP_COUNTER.with(|c| c.set(c.get() + 1)); + } +} + +#[test] +fn test_typed_arena_drop_small_count() { + DROP_COUNTER.with(|c| c.set(0)); + { + let arena: TypedArena = TypedArena::default(); + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(SmallDroppable); + } + // dropping + }; + assert_eq!(DROP_COUNTER.with(|c| c.get()), 100); +} + +#[bench] +pub fn bench_noncopy(b: &mut Bencher) { + let arena = TypedArena::default(); + b.iter(|| { + arena.alloc(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }) + }) +} + +#[bench] +pub fn bench_noncopy_nonarena(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = Box::new(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }); + }) +} diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 7d0a0035dc846..f6e9143dd0583 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -622,248 +622,4 @@ impl<'a> Parser<'a> { } #[cfg(test)] -mod tests { - use super::*; - - fn same(fmt: &'static str, p: &[Piece<'static>]) { - let parser = Parser::new(fmt, None, vec![], false); - assert!(parser.collect::>>() == p); - } - - fn fmtdflt() -> FormatSpec<'static> { - return FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }; - } - - fn musterr(s: &str) { - let mut p = Parser::new(s, None, vec![], false); - p.next(); - assert!(!p.errors.is_empty()); - } - - #[test] - fn simple() { - same("asdf", &[String("asdf")]); - same("a{{b", &[String("a"), String("{b")]); - same("a}}b", &[String("a"), String("}b")]); - same("a}}", &[String("a"), String("}")]); - same("}}", &[String("}")]); - same("\\}}", &[String("\\"), String("}")]); - } - - #[test] - fn invalid01() { - musterr("{") - } - #[test] - fn invalid02() { - musterr("}") - } - #[test] - fn invalid04() { - musterr("{3a}") - } - #[test] - fn invalid05() { - musterr("{:|}") - } - #[test] - fn invalid06() { - musterr("{:>>>}") - } - - #[test] - fn format_nothing() { - same("{}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: fmtdflt(), - })]); - } - #[test] - fn format_position() { - same("{3}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: fmtdflt(), - })]); - } - #[test] - fn format_position_nothing_else() { - same("{3:}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: fmtdflt(), - })]); - } - #[test] - fn format_type() { - same("{3:a}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "a", - }, - })]); - } - #[test] - fn format_align_fill() { - same("{3:>}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignRight, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:0<}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: Some('0'), - align: AlignLeft, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:*]) { + let parser = Parser::new(fmt, None, vec![], false); + assert!(parser.collect::>>() == p); +} + +fn fmtdflt() -> FormatSpec<'static> { + return FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }; +} + +fn musterr(s: &str) { + let mut p = Parser::new(s, None, vec![], false); + p.next(); + assert!(!p.errors.is_empty()); +} + +#[test] +fn simple() { + same("asdf", &[String("asdf")]); + same("a{{b", &[String("a"), String("{b")]); + same("a}}b", &[String("a"), String("}b")]); + same("a}}", &[String("a"), String("}")]); + same("}}", &[String("}")]); + same("\\}}", &[String("\\"), String("}")]); +} + +#[test] +fn invalid01() { + musterr("{") +} +#[test] +fn invalid02() { + musterr("}") +} +#[test] +fn invalid04() { + musterr("{3a}") +} +#[test] +fn invalid05() { + musterr("{:|}") +} +#[test] +fn invalid06() { + musterr("{:>>>}") +} + +#[test] +fn format_nothing() { + same("{}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: fmtdflt(), + })]); +} +#[test] +fn format_position() { + same("{3}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: fmtdflt(), + })]); +} +#[test] +fn format_position_nothing_else() { + same("{3:}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: fmtdflt(), + })]); +} +#[test] +fn format_type() { + same("{3:a}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "a", + }, + })]); +} +#[test] +fn format_align_fill() { + same("{3:>}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignRight, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); + same("{3:0<}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: Some('0'), + align: AlignLeft, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); + same("{3:*(g: &'a G, } #[cfg(test)] -mod tests { - use NodeLabels::*; - use super::{Id, Labeller, Nodes, Edges, GraphWalk, render, Style}; - use super::LabelText::{self, LabelStr, EscStr, HtmlStr}; - use std::io; - use std::io::prelude::*; - - /// each node is an index in a vector in the graph. - type Node = usize; - struct Edge { - from: usize, - to: usize, - label: &'static str, - style: Style, - } - - fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge { - Edge { - from, - to, - label, - style, - } - } - - struct LabelledGraph { - /// The name for this graph. Used for labeling generated `digraph`. - name: &'static str, - - /// Each node is an index into `node_labels`; these labels are - /// used as the label text for each node. (The node *names*, - /// which are unique identifiers, are derived from their index - /// in this array.) - /// - /// If a node maps to None here, then just use its name as its - /// text. - node_labels: Vec>, - - node_styles: Vec