| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use rust_gtest_interop::prelude::*; |
| |
| use gnrt_lib::gn::*; |
| |
| use std::borrow::Borrow; |
| |
| use gnrt_lib::crates::Epoch; |
| |
| #[gtest(GnTest, FormatBuildFile)] |
| fn test() { |
| // A simple lib rule. |
| let build_file = BuildFile { |
| rules: vec![( |
| "lib".to_string(), |
| Rule { |
| crate_name: Some("foo".to_string()), |
| epoch: Some(Epoch::Major(1)), |
| crate_type: "rlib".to_string(), |
| testonly: false, |
| crate_root: "crate/src/lib.rs".to_string(), |
| edition: "2021".to_string(), |
| cargo_pkg_version: "1.2.3".to_string(), |
| cargo_pkg_authors: Some("Somebody <somebody@foo.org>".to_string()), |
| cargo_pkg_name: "foo".to_string(), |
| cargo_pkg_description: Some("A generic framework for foo\nNewline\"".to_string()), |
| deps: vec![RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/bar:lib".to_string(), |
| )], |
| // dev_deps should *not* show up in the output currently. |
| dev_deps: vec![RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/rstest:lib".to_string(), |
| )], |
| build_deps: vec![RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/bindgen:lib".to_string(), |
| )], |
| features: vec!["std".to_string()], |
| build_root: Some("crate/build.rs".to_string()), |
| build_script_outputs: vec!["binding.rs".to_string()], |
| public_visibility: true, |
| }, |
| )], |
| }; |
| expect_eq_diff( |
| format!("{}", build_file.display()), |
| r#"# Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/rust/cargo_crate.gni") |
| |
| cargo_crate("lib") { |
| crate_name = "foo" |
| epoch = "1" |
| crate_type = "rlib" |
| crate_root = "crate/src/lib.rs" |
| |
| # Unit tests skipped. Generate with --with-tests to include them. |
| build_native_rust_unit_tests = false |
| sources = [ "crate/src/lib.rs" ] |
| edition = "2021" |
| cargo_pkg_version = "1.2.3" |
| cargo_pkg_authors = "Somebody <somebody@foo.org>" |
| cargo_pkg_name = "foo" |
| cargo_pkg_description = "A generic framework for fooNewline'" |
| deps = [ |
| "//third_party/rust/bar:lib", |
| ] |
| build_deps = [ |
| "//third_party/rust/bindgen:lib", |
| ] |
| features = [ |
| "std", |
| ] |
| build_root = "crate/build.rs" |
| build_sources = [ "crate/build.rs" ] |
| build_script_outputs = [ |
| "binding.rs", |
| ] |
| } |
| "#, |
| ); |
| |
| // Third-party only visibility, two rules in a file. |
| let build_file = BuildFile { |
| rules: vec![ |
| ( |
| "lib".to_string(), |
| Rule { |
| crate_name: Some("foo".to_string()), |
| epoch: Some(Epoch::Major(1)), |
| crate_type: "rlib".to_string(), |
| testonly: false, |
| crate_root: "crate/src/lib.rs".to_string(), |
| edition: "2021".to_string(), |
| cargo_pkg_version: "1.2.3".to_string(), |
| cargo_pkg_authors: None, |
| cargo_pkg_name: "foo".to_string(), |
| cargo_pkg_description: None, |
| deps: vec![], |
| // dev_deps should *not* show up in the output currently. |
| dev_deps: vec![], |
| build_deps: vec![], |
| features: vec![], |
| build_root: None, |
| build_script_outputs: vec![], |
| public_visibility: false, |
| }, |
| ), |
| ( |
| "test_support".to_string(), |
| Rule { |
| crate_name: Some("foo".to_string()), |
| epoch: Some(Epoch::Major(1)), |
| crate_type: "rlib".to_string(), |
| testonly: true, |
| crate_root: "crate/src/lib.rs".to_string(), |
| edition: "2021".to_string(), |
| cargo_pkg_version: "1.2.3".to_string(), |
| cargo_pkg_authors: None, |
| cargo_pkg_name: "foo".to_string(), |
| cargo_pkg_description: None, |
| deps: vec![], |
| // dev_deps should *not* show up in the output currently. |
| dev_deps: vec![], |
| build_deps: vec![], |
| features: vec![], |
| build_root: None, |
| build_script_outputs: vec![], |
| public_visibility: true, |
| }, |
| ), |
| ], |
| }; |
| expect_eq_diff( |
| format!("{}", build_file.display()), |
| r#"# Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/rust/cargo_crate.gni") |
| |
| cargo_crate("lib") { |
| crate_name = "foo" |
| epoch = "1" |
| crate_type = "rlib" |
| |
| # Only for usage from third-party crates. Add the crate to |
| # third_party.toml to use it from first-party code. |
| visibility = [ "//third_party/rust/*" ] |
| crate_root = "crate/src/lib.rs" |
| |
| # Unit tests skipped. Generate with --with-tests to include them. |
| build_native_rust_unit_tests = false |
| sources = [ "crate/src/lib.rs" ] |
| edition = "2021" |
| cargo_pkg_version = "1.2.3" |
| cargo_pkg_name = "foo" |
| } |
| cargo_crate("test_support") { |
| crate_name = "foo" |
| epoch = "1" |
| crate_type = "rlib" |
| testonly = true |
| crate_root = "crate/src/lib.rs" |
| |
| # Unit tests skipped. Generate with --with-tests to include them. |
| build_native_rust_unit_tests = false |
| sources = [ "crate/src/lib.rs" ] |
| edition = "2021" |
| cargo_pkg_version = "1.2.3" |
| cargo_pkg_name = "foo" |
| } |
| "#, |
| ); |
| |
| // A lib rule with conditional deps. |
| let build_file = BuildFile { |
| rules: vec![( |
| "lib".to_string(), |
| Rule { |
| crate_name: Some("foo".to_string()), |
| epoch: Some(Epoch::Major(1)), |
| crate_type: "rlib".to_string(), |
| testonly: false, |
| crate_root: "crate/src/lib.rs".to_string(), |
| edition: "2021".to_string(), |
| cargo_pkg_version: "1.2.3".to_string(), |
| cargo_pkg_authors: None, |
| cargo_pkg_name: "foo".to_string(), |
| cargo_pkg_description: None, |
| deps: vec![ |
| RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/bar:lib".to_string(), |
| ), |
| RuleDep::construct_for_testing( |
| Condition::If("foo".to_string()), |
| "//third_party/rust/dep1:lib".to_string(), |
| ), |
| RuleDep::construct_for_testing( |
| Condition::If("foo".to_string()), |
| "//third_party/rust/dep2:lib".to_string(), |
| ), |
| RuleDep::construct_for_testing( |
| Condition::If("bar".to_string()), |
| "//third_party/rust/dep3:lib".to_string(), |
| ), |
| ], |
| // dev_deps should *not* show up in the output currently. |
| dev_deps: vec![RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/rstest:lib".to_string(), |
| )], |
| build_deps: vec![RuleDep::construct_for_testing( |
| Condition::Always, |
| "//third_party/rust/bindgen:lib".to_string(), |
| )], |
| features: vec!["std".to_string()], |
| build_root: Some("crate/build.rs".to_string()), |
| build_script_outputs: vec!["binding.rs".to_string()], |
| public_visibility: true, |
| }, |
| )], |
| }; |
| expect_eq_diff( |
| format!("{}", build_file.display()), |
| r#"# Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/rust/cargo_crate.gni") |
| |
| cargo_crate("lib") { |
| crate_name = "foo" |
| epoch = "1" |
| crate_type = "rlib" |
| crate_root = "crate/src/lib.rs" |
| |
| # Unit tests skipped. Generate with --with-tests to include them. |
| build_native_rust_unit_tests = false |
| sources = [ "crate/src/lib.rs" ] |
| edition = "2021" |
| cargo_pkg_version = "1.2.3" |
| cargo_pkg_name = "foo" |
| deps = [ |
| "//third_party/rust/bar:lib", |
| ] |
| if (bar) { |
| deps += [ |
| "//third_party/rust/dep3:lib", |
| ] |
| } |
| if (foo) { |
| deps += [ |
| "//third_party/rust/dep1:lib", |
| "//third_party/rust/dep2:lib", |
| ] |
| } |
| build_deps = [ |
| "//third_party/rust/bindgen:lib", |
| ] |
| features = [ |
| "std", |
| ] |
| build_root = "crate/build.rs" |
| build_sources = [ "crate/build.rs" ] |
| build_script_outputs = [ |
| "binding.rs", |
| ] |
| } |
| "#, |
| ); |
| } |
| |
| /// Expect two strings are equal, printing a human-readable diff when they're |
| /// different. Logs a gtest failure if they're not equal. |
| fn expect_eq_diff<T: Borrow<str>, U: Borrow<str>>(actual: T, expected: U) { |
| let actual = actual.borrow(); |
| let expected = expected.borrow(); |
| |
| expect_eq!(actual, expected); |
| |
| // Do not invoke `diff` if they're equal. |
| if actual == expected { |
| return; |
| } |
| |
| use std::io::BufWriter; |
| use std::io::Write; |
| use std::process::*; |
| |
| // Closure to invoke diff on the inputs. This is wrapped in a closure so |
| // that we can fail softly if `diff` could not be run. |
| let inner = || { |
| // One of the inputs must be a temporary file since we don't have a way |
| // to pass two inputs through pipes. |
| let expected_file = tempfile::NamedTempFile::new()?; |
| let expected_file_path = expected_file.path().to_string_lossy().into_owned(); |
| write!(BufWriter::new(&expected_file), "{expected}")?; |
| |
| let mut diff = Command::new("diff") |
| .args(["-U", "3", "--color=auto", &expected_file_path, "-"]) |
| .stdin(Stdio::piped()) |
| .spawn()?; |
| |
| // Write the second input to `diff`'s stdin then wait for the result. |
| let stdin = diff.stdin.take().unwrap(); |
| write!(BufWriter::new(stdin), "{actual}")?; |
| diff.wait() |
| }; |
| |
| // Print warning message if running `diff` failed, but don't panic. The test |
| // already failed, we just don't get a pretty failure message. |
| match inner() { |
| Ok(exit_status) => { |
| if !exit_status.success() { |
| eprintln!("diff failed: {exit_status}"); |
| } |
| } |
| Err(err) => eprintln!("could not run diff: {err}"), |
| } |
| } |
| |
| #[gtest(GnTest, PlatformToCondition)] |
| fn test() { |
| use cargo_platform::CfgExpr; |
| use gnrt_lib::platforms::{Platform, PlatformSet}; |
| use std::convert::From; |
| use std::str::FromStr; |
| |
| // Try an unconditional filter. |
| expect_eq!(Condition::from(PlatformSet::one(None)), Condition::Always); |
| |
| // Try a target triple. |
| expect_eq!( |
| Condition::from(PlatformSet::one(Some(Platform::Name( |
| "x86_64-pc-windows-msvc".to_string() |
| )))) |
| .get_if() |
| .unwrap(), |
| "(is_win && target_cpu == \"x64\")" |
| ); |
| |
| // Try a cfg expression. |
| expect_eq!( |
| Condition::from(PlatformSet::one(Some(Platform::Cfg( |
| CfgExpr::from_str("any(windows, target_os = \"android\")").unwrap() |
| )))) |
| .get_if() |
| .unwrap(), |
| "((is_win) || (is_android))" |
| ); |
| |
| // Try a PlatformSet with multiple filters. |
| let mut platform_set = PlatformSet::empty(); |
| platform_set.add(Some(Platform::Name("armv7-linux-android".to_string()))); |
| platform_set.add(Some(Platform::Cfg(CfgExpr::from_str("windows").unwrap()))); |
| expect_eq!( |
| Condition::from(platform_set).get_if().unwrap(), |
| "(is_android && target_cpu == \"arm\") || (is_win)" |
| ); |
| } |
| |
| #[gtest(GnTest, StringEscaping)] |
| fn test() { |
| fn escaped(s: &str) -> String { |
| let mut out = String::new(); |
| write_str_escaped_for_testing(&mut out, s).unwrap(); |
| out |
| } |
| |
| expect_eq!("foo bar", escaped("foo bar")); |
| expect_eq!("foobar", escaped("foo\nbar")); |
| expect_eq!(r#"foo 'bar'"#, escaped(r#"foo "bar""#)); |
| expect_eq!("foo 'bar'", escaped("foo 'bar'")); |
| } |