use super::fixture::{Fixture, app, write}; fn single() -> Fixture { let mut fixture = Fixture::new(&["numbers@^1"]); fixture.package( "numbers", &[], &[("module/numbers/value/app.dever", &app("input"))], ); fixture } #[test] fn lock_bytes_and_manifest_digests_are_verified_before_parsing_sources() { let mut fixture = single(); fixture.entries[0].manifest_sha256 = "0".repeat(64); fixture.lock(); fixture.reject("manifest changed"); let mut fixture = single(); fixture.assets.values_mut().next().unwrap()[0] ^= 1; fixture.reject("SHA-256 mismatch"); let mut fixture = single(); fixture.entries[0].bytes += 1; fixture.lock(); fixture.reject("size or SHA-256 mismatch"); let mut fixture = single(); fixture.assets.clear(); fixture.reject("asset is missing"); } #[test] fn lock_closure_rejects_stale_missing_cycles_and_orphan_entries() { let fixture = single(); write( &fixture.directory.0, "config/setting.json", r#"{"package":{"registry":"https://packages.example.test","use":["numbers@^2"]}}"#, ); fixture.reject("lock is stale"); let mut fixture = single(); fixture.entries[0] .dependencies .push(super::fixture::Dependency { name: "absent".into(), version: "1.0.0".into(), }); fixture.lock(); fixture.reject("missing or mismatched dependency"); let mut fixture = Fixture::new(&["numbers@*"]); fixture.package( "numbers", &[("units", "^1")], &[("module/numbers/value/app.dever", "unused")], ); fixture.package( "units", &[("numbers", "^1")], &[("module/units/value/app.dever", "unused")], ); fixture.reject("cyclic"); let mut fixture = single(); fixture.package("units", &[], &[("module/units/value/app.dever", "unused")]); fixture.reject("unreferenced"); } #[test] fn manifest_dependencies_must_match_locked_edges_and_ranges() { let mut fixture = Fixture::new(&["numbers@*"]); fixture.package( "numbers", &[("units", "^2")], &[("module/numbers/value/app.dever", "unused")], ); fixture.package("units", &[], &[("module/units/value/app.dever", "unused")]); fixture.reject("dependency units lock is stale"); let mut fixture = Fixture::new(&["numbers@*", "units@*"]); fixture.package( "numbers", &[("units", "*")], &[("module/numbers/value/app.dever", "unused")], ); fixture.package("units", &[], &[("module/units/value/app.dever", "unused")]); fixture.entries[0].dependencies.clear(); fixture.lock(); fixture.reject("dependencies changed"); } #[test] fn settings_and_lock_validation_never_fall_back_to_local_sources() { for (settings, needle) in [ ( r#"{"package":{"registry":"http://packages.test","use":[]}}"#, "HTTPS origin", ), ( r#"{"package":{"registry":"https://packages.test/path","use":[]}}"#, "HTTPS origin", ), ( r#"{"package":{"registry":"https://packages.test","use":["numbers@*","numbers@^1"]}}"#, "repeats", ), ( r#"{"package":{"registry":"https://packages.test","use":["dever@*"]}}"#, "nonreserved", ), ( r#"{"package":{"registry":"https://packages.test","use":["numbers@*"]},"package":null}"#, "invalid project configuration JSON", ), ( r#"{"lib":["npm:example@^1"]}"#, "npm requires an exact semantic version", ), ] { let fixture = single(); write(&fixture.directory.0, "config/setting.json", settings); fixture.reject(needle); } let fixture = single(); std::fs::remove_file(fixture.directory.0.join("dever.lock")).unwrap(); fixture.reject("require dever.lock"); let fixture = single(); let path = fixture.directory.0.join("dever.lock"); let lock = std::fs::read_to_string(&path).unwrap(); std::fs::write(&path, lock.trim_end()).unwrap(); fixture.reject("not canonical"); std::fs::write(&path, lock.replace("\"workers\": []", "\"workers\": [{}]")).unwrap(); fixture.reject("missing field `port`"); std::fs::remove_file(&path).unwrap(); std::os::unix::fs::symlink("config/setting.json", path).unwrap(); fixture.reject("project input links"); }