| use std::collections::BTreeMap; |
| |
| use snapbox::assert_data_eq; |
| |
| use crate::prelude::*; |
| |
| #[test] |
| fn ensure_all_fixtures_have_tests() { |
| let mut code_gen_divider = "//".to_owned(); |
| code_gen_divider.push_str(" START CODE GENERATION"); |
| |
| let self_path = snapbox::utils::current_rs!(); |
| let self_source = std::fs::read_to_string(&self_path).unwrap(); |
| |
| let (header, _) = self_source |
| .split_once(&code_gen_divider) |
| .expect("code-gen divider is present"); |
| let header = header.trim(); |
| |
| let fixture_root = snapbox::utils::current_dir!().join("rustc_fixtures"); |
| let mut fixtures = BTreeMap::new(); |
| for entry in std::fs::read_dir(fixture_root).unwrap() { |
| let entry = entry.unwrap(); |
| let path = entry.path(); |
| let fn_name = file_to_fn(&path); |
| fixtures |
| .entry(fn_name.clone()) |
| .or_insert_with(|| Fixture::new(fn_name)) |
| .add_path(path); |
| } |
| |
| let fixtures = fixtures |
| .into_values() |
| .filter(Fixture::is_valid) |
| .map(|f| f.to_string()) |
| .collect::<String>(); |
| let actual = format!( |
| "{header} |
| |
| {code_gen_divider} |
| {fixtures}" |
| ); |
| assert_data_eq!(actual, snapbox::Data::read_from(&self_path, None).raw()); |
| } |
| |
| fn file_to_fn(path: &std::path::Path) -> String { |
| let name = path.file_stem().unwrap().to_str().unwrap(); |
| name.replace("-", "_") |
| } |
| |
| fn sanitize_path(path: &std::path::Path) -> String { |
| path.strip_prefix(env!("CARGO_MANIFEST_DIR")) |
| .unwrap() |
| .as_os_str() |
| .to_string_lossy() |
| .replace("\\", "/") |
| } |
| |
| struct Fixture { |
| fn_name: String, |
| input: std::path::PathBuf, |
| output: Option<std::path::PathBuf>, |
| } |
| |
| impl Fixture { |
| fn new(fn_name: String) -> Self { |
| Self { |
| fn_name, |
| input: Default::default(), |
| output: Default::default(), |
| } |
| } |
| |
| fn is_valid(&self) -> bool { |
| !self.input.as_os_str().is_empty() |
| } |
| |
| fn add_path(&mut self, path: std::path::PathBuf) { |
| if path.extension().map(|ext| ext.to_str().unwrap()) == Some("rs") { |
| assert!( |
| self.input.as_os_str().is_empty(), |
| "similarly named fixtures:/n{}/n{}", |
| self.input.display(), |
| path.display() |
| ); |
| self.input = path; |
| } else { |
| assert!( |
| self.output.is_none(), |
| "conflicting assertions:/n{}/n{}", |
| self.output.as_ref().unwrap().display(), |
| path.display() |
| ); |
| self.output = Some(path); |
| } |
| } |
| } |
| |
| impl std::fmt::Display for Fixture { |
| fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| let fn_name = &self.fn_name; |
| let fixture_path = sanitize_path(&self.input); |
| match self |
| .output |
| .as_ref() |
| .map(|path| path.extension().unwrap().to_str().unwrap()) |
| { |
| Some("stderr") => { |
| let assertion_path = sanitize_path(self.output.as_ref().unwrap()); |
| write!( |
| fmt, |
| r#" |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn {fn_name}() {{ |
| let fixture_path = {fixture_path:?}; |
| let assertion_path = {assertion_path:?}; |
| assert_failure(fixture_path, assertion_path); |
| }} |
| "# |
| ) |
| } |
| Some("stdout") | None => { |
| let mut backup_path = self.input.clone(); |
| backup_path.set_extension("stdout"); |
| let assertion_path = sanitize_path(self.output.as_ref().unwrap_or(&backup_path)); |
| write!( |
| fmt, |
| r#" |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn {fn_name}() {{ |
| let fixture_path = {fixture_path:?}; |
| let assertion_path = {assertion_path:?}; |
| assert_success(fixture_path, assertion_path); |
| }} |
| "# |
| ) |
| } |
| Some(_) => { |
| panic!( |
| "unsupported assertiong: {}", |
| self.output.as_ref().unwrap().display() |
| ) |
| } |
| } |
| } |
| } |
| |
| #[track_caller] |
| fn assert_success(fixture_path: &str, assertion_path: &str) { |
| let p = cargo_test_support::project() |
| .file("script", &std::fs::read_to_string(fixture_path).unwrap()) |
| .build(); |
| |
| // `read-manifest` to validate frontmatter content without processing deps, compiling |
| p.cargo("-Zscript read-manifest --manifest-path script") |
| .masquerade_as_nightly_cargo(&["script"]) |
| .with_stdout_data(snapbox::Data::read_from( |
| std::path::Path::new(assertion_path), |
| Some(snapbox::data::DataFormat::Json), |
| )) |
| .run(); |
| } |
| |
| #[track_caller] |
| fn assert_failure(fixture_path: &str, assertion_path: &str) { |
| let p = cargo_test_support::project() |
| .file("script", &std::fs::read_to_string(fixture_path).unwrap()) |
| .build(); |
| |
| // `read-manifest` to validate frontmatter content without processing deps, compiling |
| p.cargo("-Zscript read-manifest --manifest-path script") |
| .masquerade_as_nightly_cargo(&["script"]) |
| .with_status(101) |
| .with_stderr_data(snapbox::Data::read_from( |
| std::path::Path::new(assertion_path), |
| None, |
| )) |
| .run(); |
| } |
| |
| // START CODE GENERATION |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn content_contains_whitespace() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/content-contains-whitespace.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/content-contains-whitespace.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn content_non_lexible_tokens() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn escape_hyphens_leading() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn escape_hyphens_nonleading_1() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn escape_hyphens_nonleading_2() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn escape_hyphens_nonleading_3() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_close_extra_after() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-close-extra-after.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-close-extra-after.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_indented() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-indented.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-indented.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_indented_mismatch() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_mismatch_1() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-mismatch-1.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-mismatch-1.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_mismatch_2() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-mismatch-2.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-mismatch-2.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_too_many_dashes() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_1() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-1.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-1.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_2() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-2.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-2.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_3() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-3.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-3.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_4() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-4.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-4.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_5() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-5.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-5.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_unclosed_6() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-6.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-unclosed-6.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_whitespace_trailing_1() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn fence_whitespace_trailing_2() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn frontmatter_crlf() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/frontmatter-crlf.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/frontmatter-crlf.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_comma() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-comma.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-comma.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_dot_leading() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-dot-leading.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-dot-leading.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_dot_nonleading() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_hyphen_leading() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_hyphen_nonleading() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn infostring_space() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/infostring-space.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/infostring-space.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn location_after_shebang() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/location-after-shebang.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/location-after-shebang.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn location_after_tokens() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/location-after-tokens.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/location-after-tokens.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn location_include_in_expr_ctxt() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn location_include_in_item_ctxt() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn location_proc_macro_observer() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.stdout"; |
| assert_success(fixture_path, assertion_path); |
| } |
| |
| #[cargo_test(nightly, reason = "-Zscript is unstable")] |
| #[rustfmt::skip] // code-generated |
| fn multifrontmatter() { |
| let fixture_path = "tests/testsuite/script/rustc_fixtures/multifrontmatter.rs"; |
| let assertion_path = "tests/testsuite/script/rustc_fixtures/multifrontmatter.stderr"; |
| assert_failure(fixture_path, assertion_path); |
| } |