use crate::derivation::Derivation;
use crate::output::Output;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use test_case::test_case;
use test_generator::test_resources;
use tvix_store::nixpath::NixPath;
const RESOURCES_PATHS: &str = "src/tests/derivation_tests";
fn read_file(path: &str) -> String {
let path = Path::new(path);
let mut file = File::open(path).unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
return data;
}
#[test_resources("src/tests/derivation_tests/*.drv")]
fn check_serizaliation(path_to_drv_file: &str) {
let data = read_file(&format!("{}.json", path_to_drv_file));
let derivation: Derivation = serde_json::from_str(&data).expect("JSON was not well-formatted");
let mut serialized_derivation = String::new();
derivation.serialize(&mut serialized_derivation).unwrap();
let expected = read_file(path_to_drv_file);
assert_eq!(expected, serialized_derivation);
}
#[test_resources("src/tests/derivation_tests/*.drv")]
fn validate(path_to_drv_file: &str) {
let data = read_file(&format!("{}.json", path_to_drv_file));
let derivation: Derivation = serde_json::from_str(&data).expect("JSON was not well-formatted");
derivation
.validate()
.expect("derivation failed to validate")
}
#[test_resources("src/tests/derivation_tests/*.drv")]
fn check_to_string(path_to_drv_file: &str) {
let data = read_file(&format!("{}.json", path_to_drv_file));
let derivation: Derivation = serde_json::from_str(&data).expect("JSON was not well-formatted");
let expected = read_file(path_to_drv_file);
assert_eq!(expected, derivation.to_string());
}
#[test_case("bar","0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv"; "fixed_sha256")]
#[test_case("foo", "4wvvbi4jwn0prsdxb7vs673qa5h9gr7x-foo.drv"; "simple-sha256")]
#[test_case("bar", "ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv"; "fixed-sha1")]
#[test_case("foo", "ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv"; "simple-sha1")]
#[test_case("has-multi-out", "h32dahq0bx5rp1krcdx3a53asj21jvhk-has-multi-out.drv"; "multiple-outputs")]
#[test_case("structured-attrs", "9lj1lkjm2ag622mh4h9rpy6j607an8g2-structured-attrs.drv"; "structured-attrs")]
#[test_case("unicode", "52a9id8hx688hvlnz4d1n25ml1jdykz0-unicode.drv"; "unicode")]
fn derivation_path(name: &str, expected_path: &str) {
let data = read_file(&format!("{}/{}.json", RESOURCES_PATHS, expected_path));
let derivation: Derivation = serde_json::from_str(&data).expect("JSON was not well-formatted");
assert_eq!(
derivation.calculate_derivation_path(name).unwrap(),
NixPath::from_string(expected_path).unwrap()
);
}
/// This trims all outputs from a Derivation struct,
/// by setting outputs[$outputName].path and environment[$outputName] to the empty string.
fn derivation_with_trimmed_outputs(derivation: &Derivation) -> Derivation {
let mut trimmed_env = derivation.environment.clone();
let mut trimmed_outputs = derivation.outputs.clone();
for (output_name, output) in &derivation.outputs {
trimmed_env.insert(output_name.clone(), "".to_string());
assert!(trimmed_outputs.contains_key(output_name));
trimmed_outputs.insert(
output_name.to_string(),
Output {
path: "".to_string(),
..output.clone()
},
);
}
// replace environment and outputs with the trimmed variants
Derivation {
environment: trimmed_env,
outputs: trimmed_outputs,
..derivation.clone()
}
}
#[test_case("0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv", "724f3e3634fce4cbbbd3483287b8798588e80280660b9a63fd13a1bc90485b33"; "fixed_sha256")]
#[test_case("ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv", "c79aebd0ce3269393d4a1fde2cbd1d975d879b40f0bf40a48f550edc107fd5df";"fixed-sha1")]
fn replacement_drv_path(drv_path: &str, expected_replacement_str: &str) {
// read in the fixture
let data = read_file(&format!("{}/{}.json", RESOURCES_PATHS, drv_path));
let drv: Derivation = serde_json::from_str(&data).expect("must deserialize");
let drv_replacement_str = drv.calculate_drv_replacement_str(|_| panic!("must not be called"));
assert_eq!(expected_replacement_str, drv_replacement_str);
}
#[test_case("bar","0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv"; "fixed_sha256")]
#[test_case("foo", "4wvvbi4jwn0prsdxb7vs673qa5h9gr7x-foo.drv"; "simple-sha256")]
#[test_case("bar", "ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv"; "fixed-sha1")]
#[test_case("foo", "ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv"; "simple-sha1")]
#[test_case("has-multi-out", "h32dahq0bx5rp1krcdx3a53asj21jvhk-has-multi-out.drv"; "multiple-outputs")]
#[test_case("structured-attrs", "9lj1lkjm2ag622mh4h9rpy6j607an8g2-structured-attrs.drv"; "structured-attrs")]
#[test_case("unicode", "52a9id8hx688hvlnz4d1n25ml1jdykz0-unicode.drv"; "unicode")]
fn output_paths(name: &str, drv_path: &str) {
// read in the fixture
let data = read_file(&format!("{}/{}.json", RESOURCES_PATHS, drv_path));
let expected_derivation: Derivation = serde_json::from_str(&data).expect("must deserialize");
let mut derivation = derivation_with_trimmed_outputs(&expected_derivation);
// calculate the drv replacement string.
// We don't expect the lookup function to be called for most derivations.
let replacement_str = derivation.calculate_drv_replacement_str(|drv_name| {
// 4wvvbi4jwn0prsdxb7vs673qa5h9gr7x-foo.drv may lookup /nix/store/0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv
// ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv may lookup /nix/store/ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv
if name == "foo"
&& ((drv_path == "4wvvbi4jwn0prsdxb7vs673qa5h9gr7x-foo.drv"
&& drv_name == "/nix/store/0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv")
|| (drv_path == "ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv"
&& drv_name == "/nix/store/ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv"))
{
// do the lookup, by reading in the fixture of the requested
// drv_name, and calculating its drv replacement (on the non-stripped version)
// In a real-world scenario you would have already done this during construction.
let data = read_file(&format!(
"{}/{}.json",
RESOURCES_PATHS,
Path::new(drv_name).file_name().unwrap().to_string_lossy()
));
let drv: Derivation = serde_json::from_str(&data).expect("must deserialize");
// calculate replacement string. These don't trigger any subsequent requests, as they're both FOD.
drv.calculate_drv_replacement_str(|_| panic!("must not lookup"))
} else {
// we only expect this to be called in the "foo" testcase, for the "bar derivations"
panic!("may only be called for foo testcase on bar derivations");
}
});
// We need to calculate the replacement_str, as fixed-sha1 does use it.
derivation
.calculate_output_paths(&name, &replacement_str)
.unwrap();
// The derivation should now look like it was before
assert_eq!(expected_derivation, derivation);
}