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::<Vec<_>>(); - config.targets = config - .hosts - .clone() - .into_iter() - .chain(target.iter().map(|s| INTERNER.intern_str(s))) - .collect::<Vec<_>>(); - config - } - - fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> { - v.into_iter().map(|(a, _)| a).collect::<Vec<_>>() - } - - #[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>()), - &[dist::Docs { host: a },] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[dist::Mingw { host: a },] - ); - assert_eq!( - first(builder.cache.all::<dist::Rustc>()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[dist::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - },] - ); - assert_eq!(first(builder.cache.all::<dist::Src>()), &[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>()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::<dist::Rustc>()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[ - 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>()), &[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>()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::<dist::Rustc>()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[ - 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>()), &[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>()), - &[ - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::<compile::Rustc>()), - &[ - 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>()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - dist::Docs { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Rustc>()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[ - 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>()), &[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>()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - dist::Docs { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[ - 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_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>()), - &[ - dist::Docs { host: a }, - dist::Docs { host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Mingw>()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::<dist::Rustc>()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::<dist::Std>()), - &[ - 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>()), &[dist::Src]); - assert_eq!( - first(builder.cache.all::<compile::Std>()), - &[ - 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>()), - &[ - 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>()), - &[ - 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::<compile::Std>().is_empty()); - assert!(!builder.cache.all::<compile::Assemble>().is_empty()); - assert_eq!( - first(builder.cache.all::<compile::Rustc>()), - &[ - 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>()), - &[ - 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::<compile::Std>().is_empty()); - assert_eq!( - first(builder.cache.all::<compile::Assemble>()), - &[ - 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>()), - &[ - 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>()), - &[ - 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::<test::Crate>()], - &["src/libstd".into()], - ); - - // Ensure we don't build any compiler artifacts. - assert!(!builder.cache.contains::<compile::Rustc>()); - assert_eq!( - first(builder.cache.all::<test::Crate>()), - &[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::<test::RunPass>()); - assert!(!builder.cache.contains::<test::Tidy>()); - - // Ensure other tests are not affected. - assert!(builder.cache.contains::<test::RunPassFullDeps>()); - assert!(builder.cache.contains::<test::RustdocUi>()); - } -} +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::<Vec<_>>(); + config.targets = config + .hosts + .clone() + .into_iter() + .chain(target.iter().map(|s| INTERNER.intern_str(s))) + .collect::<Vec<_>>(); + config +} + +fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> { + v.into_iter().map(|(a, _)| a).collect::<Vec<_>>() +} + +#[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>()), + &[dist::Docs { host: a },] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[dist::Mingw { host: a },] + ); + assert_eq!( + first(builder.cache.all::<dist::Rustc>()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + },] + ); + assert_eq!(first(builder.cache.all::<dist::Src>()), &[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>()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::<dist::Rustc>()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[ + 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>()), &[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>()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::<dist::Rustc>()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[ + 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>()), &[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>()), + &[ + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::<compile::Rustc>()), + &[ + 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>()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Rustc>()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[ + 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>()), &[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>()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[ + 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_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>()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Mingw>()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::<dist::Rustc>()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::<dist::Std>()), + &[ + 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>()), &[dist::Src]); + assert_eq!( + first(builder.cache.all::<compile::Std>()), + &[ + 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>()), + &[ + 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>()), + &[ + 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::<compile::Std>().is_empty()); + assert!(!builder.cache.all::<compile::Assemble>().is_empty()); + assert_eq!( + first(builder.cache.all::<compile::Rustc>()), + &[ + 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>()), + &[ + 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::<compile::Std>().is_empty()); + assert_eq!( + first(builder.cache.all::<compile::Assemble>()), + &[ + 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>()), + &[ + 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>()), + &[ + 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::<test::Crate>()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(!builder.cache.contains::<compile::Rustc>()); + assert_eq!( + first(builder.cache.all::<test::Crate>()), + &[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::<test::RunPass>()); + assert!(!builder.cache.contains::<test::Tidy>()); + + // Ensure other tests are not affected. + assert!(builder.cache.contains::<test::RunPassFullDeps>()); + assert!(builder.cache.contains::<test::RustdocUi>()); +} 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<Point> = 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<EI<'a>>); - - impl<'a> Wrap<'a> { - fn alloc_inner<F: Fn() -> 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<F: Fn() -> 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<i32>, - } - - #[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<u32>, - } - - 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<DropCounter<'_>> = 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<DropCounter<'_>> = 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<u32> = 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<SmallDroppable> = 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<Point> = 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<EI<'a>>); + + impl<'a> Wrap<'a> { + fn alloc_inner<F: Fn() -> 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<F: Fn() -> 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<i32>, +} + +#[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<u32>, +} + +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<DropCounter<'_>> = 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<DropCounter<'_>> = 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<u32> = 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<SmallDroppable> = 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::<Vec<Piece<'static>>>() == 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:*<abcd}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: Some('*'), - align: AlignLeft, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "abcd", - }, - })]); - } - #[test] - fn format_counts() { - use syntax_pos::{GLOBALS, Globals, edition}; - GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { - same("{:10s}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountIs(10), - ty: "s", - }, - })]); - same("{:10$.10s}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountIs(10), - width: CountIsParam(10), - ty: "s", - }, - })]); - same("{:.*s}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(1), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountIsParam(0), - width: CountImplied, - ty: "s", - }, - })]); - same("{:.10$s}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountIsParam(10), - width: CountImplied, - ty: "s", - }, - })]); - same("{:a$.b$s}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountIsName(Symbol::intern("b")), - width: CountIsName(Symbol::intern("a")), - ty: "s", - }, - })]); - }); - } - #[test] - fn format_flags() { - same("{:-}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: (1 << FlagSignMinus as u32), - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{:+#}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32), - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - } - #[test] - fn format_mixture() { - same("abcd {3:a} efg", - &[String("abcd "), - NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "a", - }, - }), - String(" efg")]); - } -} +mod tests; diff --git a/src/libfmt_macros/tests.rs b/src/libfmt_macros/tests.rs new file mode 100644 index 0000000000000..7282d4a5f248b --- /dev/null +++ b/src/libfmt_macros/tests.rs @@ -0,0 +1,243 @@ +use super::*; + +fn same(fmt: &'static str, p: &[Piece<'static>]) { + let parser = Parser::new(fmt, None, vec![], false); + assert!(parser.collect::<Vec<Piece<'static>>>() == 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:*<abcd}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: Some('*'), + align: AlignLeft, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "abcd", + }, + })]); +} +#[test] +fn format_counts() { + use syntax_pos::{GLOBALS, Globals, edition}; + GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { + same("{:10s}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountIs(10), + ty: "s", + }, + })]); + same("{:10$.10s}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIs(10), + width: CountIsParam(10), + ty: "s", + }, + })]); + same("{:.*s}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(1), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIsParam(0), + width: CountImplied, + ty: "s", + }, + })]); + same("{:.10$s}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIsParam(10), + width: CountImplied, + ty: "s", + }, + })]); + same("{:a$.b$s}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIsName(Symbol::intern("b")), + width: CountIsName(Symbol::intern("a")), + ty: "s", + }, + })]); + }); +} +#[test] +fn format_flags() { + same("{:-}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: (1 << FlagSignMinus as u32), + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); + same("{:+#}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32), + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); +} +#[test] +fn format_mixture() { + same("abcd {3:a} efg", + &[String("abcd "), + NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "a", + }, + }), + String(" efg")]); +} diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 489020d4ee778..a34e4fb89ff27 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -684,385 +684,4 @@ pub fn render_opts<'a, N, E, G, W>(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<Option<&'static str>>, - - node_styles: Vec<Style>, - - /// Each edge relates a from-index to a to-index along with a - /// label; `edges` collects them. - edges: Vec<Edge>, - } - - // A simple wrapper around LabelledGraph that forces the labels to - // be emitted as EscStr. - struct LabelledGraphWithEscStrs { - graph: LabelledGraph, - } - - enum NodeLabels<L> { - AllNodesLabelled(Vec<L>), - UnlabelledNodes(usize), - SomeNodesLabelled(Vec<Option<L>>), - } - - type Trivial = NodeLabels<&'static str>; - - impl NodeLabels<&'static str> { - fn to_opt_strs(self) -> Vec<Option<&'static str>> { - match self { - UnlabelledNodes(len) => vec![None; len], - AllNodesLabelled(lbls) => lbls.into_iter().map(|l| Some(l)).collect(), - SomeNodesLabelled(lbls) => lbls.into_iter().collect(), - } - } - - fn len(&self) -> usize { - match self { - &UnlabelledNodes(len) => len, - &AllNodesLabelled(ref lbls) => lbls.len(), - &SomeNodesLabelled(ref lbls) => lbls.len(), - } - } - } - - impl LabelledGraph { - fn new(name: &'static str, - node_labels: Trivial, - edges: Vec<Edge>, - node_styles: Option<Vec<Style>>) - -> LabelledGraph { - let count = node_labels.len(); - LabelledGraph { - name, - node_labels: node_labels.to_opt_strs(), - edges, - node_styles: match node_styles { - Some(nodes) => nodes, - None => vec![Style::None; count], - }, - } - } - } - - impl LabelledGraphWithEscStrs { - fn new(name: &'static str, - node_labels: Trivial, - edges: Vec<Edge>) - -> LabelledGraphWithEscStrs { - LabelledGraphWithEscStrs { graph: LabelledGraph::new(name, node_labels, edges, None) } - } - } - - fn id_name<'a>(n: &Node) -> Id<'a> { - Id::new(format!("N{}", *n)).unwrap() - } - - impl<'a> Labeller<'a> for LabelledGraph { - type Node = Node; - type Edge = &'a Edge; - fn graph_id(&'a self) -> Id<'a> { - Id::new(self.name).unwrap() - } - fn node_id(&'a self, n: &Node) -> Id<'a> { - id_name(n) - } - fn node_label(&'a self, n: &Node) -> LabelText<'a> { - match self.node_labels[*n] { - Some(l) => LabelStr(l.into()), - None => LabelStr(id_name(n).name()), - } - } - fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { - LabelStr(e.label.into()) - } - fn node_style(&'a self, n: &Node) -> Style { - self.node_styles[*n] - } - fn edge_style(&'a self, e: &&'a Edge) -> Style { - e.style - } - } - - impl<'a> Labeller<'a> for LabelledGraphWithEscStrs { - type Node = Node; - type Edge = &'a Edge; - fn graph_id(&'a self) -> Id<'a> { - self.graph.graph_id() - } - fn node_id(&'a self, n: &Node) -> Id<'a> { - self.graph.node_id(n) - } - fn node_label(&'a self, n: &Node) -> LabelText<'a> { - match self.graph.node_label(n) { - LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s), - } - } - fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { - match self.graph.edge_label(e) { - LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s), - } - } - } - - impl<'a> GraphWalk<'a> for LabelledGraph { - type Node = Node; - type Edge = &'a Edge; - fn nodes(&'a self) -> Nodes<'a, Node> { - (0..self.node_labels.len()).collect() - } - fn edges(&'a self) -> Edges<'a, &'a Edge> { - self.edges.iter().collect() - } - fn source(&'a self, edge: &&'a Edge) -> Node { - edge.from - } - fn target(&'a self, edge: &&'a Edge) -> Node { - edge.to - } - } - - impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs { - type Node = Node; - type Edge = &'a Edge; - fn nodes(&'a self) -> Nodes<'a, Node> { - self.graph.nodes() - } - fn edges(&'a self) -> Edges<'a, &'a Edge> { - self.graph.edges() - } - fn source(&'a self, edge: &&'a Edge) -> Node { - edge.from - } - fn target(&'a self, edge: &&'a Edge) -> Node { - edge.to - } - } - - fn test_input(g: LabelledGraph) -> io::Result<String> { - let mut writer = Vec::new(); - render(&g, &mut writer).unwrap(); - let mut s = String::new(); - Read::read_to_string(&mut &*writer, &mut s)?; - Ok(s) - } - - // All of the tests use raw-strings as the format for the expected outputs, - // so that you can cut-and-paste the content into a .dot file yourself to - // see what the graphviz visualizer would produce. - - #[test] - fn empty_graph() { - let labels: Trivial = UnlabelledNodes(0); - let r = test_input(LabelledGraph::new("empty_graph", labels, vec![], None)); - assert_eq!(r.unwrap(), -r#"digraph empty_graph { -} -"#); - } - - #[test] - fn single_node() { - let labels: Trivial = UnlabelledNodes(1); - let r = test_input(LabelledGraph::new("single_node", labels, vec![], None)); - assert_eq!(r.unwrap(), -r#"digraph single_node { - N0[label="N0"]; -} -"#); - } - - #[test] - fn single_node_with_style() { - let labels: Trivial = UnlabelledNodes(1); - let styles = Some(vec![Style::Dashed]); - let r = test_input(LabelledGraph::new("single_node", labels, vec![], styles)); - assert_eq!(r.unwrap(), -r#"digraph single_node { - N0[label="N0"][style="dashed"]; -} -"#); - } - - #[test] - fn single_edge() { - let labels: Trivial = UnlabelledNodes(2); - let result = test_input(LabelledGraph::new("single_edge", - labels, - vec![edge(0, 1, "E", Style::None)], - None)); - assert_eq!(result.unwrap(), -r#"digraph single_edge { - N0[label="N0"]; - N1[label="N1"]; - N0 -> N1[label="E"]; -} -"#); - } - - #[test] - fn single_edge_with_style() { - let labels: Trivial = UnlabelledNodes(2); - let result = test_input(LabelledGraph::new("single_edge", - labels, - vec![edge(0, 1, "E", Style::Bold)], - None)); - assert_eq!(result.unwrap(), -r#"digraph single_edge { - N0[label="N0"]; - N1[label="N1"]; - N0 -> N1[label="E"][style="bold"]; -} -"#); - } - - #[test] - fn test_some_labelled() { - let labels: Trivial = SomeNodesLabelled(vec![Some("A"), None]); - let styles = Some(vec![Style::None, Style::Dotted]); - let result = test_input(LabelledGraph::new("test_some_labelled", - labels, - vec![edge(0, 1, "A-1", Style::None)], - styles)); - assert_eq!(result.unwrap(), -r#"digraph test_some_labelled { - N0[label="A"]; - N1[label="N1"][style="dotted"]; - N0 -> N1[label="A-1"]; -} -"#); - } - - #[test] - fn single_cyclic_node() { - let labels: Trivial = UnlabelledNodes(1); - let r = test_input(LabelledGraph::new("single_cyclic_node", - labels, - vec![edge(0, 0, "E", Style::None)], - None)); - assert_eq!(r.unwrap(), -r#"digraph single_cyclic_node { - N0[label="N0"]; - N0 -> N0[label="E"]; -} -"#); - } - - #[test] - fn hasse_diagram() { - let labels = AllNodesLabelled(vec!["{x,y}", "{x}", "{y}", "{}"]); - let r = test_input(LabelledGraph::new("hasse_diagram", - labels, - vec![edge(0, 1, "", Style::None), - edge(0, 2, "", Style::None), - edge(1, 3, "", Style::None), - edge(2, 3, "", Style::None)], - None)); - assert_eq!(r.unwrap(), -r#"digraph hasse_diagram { - N0[label="{x,y}"]; - N1[label="{x}"]; - N2[label="{y}"]; - N3[label="{}"]; - N0 -> N1[label=""]; - N0 -> N2[label=""]; - N1 -> N3[label=""]; - N2 -> N3[label=""]; -} -"#); - } - - #[test] - fn left_aligned_text() { - let labels = AllNodesLabelled(vec![ - "if test {\ - \\l branch1\ - \\l} else {\ - \\l branch2\ - \\l}\ - \\lafterward\ - \\l", - "branch1", - "branch2", - "afterward"]); - - let mut writer = Vec::new(); - - let g = LabelledGraphWithEscStrs::new("syntax_tree", - labels, - vec![edge(0, 1, "then", Style::None), - edge(0, 2, "else", Style::None), - edge(1, 3, ";", Style::None), - edge(2, 3, ";", Style::None)]); - - render(&g, &mut writer).unwrap(); - let mut r = String::new(); - Read::read_to_string(&mut &*writer, &mut r).unwrap(); - - assert_eq!(r, -r#"digraph syntax_tree { - N0[label="if test {\l branch1\l} else {\l branch2\l}\lafterward\l"]; - N1[label="branch1"]; - N2[label="branch2"]; - N3[label="afterward"]; - N0 -> N1[label="then"]; - N0 -> N2[label="else"]; - N1 -> N3[label=";"]; - N2 -> N3[label=";"]; -} -"#); - } - - #[test] - fn simple_id_construction() { - let id1 = Id::new("hello"); - match id1 { - Ok(_) => {} - Err(..) => panic!("'hello' is not a valid value for id anymore"), - } - } - - #[test] - fn badly_formatted_id() { - let id2 = Id::new("Weird { struct : ure } !!!"); - match id2 { - Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), - Err(..) => {} - } - } -} +mod tests; diff --git a/src/libgraphviz/tests.rs b/src/libgraphviz/tests.rs new file mode 100644 index 0000000000000..2f713579b17fa --- /dev/null +++ b/src/libgraphviz/tests.rs @@ -0,0 +1,380 @@ +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<Option<&'static str>>, + + node_styles: Vec<Style>, + + /// Each edge relates a from-index to a to-index along with a + /// label; `edges` collects them. + edges: Vec<Edge>, +} + +// A simple wrapper around LabelledGraph that forces the labels to +// be emitted as EscStr. +struct LabelledGraphWithEscStrs { + graph: LabelledGraph, +} + +enum NodeLabels<L> { + AllNodesLabelled(Vec<L>), + UnlabelledNodes(usize), + SomeNodesLabelled(Vec<Option<L>>), +} + +type Trivial = NodeLabels<&'static str>; + +impl NodeLabels<&'static str> { + fn to_opt_strs(self) -> Vec<Option<&'static str>> { + match self { + UnlabelledNodes(len) => vec![None; len], + AllNodesLabelled(lbls) => lbls.into_iter().map(|l| Some(l)).collect(), + SomeNodesLabelled(lbls) => lbls.into_iter().collect(), + } + } + + fn len(&self) -> usize { + match self { + &UnlabelledNodes(len) => len, + &AllNodesLabelled(ref lbls) => lbls.len(), + &SomeNodesLabelled(ref lbls) => lbls.len(), + } + } +} + +impl LabelledGraph { + fn new(name: &'static str, + node_labels: Trivial, + edges: Vec<Edge>, + node_styles: Option<Vec<Style>>) + -> LabelledGraph { + let count = node_labels.len(); + LabelledGraph { + name, + node_labels: node_labels.to_opt_strs(), + edges, + node_styles: match node_styles { + Some(nodes) => nodes, + None => vec![Style::None; count], + }, + } + } +} + +impl LabelledGraphWithEscStrs { + fn new(name: &'static str, + node_labels: Trivial, + edges: Vec<Edge>) + -> LabelledGraphWithEscStrs { + LabelledGraphWithEscStrs { graph: LabelledGraph::new(name, node_labels, edges, None) } + } +} + +fn id_name<'a>(n: &Node) -> Id<'a> { + Id::new(format!("N{}", *n)).unwrap() +} + +impl<'a> Labeller<'a> for LabelledGraph { + type Node = Node; + type Edge = &'a Edge; + fn graph_id(&'a self) -> Id<'a> { + Id::new(self.name).unwrap() + } + fn node_id(&'a self, n: &Node) -> Id<'a> { + id_name(n) + } + fn node_label(&'a self, n: &Node) -> LabelText<'a> { + match self.node_labels[*n] { + Some(l) => LabelStr(l.into()), + None => LabelStr(id_name(n).name()), + } + } + fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { + LabelStr(e.label.into()) + } + fn node_style(&'a self, n: &Node) -> Style { + self.node_styles[*n] + } + fn edge_style(&'a self, e: &&'a Edge) -> Style { + e.style + } +} + +impl<'a> Labeller<'a> for LabelledGraphWithEscStrs { + type Node = Node; + type Edge = &'a Edge; + fn graph_id(&'a self) -> Id<'a> { + self.graph.graph_id() + } + fn node_id(&'a self, n: &Node) -> Id<'a> { + self.graph.node_id(n) + } + fn node_label(&'a self, n: &Node) -> LabelText<'a> { + match self.graph.node_label(n) { + LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s), + } + } + fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { + match self.graph.edge_label(e) { + LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s), + } + } +} + +impl<'a> GraphWalk<'a> for LabelledGraph { + type Node = Node; + type Edge = &'a Edge; + fn nodes(&'a self) -> Nodes<'a, Node> { + (0..self.node_labels.len()).collect() + } + fn edges(&'a self) -> Edges<'a, &'a Edge> { + self.edges.iter().collect() + } + fn source(&'a self, edge: &&'a Edge) -> Node { + edge.from + } + fn target(&'a self, edge: &&'a Edge) -> Node { + edge.to + } +} + +impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs { + type Node = Node; + type Edge = &'a Edge; + fn nodes(&'a self) -> Nodes<'a, Node> { + self.graph.nodes() + } + fn edges(&'a self) -> Edges<'a, &'a Edge> { + self.graph.edges() + } + fn source(&'a self, edge: &&'a Edge) -> Node { + edge.from + } + fn target(&'a self, edge: &&'a Edge) -> Node { + edge.to + } +} + +fn test_input(g: LabelledGraph) -> io::Result<String> { + let mut writer = Vec::new(); + render(&g, &mut writer).unwrap(); + let mut s = String::new(); + Read::read_to_string(&mut &*writer, &mut s)?; + Ok(s) +} + +// All of the tests use raw-strings as the format for the expected outputs, +// so that you can cut-and-paste the content into a .dot file yourself to +// see what the graphviz visualizer would produce. + +#[test] +fn empty_graph() { + let labels: Trivial = UnlabelledNodes(0); + let r = test_input(LabelledGraph::new("empty_graph", labels, vec![], None)); + assert_eq!(r.unwrap(), +r#"digraph empty_graph { +} +"#); +} + +#[test] +fn single_node() { + let labels: Trivial = UnlabelledNodes(1); + let r = test_input(LabelledGraph::new("single_node", labels, vec![], None)); + assert_eq!(r.unwrap(), +r#"digraph single_node { + N0[label="N0"]; +} +"#); +} + +#[test] +fn single_node_with_style() { + let labels: Trivial = UnlabelledNodes(1); + let styles = Some(vec![Style::Dashed]); + let r = test_input(LabelledGraph::new("single_node", labels, vec![], styles)); + assert_eq!(r.unwrap(), +r#"digraph single_node { + N0[label="N0"][style="dashed"]; +} +"#); +} + +#[test] +fn single_edge() { + let labels: Trivial = UnlabelledNodes(2); + let result = test_input(LabelledGraph::new("single_edge", + labels, + vec![edge(0, 1, "E", Style::None)], + None)); + assert_eq!(result.unwrap(), +r#"digraph single_edge { + N0[label="N0"]; + N1[label="N1"]; + N0 -> N1[label="E"]; +} +"#); +} + +#[test] +fn single_edge_with_style() { + let labels: Trivial = UnlabelledNodes(2); + let result = test_input(LabelledGraph::new("single_edge", + labels, + vec![edge(0, 1, "E", Style::Bold)], + None)); + assert_eq!(result.unwrap(), +r#"digraph single_edge { + N0[label="N0"]; + N1[label="N1"]; + N0 -> N1[label="E"][style="bold"]; +} +"#); +} + +#[test] +fn test_some_labelled() { + let labels: Trivial = SomeNodesLabelled(vec![Some("A"), None]); + let styles = Some(vec![Style::None, Style::Dotted]); + let result = test_input(LabelledGraph::new("test_some_labelled", + labels, + vec![edge(0, 1, "A-1", Style::None)], + styles)); + assert_eq!(result.unwrap(), +r#"digraph test_some_labelled { + N0[label="A"]; + N1[label="N1"][style="dotted"]; + N0 -> N1[label="A-1"]; +} +"#); +} + +#[test] +fn single_cyclic_node() { + let labels: Trivial = UnlabelledNodes(1); + let r = test_input(LabelledGraph::new("single_cyclic_node", + labels, + vec![edge(0, 0, "E", Style::None)], + None)); + assert_eq!(r.unwrap(), +r#"digraph single_cyclic_node { + N0[label="N0"]; + N0 -> N0[label="E"]; +} +"#); +} + +#[test] +fn hasse_diagram() { + let labels = AllNodesLabelled(vec!["{x,y}", "{x}", "{y}", "{}"]); + let r = test_input(LabelledGraph::new("hasse_diagram", + labels, + vec![edge(0, 1, "", Style::None), + edge(0, 2, "", Style::None), + edge(1, 3, "", Style::None), + edge(2, 3, "", Style::None)], + None)); + assert_eq!(r.unwrap(), +r#"digraph hasse_diagram { + N0[label="{x,y}"]; + N1[label="{x}"]; + N2[label="{y}"]; + N3[label="{}"]; + N0 -> N1[label=""]; + N0 -> N2[label=""]; + N1 -> N3[label=""]; + N2 -> N3[label=""]; +} +"#); +} + +#[test] +fn left_aligned_text() { + let labels = AllNodesLabelled(vec![ + "if test {\ + \\l branch1\ + \\l} else {\ + \\l branch2\ + \\l}\ + \\lafterward\ + \\l", + "branch1", + "branch2", + "afterward"]); + + let mut writer = Vec::new(); + + let g = LabelledGraphWithEscStrs::new("syntax_tree", + labels, + vec![edge(0, 1, "then", Style::None), + edge(0, 2, "else", Style::None), + edge(1, 3, ";", Style::None), + edge(2, 3, ";", Style::None)]); + + render(&g, &mut writer).unwrap(); + let mut r = String::new(); + Read::read_to_string(&mut &*writer, &mut r).unwrap(); + + assert_eq!(r, +r#"digraph syntax_tree { + N0[label="if test {\l branch1\l} else {\l branch2\l}\lafterward\l"]; + N1[label="branch1"]; + N2[label="branch2"]; + N3[label="afterward"]; + N0 -> N1[label="then"]; + N0 -> N2[label="else"]; + N1 -> N3[label=";"]; + N2 -> N3[label=";"]; +} +"#); +} + +#[test] +fn simple_id_construction() { + let id1 = Id::new("hello"); + match id1 { + Ok(_) => {} + Err(..) => panic!("'hello' is not a valid value for id anymore"), + } +} + +#[test] +fn badly_formatted_id() { + let id2 = Id::new("Weird { struct : ure } !!!"); + match id2 { + Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), + Err(..) => {} + } +} diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index f4d523b92338c..fc092481a4a96 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1,5 +1,3 @@ -// ignore-tidy-filelength - //! Contains infrastructure for configuring the compiler, including parsing //! command line options. @@ -2720,711 +2718,4 @@ mod dep_tracking { } #[cfg(test)] -mod tests { - use getopts; - use crate::lint; - use crate::middle::cstore; - use crate::session::config::{ - build_configuration, - build_session_options_and_crate_config, - to_crate_config - }; - use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry}; - use crate::session::build_session; - use crate::session::search_paths::SearchPath; - use std::collections::{BTreeMap, BTreeSet}; - use std::iter::FromIterator; - use std::path::PathBuf; - use super::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; - use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; - use syntax::symbol::sym; - use syntax::edition::{Edition, DEFAULT_EDITION}; - use syntax; - use super::Options; - - impl ExternEntry { - fn new_public<S: Into<String>, - I: IntoIterator<Item = Option<S>>>(locations: I) -> ExternEntry { - let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into())) - .collect(); - - ExternEntry { - locations, - is_private_dep: false - } - } - } - - fn optgroups() -> getopts::Options { - let mut opts = getopts::Options::new(); - for group in super::rustc_optgroups() { - (group.apply)(&mut opts); - } - return opts; - } - - fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> { - BTreeMap::from_iter(entries.into_iter()) - } - - // When the user supplies --test we should implicitly supply --cfg test - #[test] - fn test_switch_implies_cfg_test() { - syntax::with_default_globals(|| { - let matches = &match optgroups().parse(&["--test".to_string()]) { - Ok(m) => m, - Err(f) => panic!("test_switch_implies_cfg_test: {}", f), - }; - let registry = errors::registry::Registry::new(&[]); - let (sessopts, cfg) = build_session_options_and_crate_config(matches); - let sess = build_session(sessopts, None, registry); - let cfg = build_configuration(&sess, to_crate_config(cfg)); - assert!(cfg.contains(&(sym::test, None))); - }); - } - - // When the user supplies --test and --cfg test, don't implicitly add - // another --cfg test - #[test] - fn test_switch_implies_cfg_test_unless_cfg_test() { - syntax::with_default_globals(|| { - let matches = &match optgroups().parse(&["--test".to_string(), - "--cfg=test".to_string()]) { - Ok(m) => m, - Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f), - }; - let registry = errors::registry::Registry::new(&[]); - let (sessopts, cfg) = build_session_options_and_crate_config(matches); - let sess = build_session(sessopts, None, registry); - let cfg = build_configuration(&sess, to_crate_config(cfg)); - let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); - assert!(test_items.next().is_some()); - assert!(test_items.next().is_none()); - }); - } - - #[test] - fn test_can_print_warnings() { - syntax::with_default_globals(|| { - let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let registry = errors::registry::Registry::new(&[]); - let (sessopts, _) = build_session_options_and_crate_config(&matches); - let sess = build_session(sessopts, None, registry); - assert!(!sess.diagnostic().flags.can_emit_warnings); - }); - - syntax::with_default_globals(|| { - let matches = optgroups() - .parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]) - .unwrap(); - let registry = errors::registry::Registry::new(&[]); - let (sessopts, _) = build_session_options_and_crate_config(&matches); - let sess = build_session(sessopts, None, registry); - assert!(sess.diagnostic().flags.can_emit_warnings); - }); - - syntax::with_default_globals(|| { - let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let registry = errors::registry::Registry::new(&[]); - let (sessopts, _) = build_session_options_and_crate_config(&matches); - let sess = build_session(sessopts, None, registry); - assert!(sess.diagnostic().flags.can_emit_warnings); - }); - } - - #[test] - fn test_output_types_tracking_hash_different_paths() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - - v1.output_types = - OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("./some/thing")))]); - v2.output_types = - OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]); - v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); - - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - } - - #[test] - fn test_output_types_tracking_hash_different_construction_order() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - - v1.output_types = OutputTypes::new(&[ - (OutputType::Exe, Some(PathBuf::from("./some/thing"))), - (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))), - ]); - - v2.output_types = OutputTypes::new(&[ - (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))), - (OutputType::Exe, Some(PathBuf::from("./some/thing"))), - ]); - - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - } - - #[test] - fn test_externs_tracking_hash_different_construction_order() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - - v1.externs = Externs::new(mk_map(vec![ - ( - String::from("a"), - ExternEntry::new_public(vec![Some("b"), Some("c")]) - ), - ( - String::from("d"), - ExternEntry::new_public(vec![Some("e"), Some("f")]) - ), - ])); - - v2.externs = Externs::new(mk_map(vec![ - ( - String::from("d"), - ExternEntry::new_public(vec![Some("e"), Some("f")]) - ), - ( - String::from("a"), - ExternEntry::new_public(vec![Some("b"), Some("c")]) - ), - ])); - - v3.externs = Externs::new(mk_map(vec![ - ( - String::from("a"), - ExternEntry::new_public(vec![Some("b"), Some("c")]) - ), - ( - String::from("d"), - ExternEntry::new_public(vec![Some("f"), Some("e")]) - ), - ])); - - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - } - - #[test] - fn test_lints_tracking_hash_different_values() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - - v1.lint_opts = vec![ - (String::from("a"), lint::Allow), - (String::from("b"), lint::Warn), - (String::from("c"), lint::Deny), - (String::from("d"), lint::Forbid), - ]; - - v2.lint_opts = vec![ - (String::from("a"), lint::Allow), - (String::from("b"), lint::Warn), - (String::from("X"), lint::Deny), - (String::from("d"), lint::Forbid), - ]; - - v3.lint_opts = vec![ - (String::from("a"), lint::Allow), - (String::from("b"), lint::Warn), - (String::from("c"), lint::Forbid), - (String::from("d"), lint::Deny), - ]; - - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - } - - #[test] - fn test_lints_tracking_hash_different_construction_order() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - - v1.lint_opts = vec![ - (String::from("a"), lint::Allow), - (String::from("b"), lint::Warn), - (String::from("c"), lint::Deny), - (String::from("d"), lint::Forbid), - ]; - - v2.lint_opts = vec![ - (String::from("a"), lint::Allow), - (String::from("c"), lint::Deny), - (String::from("b"), lint::Warn), - (String::from("d"), lint::Forbid), - ]; - - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - } - - #[test] - fn test_search_paths_tracking_hash_different_order() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - let mut v4 = Options::default(); - - const JSON: super::ErrorOutputType = super::ErrorOutputType::Json { - pretty: false, - json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never), - }; - - // Reference - v1.search_paths - .push(SearchPath::from_cli_opt("native=abc", JSON)); - v1.search_paths - .push(SearchPath::from_cli_opt("crate=def", JSON)); - v1.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v1.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v1.search_paths - .push(SearchPath::from_cli_opt("all=mno", JSON)); - - v2.search_paths - .push(SearchPath::from_cli_opt("native=abc", JSON)); - v2.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v2.search_paths - .push(SearchPath::from_cli_opt("crate=def", JSON)); - v2.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v2.search_paths - .push(SearchPath::from_cli_opt("all=mno", JSON)); - - v3.search_paths - .push(SearchPath::from_cli_opt("crate=def", JSON)); - v3.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v3.search_paths - .push(SearchPath::from_cli_opt("native=abc", JSON)); - v3.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v3.search_paths - .push(SearchPath::from_cli_opt("all=mno", JSON)); - - v4.search_paths - .push(SearchPath::from_cli_opt("all=mno", JSON)); - v4.search_paths - .push(SearchPath::from_cli_opt("native=abc", JSON)); - v4.search_paths - .push(SearchPath::from_cli_opt("crate=def", JSON)); - v4.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v4.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", JSON)); - - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); - } - - #[test] - fn test_native_libs_tracking_hash_different_values() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - let mut v4 = Options::default(); - - // Reference - v1.libs = vec![ - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("b"), None, Some(cstore::NativeFramework)), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - // Change label - v2.libs = vec![ - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("X"), None, Some(cstore::NativeFramework)), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - // Change kind - v3.libs = vec![ - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("b"), None, Some(cstore::NativeStatic)), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - // Change new-name - v4.libs = vec![ - (String::from("a"), None, Some(cstore::NativeStatic)), - ( - String::from("b"), - Some(String::from("X")), - Some(cstore::NativeFramework), - ), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); - } - - #[test] - fn test_native_libs_tracking_hash_different_order() { - let mut v1 = Options::default(); - let mut v2 = Options::default(); - let mut v3 = Options::default(); - - // Reference - v1.libs = vec![ - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("b"), None, Some(cstore::NativeFramework)), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - v2.libs = vec![ - (String::from("b"), None, Some(cstore::NativeFramework)), - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("c"), None, Some(cstore::NativeUnknown)), - ]; - - v3.libs = vec![ - (String::from("c"), None, Some(cstore::NativeUnknown)), - (String::from("a"), None, Some(cstore::NativeStatic)), - (String::from("b"), None, Some(cstore::NativeFramework)), - ]; - - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - } - - #[test] - fn test_codegen_options_tracking_hash() { - let reference = Options::default(); - let mut opts = Options::default(); - - // Make sure the changing an [UNTRACKED] option leaves the hash unchanged - opts.cg.ar = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.linker = Some(PathBuf::from("linker")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.link_dead_code = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.rpath = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.extra_filename = String::from("extra-filename"); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.codegen_units = Some(42); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.save_temps = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts.cg.incremental = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - // Make sure changing a [TRACKED] option changes the hash - opts = reference.clone(); - opts.cg.lto = LtoCli::Fat; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.target_cpu = Some(String::from("abc")); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.target_feature = String::from("all the features, all of them"); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.passes = vec![String::from("1"), String::from("2")]; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.llvm_args = vec![String::from("1"), String::from("2")]; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.overflow_checks = Some(true); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.no_prepopulate_passes = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.no_vectorize_loops = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.no_vectorize_slp = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.soft_float = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.prefer_dynamic = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.no_integrated_as = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.no_redzone = Some(true); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.relocation_model = Some(String::from("relocation model")); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.code_model = Some(String::from("code model")); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.tls_model = Some(String::from("tls model")); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None); - assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.pgo_use = Some(PathBuf::from("abc")); - assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.metadata = vec![String::from("A"), String::from("B")]; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.debuginfo = Some(0xdeadbeef); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.debuginfo = Some(0xba5eba11); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.force_frame_pointers = Some(false); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.debug_assertions = Some(true); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.inline_threshold = Some(0xf007ba11); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.panic = Some(PanicStrategy::Abort); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.cg.linker_plugin_lto = LinkerPluginLto::LinkerPluginAuto; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - } - - #[test] - fn test_debugging_options_tracking_hash() { - let reference = Options::default(); - let mut opts = Options::default(); - - // Make sure the changing an [UNTRACKED] option leaves the hash unchanged - opts.debugging_opts.verbose = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.time_passes = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.time_llvm_passes = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.input_stats = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.borrowck_stats = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.meta_stats = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.print_link_args = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.print_llvm_passes = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.ast_json = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.ast_json_noexpand = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.ls = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.save_analysis = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.flowgraph_print_loans = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.flowgraph_print_moves = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.flowgraph_print_assigns = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.flowgraph_print_all = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.print_region_graph = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.parse_only = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.incremental = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.dump_dep_graph = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.query_dep_graph = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.no_analysis = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.unstable_options = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.trace_macros = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.keep_hygiene_data = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.keep_ast = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.print_mono_items = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.dump_mir = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.dump_mir_dir = String::from("abc"); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.dump_mir_graphviz = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - - // Make sure changing a [TRACKED] option changes the hash - opts = reference.clone(); - opts.debugging_opts.asm_comments = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.verify_llvm_ir = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.no_landing_pads = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.fewer_names = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.no_codegen = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.treat_err_as_bug = Some(1); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.report_delayed_bugs = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.continue_parse_after_error = true; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")]; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.force_overflow_checks = Some(true); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.show_span = Some(String::from("abc")); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.mir_opt_level = 3; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.relro_level = Some(RelroLevel::Full); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.allow_features = Some(vec![String::from("lang_items")]); - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - - opts = reference.clone(); - opts.debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0; - assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); - } - - #[test] - fn test_edition_parsing() { - // test default edition - let options = Options::default(); - assert!(options.edition == DEFAULT_EDITION); - - let matches = optgroups() - .parse(&["--edition=2018".to_string()]) - .unwrap(); - let (sessopts, _) = build_session_options_and_crate_config(&matches); - assert!(sessopts.edition == Edition::Edition2018) - } -} +mod tests; diff --git a/src/librustc/session/config/tests.rs b/src/librustc/session/config/tests.rs new file mode 100644 index 0000000000000..b8477f8dd1789 --- /dev/null +++ b/src/librustc/session/config/tests.rs @@ -0,0 +1,706 @@ +use getopts; +use crate::lint; +use crate::middle::cstore; +use crate::session::config::{ + build_configuration, + build_session_options_and_crate_config, + to_crate_config +}; +use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry}; +use crate::session::build_session; +use crate::session::search_paths::SearchPath; +use std::collections::{BTreeMap, BTreeSet}; +use std::iter::FromIterator; +use std::path::PathBuf; +use super::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; +use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; +use syntax::symbol::sym; +use syntax::edition::{Edition, DEFAULT_EDITION}; +use syntax; +use super::Options; + +impl ExternEntry { + fn new_public<S: Into<String>, + I: IntoIterator<Item = Option<S>>>(locations: I) -> ExternEntry { + let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into())) + .collect(); + + ExternEntry { + locations, + is_private_dep: false + } + } +} + +fn optgroups() -> getopts::Options { + let mut opts = getopts::Options::new(); + for group in super::rustc_optgroups() { + (group.apply)(&mut opts); + } + return opts; +} + +fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> { + BTreeMap::from_iter(entries.into_iter()) +} + +// When the user supplies --test we should implicitly supply --cfg test +#[test] +fn test_switch_implies_cfg_test() { + syntax::with_default_globals(|| { + let matches = &match optgroups().parse(&["--test".to_string()]) { + Ok(m) => m, + Err(f) => panic!("test_switch_implies_cfg_test: {}", f), + }; + let registry = errors::registry::Registry::new(&[]); + let (sessopts, cfg) = build_session_options_and_crate_config(matches); + let sess = build_session(sessopts, None, registry); + let cfg = build_configuration(&sess, to_crate_config(cfg)); + assert!(cfg.contains(&(sym::test, None))); + }); +} + +// When the user supplies --test and --cfg test, don't implicitly add +// another --cfg test +#[test] +fn test_switch_implies_cfg_test_unless_cfg_test() { + syntax::with_default_globals(|| { + let matches = &match optgroups().parse(&["--test".to_string(), + "--cfg=test".to_string()]) { + Ok(m) => m, + Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f), + }; + let registry = errors::registry::Registry::new(&[]); + let (sessopts, cfg) = build_session_options_and_crate_config(matches); + let sess = build_session(sessopts, None, registry); + let cfg = build_configuration(&sess, to_crate_config(cfg)); + let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); + assert!(test_items.next().is_some()); + assert!(test_items.next().is_none()); + }); +} + +#[test] +fn test_can_print_warnings() { + syntax::with_default_globals(|| { + let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); + let registry = errors::registry::Registry::new(&[]); + let (sessopts, _) = build_session_options_and_crate_config(&matches); + let sess = build_session(sessopts, None, registry); + assert!(!sess.diagnostic().flags.can_emit_warnings); + }); + + syntax::with_default_globals(|| { + let matches = optgroups() + .parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]) + .unwrap(); + let registry = errors::registry::Registry::new(&[]); + let (sessopts, _) = build_session_options_and_crate_config(&matches); + let sess = build_session(sessopts, None, registry); + assert!(sess.diagnostic().flags.can_emit_warnings); + }); + + syntax::with_default_globals(|| { + let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); + let registry = errors::registry::Registry::new(&[]); + let (sessopts, _) = build_session_options_and_crate_config(&matches); + let sess = build_session(sessopts, None, registry); + assert!(sess.diagnostic().flags.can_emit_warnings); + }); +} + +#[test] +fn test_output_types_tracking_hash_different_paths() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + + v1.output_types = + OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("./some/thing")))]); + v2.output_types = + OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]); + v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); + + assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); + assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); +} + +#[test] +fn test_output_types_tracking_hash_different_construction_order() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + + v1.output_types = OutputTypes::new(&[ + (OutputType::Exe, Some(PathBuf::from("./some/thing"))), + (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))), + ]); + + v2.output_types = OutputTypes::new(&[ + (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))), + (OutputType::Exe, Some(PathBuf::from("./some/thing"))), + ]); + + assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); +} + +#[test] +fn test_externs_tracking_hash_different_construction_order() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + + v1.externs = Externs::new(mk_map(vec![ + ( + String::from("a"), + ExternEntry::new_public(vec![Some("b"), Some("c")]) + ), + ( + String::from("d"), + ExternEntry::new_public(vec![Some("e"), Some("f")]) + ), + ])); + + v2.externs = Externs::new(mk_map(vec![ + ( + String::from("d"), + ExternEntry::new_public(vec![Some("e"), Some("f")]) + ), + ( + String::from("a"), + ExternEntry::new_public(vec![Some("b"), Some("c")]) + ), + ])); + + v3.externs = Externs::new(mk_map(vec![ + ( + String::from("a"), + ExternEntry::new_public(vec![Some("b"), Some("c")]) + ), + ( + String::from("d"), + ExternEntry::new_public(vec![Some("f"), Some("e")]) + ), + ])); + + assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); + assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); +} + +#[test] +fn test_lints_tracking_hash_different_values() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + + v1.lint_opts = vec![ + (String::from("a"), lint::Allow), + (String::from("b"), lint::Warn), + (String::from("c"), lint::Deny), + (String::from("d"), lint::Forbid), + ]; + + v2.lint_opts = vec![ + (String::from("a"), lint::Allow), + (String::from("b"), lint::Warn), + (String::from("X"), lint::Deny), + (String::from("d"), lint::Forbid), + ]; + + v3.lint_opts = vec![ + (String::from("a"), lint::Allow), + (String::from("b"), lint::Warn), + (String::from("c"), lint::Forbid), + (String::from("d"), lint::Deny), + ]; + + assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); + assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); +} + +#[test] +fn test_lints_tracking_hash_different_construction_order() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + + v1.lint_opts = vec![ + (String::from("a"), lint::Allow), + (String::from("b"), lint::Warn), + (String::from("c"), lint::Deny), + (String::from("d"), lint::Forbid), + ]; + + v2.lint_opts = vec![ + (String::from("a"), lint::Allow), + (String::from("c"), lint::Deny), + (String::from("b"), lint::Warn), + (String::from("d"), lint::Forbid), + ]; + + assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); +} + +#[test] +fn test_search_paths_tracking_hash_different_order() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + let mut v4 = Options::default(); + + const JSON: super::ErrorOutputType = super::ErrorOutputType::Json { + pretty: false, + json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never), + }; + + // Reference + v1.search_paths + .push(SearchPath::from_cli_opt("native=abc", JSON)); + v1.search_paths + .push(SearchPath::from_cli_opt("crate=def", JSON)); + v1.search_paths + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); + v1.search_paths + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); + v1.search_paths + .push(SearchPath::from_cli_opt("all=mno", JSON)); + + v2.search_paths + .push(SearchPath::from_cli_opt("native=abc", JSON)); + v2.search_paths + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); + v2.search_paths + .push(SearchPath::from_cli_opt("crate=def", JSON)); + v2.search_paths + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); + v2.search_paths + .push(SearchPath::from_cli_opt("all=mno", JSON)); + + v3.search_paths + .push(SearchPath::from_cli_opt("crate=def", JSON)); + v3.search_paths + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); + v3.search_paths + .push(SearchPath::from_cli_opt("native=abc", JSON)); + v3.search_paths + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); + v3.search_paths + .push(SearchPath::from_cli_opt("all=mno", JSON)); + + v4.search_paths + .push(SearchPath::from_cli_opt("all=mno", JSON)); + v4.search_paths + .push(SearchPath::from_cli_opt("native=abc", JSON)); + v4.search_paths + .push(SearchPath::from_cli_opt("crate=def", JSON)); + v4.search_paths + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); + v4.search_paths + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); + + assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); +} + +#[test] +fn test_native_libs_tracking_hash_different_values() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + let mut v4 = Options::default(); + + // Reference + v1.libs = vec![ + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("b"), None, Some(cstore::NativeFramework)), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + // Change label + v2.libs = vec![ + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("X"), None, Some(cstore::NativeFramework)), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + // Change kind + v3.libs = vec![ + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("b"), None, Some(cstore::NativeStatic)), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + // Change new-name + v4.libs = vec![ + (String::from("a"), None, Some(cstore::NativeStatic)), + ( + String::from("b"), + Some(String::from("X")), + Some(cstore::NativeFramework), + ), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); +} + +#[test] +fn test_native_libs_tracking_hash_different_order() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + + // Reference + v1.libs = vec![ + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("b"), None, Some(cstore::NativeFramework)), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + v2.libs = vec![ + (String::from("b"), None, Some(cstore::NativeFramework)), + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("c"), None, Some(cstore::NativeUnknown)), + ]; + + v3.libs = vec![ + (String::from("c"), None, Some(cstore::NativeUnknown)), + (String::from("a"), None, Some(cstore::NativeStatic)), + (String::from("b"), None, Some(cstore::NativeFramework)), + ]; + + assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); + assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); + assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash()); + + // Check clone + assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); +} + +#[test] +fn test_codegen_options_tracking_hash() { + let reference = Options::default(); + let mut opts = Options::default(); + + // Make sure the changing an [UNTRACKED] option leaves the hash unchanged + opts.cg.ar = Some(String::from("abc")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.linker = Some(PathBuf::from("linker")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.link_dead_code = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.rpath = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.extra_filename = String::from("extra-filename"); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.codegen_units = Some(42); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.save_temps = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts.cg.incremental = Some(String::from("abc")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + // Make sure changing a [TRACKED] option changes the hash + opts = reference.clone(); + opts.cg.lto = LtoCli::Fat; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.target_cpu = Some(String::from("abc")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.target_feature = String::from("all the features, all of them"); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.passes = vec![String::from("1"), String::from("2")]; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.llvm_args = vec![String::from("1"), String::from("2")]; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.overflow_checks = Some(true); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.no_prepopulate_passes = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.no_vectorize_loops = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.no_vectorize_slp = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.soft_float = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.prefer_dynamic = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.no_integrated_as = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.no_redzone = Some(true); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.relocation_model = Some(String::from("relocation model")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.code_model = Some(String::from("code model")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.tls_model = Some(String::from("tls model")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None); + assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.pgo_use = Some(PathBuf::from("abc")); + assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.metadata = vec![String::from("A"), String::from("B")]; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.debuginfo = Some(0xdeadbeef); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.debuginfo = Some(0xba5eba11); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.force_frame_pointers = Some(false); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.debug_assertions = Some(true); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.inline_threshold = Some(0xf007ba11); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.panic = Some(PanicStrategy::Abort); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.linker_plugin_lto = LinkerPluginLto::LinkerPluginAuto; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); +} + +#[test] +fn test_debugging_options_tracking_hash() { + let reference = Options::default(); + let mut opts = Options::default(); + + // Make sure the changing an [UNTRACKED] option leaves the hash unchanged + opts.debugging_opts.verbose = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.time_passes = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.time_llvm_passes = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.input_stats = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.borrowck_stats = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.meta_stats = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.print_link_args = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.print_llvm_passes = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.ast_json = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.ast_json_noexpand = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.ls = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.save_analysis = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.flowgraph_print_loans = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.flowgraph_print_moves = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.flowgraph_print_assigns = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.flowgraph_print_all = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.print_region_graph = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.parse_only = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.incremental = Some(String::from("abc")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.dump_dep_graph = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.query_dep_graph = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.no_analysis = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.unstable_options = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.trace_macros = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.keep_hygiene_data = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.keep_ast = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.print_mono_items = Some(String::from("abc")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.dump_mir = Some(String::from("abc")); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.dump_mir_dir = String::from("abc"); + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.dump_mir_graphviz = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + + // Make sure changing a [TRACKED] option changes the hash + opts = reference.clone(); + opts.debugging_opts.asm_comments = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.verify_llvm_ir = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.no_landing_pads = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.fewer_names = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.no_codegen = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.treat_err_as_bug = Some(1); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.report_delayed_bugs = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.continue_parse_after_error = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")]; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.force_overflow_checks = Some(true); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.show_span = Some(String::from("abc")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.mir_opt_level = 3; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.relro_level = Some(RelroLevel::Full); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.allow_features = Some(vec![String::from("lang_items")]); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); +} + +#[test] +fn test_edition_parsing() { + // test default edition + let options = Options::default(); + assert!(options.edition == DEFAULT_EDITION); + + let matches = optgroups() + .parse(&["--edition=2018".to_string()]) + .unwrap(); + let (sessopts, _) = build_session_options_and_crate_config(&matches); + assert!(sessopts.edition == Edition::Edition2018) +} diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs index 2b7abcb52bef8..e27cb6d8dda89 100644 --- a/src/librustc_codegen_ssa/back/rpath.rs +++ b/src/librustc_codegen_ssa/back/rpath.rs @@ -173,98 +173,4 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec<String> { } #[cfg(all(unix, test))] -mod tests { - use super::{RPathConfig}; - use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output}; - use std::path::{Path, PathBuf}; - - #[test] - fn test_rpaths_to_flags() { - let flags = rpaths_to_flags(&[ - "path1".to_string(), - "path2".to_string() - ]); - assert_eq!(flags, - ["-Wl,-rpath,path1", - "-Wl,-rpath,path2"]); - } - - #[test] - fn test_minimize1() { - let res = minimize_rpaths(&[ - "rpath1".to_string(), - "rpath2".to_string(), - "rpath1".to_string() - ]); - assert!(res == [ - "rpath1", - "rpath2", - ]); - } - - #[test] - fn test_minimize2() { - let res = minimize_rpaths(&[ - "1a".to_string(), - "2".to_string(), - "2".to_string(), - "1a".to_string(), - "4a".to_string(), - "1a".to_string(), - "2".to_string(), - "3".to_string(), - "4a".to_string(), - "3".to_string() - ]); - assert!(res == [ - "1a", - "2", - "4a", - "3", - ]); - } - - #[test] - fn test_rpath_relative() { - if cfg!(target_os = "macos") { - let config = &mut RPathConfig { - used_crates: Vec::new(), - has_rpath: true, - is_like_osx: true, - linker_is_gnu: false, - out_filename: PathBuf::from("bin/rustc"), - get_install_prefix_lib_path: &mut || panic!(), - }; - let res = get_rpath_relative_to_output(config, - Path::new("lib/libstd.so")); - assert_eq!(res, "@loader_path/../lib"); - } else { - let config = &mut RPathConfig { - used_crates: Vec::new(), - out_filename: PathBuf::from("bin/rustc"), - get_install_prefix_lib_path: &mut || panic!(), - has_rpath: true, - is_like_osx: false, - linker_is_gnu: true, - }; - let res = get_rpath_relative_to_output(config, - Path::new("lib/libstd.so")); - assert_eq!(res, "$ORIGIN/../lib"); - } - } - - #[test] - fn test_xlinker() { - let args = rpaths_to_flags(&[ - "a/normal/path".to_string(), - "a,comma,path".to_string() - ]); - - assert_eq!(args, vec![ - "-Wl,-rpath,a/normal/path".to_string(), - "-Wl,-rpath".to_string(), - "-Xlinker".to_string(), - "a,comma,path".to_string() - ]); - } -} +mod tests; diff --git a/src/librustc_codegen_ssa/back/rpath/tests.rs b/src/librustc_codegen_ssa/back/rpath/tests.rs new file mode 100644 index 0000000000000..e42a878d7e45e --- /dev/null +++ b/src/librustc_codegen_ssa/back/rpath/tests.rs @@ -0,0 +1,93 @@ +use super::{RPathConfig}; +use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output}; +use std::path::{Path, PathBuf}; + +#[test] +fn test_rpaths_to_flags() { + let flags = rpaths_to_flags(&[ + "path1".to_string(), + "path2".to_string() + ]); + assert_eq!(flags, + ["-Wl,-rpath,path1", + "-Wl,-rpath,path2"]); +} + +#[test] +fn test_minimize1() { + let res = minimize_rpaths(&[ + "rpath1".to_string(), + "rpath2".to_string(), + "rpath1".to_string() + ]); + assert!(res == [ + "rpath1", + "rpath2", + ]); +} + +#[test] +fn test_minimize2() { + let res = minimize_rpaths(&[ + "1a".to_string(), + "2".to_string(), + "2".to_string(), + "1a".to_string(), + "4a".to_string(), + "1a".to_string(), + "2".to_string(), + "3".to_string(), + "4a".to_string(), + "3".to_string() + ]); + assert!(res == [ + "1a", + "2", + "4a", + "3", + ]); +} + +#[test] +fn test_rpath_relative() { + if cfg!(target_os = "macos") { + let config = &mut RPathConfig { + used_crates: Vec::new(), + has_rpath: true, + is_like_osx: true, + linker_is_gnu: false, + out_filename: PathBuf::from("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "@loader_path/../lib"); + } else { + let config = &mut RPathConfig { + used_crates: Vec::new(), + out_filename: PathBuf::from("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + has_rpath: true, + is_like_osx: false, + linker_is_gnu: true, + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "$ORIGIN/../lib"); + } +} + +#[test] +fn test_xlinker() { + let args = rpaths_to_flags(&[ + "a/normal/path".to_string(), + "a,comma,path".to_string() + ]); + + assert_eq!(args, vec![ + "-Wl,-rpath,a/normal/path".to_string(), + "-Wl,-rpath".to_string(), + "-Xlinker".to_string(), + "a,comma,path".to_string() + ]); +} diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index 0301891c9b292..a7af615fa5000 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -1221,717 +1221,4 @@ pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>; pub type ErasedBoxRefMut<U> = OwningRefMut<Box<dyn Erased>, U>; #[cfg(test)] -mod tests { - mod owning_ref { - use super::super::OwningRef; - use super::super::{RcRef, BoxRef, Erased, ErasedBoxRef}; - use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; - use std::hash::{Hash, Hasher}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::rc::Rc; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn into() { - let or: OwningRef<Box<()>, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &x.0); - assert_eq!(&*or, &42); - - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRef<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_chained() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or: BoxRef<_, str> = or.map(|x| &x[1..5]); - let or: BoxRef<_, str> = or.map(|x| &x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRef::new(Box::new(example().1)) - .map(|x| &x[..5]) - .map(|x| &x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn owner() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example())) - .map(|x| &x.1[..]); - - let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1)) - .map(|x| &x[..]); - - let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::{RefRef, RefMutRef}; - use std::cell::RefCell; - use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefRef::new(a.borrow()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RefCell::new(1); - let a = { - let a = RefMutRef::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRef::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockReadGuardRef::new(a.read().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRef::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key = RcRef::<String>::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); - - hash.insert(key.clone().map(|s| &s[..3]), 42); - hash.insert(key.clone().map(|s| &s[4..]), 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRef<Vec<u8>, [u8]> - = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef<Box<[u8]>, [u8]> - = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe {a.map_owner(Rc::new)}; - let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Rc::new)}; - - let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner(); - let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner(); - - let _g = e.clone(); - let _h = f.clone(); - } - - #[test] - fn total_erase_box() { - let a: OwningRef<Vec<u8>, [u8]> - = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef<Box<[u8]>, [u8]> - = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box(); - let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); - - let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); - } - } - - mod owning_handle { - use super::super::OwningHandle; - use super::super::RcRef; - use std::rc::Rc; - use std::cell::RefCell; - use std::sync::Arc; - use std::sync::RwLock; - - #[test] - fn owning_handle() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_ok() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - Ok(unsafe { - x.as_ref() - }.unwrap().borrow_mut()) - }).unwrap(); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_err() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - if false { - return Ok(unsafe { - x.as_ref() - }.unwrap().borrow_mut()) - } - Err(()) - }); - assert!(handle.is_err()); - } - - #[test] - fn nested() { - use std::cell::RefCell; - use std::sync::{Arc, RwLock}; - - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - - #[test] - fn owning_handle_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::new(cell_ref); - assert_eq!(*handle, 2); - } - - #[test] - fn owning_handle_mut_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_mut(cell_ref); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn owning_handle_safe_2() { - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - } - - mod owning_ref_mut { - use super::super::{OwningRefMut, BoxRefMut, Erased, ErasedBoxRefMut}; - use super::super::BoxRef; - use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; - use std::hash::{Hash, Hasher}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn new_deref_mut() { - let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&mut *or, &mut ()); - } - - #[test] - fn mutate() { - let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0)); - assert_eq!(&*or, &0); - *or = 1; - assert_eq!(&*or, &1); - } - - #[test] - fn into() { - let or: OwningRefMut<Box<()>, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_offset_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_mut_heap_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_static_ref() { - static mut MUT_S: [u8; 5] = *b"hello"; - - let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); - assert_eq!(&*or, b"hello"); - } - - #[test] - fn map_mut_chained() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..5]) - .map_mut(|x| &mut x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn try_map_mut() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); - assert_eq!(&*or.unwrap(), "ello"); - - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(())); - assert!(or.is_err()); - } - - #[test] - fn owner() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, - "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRefMut<Example, str> = BoxRefMut::new(Box::new(example())) - .map_mut(|x| &mut x.1[..]); - - let o2: BoxRefMut<String, str> = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..]); - - let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::RefMutRefMut; - use std::cell::RefCell; - use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefMutRefMut::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRefMut::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key1 = BoxRefMut::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]); - let key2 = BoxRefMut::<String>::new(Box::new("bar".to_string())).map(|s| &s[..]); - - hash.insert(key1, 42); - hash.insert(key2, 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRefMut<Vec<u8>, [u8]> - = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut<Box<[u8]>, [u8]> - = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe {a.map_owner(Box::new)}; - let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Box::new)}; - - let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn total_erase_box() { - let a: OwningRefMut<Vec<u8>, [u8]> - = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut<Box<[u8]>, [u8]> - = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box(); - let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); - - let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_err()); - } - - #[test] - fn try_map3() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map4() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); - } - - #[test] - fn into_owning_ref() { - use super::super::BoxRef; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<()> = or.into(); - assert_eq!(&*or, &()); - } - - struct Foo { - u: u32, - } - struct Bar { - f: Foo, - } - - #[test] - fn ref_mut() { - use std::cell::RefCell; - - let a = RefCell::new(Bar { f: Foo { u: 42 } }); - let mut b = OwningRefMut::new(a.borrow_mut()); - assert_eq!(b.f.u, 42); - b.f.u = 43; - let mut c = b.map_mut(|x| &mut x.f); - assert_eq!(c.u, 43); - c.u = 44; - let mut d = c.map_mut(|x| &mut x.u); - assert_eq!(*d, 44); - *d = 45; - assert_eq!(*d, 45); - } - } -} +mod tests; diff --git a/src/librustc_data_structures/owning_ref/tests.rs b/src/librustc_data_structures/owning_ref/tests.rs new file mode 100644 index 0000000000000..d368219cab3eb --- /dev/null +++ b/src/librustc_data_structures/owning_ref/tests.rs @@ -0,0 +1,712 @@ +mod owning_ref { + use super::super::OwningRef; + use super::super::{RcRef, BoxRef, Erased, ErasedBoxRef}; + use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; + use std::hash::{Hash, Hasher}; + use std::collections::hash_map::DefaultHasher; + use std::collections::HashMap; + use std::rc::Rc; + + #[derive(Debug, PartialEq)] + struct Example(u32, String, [u8; 3]); + fn example() -> Example { + Example(42, "hello world".to_string(), [1, 2, 3]) + } + + #[test] + fn new_deref() { + let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(())); + assert_eq!(&*or, &()); + } + + #[test] + fn into() { + let or: OwningRef<Box<()>, ()> = Box::new(()).into(); + assert_eq!(&*or, &()); + } + + #[test] + fn map_offset_ref() { + let or: BoxRef<Example> = Box::new(example()).into(); + let or: BoxRef<_, u32> = or.map(|x| &x.0); + assert_eq!(&*or, &42); + + let or: BoxRef<Example> = Box::new(example()).into(); + let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); + assert_eq!(&*or, &2); + } + + #[test] + fn map_heap_ref() { + let or: BoxRef<Example> = Box::new(example()).into(); + let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); + assert_eq!(&*or, "hello"); + } + + #[test] + fn map_static_ref() { + let or: BoxRef<()> = Box::new(()).into(); + let or: BoxRef<_, str> = or.map(|_| "hello"); + assert_eq!(&*or, "hello"); + } + + #[test] + fn map_chained() { + let or: BoxRef<String> = Box::new(example().1).into(); + let or: BoxRef<_, str> = or.map(|x| &x[1..5]); + let or: BoxRef<_, str> = or.map(|x| &x[..2]); + assert_eq!(&*or, "el"); + } + + #[test] + fn map_chained_inference() { + let or = BoxRef::new(Box::new(example().1)) + .map(|x| &x[..5]) + .map(|x| &x[1..3]); + assert_eq!(&*or, "el"); + } + + #[test] + fn owner() { + let or: BoxRef<String> = Box::new(example().1).into(); + let or = or.map(|x| &x[..5]); + assert_eq!(&*or, "hello"); + assert_eq!(&**or.owner(), "hello world"); + } + + #[test] + fn into_inner() { + let or: BoxRef<String> = Box::new(example().1).into(); + let or = or.map(|x| &x[..5]); + assert_eq!(&*or, "hello"); + let s = *or.into_inner(); + assert_eq!(&s, "hello world"); + } + + #[test] + fn fmt_debug() { + let or: BoxRef<String> = Box::new(example().1).into(); + let or = or.map(|x| &x[..5]); + let s = format!("{:?}", or); + assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); + } + + #[test] + fn erased_owner() { + let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example())) + .map(|x| &x.1[..]); + + let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1)) + .map(|x| &x[..]); + + let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()]; + assert!(os.iter().all(|e| &e[..] == "hello world")); + } + + #[test] + fn raii_locks() { + use super::super::{RefRef, RefMutRef}; + use std::cell::RefCell; + use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; + use std::sync::{Mutex, RwLock}; + + { + let a = RefCell::new(1); + let a = { + let a = RefRef::new(a.borrow()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = RefCell::new(1); + let a = { + let a = RefMutRef::new(a.borrow_mut()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = Mutex::new(1); + let a = { + let a = MutexGuardRef::new(a.lock().unwrap()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = RwLock::new(1); + let a = { + let a = RwLockReadGuardRef::new(a.read().unwrap()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = RwLock::new(1); + let a = { + let a = RwLockWriteGuardRef::new(a.write().unwrap()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + } + + #[test] + fn eq() { + let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + assert_eq!(or1.eq(&or2), true); + } + + #[test] + fn cmp() { + let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); + assert_eq!(or1.cmp(&or2), Ordering::Less); + } + + #[test] + fn partial_cmp() { + let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); + let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); + } + + #[test] + fn hash() { + let mut h1 = DefaultHasher::new(); + let mut h2 = DefaultHasher::new(); + + let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); + + or1.hash(&mut h1); + or2.hash(&mut h2); + + assert_eq!(h1.finish(), h2.finish()); + } + + #[test] + fn borrow() { + let mut hash = HashMap::new(); + let key = RcRef::<String>::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); + + hash.insert(key.clone().map(|s| &s[..3]), 42); + hash.insert(key.clone().map(|s| &s[4..]), 23); + + assert_eq!(hash.get("foo"), Some(&42)); + assert_eq!(hash.get("bar"), Some(&23)); + } + + #[test] + fn total_erase() { + let a: OwningRef<Vec<u8>, [u8]> + = OwningRef::new(vec![]).map(|x| &x[..]); + let b: OwningRef<Box<[u8]>, [u8]> + = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); + + let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe {a.map_owner(Rc::new)}; + let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Rc::new)}; + + let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner(); + let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner(); + + let _g = e.clone(); + let _h = f.clone(); + } + + #[test] + fn total_erase_box() { + let a: OwningRef<Vec<u8>, [u8]> + = OwningRef::new(vec![]).map(|x| &x[..]); + let b: OwningRef<Box<[u8]>, [u8]> + = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); + + let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box(); + let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); + + let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner(); + let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner(); + } + + #[test] + fn try_map1() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); + } + + #[test] + fn try_map2() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); + } +} + +mod owning_handle { + use super::super::OwningHandle; + use super::super::RcRef; + use std::rc::Rc; + use std::cell::RefCell; + use std::sync::Arc; + use std::sync::RwLock; + + #[test] + fn owning_handle() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + assert_eq!(*handle, 2); + *handle = 3; + assert_eq!(*handle, 3); + } + + #[test] + fn try_owning_handle_ok() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { + Ok(unsafe { + x.as_ref() + }.unwrap().borrow_mut()) + }).unwrap(); + assert_eq!(*handle, 2); + *handle = 3; + assert_eq!(*handle, 3); + } + + #[test] + fn try_owning_handle_err() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { + if false { + return Ok(unsafe { + x.as_ref() + }.unwrap().borrow_mut()) + } + Err(()) + }); + assert!(handle.is_err()); + } + + #[test] + fn nested() { + use std::cell::RefCell; + use std::sync::{Arc, RwLock}; + + let result = { + let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); + let curr = RcRef::new(complex); + let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); + assert_eq!(*curr, "someString"); + *curr = "someOtherString"; + curr + }; + assert_eq!(*result, "someOtherString"); + } + + #[test] + fn owning_handle_safe() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let handle = OwningHandle::new(cell_ref); + assert_eq!(*handle, 2); + } + + #[test] + fn owning_handle_mut_safe() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let mut handle = OwningHandle::new_mut(cell_ref); + assert_eq!(*handle, 2); + *handle = 3; + assert_eq!(*handle, 3); + } + + #[test] + fn owning_handle_safe_2() { + let result = { + let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); + let curr = RcRef::new(complex); + let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); + assert_eq!(*curr, "someString"); + *curr = "someOtherString"; + curr + }; + assert_eq!(*result, "someOtherString"); + } +} + +mod owning_ref_mut { + use super::super::{OwningRefMut, BoxRefMut, Erased, ErasedBoxRefMut}; + use super::super::BoxRef; + use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; + use std::hash::{Hash, Hasher}; + use std::collections::hash_map::DefaultHasher; + use std::collections::HashMap; + + #[derive(Debug, PartialEq)] + struct Example(u32, String, [u8; 3]); + fn example() -> Example { + Example(42, "hello world".to_string(), [1, 2, 3]) + } + + #[test] + fn new_deref() { + let or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); + assert_eq!(&*or, &()); + } + + #[test] + fn new_deref_mut() { + let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); + assert_eq!(&mut *or, &mut ()); + } + + #[test] + fn mutate() { + let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0)); + assert_eq!(&*or, &0); + *or = 1; + assert_eq!(&*or, &1); + } + + #[test] + fn into() { + let or: OwningRefMut<Box<()>, ()> = Box::new(()).into(); + assert_eq!(&*or, &()); + } + + #[test] + fn map_offset_ref() { + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRef<_, u32> = or.map(|x| &mut x.0); + assert_eq!(&*or, &42); + + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); + assert_eq!(&*or, &2); + } + + #[test] + fn map_heap_ref() { + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); + assert_eq!(&*or, "hello"); + } + + #[test] + fn map_static_ref() { + let or: BoxRefMut<()> = Box::new(()).into(); + let or: BoxRef<_, str> = or.map(|_| "hello"); + assert_eq!(&*or, "hello"); + } + + #[test] + fn map_mut_offset_ref() { + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); + assert_eq!(&*or, &42); + + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); + assert_eq!(&*or, &2); + } + + #[test] + fn map_mut_heap_ref() { + let or: BoxRefMut<Example> = Box::new(example()).into(); + let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); + assert_eq!(&*or, "hello"); + } + + #[test] + fn map_mut_static_ref() { + static mut MUT_S: [u8; 5] = *b"hello"; + + let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; + + let or: BoxRefMut<()> = Box::new(()).into(); + let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); + assert_eq!(&*or, b"hello"); + } + + #[test] + fn map_mut_chained() { + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); + let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); + assert_eq!(&*or, "el"); + } + + #[test] + fn map_chained_inference() { + let or = BoxRefMut::new(Box::new(example().1)) + .map_mut(|x| &mut x[..5]) + .map_mut(|x| &mut x[1..3]); + assert_eq!(&*or, "el"); + } + + #[test] + fn try_map_mut() { + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); + assert_eq!(&*or.unwrap(), "ello"); + + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(())); + assert!(or.is_err()); + } + + #[test] + fn owner() { + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or = or.map_mut(|x| &mut x[..5]); + assert_eq!(&*or, "hello"); + assert_eq!(&**or.owner(), "hello world"); + } + + #[test] + fn into_inner() { + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or = or.map_mut(|x| &mut x[..5]); + assert_eq!(&*or, "hello"); + let s = *or.into_inner(); + assert_eq!(&s, "hello world"); + } + + #[test] + fn fmt_debug() { + let or: BoxRefMut<String> = Box::new(example().1).into(); + let or = or.map_mut(|x| &mut x[..5]); + let s = format!("{:?}", or); + assert_eq!(&s, + "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); + } + + #[test] + fn erased_owner() { + let o1: BoxRefMut<Example, str> = BoxRefMut::new(Box::new(example())) + .map_mut(|x| &mut x.1[..]); + + let o2: BoxRefMut<String, str> = BoxRefMut::new(Box::new(example().1)) + .map_mut(|x| &mut x[..]); + + let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()]; + assert!(os.iter().all(|e| &e[..] == "hello world")); + } + + #[test] + fn raii_locks() { + use super::super::RefMutRefMut; + use std::cell::RefCell; + use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; + use std::sync::{Mutex, RwLock}; + + { + let a = RefCell::new(1); + let a = { + let a = RefMutRefMut::new(a.borrow_mut()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = Mutex::new(1); + let a = { + let a = MutexGuardRefMut::new(a.lock().unwrap()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + { + let a = RwLock::new(1); + let a = { + let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); + assert_eq!(*a, 1); + a + }; + assert_eq!(*a, 1); + drop(a); + } + } + + #[test] + fn eq() { + let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + assert_eq!(or1.eq(&or2), true); + } + + #[test] + fn cmp() { + let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); + assert_eq!(or1.cmp(&or2), Ordering::Less); + } + + #[test] + fn partial_cmp() { + let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); + let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); + } + + #[test] + fn hash() { + let mut h1 = DefaultHasher::new(); + let mut h2 = DefaultHasher::new(); + + let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); + + or1.hash(&mut h1); + or2.hash(&mut h2); + + assert_eq!(h1.finish(), h2.finish()); + } + + #[test] + fn borrow() { + let mut hash = HashMap::new(); + let key1 = BoxRefMut::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]); + let key2 = BoxRefMut::<String>::new(Box::new("bar".to_string())).map(|s| &s[..]); + + hash.insert(key1, 42); + hash.insert(key2, 23); + + assert_eq!(hash.get("foo"), Some(&42)); + assert_eq!(hash.get("bar"), Some(&23)); + } + + #[test] + fn total_erase() { + let a: OwningRefMut<Vec<u8>, [u8]> + = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); + let b: OwningRefMut<Box<[u8]>, [u8]> + = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); + + let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe {a.map_owner(Box::new)}; + let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Box::new)}; + + let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); + let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); + } + + #[test] + fn total_erase_box() { + let a: OwningRefMut<Vec<u8>, [u8]> + = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); + let b: OwningRefMut<Box<[u8]>, [u8]> + = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); + + let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box(); + let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); + + let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); + let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); + } + + #[test] + fn try_map1() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_ok()); + } + + #[test] + fn try_map2() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_err()); + } + + #[test] + fn try_map3() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); + } + + #[test] + fn try_map4() { + use std::any::Any; + + let x = Box::new(123_i32); + let y: Box<dyn Any> = x; + + assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); + } + + #[test] + fn into_owning_ref() { + use super::super::BoxRef; + + let or: BoxRefMut<()> = Box::new(()).into(); + let or: BoxRef<()> = or.into(); + assert_eq!(&*or, &()); + } + + struct Foo { + u: u32, + } + struct Bar { + f: Foo, + } + + #[test] + fn ref_mut() { + use std::cell::RefCell; + + let a = RefCell::new(Bar { f: Foo { u: 42 } }); + let mut b = OwningRefMut::new(a.borrow_mut()); + assert_eq!(b.f.u, 42); + b.f.u = 43; + let mut c = b.map_mut(|x| &mut x.f); + assert_eq!(c.u, 43); + c.u = 44; + let mut d = c.map_mut(|x| &mut x.u); + assert_eq!(*d, 44); + *d = 45; + assert_eq!(*d, 45); + } +} diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs index 1f674c1c664e4..fb819dd18a8d6 100644 --- a/src/librustc_data_structures/sorted_map.rs +++ b/src/librustc_data_structures/sorted_map.rs @@ -305,204 +305,4 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> { } #[cfg(test)] -mod tests { - use super::SortedMap; - - #[test] - fn test_insert_and_iter() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0 .. 100 { - assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected); - - let x = 1000 - x * 2; - map.insert(x, x); - expected.insert(0, (x, x)); - } - } - - #[test] - fn test_get_and_index() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0 .. 100 { - let x = 1000 - x; - if x & 1 == 0 { - map.insert(x, x); - } - expected.push(x); - } - - for mut x in expected { - if x & 1 == 0 { - assert_eq!(map.get(&x), Some(&x)); - assert_eq!(map.get_mut(&x), Some(&mut x)); - assert_eq!(map[&x], x); - assert_eq!(&mut map[&x], &mut x); - } else { - assert_eq!(map.get(&x), None); - assert_eq!(map.get_mut(&x), None); - } - } - } - - #[test] - fn test_range() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - map.insert(9, 9); - - let keys = |s: &[(_, _)]| { - s.into_iter().map(|e| e.0).collect::<Vec<u32>>() - }; - - for start in 0 .. 11 { - for end in 0 .. 11 { - if end < start { - continue - } - - let mut expected = vec![1, 3, 6, 9]; - expected.retain(|&x| x >= start && x < end); - - assert_eq!(keys(map.range(start..end)), expected, "range = {}..{}", start, end); - } - } - } - - - #[test] - fn test_offset_keys() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - - map.offset_keys(|k| *k += 1); - - let mut expected = SortedMap::new(); - expected.insert(2, 1); - expected.insert(4, 3); - expected.insert(7, 6); - - assert_eq!(map, expected); - } - - fn keys(s: SortedMap<u32, u32>) -> Vec<u32> { - s.into_iter().map(|(k, _)| k).collect::<Vec<u32>>() - } - - fn elements(s: SortedMap<u32, u32>) -> Vec<(u32, u32)> { - s.into_iter().collect::<Vec<(u32, u32)>>() - } - - #[test] - fn test_remove_range() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - map.insert(9, 9); - - for start in 0 .. 11 { - for end in 0 .. 11 { - if end < start { - continue - } - - let mut expected = vec![1, 3, 6, 9]; - expected.retain(|&x| x < start || x >= end); - - let mut map = map.clone(); - map.remove_range(start .. end); - - assert_eq!(keys(map), expected, "range = {}..{}", start, end); - } - } - } - - #[test] - fn test_remove() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0..10 { - map.insert(x, x); - expected.push((x, x)); - } - - for x in 0 .. 10 { - let mut map = map.clone(); - let mut expected = expected.clone(); - - assert_eq!(map.remove(&x), Some(x)); - expected.remove(x as usize); - - assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected); - } - } - - #[test] - fn test_insert_presorted_non_overlapping() { - let mut map = SortedMap::new(); - map.insert(2, 0); - map.insert(8, 0); - - map.insert_presorted(vec![(3, 0), (7, 0)]); - - let expected = vec![2, 3, 7, 8]; - assert_eq!(keys(map), expected); - } - - #[test] - fn test_insert_presorted_first_elem_equal() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(8, 8); - - map.insert_presorted(vec![(2, 0), (7, 7)]); - - let expected = vec![(2, 0), (7, 7), (8, 8)]; - assert_eq!(elements(map), expected); - } - - #[test] - fn test_insert_presorted_last_elem_equal() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(8, 8); - - map.insert_presorted(vec![(3, 3), (8, 0)]); - - let expected = vec![(2, 2), (3, 3), (8, 0)]; - assert_eq!(elements(map), expected); - } - - #[test] - fn test_insert_presorted_shuffle() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(7, 7); - - map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)]); - - let expected = vec![(1, 1), (2, 2), (3, 3), (7, 7), (8, 8)]; - assert_eq!(elements(map), expected); - } - - #[test] - fn test_insert_presorted_at_end() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(2, 2); - - map.insert_presorted(vec![(3, 3), (8, 8)]); - - let expected = vec![(1, 1), (2, 2), (3, 3), (8, 8)]; - assert_eq!(elements(map), expected); - } -} +mod tests; diff --git a/src/librustc_data_structures/sorted_map/tests.rs b/src/librustc_data_structures/sorted_map/tests.rs new file mode 100644 index 0000000000000..f970409cc3d58 --- /dev/null +++ b/src/librustc_data_structures/sorted_map/tests.rs @@ -0,0 +1,199 @@ +use super::SortedMap; + +#[test] +fn test_insert_and_iter() { + let mut map = SortedMap::new(); + let mut expected = Vec::new(); + + for x in 0 .. 100 { + assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected); + + let x = 1000 - x * 2; + map.insert(x, x); + expected.insert(0, (x, x)); + } +} + +#[test] +fn test_get_and_index() { + let mut map = SortedMap::new(); + let mut expected = Vec::new(); + + for x in 0 .. 100 { + let x = 1000 - x; + if x & 1 == 0 { + map.insert(x, x); + } + expected.push(x); + } + + for mut x in expected { + if x & 1 == 0 { + assert_eq!(map.get(&x), Some(&x)); + assert_eq!(map.get_mut(&x), Some(&mut x)); + assert_eq!(map[&x], x); + assert_eq!(&mut map[&x], &mut x); + } else { + assert_eq!(map.get(&x), None); + assert_eq!(map.get_mut(&x), None); + } + } +} + +#[test] +fn test_range() { + let mut map = SortedMap::new(); + map.insert(1, 1); + map.insert(3, 3); + map.insert(6, 6); + map.insert(9, 9); + + let keys = |s: &[(_, _)]| { + s.into_iter().map(|e| e.0).collect::<Vec<u32>>() + }; + + for start in 0 .. 11 { + for end in 0 .. 11 { + if end < start { + continue + } + + let mut expected = vec![1, 3, 6, 9]; + expected.retain(|&x| x >= start && x < end); + + assert_eq!(keys(map.range(start..end)), expected, "range = {}..{}", start, end); + } + } +} + + +#[test] +fn test_offset_keys() { + let mut map = SortedMap::new(); + map.insert(1, 1); + map.insert(3, 3); + map.insert(6, 6); + + map.offset_keys(|k| *k += 1); + + let mut expected = SortedMap::new(); + expected.insert(2, 1); + expected.insert(4, 3); + expected.insert(7, 6); + + assert_eq!(map, expected); +} + +fn keys(s: SortedMap<u32, u32>) -> Vec<u32> { + s.into_iter().map(|(k, _)| k).collect::<Vec<u32>>() +} + +fn elements(s: SortedMap<u32, u32>) -> Vec<(u32, u32)> { + s.into_iter().collect::<Vec<(u32, u32)>>() +} + +#[test] +fn test_remove_range() { + let mut map = SortedMap::new(); + map.insert(1, 1); + map.insert(3, 3); + map.insert(6, 6); + map.insert(9, 9); + + for start in 0 .. 11 { + for end in 0 .. 11 { + if end < start { + continue + } + + let mut expected = vec![1, 3, 6, 9]; + expected.retain(|&x| x < start || x >= end); + + let mut map = map.clone(); + map.remove_range(start .. end); + + assert_eq!(keys(map), expected, "range = {}..{}", start, end); + } + } +} + +#[test] +fn test_remove() { + let mut map = SortedMap::new(); + let mut expected = Vec::new(); + + for x in 0..10 { + map.insert(x, x); + expected.push((x, x)); + } + + for x in 0 .. 10 { + let mut map = map.clone(); + let mut expected = expected.clone(); + + assert_eq!(map.remove(&x), Some(x)); + expected.remove(x as usize); + + assert_eq!(map.iter().cloned().collect::<Vec<_>>(), expected); + } +} + +#[test] +fn test_insert_presorted_non_overlapping() { + let mut map = SortedMap::new(); + map.insert(2, 0); + map.insert(8, 0); + + map.insert_presorted(vec![(3, 0), (7, 0)]); + + let expected = vec![2, 3, 7, 8]; + assert_eq!(keys(map), expected); +} + +#[test] +fn test_insert_presorted_first_elem_equal() { + let mut map = SortedMap::new(); + map.insert(2, 2); + map.insert(8, 8); + + map.insert_presorted(vec![(2, 0), (7, 7)]); + + let expected = vec![(2, 0), (7, 7), (8, 8)]; + assert_eq!(elements(map), expected); +} + +#[test] +fn test_insert_presorted_last_elem_equal() { + let mut map = SortedMap::new(); + map.insert(2, 2); + map.insert(8, 8); + + map.insert_presorted(vec![(3, 3), (8, 0)]); + + let expected = vec![(2, 2), (3, 3), (8, 0)]; + assert_eq!(elements(map), expected); +} + +#[test] +fn test_insert_presorted_shuffle() { + let mut map = SortedMap::new(); + map.insert(2, 2); + map.insert(7, 7); + + map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)]); + + let expected = vec![(1, 1), (2, 2), (3, 3), (7, 7), (8, 8)]; + assert_eq!(elements(map), expected); +} + +#[test] +fn test_insert_presorted_at_end() { + let mut map = SortedMap::new(); + map.insert(1, 1); + map.insert(2, 2); + + map.insert_presorted(vec![(3, 3), (8, 8)]); + + let expected = vec![(1, 1), (2, 2), (3, 3), (8, 8)]; + assert_eq!(elements(map), expected); +} diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 551eded9858a3..903a2d6801230 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -440,26 +440,4 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { } #[cfg(test)] -mod tests { - use super::{is_camel_case, to_camel_case}; - - #[test] - fn camel_case() { - assert!(!is_camel_case("userData")); - assert_eq!(to_camel_case("userData"), "UserData"); - - assert!(is_camel_case("X86_64")); - - assert!(!is_camel_case("X86__64")); - assert_eq!(to_camel_case("X86__64"), "X86_64"); - - assert!(!is_camel_case("Abc_123")); - assert_eq!(to_camel_case("Abc_123"), "Abc123"); - - assert!(!is_camel_case("A1_b2_c3")); - assert_eq!(to_camel_case("A1_b2_c3"), "A1B2C3"); - - assert!(!is_camel_case("ONE_TWO_THREE")); - assert_eq!(to_camel_case("ONE_TWO_THREE"), "OneTwoThree"); - } -} +mod tests; diff --git a/src/librustc_lint/nonstandard_style/tests.rs b/src/librustc_lint/nonstandard_style/tests.rs new file mode 100644 index 0000000000000..39c525b8623d0 --- /dev/null +++ b/src/librustc_lint/nonstandard_style/tests.rs @@ -0,0 +1,21 @@ +use super::{is_camel_case, to_camel_case}; + +#[test] +fn camel_case() { + assert!(!is_camel_case("userData")); + assert_eq!(to_camel_case("userData"), "UserData"); + + assert!(is_camel_case("X86_64")); + + assert!(!is_camel_case("X86__64")); + assert_eq!(to_camel_case("X86__64"), "X86_64"); + + assert!(!is_camel_case("Abc_123")); + assert_eq!(to_camel_case("Abc_123"), "Abc123"); + + assert!(!is_camel_case("A1_b2_c3")); + assert_eq!(to_camel_case("A1_b2_c3"), "A1B2C3"); + + assert!(!is_camel_case("ONE_TWO_THREE")); + assert_eq!(to_camel_case("ONE_TWO_THREE"), "OneTwoThree"); +} diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs index 395270f5bb53a..76a9a3405bd81 100644 --- a/src/librustc_metadata/dynamic_lib.rs +++ b/src/librustc_metadata/dynamic_lib.rs @@ -74,55 +74,7 @@ impl DynamicLibrary { } #[cfg(test)] -mod tests { - use super::*; - use std::mem; - - #[test] - fn test_loading_atoi() { - if cfg!(windows) { - return - } - - // The C library does not need to be loaded since it is already linked in - let lib = match DynamicLibrary::open(None) { - Err(error) => panic!("Could not load self as module: {}", error), - Ok(lib) => lib - }; - - let atoi: extern fn(*const libc::c_char) -> libc::c_int = unsafe { - match lib.symbol("atoi") { - Err(error) => panic!("Could not load function atoi: {}", error), - Ok(atoi) => mem::transmute::<*mut u8, _>(atoi) - } - }; - - let argument = CString::new("1383428980").unwrap(); - let expected_result = 0x52757374; - let result = atoi(argument.as_ptr()); - if result != expected_result { - panic!("atoi({:?}) != {} but equaled {} instead", argument, - expected_result, result) - } - } - - #[test] - fn test_errors_do_not_crash() { - use std::path::Path; - - if !cfg!(unix) { - return - } - - // Open /dev/null as a library to get an error, and make sure - // that only causes an error, and not a crash. - let path = Path::new("/dev/null"); - match DynamicLibrary::open(Some(&path)) { - Err(_) => {} - Ok(_) => panic!("Successfully opened the empty library.") - } - } -} +mod tests; #[cfg(unix)] mod dl { diff --git a/src/librustc_metadata/dynamic_lib/tests.rs b/src/librustc_metadata/dynamic_lib/tests.rs new file mode 100644 index 0000000000000..b2302f2f1b5b7 --- /dev/null +++ b/src/librustc_metadata/dynamic_lib/tests.rs @@ -0,0 +1,47 @@ +use super::*; +use std::mem; + +#[test] +fn test_loading_atoi() { + if cfg!(windows) { + return + } + + // The C library does not need to be loaded since it is already linked in + let lib = match DynamicLibrary::open(None) { + Err(error) => panic!("Could not load self as module: {}", error), + Ok(lib) => lib + }; + + let atoi: extern fn(*const libc::c_char) -> libc::c_int = unsafe { + match lib.symbol("atoi") { + Err(error) => panic!("Could not load function atoi: {}", error), + Ok(atoi) => mem::transmute::<*mut u8, _>(atoi) + } + }; + + let argument = CString::new("1383428980").unwrap(); + let expected_result = 0x52757374; + let result = atoi(argument.as_ptr()); + if result != expected_result { + panic!("atoi({:?}) != {} but equaled {} instead", argument, + expected_result, result) + } +} + +#[test] +fn test_errors_do_not_crash() { + use std::path::Path; + + if !cfg!(unix) { + return + } + + // Open /dev/null as a library to get an error, and make sure + // that only causes an error, and not a crash. + let path = Path::new("/dev/null"); + match DynamicLibrary::open(Some(&path)) { + Err(_) => {} + Ok(_) => panic!("Successfully opened the empty library.") + } +} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 334b831565076..c698200039623 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -43,25 +43,30 @@ fn opts() -> Options { Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES } -/// A unit struct which has the `fmt::Display` trait implemented. When -/// formatted, this struct will emit the HTML corresponding to the rendered +/// A tuple struct that has the `fmt::Display` trait implemented. +/// When formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. -/// -/// The second parameter is a list of link replacements. -/// -/// The third is the current list of used header IDs. -/// -/// The fourth is whether to allow the use of explicit error codes in doctest lang strings. -/// -/// The fifth is what default edition to use when parsing doctests (to add a `fn main`). pub struct Markdown<'a>( - pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); -/// A unit struct like `Markdown`, that renders the markdown with a -/// table of contents. -pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); -/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags. + pub &'a str, + /// A list of link replacements. + pub &'a [(String, String)], + /// The current list of used header IDs. + pub RefCell<&'a mut IdMap>, + /// Whether to allow the use of explicit error codes in doctest lang strings. + pub ErrorCodes, + /// Default edition to use when parsing doctests (to add a `fn main`). + pub Edition, +); +/// A tuple struct like `Markdown` that renders the markdown with a table of contents. +pub struct MarkdownWithToc<'a>( + pub &'a str, + pub RefCell<&'a mut IdMap>, + pub ErrorCodes, + pub Edition, +); +/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags. pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); -/// A unit struct like `Markdown`, that renders only the first paragraph. +/// A tuple struct like `Markdown` that renders only the first paragraph. pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]); #[derive(Copy, Clone, PartialEq, Debug)] @@ -1050,130 +1055,4 @@ fn test_unique_id() { } #[cfg(test)] -mod tests { - use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap}; - use super::plain_summary_line; - use std::cell::RefCell; - use syntax::edition::{Edition, DEFAULT_EDITION}; - - #[test] - fn test_lang_string_parse() { - fn t(s: &str, - should_panic: bool, no_run: bool, ignore: bool, 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 { - should_panic, - no_run, - ignore, - rust, - test_harness, - compile_fail, - error_codes, - original: s.to_owned(), - allow_fail, - edition, - }) - } - - fn v() -> Vec<String> { - Vec::new() - } - - // 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)); - } - - #[test] - fn test_header() { - fn t(input: &str, expect: &str) { - let mut map = IdMap::new(); - let output = Markdown(input, &[], RefCell::new(&mut map), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); - assert_eq!(output, expect, "original: {}", input); - } - - t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\ - <a href=\"#foo-bar\">Foo bar</a></h1>"); - t("## Foo-bar_baz qux", "<h2 id=\"foo-bar_baz-qux\" class=\"section-\ - header\"><a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h2>"); - t("### **Foo** *bar* baz!?!& -_qux_-%", - "<h3 id=\"foo-bar-baz--qux-\" class=\"section-header\">\ - <a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \ - <em>bar</em> baz!?!& -<em>qux</em>-%</a></h3>"); - t("#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", - "<h4 id=\"foo--bar--baz--qux\" class=\"section-header\">\ - <a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> & *bar?!* \ - <em><code>baz</code></em> ❤ #qux</a></h4>"); - } - - #[test] - fn test_header_ids_multiple_blocks() { - let mut map = IdMap::new(); - fn t(map: &mut IdMap, input: &str, expect: &str) { - let output = Markdown(input, &[], RefCell::new(map), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); - assert_eq!(output, expect, "original: {}", input); - } - - t(&mut map, "# Example", "<h1 id=\"example\" class=\"section-header\">\ - <a href=\"#example\">Example</a></h1>"); - t(&mut map, "# Panics", "<h1 id=\"panics\" class=\"section-header\">\ - <a href=\"#panics\">Panics</a></h1>"); - t(&mut map, "# Example", "<h1 id=\"example-1\" class=\"section-header\">\ - <a href=\"#example-1\">Example</a></h1>"); - t(&mut map, "# Main", "<h1 id=\"main\" class=\"section-header\">\ - <a href=\"#main\">Main</a></h1>"); - t(&mut map, "# Example", "<h1 id=\"example-2\" class=\"section-header\">\ - <a href=\"#example-2\">Example</a></h1>"); - t(&mut map, "# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\ - <a href=\"#panics-1\">Panics</a></h1>"); - } - - #[test] - fn test_plain_summary_line() { - fn t(input: &str, expect: &str) { - let output = plain_summary_line(input); - assert_eq!(output, expect, "original: {}", input); - } - - t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)"); - t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)"); - t("code `let x = i32;` ...", "code `let x = i32;` ..."); - t("type `Type<'static>` ...", "type `Type<'static>` ..."); - t("# top header", "top header"); - t("## header", "header"); - } - - #[test] - fn test_markdown_html_escape() { - fn t(input: &str, expect: &str) { - let mut idmap = IdMap::new(); - let output = MarkdownHtml(input, RefCell::new(&mut idmap), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); - assert_eq!(output, expect, "original: {}", input); - } - - t("`Struct<'a, T>`", "<p><code>Struct<'a, T></code></p>\n"); - t("Struct<'a, T>", "<p>Struct<'a, T></p>\n"); - t("Struct<br>", "<p>Struct<br></p>\n"); - } -} +mod tests; diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs new file mode 100644 index 0000000000000..f470e649d8265 --- /dev/null +++ b/src/librustdoc/html/markdown/tests.rs @@ -0,0 +1,125 @@ +use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap}; +use super::plain_summary_line; +use std::cell::RefCell; +use syntax::edition::{Edition, DEFAULT_EDITION}; + +#[test] +fn test_lang_string_parse() { + fn t(s: &str, + should_panic: bool, no_run: bool, ignore: bool, 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 { + should_panic, + no_run, + ignore, + rust, + test_harness, + compile_fail, + error_codes, + original: s.to_owned(), + allow_fail, + edition, + }) + } + + fn v() -> Vec<String> { + Vec::new() + } + + // 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)); +} + +#[test] +fn test_header() { + fn t(input: &str, expect: &str) { + let mut map = IdMap::new(); + let output = Markdown(input, &[], RefCell::new(&mut map), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + assert_eq!(output, expect, "original: {}", input); + } + + t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\ + <a href=\"#foo-bar\">Foo bar</a></h1>"); + t("## Foo-bar_baz qux", "<h2 id=\"foo-bar_baz-qux\" class=\"section-\ + header\"><a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h2>"); + t("### **Foo** *bar* baz!?!& -_qux_-%", + "<h3 id=\"foo-bar-baz--qux-\" class=\"section-header\">\ + <a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \ + <em>bar</em> baz!?!& -<em>qux</em>-%</a></h3>"); + t("#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", + "<h4 id=\"foo--bar--baz--qux\" class=\"section-header\">\ + <a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> & *bar?!* \ + <em><code>baz</code></em> ❤ #qux</a></h4>"); +} + +#[test] +fn test_header_ids_multiple_blocks() { + let mut map = IdMap::new(); + fn t(map: &mut IdMap, input: &str, expect: &str) { + let output = Markdown(input, &[], RefCell::new(map), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + assert_eq!(output, expect, "original: {}", input); + } + + t(&mut map, "# Example", "<h1 id=\"example\" class=\"section-header\">\ + <a href=\"#example\">Example</a></h1>"); + t(&mut map, "# Panics", "<h1 id=\"panics\" class=\"section-header\">\ + <a href=\"#panics\">Panics</a></h1>"); + t(&mut map, "# Example", "<h1 id=\"example-1\" class=\"section-header\">\ + <a href=\"#example-1\">Example</a></h1>"); + t(&mut map, "# Main", "<h1 id=\"main\" class=\"section-header\">\ + <a href=\"#main\">Main</a></h1>"); + t(&mut map, "# Example", "<h1 id=\"example-2\" class=\"section-header\">\ + <a href=\"#example-2\">Example</a></h1>"); + t(&mut map, "# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\ + <a href=\"#panics-1\">Panics</a></h1>"); +} + +#[test] +fn test_plain_summary_line() { + fn t(input: &str, expect: &str) { + let output = plain_summary_line(input); + assert_eq!(output, expect, "original: {}", input); + } + + t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)"); + t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)"); + t("code `let x = i32;` ...", "code `let x = i32;` ..."); + t("type `Type<'static>` ...", "type `Type<'static>` ..."); + t("# top header", "top header"); + t("## header", "header"); +} + +#[test] +fn test_markdown_html_escape() { + fn t(input: &str, expect: &str) { + let mut idmap = IdMap::new(); + let output = MarkdownHtml(input, RefCell::new(&mut idmap), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + assert_eq!(output, expect, "original: {}", input); + } + + t("`Struct<'a, T>`", "<p><code>Struct<'a, T></code></p>\n"); + t("Struct<'a, T>", "<p>Struct<'a, T></p>\n"); + t("Struct<br>", "<p>Struct<br></p>\n"); +} diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 409f2479ccc7c..2564c611e54e5 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -188,85 +188,4 @@ impl fmt::Display for Toc { } #[cfg(test)] -mod tests { - use super::{TocBuilder, Toc, TocEntry}; - - #[test] - fn builder_smoke() { - let mut builder = TocBuilder::new(); - - // this is purposely not using a fancy macro like below so - // that we're sure that this is doing the correct thing, and - // there's been no macro mistake. - macro_rules! push { - ($level: expr, $name: expr) => { - assert_eq!(builder.push($level, - $name.to_string(), - "".to_string()), - $name); - } - } - push!(2, "0.1"); - push!(1, "1"); - { - push!(2, "1.1"); - { - push!(3, "1.1.1"); - push!(3, "1.1.2"); - } - push!(2, "1.2"); - { - push!(3, "1.2.1"); - push!(3, "1.2.2"); - } - } - push!(1, "2"); - push!(1, "3"); - { - push!(4, "3.0.0.1"); - { - push!(6, "3.0.0.1.0.1"); - } - push!(4, "3.0.0.2"); - push!(2, "3.1"); - { - push!(4, "3.1.0.1"); - } - } - - macro_rules! toc { - ($(($level: expr, $name: expr, $(($sub: tt))* )),*) => { - Toc { - entries: vec![ - $( - TocEntry { - level: $level, - name: $name.to_string(), - sec_number: $name.to_string(), - id: "".to_string(), - children: toc!($($sub),*) - } - ),* - ] - } - } - } - let expected = toc!( - (2, "0.1", ), - - (1, "1", - ((2, "1.1", ((3, "1.1.1", )) ((3, "1.1.2", )))) - ((2, "1.2", ((3, "1.2.1", )) ((3, "1.2.2", )))) - ), - - (1, "2", ), - - (1, "3", - ((4, "3.0.0.1", ((6, "3.0.0.1.0.1", )))) - ((4, "3.0.0.2", )) - ((2, "3.1", ((4, "3.1.0.1", )))) - ) - ); - assert_eq!(expected, builder.into_toc()); - } -} +mod tests; diff --git a/src/librustdoc/html/toc/tests.rs b/src/librustdoc/html/toc/tests.rs new file mode 100644 index 0000000000000..ef69ada466496 --- /dev/null +++ b/src/librustdoc/html/toc/tests.rs @@ -0,0 +1,80 @@ +use super::{TocBuilder, Toc, TocEntry}; + +#[test] +fn builder_smoke() { + let mut builder = TocBuilder::new(); + + // this is purposely not using a fancy macro like below so + // that we're sure that this is doing the correct thing, and + // there's been no macro mistake. + macro_rules! push { + ($level: expr, $name: expr) => { + assert_eq!(builder.push($level, + $name.to_string(), + "".to_string()), + $name); + } + } + push!(2, "0.1"); + push!(1, "1"); + { + push!(2, "1.1"); + { + push!(3, "1.1.1"); + push!(3, "1.1.2"); + } + push!(2, "1.2"); + { + push!(3, "1.2.1"); + push!(3, "1.2.2"); + } + } + push!(1, "2"); + push!(1, "3"); + { + push!(4, "3.0.0.1"); + { + push!(6, "3.0.0.1.0.1"); + } + push!(4, "3.0.0.2"); + push!(2, "3.1"); + { + push!(4, "3.1.0.1"); + } + } + + macro_rules! toc { + ($(($level: expr, $name: expr, $(($sub: tt))* )),*) => { + Toc { + entries: vec![ + $( + TocEntry { + level: $level, + name: $name.to_string(), + sec_number: $name.to_string(), + id: "".to_string(), + children: toc!($($sub),*) + } + ),* + ] + } + } + } + let expected = toc!( + (2, "0.1", ), + + (1, "1", + ((2, "1.1", ((3, "1.1.1", )) ((3, "1.1.2", )))) + ((2, "1.2", ((3, "1.2.1", )) ((3, "1.2.2", )))) + ), + + (1, "2", ), + + (1, "3", + ((4, "3.0.0.1", ((6, "3.0.0.1.0.1", )))) + ((4, "3.0.0.2", )) + ((2, "3.1", ((4, "3.1.0.1", )))) + ) + ); + assert_eq!(expected, builder.into_toc()); +} diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index baf99bacb8ee6..9a9fd941240bc 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -975,304 +975,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { } #[cfg(test)] -mod tests { - use super::{TestOptions, make_test}; - use syntax::edition::DEFAULT_EDITION; - - #[test] - fn make_test_basic() { - //basic use: wraps with `fn main`, adds `#![allow(unused)]` - let opts = TestOptions::default(); - let input = -"assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -fn main() { -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_crate_name_no_use() { - // If you give a crate name but *don't* use it within the test, it won't bother inserting - // the `extern crate` statement. - let opts = TestOptions::default(); - let input = -"assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -fn main() { -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_crate_name() { - // If you give a crate name and use it within the test, it will insert an `extern crate` - // statement before `fn main`. - let opts = TestOptions::default(); - let input = -"use asdf::qwop; -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -extern crate asdf; -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 3)); - } - - #[test] - fn make_test_no_crate_inject() { - // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip - // adding it anyway. - let opts = TestOptions { - no_crate_inject: true, - display_warnings: false, - attrs: vec![], - }; - let input = -"use asdf::qwop; -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_ignore_std() { - // Even if you include a crate name, and use it in the doctest, we still won't include an - // `extern crate` statement if the crate is "std" -- that's included already by the - // compiler! - let opts = TestOptions::default(); - let input = -"use std::*; -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -fn main() { -use std::*; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_manual_extern_crate() { - // When you manually include an `extern crate` statement in your doctest, `make_test` - // assumes you've included one for your own crate too. - let opts = TestOptions::default(); - let input = -"extern crate asdf; -use asdf::qwop; -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -extern crate asdf; -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_manual_extern_crate_with_macro_use() { - let opts = TestOptions::default(); - let input = -"#[macro_use] extern crate asdf; -use asdf::qwop; -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -#[macro_use] extern crate asdf; -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_opts_attrs() { - // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use - // those instead of the stock `#![allow(unused)]`. - let mut opts = TestOptions::default(); - opts.attrs.push("feature(sick_rad)".to_string()); - let input = -"use asdf::qwop; -assert_eq!(2+2, 4);"; - let expected = -"#![feature(sick_rad)] -extern crate asdf; -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 3)); - - // Adding more will also bump the returned line offset. - opts.attrs.push("feature(hella_dope)".to_string()); - let expected = -"#![feature(sick_rad)] -#![feature(hella_dope)] -extern crate asdf; -fn main() { -use asdf::qwop; -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 4)); - } - - #[test] - fn make_test_crate_attrs() { - // Including inner attributes in your doctest will apply them to the whole "crate", pasting - // them outside the generated main function. - let opts = TestOptions::default(); - let input = -"#![feature(sick_rad)] -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -#![feature(sick_rad)] -fn main() { -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_with_main() { - // Including your own `fn main` wrapper lets the test use it verbatim. - let opts = TestOptions::default(); - let input = -"fn main() { - assert_eq!(2+2, 4); -}"; - let expected = -"#![allow(unused)] -fn main() { - assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 1)); - } - - #[test] - fn make_test_fake_main() { - // ... but putting it in a comment will still provide a wrapper. - let opts = TestOptions::default(); - let input = -"//Ceci n'est pas une `fn main` -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -//Ceci n'est pas une `fn main` -fn main() { -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - } - - #[test] - fn make_test_dont_insert_main() { - // Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper. - let opts = TestOptions::default(); - let input = -"//Ceci n'est pas une `fn main` -assert_eq!(2+2, 4);"; - let expected = -"#![allow(unused)] -//Ceci n'est pas une `fn main` -assert_eq!(2+2, 4);".to_string(); - let output = make_test(input, None, true, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 1)); - } - - #[test] - fn make_test_display_warnings() { - // If the user is asking to display doctest warnings, suppress the default `allow(unused)`. - let mut opts = TestOptions::default(); - opts.display_warnings = true; - let input = -"assert_eq!(2+2, 4);"; - let expected = -"fn main() { -assert_eq!(2+2, 4); -}".to_string(); - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 1)); - } - - #[test] - fn make_test_issues_21299_33731() { - let opts = TestOptions::default(); - - let input = -"// fn main -assert_eq!(2+2, 4);"; - - let expected = -"#![allow(unused)] -// fn main -fn main() { -assert_eq!(2+2, 4); -}".to_string(); - - let output = make_test(input, None, false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 2)); - - let input = -"extern crate hella_qwop; -assert_eq!(asdf::foo, 4);"; - - let expected = -"#![allow(unused)] -extern crate hella_qwop; -extern crate asdf; -fn main() { -assert_eq!(asdf::foo, 4); -}".to_string(); - - let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 3)); - } - - #[test] - fn make_test_main_in_macro() { - let opts = TestOptions::default(); - let input = -"#[macro_use] extern crate my_crate; -test_wrapper! { - fn main() {} -}"; - let expected = -"#![allow(unused)] -#[macro_use] extern crate my_crate; -test_wrapper! { - fn main() {} -}".to_string(); - - let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION); - assert_eq!(output, (expected, 1)); - } -} +mod tests; diff --git a/src/librustdoc/test/tests.rs b/src/librustdoc/test/tests.rs new file mode 100644 index 0000000000000..d4d558b7cd78c --- /dev/null +++ b/src/librustdoc/test/tests.rs @@ -0,0 +1,299 @@ +use super::{TestOptions, make_test}; +use syntax::edition::DEFAULT_EDITION; + +#[test] +fn make_test_basic() { + //basic use: wraps with `fn main`, adds `#![allow(unused)]` + let opts = TestOptions::default(); + let input = +"assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +fn main() { +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_crate_name_no_use() { + // If you give a crate name but *don't* use it within the test, it won't bother inserting + // the `extern crate` statement. + let opts = TestOptions::default(); + let input = +"assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +fn main() { +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_crate_name() { + // If you give a crate name and use it within the test, it will insert an `extern crate` + // statement before `fn main`. + let opts = TestOptions::default(); + let input = +"use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 3)); +} + +#[test] +fn make_test_no_crate_inject() { + // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip + // adding it anyway. + let opts = TestOptions { + no_crate_inject: true, + display_warnings: false, + attrs: vec![], + }; + let input = +"use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_ignore_std() { + // Even if you include a crate name, and use it in the doctest, we still won't include an + // `extern crate` statement if the crate is "std" -- that's included already by the + // compiler! + let opts = TestOptions::default(); + let input = +"use std::*; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +fn main() { +use std::*; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_manual_extern_crate() { + // When you manually include an `extern crate` statement in your doctest, `make_test` + // assumes you've included one for your own crate too. + let opts = TestOptions::default(); + let input = +"extern crate asdf; +use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_manual_extern_crate_with_macro_use() { + let opts = TestOptions::default(); + let input = +"#[macro_use] extern crate asdf; +use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +#[macro_use] extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_opts_attrs() { + // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use + // those instead of the stock `#![allow(unused)]`. + let mut opts = TestOptions::default(); + opts.attrs.push("feature(sick_rad)".to_string()); + let input = +"use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![feature(sick_rad)] +extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 3)); + + // Adding more will also bump the returned line offset. + opts.attrs.push("feature(hella_dope)".to_string()); + let expected = +"#![feature(sick_rad)] +#![feature(hella_dope)] +extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 4)); +} + +#[test] +fn make_test_crate_attrs() { + // Including inner attributes in your doctest will apply them to the whole "crate", pasting + // them outside the generated main function. + let opts = TestOptions::default(); + let input = +"#![feature(sick_rad)] +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +#![feature(sick_rad)] +fn main() { +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_with_main() { + // Including your own `fn main` wrapper lets the test use it verbatim. + let opts = TestOptions::default(); + let input = +"fn main() { + assert_eq!(2+2, 4); +}"; + let expected = +"#![allow(unused)] +fn main() { + assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 1)); +} + +#[test] +fn make_test_fake_main() { + // ... but putting it in a comment will still provide a wrapper. + let opts = TestOptions::default(); + let input = +"//Ceci n'est pas une `fn main` +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +//Ceci n'est pas une `fn main` +fn main() { +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); +} + +#[test] +fn make_test_dont_insert_main() { + // Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper. + let opts = TestOptions::default(); + let input = +"//Ceci n'est pas une `fn main` +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +//Ceci n'est pas une `fn main` +assert_eq!(2+2, 4);".to_string(); + let output = make_test(input, None, true, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 1)); +} + +#[test] +fn make_test_display_warnings() { + // If the user is asking to display doctest warnings, suppress the default `allow(unused)`. + let mut opts = TestOptions::default(); + opts.display_warnings = true; + let input = +"assert_eq!(2+2, 4);"; + let expected = +"fn main() { +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 1)); +} + +#[test] +fn make_test_issues_21299_33731() { + let opts = TestOptions::default(); + + let input = +"// fn main +assert_eq!(2+2, 4);"; + + let expected = +"#![allow(unused)] +// fn main +fn main() { +assert_eq!(2+2, 4); +}".to_string(); + + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 2)); + + let input = +"extern crate hella_qwop; +assert_eq!(asdf::foo, 4);"; + + let expected = +"#![allow(unused)] +extern crate hella_qwop; +extern crate asdf; +fn main() { +assert_eq!(asdf::foo, 4); +}".to_string(); + + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 3)); +} + +#[test] +fn make_test_main_in_macro() { + let opts = TestOptions::default(); + let input = +"#[macro_use] extern crate my_crate; +test_wrapper! { + fn main() {} +}"; + let expected = +"#![allow(unused)] +#[macro_use] extern crate my_crate; +test_wrapper! { + fn main() {} +}".to_string(); + + let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION); + assert_eq!(output, (expected, 1)); +} diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 8a7927e42c9c3..95d92f311ed3c 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -143,79 +143,4 @@ impl FromHex for str { } #[cfg(test)] -mod tests { - extern crate test; - use test::Bencher; - use crate::hex::{FromHex, ToHex}; - - #[test] - pub fn test_to_hex() { - assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172"); - } - - #[test] - pub fn test_from_hex_okay() { - assert_eq!("666f6f626172".from_hex().unwrap(), - b"foobar"); - assert_eq!("666F6F626172".from_hex().unwrap(), - b"foobar"); - } - - #[test] - pub fn test_from_hex_odd_len() { - assert!("666".from_hex().is_err()); - assert!("66 6".from_hex().is_err()); - } - - #[test] - pub fn test_from_hex_invalid_char() { - assert!("66y6".from_hex().is_err()); - } - - #[test] - pub fn test_from_hex_ignores_whitespace() { - assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(), - b"foobar"); - } - - #[test] - pub fn test_to_hex_all_bytes() { - for i in 0..256 { - assert_eq!([i as u8].to_hex(), format!("{:02x}", i as usize)); - } - } - - #[test] - pub fn test_from_hex_all_bytes() { - for i in 0..256 { - let ii: &[u8] = &[i as u8]; - assert_eq!(format!("{:02x}", i as usize).from_hex() - .unwrap(), - ii); - assert_eq!(format!("{:02X}", i as usize).from_hex() - .unwrap(), - ii); - } - } - - #[bench] - pub fn bench_to_hex(b: &mut Bencher) { - let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ - ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; - b.iter(|| { - s.as_bytes().to_hex(); - }); - b.bytes = s.len() as u64; - } - - #[bench] - pub fn bench_from_hex(b: &mut Bencher) { - let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ - ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; - let sb = s.as_bytes().to_hex(); - b.iter(|| { - sb.from_hex().unwrap(); - }); - b.bytes = sb.len() as u64; - } -} +mod tests; diff --git a/src/libserialize/hex/tests.rs b/src/libserialize/hex/tests.rs new file mode 100644 index 0000000000000..471912c11d06f --- /dev/null +++ b/src/libserialize/hex/tests.rs @@ -0,0 +1,74 @@ +extern crate test; +use test::Bencher; +use crate::hex::{FromHex, ToHex}; + +#[test] +pub fn test_to_hex() { + assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172"); +} + +#[test] +pub fn test_from_hex_okay() { + assert_eq!("666f6f626172".from_hex().unwrap(), + b"foobar"); + assert_eq!("666F6F626172".from_hex().unwrap(), + b"foobar"); +} + +#[test] +pub fn test_from_hex_odd_len() { + assert!("666".from_hex().is_err()); + assert!("66 6".from_hex().is_err()); +} + +#[test] +pub fn test_from_hex_invalid_char() { + assert!("66y6".from_hex().is_err()); +} + +#[test] +pub fn test_from_hex_ignores_whitespace() { + assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(), + b"foobar"); +} + +#[test] +pub fn test_to_hex_all_bytes() { + for i in 0..256 { + assert_eq!([i as u8].to_hex(), format!("{:02x}", i as usize)); + } +} + +#[test] +pub fn test_from_hex_all_bytes() { + for i in 0..256 { + let ii: &[u8] = &[i as u8]; + assert_eq!(format!("{:02x}", i as usize).from_hex() + .unwrap(), + ii); + assert_eq!(format!("{:02X}", i as usize).from_hex() + .unwrap(), + ii); + } +} + +#[bench] +pub fn bench_to_hex(b: &mut Bencher) { + let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ + ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; + b.iter(|| { + s.as_bytes().to_hex(); + }); + b.bytes = s.len() as u64; +} + +#[bench] +pub fn bench_from_hex(b: &mut Bencher) { + let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ + ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; + let sb = s.as_bytes().to_hex(); + b.iter(|| { + sb.from_hex().unwrap(); + }); + b.bytes = sb.len() as u64; +} diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a4fd288451205..8f926e6dd2909 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -2582,139 +2582,4 @@ impl FromStr for Json { } #[cfg(test)] -mod tests { - // Benchmarks and tests that require private items - - extern crate test; - use test::Bencher; - use super::{from_str, Parser, StackElement, Stack}; - use std::string; - - #[test] - fn test_stack() { - let mut stack = Stack::new(); - - assert!(stack.is_empty()); - assert!(stack.is_empty()); - assert!(!stack.last_is_index()); - - stack.push_index(0); - stack.bump_index(); - - assert!(stack.len() == 1); - assert!(stack.is_equal_to(&[StackElement::Index(1)])); - assert!(stack.starts_with(&[StackElement::Index(1)])); - assert!(stack.ends_with(&[StackElement::Index(1)])); - assert!(stack.last_is_index()); - assert!(stack.get(0) == StackElement::Index(1)); - - stack.push_key("foo".to_string()); - - assert!(stack.len() == 2); - assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.starts_with(&[StackElement::Index(1)])); - assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.ends_with(&[StackElement::Key("foo")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == StackElement::Index(1)); - assert!(stack.get(1) == StackElement::Key("foo")); - - stack.push_key("bar".to_string()); - - assert!(stack.len() == 3); - assert!(stack.is_equal_to(&[StackElement::Index(1), - StackElement::Key("foo"), - StackElement::Key("bar")])); - assert!(stack.starts_with(&[StackElement::Index(1)])); - assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.starts_with(&[StackElement::Index(1), - StackElement::Key("foo"), - StackElement::Key("bar")])); - assert!(stack.ends_with(&[StackElement::Key("bar")])); - assert!(stack.ends_with(&[StackElement::Key("foo"), StackElement::Key("bar")])); - assert!(stack.ends_with(&[StackElement::Index(1), - StackElement::Key("foo"), - StackElement::Key("bar")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == StackElement::Index(1)); - assert!(stack.get(1) == StackElement::Key("foo")); - assert!(stack.get(2) == StackElement::Key("bar")); - - stack.pop(); - - assert!(stack.len() == 2); - assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.starts_with(&[StackElement::Index(1)])); - assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); - assert!(stack.ends_with(&[StackElement::Key("foo")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == StackElement::Index(1)); - assert!(stack.get(1) == StackElement::Key("foo")); - } - - #[bench] - fn bench_streaming_small(b: &mut Bencher) { - b.iter( || { - let mut parser = Parser::new( - r#"{ - "a": 1.0, - "b": [ - true, - "foo\nbar", - { "c": {"d": null} } - ] - }"#.chars() - ); - loop { - match parser.next() { - None => return, - _ => {} - } - } - }); - } - #[bench] - fn bench_small(b: &mut Bencher) { - b.iter( || { - let _ = from_str(r#"{ - "a": 1.0, - "b": [ - true, - "foo\nbar", - { "c": {"d": null} } - ] - }"#); - }); - } - - fn big_json() -> string::String { - let mut src = "[\n".to_string(); - for _ in 0..500 { - src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \ - [1,2,3]},"#); - } - src.push_str("{}]"); - return src; - } - - #[bench] - fn bench_streaming_large(b: &mut Bencher) { - let src = big_json(); - b.iter( || { - let mut parser = Parser::new(src.chars()); - loop { - match parser.next() { - None => return, - _ => {} - } - } - }); - } - #[bench] - fn bench_large(b: &mut Bencher) { - let src = big_json(); - b.iter( || { let _ = from_str(&src); }); - } -} +mod tests; diff --git a/src/libserialize/json/tests.rs b/src/libserialize/json/tests.rs new file mode 100644 index 0000000000000..a16b8bdd78704 --- /dev/null +++ b/src/libserialize/json/tests.rs @@ -0,0 +1,134 @@ +// Benchmarks and tests that require private items + +extern crate test; +use test::Bencher; +use super::{from_str, Parser, StackElement, Stack}; +use std::string; + +#[test] +fn test_stack() { + let mut stack = Stack::new(); + + assert!(stack.is_empty()); + assert!(stack.is_empty()); + assert!(!stack.last_is_index()); + + stack.push_index(0); + stack.bump_index(); + + assert!(stack.len() == 1); + assert!(stack.is_equal_to(&[StackElement::Index(1)])); + assert!(stack.starts_with(&[StackElement::Index(1)])); + assert!(stack.ends_with(&[StackElement::Index(1)])); + assert!(stack.last_is_index()); + assert!(stack.get(0) == StackElement::Index(1)); + + stack.push_key("foo".to_string()); + + assert!(stack.len() == 2); + assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.starts_with(&[StackElement::Index(1)])); + assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.ends_with(&[StackElement::Key("foo")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == StackElement::Index(1)); + assert!(stack.get(1) == StackElement::Key("foo")); + + stack.push_key("bar".to_string()); + + assert!(stack.len() == 3); + assert!(stack.is_equal_to(&[StackElement::Index(1), + StackElement::Key("foo"), + StackElement::Key("bar")])); + assert!(stack.starts_with(&[StackElement::Index(1)])); + assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.starts_with(&[StackElement::Index(1), + StackElement::Key("foo"), + StackElement::Key("bar")])); + assert!(stack.ends_with(&[StackElement::Key("bar")])); + assert!(stack.ends_with(&[StackElement::Key("foo"), StackElement::Key("bar")])); + assert!(stack.ends_with(&[StackElement::Index(1), + StackElement::Key("foo"), + StackElement::Key("bar")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == StackElement::Index(1)); + assert!(stack.get(1) == StackElement::Key("foo")); + assert!(stack.get(2) == StackElement::Key("bar")); + + stack.pop(); + + assert!(stack.len() == 2); + assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.starts_with(&[StackElement::Index(1)])); + assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); + assert!(stack.ends_with(&[StackElement::Key("foo")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == StackElement::Index(1)); + assert!(stack.get(1) == StackElement::Key("foo")); +} + +#[bench] +fn bench_streaming_small(b: &mut Bencher) { + b.iter( || { + let mut parser = Parser::new( + r#"{ + "a": 1.0, + "b": [ + true, + "foo\nbar", + { "c": {"d": null} } + ] + }"#.chars() + ); + loop { + match parser.next() { + None => return, + _ => {} + } + } + }); +} +#[bench] +fn bench_small(b: &mut Bencher) { + b.iter( || { + let _ = from_str(r#"{ + "a": 1.0, + "b": [ + true, + "foo\nbar", + { "c": {"d": null} } + ] + }"#); + }); +} + +fn big_json() -> string::String { + let mut src = "[\n".to_string(); + for _ in 0..500 { + src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \ + [1,2,3]},"#); + } + src.push_str("{}]"); + return src; +} + +#[bench] +fn bench_streaming_large(b: &mut Bencher) { + let src = big_json(); + b.iter( || { + let mut parser = Parser::new(src.chars()); + loop { + match parser.next() { + None => return, + _ => {} + } + } + }); +} +#[bench] +fn bench_large(b: &mut Bencher) { + let src = big_json(); + b.iter( || { let _ = from_str(&src); }); +} diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 7ad5997bf2c09..3d4f82764413a 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -605,159 +605,7 @@ pub mod printf { } #[cfg(test)] - mod tests { - use super::{ - Format as F, - Num as N, - Substitution as S, - iter_subs, - parse_next_substitution as pns, - }; - - macro_rules! assert_eq_pnsat { - ($lhs:expr, $rhs:expr) => { - assert_eq!( - pns($lhs).and_then(|(s, _)| s.translate()), - $rhs.map(<String as From<&str>>::from) - ) - }; - } - - #[test] - fn test_escape() { - assert_eq!(pns("has no escapes"), None); - assert_eq!(pns("has no escapes, either %"), None); - assert_eq!(pns("*so* has a %% escape"), Some((S::Escape," escape"))); - assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); - assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); - } - - #[test] - fn test_parse() { - macro_rules! assert_pns_eq_sub { - ($in_:expr, { - $param:expr, $flags:expr, - $width:expr, $prec:expr, $len:expr, $type_:expr, - $pos:expr, - }) => { - assert_eq!( - pns(concat!($in_, "!")), - Some(( - S::Format(F { - span: $in_, - parameter: $param, - flags: $flags, - width: $width, - precision: $prec, - length: $len, - type_: $type_, - position: syntax_pos::InnerSpan::new($pos.0, $pos.1), - }), - "!" - )) - ) - }; - } - - assert_pns_eq_sub!("%!", - { None, "", None, None, None, "!", (0, 2), }); - assert_pns_eq_sub!("%c", - { None, "", None, None, None, "c", (0, 2), }); - assert_pns_eq_sub!("%s", - { None, "", None, None, None, "s", (0, 2), }); - assert_pns_eq_sub!("%06d", - { None, "0", Some(N::Num(6)), None, None, "d", (0, 4), }); - assert_pns_eq_sub!("%4.2f", - { None, "", Some(N::Num(4)), Some(N::Num(2)), None, "f", (0, 5), }); - assert_pns_eq_sub!("%#x", - { None, "#", None, None, None, "x", (0, 3), }); - assert_pns_eq_sub!("%-10s", - { None, "-", Some(N::Num(10)), None, None, "s", (0, 5), }); - assert_pns_eq_sub!("%*s", - { None, "", Some(N::Next), None, None, "s", (0, 3), }); - assert_pns_eq_sub!("%-10.*s", - { None, "-", Some(N::Num(10)), Some(N::Next), None, "s", (0, 7), }); - assert_pns_eq_sub!("%-*.*s", - { None, "-", Some(N::Next), Some(N::Next), None, "s", (0, 6), }); - assert_pns_eq_sub!("%.6i", - { None, "", None, Some(N::Num(6)), None, "i", (0, 4), }); - assert_pns_eq_sub!("%+i", - { None, "+", None, None, None, "i", (0, 3), }); - assert_pns_eq_sub!("%08X", - { None, "0", Some(N::Num(8)), None, None, "X", (0, 4), }); - assert_pns_eq_sub!("%lu", - { None, "", None, None, Some("l"), "u", (0, 3), }); - assert_pns_eq_sub!("%Iu", - { None, "", None, None, Some("I"), "u", (0, 3), }); - assert_pns_eq_sub!("%I32u", - { None, "", None, None, Some("I32"), "u", (0, 5), }); - assert_pns_eq_sub!("%I64u", - { None, "", None, None, Some("I64"), "u", (0, 5), }); - assert_pns_eq_sub!("%'d", - { None, "'", None, None, None, "d", (0, 3), }); - assert_pns_eq_sub!("%10s", - { None, "", Some(N::Num(10)), None, None, "s", (0, 4), }); - assert_pns_eq_sub!("%-10.10s", - { None, "-", Some(N::Num(10)), Some(N::Num(10)), None, "s", (0, 8), }); - assert_pns_eq_sub!("%1$d", - { Some(1), "", None, None, None, "d", (0, 4), }); - assert_pns_eq_sub!("%2$.*3$d", - { Some(2), "", None, Some(N::Arg(3)), None, "d", (0, 8), }); - assert_pns_eq_sub!("%1$*2$.*3$d", - { Some(1), "", Some(N::Arg(2)), Some(N::Arg(3)), None, "d", (0, 11), }); - assert_pns_eq_sub!("%-8ld", - { None, "-", Some(N::Num(8)), None, Some("l"), "d", (0, 5), }); - } - - #[test] - fn test_iter() { - let s = "The %d'th word %% is: `%.*s` %!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); - assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), - vec![Some("{}"), None, Some("{:.*}"), None] - ); - } - - /// Checks that the translations are what we expect. - #[test] - fn test_translation() { - assert_eq_pnsat!("%c", Some("{}")); - assert_eq_pnsat!("%d", Some("{}")); - assert_eq_pnsat!("%u", Some("{}")); - assert_eq_pnsat!("%x", Some("{:x}")); - assert_eq_pnsat!("%X", Some("{:X}")); - assert_eq_pnsat!("%e", Some("{:e}")); - assert_eq_pnsat!("%E", Some("{:E}")); - assert_eq_pnsat!("%f", Some("{}")); - assert_eq_pnsat!("%g", Some("{:e}")); - assert_eq_pnsat!("%G", Some("{:E}")); - assert_eq_pnsat!("%s", Some("{}")); - assert_eq_pnsat!("%p", Some("{:p}")); - - assert_eq_pnsat!("%06d", Some("{:06}")); - assert_eq_pnsat!("%4.2f", Some("{:4.2}")); - assert_eq_pnsat!("%#x", Some("{:#x}")); - assert_eq_pnsat!("%-10s", Some("{:<10}")); - assert_eq_pnsat!("%*s", None); - assert_eq_pnsat!("%-10.*s", Some("{:<10.*}")); - assert_eq_pnsat!("%-*.*s", None); - assert_eq_pnsat!("%.6i", Some("{:06}")); - assert_eq_pnsat!("%+i", Some("{:+}")); - assert_eq_pnsat!("%08X", Some("{:08X}")); - assert_eq_pnsat!("%lu", Some("{}")); - assert_eq_pnsat!("%Iu", Some("{}")); - assert_eq_pnsat!("%I32u", Some("{}")); - assert_eq_pnsat!("%I64u", Some("{}")); - assert_eq_pnsat!("%'d", None); - assert_eq_pnsat!("%10s", Some("{:>10}")); - assert_eq_pnsat!("%-10.10s", Some("{:<10.10}")); - assert_eq_pnsat!("%1$d", Some("{0}")); - assert_eq_pnsat!("%2$.*3$d", Some("{1:02$}")); - assert_eq_pnsat!("%1$*2$.*3$s", Some("{0:>1$.2$}")); - assert_eq_pnsat!("%-8ld", Some("{:<8}")); - } - } + mod tests; } pub mod shell { @@ -899,68 +747,7 @@ pub mod shell { } #[cfg(test)] - mod tests { - use super::{ - Substitution as S, - parse_next_substitution as pns, - }; - - macro_rules! assert_eq_pnsat { - ($lhs:expr, $rhs:expr) => { - assert_eq!( - pns($lhs).and_then(|(f, _)| f.translate()), - $rhs.map(<String as From<&str>>::from) - ) - }; - } - - #[test] - fn test_escape() { - assert_eq!(pns("has no escapes"), None); - assert_eq!(pns("has no escapes, either $"), None); - assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape"))); - assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape"))); - assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), ""))); - } - - #[test] - fn test_parse() { - macro_rules! assert_pns_eq_sub { - ($in_:expr, $kind:ident($arg:expr, $pos:expr)) => { - assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!"))) - }; - } - - assert_pns_eq_sub!("$0", Ordinal(0, (0, 2))); - assert_pns_eq_sub!("$1", Ordinal(1, (0, 2))); - assert_pns_eq_sub!("$9", Ordinal(9, (0, 2))); - assert_pns_eq_sub!("$N", Name("N", (0, 2))); - assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5))); - } - - #[test] - fn test_iter() { - use super::iter_subs; - let s = "The $0'th word $$ is: `$WORD` $!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); - assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), - vec![Some("{0}"), None, Some("{WORD}")] - ); - } - - #[test] - fn test_translation() { - assert_eq_pnsat!("$0", Some("{0}")); - assert_eq_pnsat!("$9", Some("{9}")); - assert_eq_pnsat!("$1", Some("{1}")); - assert_eq_pnsat!("$10", Some("{1}")); - assert_eq_pnsat!("$stuff", Some("{stuff}")); - assert_eq_pnsat!("$NAME", Some("{NAME}")); - assert_eq_pnsat!("$PREFIX/bin", Some("{PREFIX}")); - } - - } + mod tests; } mod strcursor { diff --git a/src/libsyntax_ext/format_foreign/printf/tests.rs b/src/libsyntax_ext/format_foreign/printf/tests.rs new file mode 100644 index 0000000000000..87021f1ef5a52 --- /dev/null +++ b/src/libsyntax_ext/format_foreign/printf/tests.rs @@ -0,0 +1,151 @@ +use super::{ + Format as F, + Num as N, + Substitution as S, + iter_subs, + parse_next_substitution as pns, +}; + +macro_rules! assert_eq_pnsat { + ($lhs:expr, $rhs:expr) => { + assert_eq!( + pns($lhs).and_then(|(s, _)| s.translate()), + $rhs.map(<String as From<&str>>::from) + ) + }; +} + +#[test] +fn test_escape() { + assert_eq!(pns("has no escapes"), None); + assert_eq!(pns("has no escapes, either %"), None); + assert_eq!(pns("*so* has a %% escape"), Some((S::Escape," escape"))); + assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); + assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); +} + +#[test] +fn test_parse() { + macro_rules! assert_pns_eq_sub { + ($in_:expr, { + $param:expr, $flags:expr, + $width:expr, $prec:expr, $len:expr, $type_:expr, + $pos:expr, + }) => { + assert_eq!( + pns(concat!($in_, "!")), + Some(( + S::Format(F { + span: $in_, + parameter: $param, + flags: $flags, + width: $width, + precision: $prec, + length: $len, + type_: $type_, + position: syntax_pos::InnerSpan::new($pos.0, $pos.1), + }), + "!" + )) + ) + }; + } + + assert_pns_eq_sub!("%!", + { None, "", None, None, None, "!", (0, 2), }); + assert_pns_eq_sub!("%c", + { None, "", None, None, None, "c", (0, 2), }); + assert_pns_eq_sub!("%s", + { None, "", None, None, None, "s", (0, 2), }); + assert_pns_eq_sub!("%06d", + { None, "0", Some(N::Num(6)), None, None, "d", (0, 4), }); + assert_pns_eq_sub!("%4.2f", + { None, "", Some(N::Num(4)), Some(N::Num(2)), None, "f", (0, 5), }); + assert_pns_eq_sub!("%#x", + { None, "#", None, None, None, "x", (0, 3), }); + assert_pns_eq_sub!("%-10s", + { None, "-", Some(N::Num(10)), None, None, "s", (0, 5), }); + assert_pns_eq_sub!("%*s", + { None, "", Some(N::Next), None, None, "s", (0, 3), }); + assert_pns_eq_sub!("%-10.*s", + { None, "-", Some(N::Num(10)), Some(N::Next), None, "s", (0, 7), }); + assert_pns_eq_sub!("%-*.*s", + { None, "-", Some(N::Next), Some(N::Next), None, "s", (0, 6), }); + assert_pns_eq_sub!("%.6i", + { None, "", None, Some(N::Num(6)), None, "i", (0, 4), }); + assert_pns_eq_sub!("%+i", + { None, "+", None, None, None, "i", (0, 3), }); + assert_pns_eq_sub!("%08X", + { None, "0", Some(N::Num(8)), None, None, "X", (0, 4), }); + assert_pns_eq_sub!("%lu", + { None, "", None, None, Some("l"), "u", (0, 3), }); + assert_pns_eq_sub!("%Iu", + { None, "", None, None, Some("I"), "u", (0, 3), }); + assert_pns_eq_sub!("%I32u", + { None, "", None, None, Some("I32"), "u", (0, 5), }); + assert_pns_eq_sub!("%I64u", + { None, "", None, None, Some("I64"), "u", (0, 5), }); + assert_pns_eq_sub!("%'d", + { None, "'", None, None, None, "d", (0, 3), }); + assert_pns_eq_sub!("%10s", + { None, "", Some(N::Num(10)), None, None, "s", (0, 4), }); + assert_pns_eq_sub!("%-10.10s", + { None, "-", Some(N::Num(10)), Some(N::Num(10)), None, "s", (0, 8), }); + assert_pns_eq_sub!("%1$d", + { Some(1), "", None, None, None, "d", (0, 4), }); + assert_pns_eq_sub!("%2$.*3$d", + { Some(2), "", None, Some(N::Arg(3)), None, "d", (0, 8), }); + assert_pns_eq_sub!("%1$*2$.*3$d", + { Some(1), "", Some(N::Arg(2)), Some(N::Arg(3)), None, "d", (0, 11), }); + assert_pns_eq_sub!("%-8ld", + { None, "-", Some(N::Num(8)), None, Some("l"), "d", (0, 5), }); +} + +#[test] +fn test_iter() { + let s = "The %d'th word %% is: `%.*s` %!\n"; + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); + assert_eq!( + subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), + vec![Some("{}"), None, Some("{:.*}"), None] + ); +} + +/// Checks that the translations are what we expect. +#[test] +fn test_translation() { + assert_eq_pnsat!("%c", Some("{}")); + assert_eq_pnsat!("%d", Some("{}")); + assert_eq_pnsat!("%u", Some("{}")); + assert_eq_pnsat!("%x", Some("{:x}")); + assert_eq_pnsat!("%X", Some("{:X}")); + assert_eq_pnsat!("%e", Some("{:e}")); + assert_eq_pnsat!("%E", Some("{:E}")); + assert_eq_pnsat!("%f", Some("{}")); + assert_eq_pnsat!("%g", Some("{:e}")); + assert_eq_pnsat!("%G", Some("{:E}")); + assert_eq_pnsat!("%s", Some("{}")); + assert_eq_pnsat!("%p", Some("{:p}")); + + assert_eq_pnsat!("%06d", Some("{:06}")); + assert_eq_pnsat!("%4.2f", Some("{:4.2}")); + assert_eq_pnsat!("%#x", Some("{:#x}")); + assert_eq_pnsat!("%-10s", Some("{:<10}")); + assert_eq_pnsat!("%*s", None); + assert_eq_pnsat!("%-10.*s", Some("{:<10.*}")); + assert_eq_pnsat!("%-*.*s", None); + assert_eq_pnsat!("%.6i", Some("{:06}")); + assert_eq_pnsat!("%+i", Some("{:+}")); + assert_eq_pnsat!("%08X", Some("{:08X}")); + assert_eq_pnsat!("%lu", Some("{}")); + assert_eq_pnsat!("%Iu", Some("{}")); + assert_eq_pnsat!("%I32u", Some("{}")); + assert_eq_pnsat!("%I64u", Some("{}")); + assert_eq_pnsat!("%'d", None); + assert_eq_pnsat!("%10s", Some("{:>10}")); + assert_eq_pnsat!("%-10.10s", Some("{:<10.10}")); + assert_eq_pnsat!("%1$d", Some("{0}")); + assert_eq_pnsat!("%2$.*3$d", Some("{1:02$}")); + assert_eq_pnsat!("%1$*2$.*3$s", Some("{0:>1$.2$}")); + assert_eq_pnsat!("%-8ld", Some("{:<8}")); +} diff --git a/src/libsyntax_ext/format_foreign/shell/tests.rs b/src/libsyntax_ext/format_foreign/shell/tests.rs new file mode 100644 index 0000000000000..8ef58b8387e5a --- /dev/null +++ b/src/libsyntax_ext/format_foreign/shell/tests.rs @@ -0,0 +1,59 @@ +use super::{ + Substitution as S, + parse_next_substitution as pns, +}; + +macro_rules! assert_eq_pnsat { + ($lhs:expr, $rhs:expr) => { + assert_eq!( + pns($lhs).and_then(|(f, _)| f.translate()), + $rhs.map(<String as From<&str>>::from) + ) + }; +} + +#[test] +fn test_escape() { + assert_eq!(pns("has no escapes"), None); + assert_eq!(pns("has no escapes, either $"), None); + assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape"))); + assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape"))); + assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), ""))); +} + +#[test] +fn test_parse() { + macro_rules! assert_pns_eq_sub { + ($in_:expr, $kind:ident($arg:expr, $pos:expr)) => { + assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!"))) + }; + } + + assert_pns_eq_sub!("$0", Ordinal(0, (0, 2))); + assert_pns_eq_sub!("$1", Ordinal(1, (0, 2))); + assert_pns_eq_sub!("$9", Ordinal(9, (0, 2))); + assert_pns_eq_sub!("$N", Name("N", (0, 2))); + assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5))); +} + +#[test] +fn test_iter() { + use super::iter_subs; + let s = "The $0'th word $$ is: `$WORD` $!\n"; + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); + assert_eq!( + subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), + vec![Some("{0}"), None, Some("{WORD}")] + ); +} + +#[test] +fn test_translation() { + assert_eq_pnsat!("$0", Some("{0}")); + assert_eq_pnsat!("$9", Some("{9}")); + assert_eq_pnsat!("$1", Some("{1}")); + assert_eq_pnsat!("$10", Some("{1}")); + assert_eq_pnsat!("$stuff", Some("{stuff}")); + assert_eq_pnsat!("$NAME", Some("{NAME}")); + assert_eq_pnsat!("$PREFIX/bin", Some("{PREFIX}")); +} diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 810a98e4a014c..53bf67bdf671f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1772,458 +1772,4 @@ pub mod bench { } #[cfg(test)] -mod tests { - use crate::bench; - use crate::test::{ - filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, - TrIgnored, TrOk, - }; - use crate::Bencher; - use crate::Concurrent; - use std::sync::mpsc::channel; - - fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { - vec![ - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("1"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("2"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - ] - } - - #[test] - pub fn do_not_run_ignored_tests() { - fn f() { - panic!(); - } - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res != TrOk); - } - - #[test] - pub fn ignored_tests_result_in_ignored() { - fn f() {} - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res == TrIgnored); - } - - #[test] - fn test_should_panic() { - fn f() { - panic!(); - } - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::Yes, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res == TrOk); - } - - #[test] - fn test_should_panic_good_message() { - fn f() { - panic!("an error message"); - } - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::YesWithMessage("error message"), - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res == TrOk); - } - - #[test] - fn test_should_panic_bad_message() { - fn f() { - panic!("an error message"); - } - let expected = "foobar"; - let failed_msg = "panic did not include expected string"; - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::YesWithMessage(expected), - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); - } - - #[test] - fn test_should_panic_but_succeeds() { - fn f() {} - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::Yes, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); - assert!(res == TrFailed); - } - - #[test] - fn parse_ignored_flag() { - let args = vec![ - "progname".to_string(), - "filter".to_string(), - "--ignored".to_string(), - ]; - let opts = parse_opts(&args).unwrap().unwrap(); - assert_eq!(opts.run_ignored, RunIgnored::Only); - } - - #[test] - fn parse_include_ignored_flag() { - let args = vec![ - "progname".to_string(), - "filter".to_string(), - "-Zunstable-options".to_string(), - "--include-ignored".to_string(), - ]; - let opts = parse_opts(&args).unwrap().unwrap(); - assert_eq!(opts.run_ignored, RunIgnored::Yes); - } - - #[test] - pub fn filter_for_ignored_option() { - // When we run ignored tests the test filter should filter out all the - // unignored tests and flip the ignore flag on the rest to false - - let mut opts = TestOpts::new(); - opts.run_tests = true; - opts.run_ignored = RunIgnored::Only; - - let tests = one_ignored_one_unignored_test(); - let filtered = filter_tests(&opts, tests); - - assert_eq!(filtered.len(), 1); - assert_eq!(filtered[0].desc.name.to_string(), "1"); - assert!(!filtered[0].desc.ignore); - } - - #[test] - pub fn run_include_ignored_option() { - // When we "--include-ignored" tests, the ignore flag should be set to false on - // all tests and no test filtered out - - let mut opts = TestOpts::new(); - opts.run_tests = true; - opts.run_ignored = RunIgnored::Yes; - - let tests = one_ignored_one_unignored_test(); - let filtered = filter_tests(&opts, tests); - - assert_eq!(filtered.len(), 2); - assert!(!filtered[0].desc.ignore); - assert!(!filtered[1].desc.ignore); - } - - #[test] - pub fn exclude_should_panic_option() { - let mut opts = TestOpts::new(); - opts.run_tests = true; - opts.exclude_should_panic = true; - - let mut tests = one_ignored_one_unignored_test(); - tests.push(TestDescAndFn { - desc: TestDesc { - name: StaticTestName("3"), - ignore: false, - should_panic: ShouldPanic::Yes, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }); - - let filtered = filter_tests(&opts, tests); - - assert_eq!(filtered.len(), 2); - assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No)); - } - - #[test] - pub fn exact_filter_match() { - fn tests() -> Vec<TestDescAndFn> { - vec!["base", "base::test", "base::test1", "base::test2"] - .into_iter() - .map(|name| TestDescAndFn { - desc: TestDesc { - name: StaticTestName(name), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }) - .collect() - } - - let substr = filter_tests( - &TestOpts { - filter: Some("base".into()), - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(substr.len(), 4); - - let substr = filter_tests( - &TestOpts { - filter: Some("bas".into()), - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(substr.len(), 4); - - let substr = filter_tests( - &TestOpts { - filter: Some("::test".into()), - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(substr.len(), 3); - - let substr = filter_tests( - &TestOpts { - filter: Some("base::test".into()), - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(substr.len(), 3); - - let exact = filter_tests( - &TestOpts { - filter: Some("base".into()), - filter_exact: true, - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(exact.len(), 1); - - let exact = filter_tests( - &TestOpts { - filter: Some("bas".into()), - filter_exact: true, - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(exact.len(), 0); - - let exact = filter_tests( - &TestOpts { - filter: Some("::test".into()), - filter_exact: true, - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(exact.len(), 0); - - let exact = filter_tests( - &TestOpts { - filter: Some("base::test".into()), - filter_exact: true, - ..TestOpts::new() - }, - tests(), - ); - assert_eq!(exact.len(), 1); - } - - #[test] - pub fn sort_tests() { - let mut opts = TestOpts::new(); - opts.run_tests = true; - - let names = vec![ - "sha1::test".to_string(), - "isize::test_to_str".to_string(), - "isize::test_pow".to_string(), - "test::do_not_run_ignored_tests".to_string(), - "test::ignored_tests_result_in_ignored".to_string(), - "test::first_free_arg_should_be_a_filter".to_string(), - "test::parse_ignored_flag".to_string(), - "test::parse_include_ignored_flag".to_string(), - "test::filter_for_ignored_option".to_string(), - "test::run_include_ignored_option".to_string(), - "test::sort_tests".to_string(), - ]; - let tests = { - fn testfn() {} - let mut tests = Vec::new(); - for name in &names { - let test = TestDescAndFn { - desc: TestDesc { - name: DynTestName((*name).clone()), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(testfn)), - }; - tests.push(test); - } - tests - }; - let filtered = filter_tests(&opts, tests); - - let expected = vec![ - "isize::test_pow".to_string(), - "isize::test_to_str".to_string(), - "sha1::test".to_string(), - "test::do_not_run_ignored_tests".to_string(), - "test::filter_for_ignored_option".to_string(), - "test::first_free_arg_should_be_a_filter".to_string(), - "test::ignored_tests_result_in_ignored".to_string(), - "test::parse_ignored_flag".to_string(), - "test::parse_include_ignored_flag".to_string(), - "test::run_include_ignored_option".to_string(), - "test::sort_tests".to_string(), - ]; - - for (a, b) in expected.iter().zip(filtered) { - assert!(*a == b.desc.name.to_string()); - } - } - - #[test] - pub fn test_metricmap_compare() { - let mut m1 = MetricMap::new(); - let mut m2 = MetricMap::new(); - m1.insert_metric("in-both-noise", 1000.0, 200.0); - m2.insert_metric("in-both-noise", 1100.0, 200.0); - - m1.insert_metric("in-first-noise", 1000.0, 2.0); - m2.insert_metric("in-second-noise", 1000.0, 2.0); - - m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0); - m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0); - - m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0); - m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0); - - m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0); - m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0); - - m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0); - m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0); - } - - #[test] - pub fn test_bench_once_no_iter() { - fn f(_: &mut Bencher) {} - bench::run_once(f); - } - - #[test] - pub fn test_bench_once_iter() { - fn f(b: &mut Bencher) { - b.iter(|| {}) - } - bench::run_once(f); - } - - #[test] - pub fn test_bench_no_iter() { - fn f(_: &mut Bencher) {} - - let (tx, rx) = channel(); - - let desc = TestDesc { - name: StaticTestName("f"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }; - - crate::bench::benchmark(desc, tx, true, f); - rx.recv().unwrap(); - } - - #[test] - pub fn test_bench_iter() { - fn f(b: &mut Bencher) { - b.iter(|| {}) - } - - let (tx, rx) = channel(); - - let desc = TestDesc { - name: StaticTestName("f"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }; - - crate::bench::benchmark(desc, tx, true, f); - rx.recv().unwrap(); - } -} +mod tests; diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 5c9421d5ea4b0..32c30061983ab 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -318,582 +318,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) { // Test vectors generated from R, using the script src/etc/stat-test-vectors.r. #[cfg(test)] -mod tests { - use crate::stats::Stats; - use crate::stats::Summary; - use std::f64; - use std::io::prelude::*; - use std::io; - - macro_rules! assert_approx_eq { - ($a: expr, $b: expr) => {{ - let (a, b) = (&$a, &$b); - assert!( - (*a - *b).abs() < 1.0e-6, - "{} is not approximately equal to {}", - *a, - *b - ); - }}; - } - - fn check(samples: &[f64], summ: &Summary) { - let summ2 = Summary::new(samples); - - let mut w = io::sink(); - let w = &mut w; - (write!(w, "\n")).unwrap(); - - assert_eq!(summ.sum, summ2.sum); - assert_eq!(summ.min, summ2.min); - assert_eq!(summ.max, summ2.max); - assert_eq!(summ.mean, summ2.mean); - assert_eq!(summ.median, summ2.median); - - // We needed a few more digits to get exact equality on these - // but they're within float epsilon, which is 1.0e-6. - assert_approx_eq!(summ.var, summ2.var); - assert_approx_eq!(summ.std_dev, summ2.std_dev); - assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct); - assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev); - assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct); - - assert_eq!(summ.quartiles, summ2.quartiles); - assert_eq!(summ.iqr, summ2.iqr); - } - - #[test] - fn test_min_max_nan() { - let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0]; - let summary = Summary::new(xs); - assert_eq!(summary.min, 1.0); - assert_eq!(summary.max, 4.0); - } - - #[test] - fn test_norm2() { - let val = &[958.0000000000, 924.0000000000]; - let summ = &Summary { - sum: 1882.0000000000, - min: 924.0000000000, - max: 958.0000000000, - mean: 941.0000000000, - median: 941.0000000000, - var: 578.0000000000, - std_dev: 24.0416305603, - std_dev_pct: 2.5549022912, - median_abs_dev: 25.2042000000, - median_abs_dev_pct: 2.6784484591, - quartiles: (932.5000000000, 941.0000000000, 949.5000000000), - iqr: 17.0000000000, - }; - check(val, summ); - } - #[test] - fn test_norm10narrow() { - let val = &[ - 966.0000000000, - 985.0000000000, - 1110.0000000000, - 848.0000000000, - 821.0000000000, - 975.0000000000, - 962.0000000000, - 1157.0000000000, - 1217.0000000000, - 955.0000000000, - ]; - let summ = &Summary { - sum: 9996.0000000000, - min: 821.0000000000, - max: 1217.0000000000, - mean: 999.6000000000, - median: 970.5000000000, - var: 16050.7111111111, - std_dev: 126.6914010938, - std_dev_pct: 12.6742097933, - median_abs_dev: 102.2994000000, - median_abs_dev_pct: 10.5408964451, - quartiles: (956.7500000000, 970.5000000000, 1078.7500000000), - iqr: 122.0000000000, - }; - check(val, summ); - } - #[test] - fn test_norm10medium() { - let val = &[ - 954.0000000000, - 1064.0000000000, - 855.0000000000, - 1000.0000000000, - 743.0000000000, - 1084.0000000000, - 704.0000000000, - 1023.0000000000, - 357.0000000000, - 869.0000000000, - ]; - let summ = &Summary { - sum: 8653.0000000000, - min: 357.0000000000, - max: 1084.0000000000, - mean: 865.3000000000, - median: 911.5000000000, - var: 48628.4555555556, - std_dev: 220.5186059170, - std_dev_pct: 25.4846418487, - median_abs_dev: 195.7032000000, - median_abs_dev_pct: 21.4704552935, - quartiles: (771.0000000000, 911.5000000000, 1017.2500000000), - iqr: 246.2500000000, - }; - check(val, summ); - } - #[test] - fn test_norm10wide() { - let val = &[ - 505.0000000000, - 497.0000000000, - 1591.0000000000, - 887.0000000000, - 1026.0000000000, - 136.0000000000, - 1580.0000000000, - 940.0000000000, - 754.0000000000, - 1433.0000000000, - ]; - let summ = &Summary { - sum: 9349.0000000000, - min: 136.0000000000, - max: 1591.0000000000, - mean: 934.9000000000, - median: 913.5000000000, - var: 239208.9888888889, - std_dev: 489.0899599142, - std_dev_pct: 52.3146817750, - median_abs_dev: 611.5725000000, - median_abs_dev_pct: 66.9482758621, - quartiles: (567.2500000000, 913.5000000000, 1331.2500000000), - iqr: 764.0000000000, - }; - check(val, summ); - } - #[test] - fn test_norm25verynarrow() { - let val = &[ - 991.0000000000, - 1018.0000000000, - 998.0000000000, - 1013.0000000000, - 974.0000000000, - 1007.0000000000, - 1014.0000000000, - 999.0000000000, - 1011.0000000000, - 978.0000000000, - 985.0000000000, - 999.0000000000, - 983.0000000000, - 982.0000000000, - 1015.0000000000, - 1002.0000000000, - 977.0000000000, - 948.0000000000, - 1040.0000000000, - 974.0000000000, - 996.0000000000, - 989.0000000000, - 1015.0000000000, - 994.0000000000, - 1024.0000000000, - ]; - let summ = &Summary { - sum: 24926.0000000000, - min: 948.0000000000, - max: 1040.0000000000, - mean: 997.0400000000, - median: 998.0000000000, - var: 393.2066666667, - std_dev: 19.8294393937, - std_dev_pct: 1.9888308788, - median_abs_dev: 22.2390000000, - median_abs_dev_pct: 2.2283567134, - quartiles: (983.0000000000, 998.0000000000, 1013.0000000000), - iqr: 30.0000000000, - }; - check(val, summ); - } - #[test] - fn test_exp10a() { - let val = &[ - 23.0000000000, - 11.0000000000, - 2.0000000000, - 57.0000000000, - 4.0000000000, - 12.0000000000, - 5.0000000000, - 29.0000000000, - 3.0000000000, - 21.0000000000, - ]; - let summ = &Summary { - sum: 167.0000000000, - min: 2.0000000000, - max: 57.0000000000, - mean: 16.7000000000, - median: 11.5000000000, - var: 287.7888888889, - std_dev: 16.9643416875, - std_dev_pct: 101.5828843560, - median_abs_dev: 13.3434000000, - median_abs_dev_pct: 116.0295652174, - quartiles: (4.2500000000, 11.5000000000, 22.5000000000), - iqr: 18.2500000000, - }; - check(val, summ); - } - #[test] - fn test_exp10b() { - let val = &[ - 24.0000000000, - 17.0000000000, - 6.0000000000, - 38.0000000000, - 25.0000000000, - 7.0000000000, - 51.0000000000, - 2.0000000000, - 61.0000000000, - 32.0000000000, - ]; - let summ = &Summary { - sum: 263.0000000000, - min: 2.0000000000, - max: 61.0000000000, - mean: 26.3000000000, - median: 24.5000000000, - var: 383.5666666667, - std_dev: 19.5848580967, - std_dev_pct: 74.4671410520, - median_abs_dev: 22.9803000000, - median_abs_dev_pct: 93.7971428571, - quartiles: (9.5000000000, 24.5000000000, 36.5000000000), - iqr: 27.0000000000, - }; - check(val, summ); - } - #[test] - fn test_exp10c() { - let val = &[ - 71.0000000000, - 2.0000000000, - 32.0000000000, - 1.0000000000, - 6.0000000000, - 28.0000000000, - 13.0000000000, - 37.0000000000, - 16.0000000000, - 36.0000000000, - ]; - let summ = &Summary { - sum: 242.0000000000, - min: 1.0000000000, - max: 71.0000000000, - mean: 24.2000000000, - median: 22.0000000000, - var: 458.1777777778, - std_dev: 21.4050876611, - std_dev_pct: 88.4507754589, - median_abs_dev: 21.4977000000, - median_abs_dev_pct: 97.7168181818, - quartiles: (7.7500000000, 22.0000000000, 35.0000000000), - iqr: 27.2500000000, - }; - check(val, summ); - } - #[test] - fn test_exp25() { - let val = &[ - 3.0000000000, - 24.0000000000, - 1.0000000000, - 19.0000000000, - 7.0000000000, - 5.0000000000, - 30.0000000000, - 39.0000000000, - 31.0000000000, - 13.0000000000, - 25.0000000000, - 48.0000000000, - 1.0000000000, - 6.0000000000, - 42.0000000000, - 63.0000000000, - 2.0000000000, - 12.0000000000, - 108.0000000000, - 26.0000000000, - 1.0000000000, - 7.0000000000, - 44.0000000000, - 25.0000000000, - 11.0000000000, - ]; - let summ = &Summary { - sum: 593.0000000000, - min: 1.0000000000, - max: 108.0000000000, - mean: 23.7200000000, - median: 19.0000000000, - var: 601.0433333333, - std_dev: 24.5161851301, - std_dev_pct: 103.3565983562, - median_abs_dev: 19.2738000000, - median_abs_dev_pct: 101.4410526316, - quartiles: (6.0000000000, 19.0000000000, 31.0000000000), - iqr: 25.0000000000, - }; - check(val, summ); - } - #[test] - fn test_binom25() { - let val = &[ - 18.0000000000, - 17.0000000000, - 27.0000000000, - 15.0000000000, - 21.0000000000, - 25.0000000000, - 17.0000000000, - 24.0000000000, - 25.0000000000, - 24.0000000000, - 26.0000000000, - 26.0000000000, - 23.0000000000, - 15.0000000000, - 23.0000000000, - 17.0000000000, - 18.0000000000, - 18.0000000000, - 21.0000000000, - 16.0000000000, - 15.0000000000, - 31.0000000000, - 20.0000000000, - 17.0000000000, - 15.0000000000, - ]; - let summ = &Summary { - sum: 514.0000000000, - min: 15.0000000000, - max: 31.0000000000, - mean: 20.5600000000, - median: 20.0000000000, - var: 20.8400000000, - std_dev: 4.5650848842, - std_dev_pct: 22.2037202539, - median_abs_dev: 5.9304000000, - median_abs_dev_pct: 29.6520000000, - quartiles: (17.0000000000, 20.0000000000, 24.0000000000), - iqr: 7.0000000000, - }; - check(val, summ); - } - #[test] - fn test_pois25lambda30() { - let val = &[ - 27.0000000000, - 33.0000000000, - 34.0000000000, - 34.0000000000, - 24.0000000000, - 39.0000000000, - 28.0000000000, - 27.0000000000, - 31.0000000000, - 28.0000000000, - 38.0000000000, - 21.0000000000, - 33.0000000000, - 36.0000000000, - 29.0000000000, - 37.0000000000, - 32.0000000000, - 34.0000000000, - 31.0000000000, - 39.0000000000, - 25.0000000000, - 31.0000000000, - 32.0000000000, - 40.0000000000, - 24.0000000000, - ]; - let summ = &Summary { - sum: 787.0000000000, - min: 21.0000000000, - max: 40.0000000000, - mean: 31.4800000000, - median: 32.0000000000, - var: 26.5933333333, - std_dev: 5.1568724372, - std_dev_pct: 16.3814245145, - median_abs_dev: 5.9304000000, - median_abs_dev_pct: 18.5325000000, - quartiles: (28.0000000000, 32.0000000000, 34.0000000000), - iqr: 6.0000000000, - }; - check(val, summ); - } - #[test] - fn test_pois25lambda40() { - let val = &[ - 42.0000000000, - 50.0000000000, - 42.0000000000, - 46.0000000000, - 34.0000000000, - 45.0000000000, - 34.0000000000, - 49.0000000000, - 39.0000000000, - 28.0000000000, - 40.0000000000, - 35.0000000000, - 37.0000000000, - 39.0000000000, - 46.0000000000, - 44.0000000000, - 32.0000000000, - 45.0000000000, - 42.0000000000, - 37.0000000000, - 48.0000000000, - 42.0000000000, - 33.0000000000, - 42.0000000000, - 48.0000000000, - ]; - let summ = &Summary { - sum: 1019.0000000000, - min: 28.0000000000, - max: 50.0000000000, - mean: 40.7600000000, - median: 42.0000000000, - var: 34.4400000000, - std_dev: 5.8685603004, - std_dev_pct: 14.3978417577, - median_abs_dev: 5.9304000000, - median_abs_dev_pct: 14.1200000000, - quartiles: (37.0000000000, 42.0000000000, 45.0000000000), - iqr: 8.0000000000, - }; - check(val, summ); - } - #[test] - fn test_pois25lambda50() { - let val = &[ - 45.0000000000, - 43.0000000000, - 44.0000000000, - 61.0000000000, - 51.0000000000, - 53.0000000000, - 59.0000000000, - 52.0000000000, - 49.0000000000, - 51.0000000000, - 51.0000000000, - 50.0000000000, - 49.0000000000, - 56.0000000000, - 42.0000000000, - 52.0000000000, - 51.0000000000, - 43.0000000000, - 48.0000000000, - 48.0000000000, - 50.0000000000, - 42.0000000000, - 43.0000000000, - 42.0000000000, - 60.0000000000, - ]; - let summ = &Summary { - sum: 1235.0000000000, - min: 42.0000000000, - max: 61.0000000000, - mean: 49.4000000000, - median: 50.0000000000, - var: 31.6666666667, - std_dev: 5.6273143387, - std_dev_pct: 11.3913245723, - median_abs_dev: 4.4478000000, - median_abs_dev_pct: 8.8956000000, - quartiles: (44.0000000000, 50.0000000000, 52.0000000000), - iqr: 8.0000000000, - }; - check(val, summ); - } - #[test] - fn test_unif25() { - let val = &[ - 99.0000000000, - 55.0000000000, - 92.0000000000, - 79.0000000000, - 14.0000000000, - 2.0000000000, - 33.0000000000, - 49.0000000000, - 3.0000000000, - 32.0000000000, - 84.0000000000, - 59.0000000000, - 22.0000000000, - 86.0000000000, - 76.0000000000, - 31.0000000000, - 29.0000000000, - 11.0000000000, - 41.0000000000, - 53.0000000000, - 45.0000000000, - 44.0000000000, - 98.0000000000, - 98.0000000000, - 7.0000000000, - ]; - let summ = &Summary { - sum: 1242.0000000000, - min: 2.0000000000, - max: 99.0000000000, - mean: 49.6800000000, - median: 45.0000000000, - var: 1015.6433333333, - std_dev: 31.8691595957, - std_dev_pct: 64.1488719719, - median_abs_dev: 45.9606000000, - median_abs_dev_pct: 102.1346666667, - quartiles: (29.0000000000, 45.0000000000, 79.0000000000), - iqr: 50.0000000000, - }; - check(val, summ); - } - - #[test] - fn test_sum_f64s() { - assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999); - } - #[test] - fn test_sum_f64_between_ints_that_sum_to_0() { - assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2); - } -} +mod tests; #[cfg(test)] mod bench { diff --git a/src/libtest/stats/tests.rs b/src/libtest/stats/tests.rs new file mode 100644 index 0000000000000..59f936453602a --- /dev/null +++ b/src/libtest/stats/tests.rs @@ -0,0 +1,574 @@ +use crate::stats::Stats; +use crate::stats::Summary; +use std::f64; +use std::io::prelude::*; +use std::io; + +macro_rules! assert_approx_eq { + ($a: expr, $b: expr) => {{ + let (a, b) = (&$a, &$b); + assert!( + (*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", + *a, + *b + ); + }}; +} + +fn check(samples: &[f64], summ: &Summary) { + let summ2 = Summary::new(samples); + + let mut w = io::sink(); + let w = &mut w; + (write!(w, "\n")).unwrap(); + + assert_eq!(summ.sum, summ2.sum); + assert_eq!(summ.min, summ2.min); + assert_eq!(summ.max, summ2.max); + assert_eq!(summ.mean, summ2.mean); + assert_eq!(summ.median, summ2.median); + + // We needed a few more digits to get exact equality on these + // but they're within float epsilon, which is 1.0e-6. + assert_approx_eq!(summ.var, summ2.var); + assert_approx_eq!(summ.std_dev, summ2.std_dev); + assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct); + assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev); + assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct); + + assert_eq!(summ.quartiles, summ2.quartiles); + assert_eq!(summ.iqr, summ2.iqr); +} + +#[test] +fn test_min_max_nan() { + let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0]; + let summary = Summary::new(xs); + assert_eq!(summary.min, 1.0); + assert_eq!(summary.max, 4.0); +} + +#[test] +fn test_norm2() { + let val = &[958.0000000000, 924.0000000000]; + let summ = &Summary { + sum: 1882.0000000000, + min: 924.0000000000, + max: 958.0000000000, + mean: 941.0000000000, + median: 941.0000000000, + var: 578.0000000000, + std_dev: 24.0416305603, + std_dev_pct: 2.5549022912, + median_abs_dev: 25.2042000000, + median_abs_dev_pct: 2.6784484591, + quartiles: (932.5000000000, 941.0000000000, 949.5000000000), + iqr: 17.0000000000, + }; + check(val, summ); +} +#[test] +fn test_norm10narrow() { + let val = &[ + 966.0000000000, + 985.0000000000, + 1110.0000000000, + 848.0000000000, + 821.0000000000, + 975.0000000000, + 962.0000000000, + 1157.0000000000, + 1217.0000000000, + 955.0000000000, + ]; + let summ = &Summary { + sum: 9996.0000000000, + min: 821.0000000000, + max: 1217.0000000000, + mean: 999.6000000000, + median: 970.5000000000, + var: 16050.7111111111, + std_dev: 126.6914010938, + std_dev_pct: 12.6742097933, + median_abs_dev: 102.2994000000, + median_abs_dev_pct: 10.5408964451, + quartiles: (956.7500000000, 970.5000000000, 1078.7500000000), + iqr: 122.0000000000, + }; + check(val, summ); +} +#[test] +fn test_norm10medium() { + let val = &[ + 954.0000000000, + 1064.0000000000, + 855.0000000000, + 1000.0000000000, + 743.0000000000, + 1084.0000000000, + 704.0000000000, + 1023.0000000000, + 357.0000000000, + 869.0000000000, + ]; + let summ = &Summary { + sum: 8653.0000000000, + min: 357.0000000000, + max: 1084.0000000000, + mean: 865.3000000000, + median: 911.5000000000, + var: 48628.4555555556, + std_dev: 220.5186059170, + std_dev_pct: 25.4846418487, + median_abs_dev: 195.7032000000, + median_abs_dev_pct: 21.4704552935, + quartiles: (771.0000000000, 911.5000000000, 1017.2500000000), + iqr: 246.2500000000, + }; + check(val, summ); +} +#[test] +fn test_norm10wide() { + let val = &[ + 505.0000000000, + 497.0000000000, + 1591.0000000000, + 887.0000000000, + 1026.0000000000, + 136.0000000000, + 1580.0000000000, + 940.0000000000, + 754.0000000000, + 1433.0000000000, + ]; + let summ = &Summary { + sum: 9349.0000000000, + min: 136.0000000000, + max: 1591.0000000000, + mean: 934.9000000000, + median: 913.5000000000, + var: 239208.9888888889, + std_dev: 489.0899599142, + std_dev_pct: 52.3146817750, + median_abs_dev: 611.5725000000, + median_abs_dev_pct: 66.9482758621, + quartiles: (567.2500000000, 913.5000000000, 1331.2500000000), + iqr: 764.0000000000, + }; + check(val, summ); +} +#[test] +fn test_norm25verynarrow() { + let val = &[ + 991.0000000000, + 1018.0000000000, + 998.0000000000, + 1013.0000000000, + 974.0000000000, + 1007.0000000000, + 1014.0000000000, + 999.0000000000, + 1011.0000000000, + 978.0000000000, + 985.0000000000, + 999.0000000000, + 983.0000000000, + 982.0000000000, + 1015.0000000000, + 1002.0000000000, + 977.0000000000, + 948.0000000000, + 1040.0000000000, + 974.0000000000, + 996.0000000000, + 989.0000000000, + 1015.0000000000, + 994.0000000000, + 1024.0000000000, + ]; + let summ = &Summary { + sum: 24926.0000000000, + min: 948.0000000000, + max: 1040.0000000000, + mean: 997.0400000000, + median: 998.0000000000, + var: 393.2066666667, + std_dev: 19.8294393937, + std_dev_pct: 1.9888308788, + median_abs_dev: 22.2390000000, + median_abs_dev_pct: 2.2283567134, + quartiles: (983.0000000000, 998.0000000000, 1013.0000000000), + iqr: 30.0000000000, + }; + check(val, summ); +} +#[test] +fn test_exp10a() { + let val = &[ + 23.0000000000, + 11.0000000000, + 2.0000000000, + 57.0000000000, + 4.0000000000, + 12.0000000000, + 5.0000000000, + 29.0000000000, + 3.0000000000, + 21.0000000000, + ]; + let summ = &Summary { + sum: 167.0000000000, + min: 2.0000000000, + max: 57.0000000000, + mean: 16.7000000000, + median: 11.5000000000, + var: 287.7888888889, + std_dev: 16.9643416875, + std_dev_pct: 101.5828843560, + median_abs_dev: 13.3434000000, + median_abs_dev_pct: 116.0295652174, + quartiles: (4.2500000000, 11.5000000000, 22.5000000000), + iqr: 18.2500000000, + }; + check(val, summ); +} +#[test] +fn test_exp10b() { + let val = &[ + 24.0000000000, + 17.0000000000, + 6.0000000000, + 38.0000000000, + 25.0000000000, + 7.0000000000, + 51.0000000000, + 2.0000000000, + 61.0000000000, + 32.0000000000, + ]; + let summ = &Summary { + sum: 263.0000000000, + min: 2.0000000000, + max: 61.0000000000, + mean: 26.3000000000, + median: 24.5000000000, + var: 383.5666666667, + std_dev: 19.5848580967, + std_dev_pct: 74.4671410520, + median_abs_dev: 22.9803000000, + median_abs_dev_pct: 93.7971428571, + quartiles: (9.5000000000, 24.5000000000, 36.5000000000), + iqr: 27.0000000000, + }; + check(val, summ); +} +#[test] +fn test_exp10c() { + let val = &[ + 71.0000000000, + 2.0000000000, + 32.0000000000, + 1.0000000000, + 6.0000000000, + 28.0000000000, + 13.0000000000, + 37.0000000000, + 16.0000000000, + 36.0000000000, + ]; + let summ = &Summary { + sum: 242.0000000000, + min: 1.0000000000, + max: 71.0000000000, + mean: 24.2000000000, + median: 22.0000000000, + var: 458.1777777778, + std_dev: 21.4050876611, + std_dev_pct: 88.4507754589, + median_abs_dev: 21.4977000000, + median_abs_dev_pct: 97.7168181818, + quartiles: (7.7500000000, 22.0000000000, 35.0000000000), + iqr: 27.2500000000, + }; + check(val, summ); +} +#[test] +fn test_exp25() { + let val = &[ + 3.0000000000, + 24.0000000000, + 1.0000000000, + 19.0000000000, + 7.0000000000, + 5.0000000000, + 30.0000000000, + 39.0000000000, + 31.0000000000, + 13.0000000000, + 25.0000000000, + 48.0000000000, + 1.0000000000, + 6.0000000000, + 42.0000000000, + 63.0000000000, + 2.0000000000, + 12.0000000000, + 108.0000000000, + 26.0000000000, + 1.0000000000, + 7.0000000000, + 44.0000000000, + 25.0000000000, + 11.0000000000, + ]; + let summ = &Summary { + sum: 593.0000000000, + min: 1.0000000000, + max: 108.0000000000, + mean: 23.7200000000, + median: 19.0000000000, + var: 601.0433333333, + std_dev: 24.5161851301, + std_dev_pct: 103.3565983562, + median_abs_dev: 19.2738000000, + median_abs_dev_pct: 101.4410526316, + quartiles: (6.0000000000, 19.0000000000, 31.0000000000), + iqr: 25.0000000000, + }; + check(val, summ); +} +#[test] +fn test_binom25() { + let val = &[ + 18.0000000000, + 17.0000000000, + 27.0000000000, + 15.0000000000, + 21.0000000000, + 25.0000000000, + 17.0000000000, + 24.0000000000, + 25.0000000000, + 24.0000000000, + 26.0000000000, + 26.0000000000, + 23.0000000000, + 15.0000000000, + 23.0000000000, + 17.0000000000, + 18.0000000000, + 18.0000000000, + 21.0000000000, + 16.0000000000, + 15.0000000000, + 31.0000000000, + 20.0000000000, + 17.0000000000, + 15.0000000000, + ]; + let summ = &Summary { + sum: 514.0000000000, + min: 15.0000000000, + max: 31.0000000000, + mean: 20.5600000000, + median: 20.0000000000, + var: 20.8400000000, + std_dev: 4.5650848842, + std_dev_pct: 22.2037202539, + median_abs_dev: 5.9304000000, + median_abs_dev_pct: 29.6520000000, + quartiles: (17.0000000000, 20.0000000000, 24.0000000000), + iqr: 7.0000000000, + }; + check(val, summ); +} +#[test] +fn test_pois25lambda30() { + let val = &[ + 27.0000000000, + 33.0000000000, + 34.0000000000, + 34.0000000000, + 24.0000000000, + 39.0000000000, + 28.0000000000, + 27.0000000000, + 31.0000000000, + 28.0000000000, + 38.0000000000, + 21.0000000000, + 33.0000000000, + 36.0000000000, + 29.0000000000, + 37.0000000000, + 32.0000000000, + 34.0000000000, + 31.0000000000, + 39.0000000000, + 25.0000000000, + 31.0000000000, + 32.0000000000, + 40.0000000000, + 24.0000000000, + ]; + let summ = &Summary { + sum: 787.0000000000, + min: 21.0000000000, + max: 40.0000000000, + mean: 31.4800000000, + median: 32.0000000000, + var: 26.5933333333, + std_dev: 5.1568724372, + std_dev_pct: 16.3814245145, + median_abs_dev: 5.9304000000, + median_abs_dev_pct: 18.5325000000, + quartiles: (28.0000000000, 32.0000000000, 34.0000000000), + iqr: 6.0000000000, + }; + check(val, summ); +} +#[test] +fn test_pois25lambda40() { + let val = &[ + 42.0000000000, + 50.0000000000, + 42.0000000000, + 46.0000000000, + 34.0000000000, + 45.0000000000, + 34.0000000000, + 49.0000000000, + 39.0000000000, + 28.0000000000, + 40.0000000000, + 35.0000000000, + 37.0000000000, + 39.0000000000, + 46.0000000000, + 44.0000000000, + 32.0000000000, + 45.0000000000, + 42.0000000000, + 37.0000000000, + 48.0000000000, + 42.0000000000, + 33.0000000000, + 42.0000000000, + 48.0000000000, + ]; + let summ = &Summary { + sum: 1019.0000000000, + min: 28.0000000000, + max: 50.0000000000, + mean: 40.7600000000, + median: 42.0000000000, + var: 34.4400000000, + std_dev: 5.8685603004, + std_dev_pct: 14.3978417577, + median_abs_dev: 5.9304000000, + median_abs_dev_pct: 14.1200000000, + quartiles: (37.0000000000, 42.0000000000, 45.0000000000), + iqr: 8.0000000000, + }; + check(val, summ); +} +#[test] +fn test_pois25lambda50() { + let val = &[ + 45.0000000000, + 43.0000000000, + 44.0000000000, + 61.0000000000, + 51.0000000000, + 53.0000000000, + 59.0000000000, + 52.0000000000, + 49.0000000000, + 51.0000000000, + 51.0000000000, + 50.0000000000, + 49.0000000000, + 56.0000000000, + 42.0000000000, + 52.0000000000, + 51.0000000000, + 43.0000000000, + 48.0000000000, + 48.0000000000, + 50.0000000000, + 42.0000000000, + 43.0000000000, + 42.0000000000, + 60.0000000000, + ]; + let summ = &Summary { + sum: 1235.0000000000, + min: 42.0000000000, + max: 61.0000000000, + mean: 49.4000000000, + median: 50.0000000000, + var: 31.6666666667, + std_dev: 5.6273143387, + std_dev_pct: 11.3913245723, + median_abs_dev: 4.4478000000, + median_abs_dev_pct: 8.8956000000, + quartiles: (44.0000000000, 50.0000000000, 52.0000000000), + iqr: 8.0000000000, + }; + check(val, summ); +} +#[test] +fn test_unif25() { + let val = &[ + 99.0000000000, + 55.0000000000, + 92.0000000000, + 79.0000000000, + 14.0000000000, + 2.0000000000, + 33.0000000000, + 49.0000000000, + 3.0000000000, + 32.0000000000, + 84.0000000000, + 59.0000000000, + 22.0000000000, + 86.0000000000, + 76.0000000000, + 31.0000000000, + 29.0000000000, + 11.0000000000, + 41.0000000000, + 53.0000000000, + 45.0000000000, + 44.0000000000, + 98.0000000000, + 98.0000000000, + 7.0000000000, + ]; + let summ = &Summary { + sum: 1242.0000000000, + min: 2.0000000000, + max: 99.0000000000, + mean: 49.6800000000, + median: 45.0000000000, + var: 1015.6433333333, + std_dev: 31.8691595957, + std_dev_pct: 64.1488719719, + median_abs_dev: 45.9606000000, + median_abs_dev_pct: 102.1346666667, + quartiles: (29.0000000000, 45.0000000000, 79.0000000000), + iqr: 50.0000000000, + }; + check(val, summ); +} + +#[test] +fn test_sum_f64s() { + assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999); +} +#[test] +fn test_sum_f64_between_ints_that_sum_to_0() { + assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2); +} diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs new file mode 100644 index 0000000000000..d8734d8caa03e --- /dev/null +++ b/src/libtest/tests.rs @@ -0,0 +1,453 @@ +use crate::bench; +use crate::test::{ + filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, + TrIgnored, TrOk, +}; +use crate::Bencher; +use crate::Concurrent; +use std::sync::mpsc::channel; + +fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { + vec![ + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("1"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("2"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + ] +} + +#[test] +pub fn do_not_run_ignored_tests() { + fn f() { + panic!(); + } + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res != TrOk); +} + +#[test] +pub fn ignored_tests_result_in_ignored() { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res == TrIgnored); +} + +#[test] +fn test_should_panic() { + fn f() { + panic!(); + } + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::Yes, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res == TrOk); +} + +#[test] +fn test_should_panic_good_message() { + fn f() { + panic!("an error message"); + } + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::YesWithMessage("error message"), + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res == TrOk); +} + +#[test] +fn test_should_panic_bad_message() { + fn f() { + panic!("an error message"); + } + let expected = "foobar"; + let failed_msg = "panic did not include expected string"; + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::YesWithMessage(expected), + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); +} + +#[test] +fn test_should_panic_but_succeeds() { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::Yes, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + let (_, res, _) = rx.recv().unwrap(); + assert!(res == TrFailed); +} + +#[test] +fn parse_ignored_flag() { + let args = vec![ + "progname".to_string(), + "filter".to_string(), + "--ignored".to_string(), + ]; + let opts = parse_opts(&args).unwrap().unwrap(); + assert_eq!(opts.run_ignored, RunIgnored::Only); +} + +#[test] +fn parse_include_ignored_flag() { + let args = vec![ + "progname".to_string(), + "filter".to_string(), + "-Zunstable-options".to_string(), + "--include-ignored".to_string(), + ]; + let opts = parse_opts(&args).unwrap().unwrap(); + assert_eq!(opts.run_ignored, RunIgnored::Yes); +} + +#[test] +pub fn filter_for_ignored_option() { + // When we run ignored tests the test filter should filter out all the + // unignored tests and flip the ignore flag on the rest to false + + let mut opts = TestOpts::new(); + opts.run_tests = true; + opts.run_ignored = RunIgnored::Only; + + let tests = one_ignored_one_unignored_test(); + let filtered = filter_tests(&opts, tests); + + assert_eq!(filtered.len(), 1); + assert_eq!(filtered[0].desc.name.to_string(), "1"); + assert!(!filtered[0].desc.ignore); +} + +#[test] +pub fn run_include_ignored_option() { + // When we "--include-ignored" tests, the ignore flag should be set to false on + // all tests and no test filtered out + + let mut opts = TestOpts::new(); + opts.run_tests = true; + opts.run_ignored = RunIgnored::Yes; + + let tests = one_ignored_one_unignored_test(); + let filtered = filter_tests(&opts, tests); + + assert_eq!(filtered.len(), 2); + assert!(!filtered[0].desc.ignore); + assert!(!filtered[1].desc.ignore); +} + +#[test] +pub fn exclude_should_panic_option() { + let mut opts = TestOpts::new(); + opts.run_tests = true; + opts.exclude_should_panic = true; + + let mut tests = one_ignored_one_unignored_test(); + tests.push(TestDescAndFn { + desc: TestDesc { + name: StaticTestName("3"), + ignore: false, + should_panic: ShouldPanic::Yes, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }); + + let filtered = filter_tests(&opts, tests); + + assert_eq!(filtered.len(), 2); + assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No)); +} + +#[test] +pub fn exact_filter_match() { + fn tests() -> Vec<TestDescAndFn> { + vec!["base", "base::test", "base::test1", "base::test2"] + .into_iter() + .map(|name| TestDescAndFn { + desc: TestDesc { + name: StaticTestName(name), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }) + .collect() + } + + let substr = filter_tests( + &TestOpts { + filter: Some("base".into()), + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(substr.len(), 4); + + let substr = filter_tests( + &TestOpts { + filter: Some("bas".into()), + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(substr.len(), 4); + + let substr = filter_tests( + &TestOpts { + filter: Some("::test".into()), + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(substr.len(), 3); + + let substr = filter_tests( + &TestOpts { + filter: Some("base::test".into()), + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(substr.len(), 3); + + let exact = filter_tests( + &TestOpts { + filter: Some("base".into()), + filter_exact: true, + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(exact.len(), 1); + + let exact = filter_tests( + &TestOpts { + filter: Some("bas".into()), + filter_exact: true, + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(exact.len(), 0); + + let exact = filter_tests( + &TestOpts { + filter: Some("::test".into()), + filter_exact: true, + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(exact.len(), 0); + + let exact = filter_tests( + &TestOpts { + filter: Some("base::test".into()), + filter_exact: true, + ..TestOpts::new() + }, + tests(), + ); + assert_eq!(exact.len(), 1); +} + +#[test] +pub fn sort_tests() { + let mut opts = TestOpts::new(); + opts.run_tests = true; + + let names = vec![ + "sha1::test".to_string(), + "isize::test_to_str".to_string(), + "isize::test_pow".to_string(), + "test::do_not_run_ignored_tests".to_string(), + "test::ignored_tests_result_in_ignored".to_string(), + "test::first_free_arg_should_be_a_filter".to_string(), + "test::parse_ignored_flag".to_string(), + "test::parse_include_ignored_flag".to_string(), + "test::filter_for_ignored_option".to_string(), + "test::run_include_ignored_option".to_string(), + "test::sort_tests".to_string(), + ]; + let tests = { + fn testfn() {} + let mut tests = Vec::new(); + for name in &names { + let test = TestDescAndFn { + desc: TestDesc { + name: DynTestName((*name).clone()), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(testfn)), + }; + tests.push(test); + } + tests + }; + let filtered = filter_tests(&opts, tests); + + let expected = vec![ + "isize::test_pow".to_string(), + "isize::test_to_str".to_string(), + "sha1::test".to_string(), + "test::do_not_run_ignored_tests".to_string(), + "test::filter_for_ignored_option".to_string(), + "test::first_free_arg_should_be_a_filter".to_string(), + "test::ignored_tests_result_in_ignored".to_string(), + "test::parse_ignored_flag".to_string(), + "test::parse_include_ignored_flag".to_string(), + "test::run_include_ignored_option".to_string(), + "test::sort_tests".to_string(), + ]; + + for (a, b) in expected.iter().zip(filtered) { + assert!(*a == b.desc.name.to_string()); + } +} + +#[test] +pub fn test_metricmap_compare() { + let mut m1 = MetricMap::new(); + let mut m2 = MetricMap::new(); + m1.insert_metric("in-both-noise", 1000.0, 200.0); + m2.insert_metric("in-both-noise", 1100.0, 200.0); + + m1.insert_metric("in-first-noise", 1000.0, 2.0); + m2.insert_metric("in-second-noise", 1000.0, 2.0); + + m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0); + m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0); + + m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0); + m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0); + + m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0); + m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0); + + m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0); + m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0); +} + +#[test] +pub fn test_bench_once_no_iter() { + fn f(_: &mut Bencher) {} + bench::run_once(f); +} + +#[test] +pub fn test_bench_once_iter() { + fn f(b: &mut Bencher) { + b.iter(|| {}) + } + bench::run_once(f); +} + +#[test] +pub fn test_bench_no_iter() { + fn f(_: &mut Bencher) {} + + let (tx, rx) = channel(); + + let desc = TestDesc { + name: StaticTestName("f"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }; + + crate::bench::benchmark(desc, tx, true, f); + rx.recv().unwrap(); +} + +#[test] +pub fn test_bench_iter() { + fn f(b: &mut Bencher) { + b.iter(|| {}) + } + + let (tx, rx) = channel(); + + let desc = TestDesc { + name: StaticTestName("f"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }; + + crate::bench::benchmark(desc, tx, true, f); + rx.recv().unwrap(); +}