Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,333 @@
|
||||
//! Go 模块协议验收只使用拥有的传输和临时摘要缓存。
|
||||
|
||||
use super::*;
|
||||
mod fixture;
|
||||
mod proofs;
|
||||
|
||||
#[test]
|
||||
fn independent_worker_graphs_merge_without_erasing_previous_modules() {
|
||||
let mut registry = fixture::graph();
|
||||
registry.module(
|
||||
"example.com/z",
|
||||
"1.0.0",
|
||||
"module example.com/z\nrequire example.com/b v1.0.0\n",
|
||||
);
|
||||
registry.seal();
|
||||
let cache = fixture::Cache::default();
|
||||
let mut lock = Lock::new(vec![]);
|
||||
for root in ["go:example.com/a@1.0.0", "go:example.com/z@1.0.0"] {
|
||||
resolve_with(
|
||||
&[root.parse().unwrap()],
|
||||
BuildTarget::host().unwrap(),
|
||||
&fixture::runtime(),
|
||||
®istry,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
assert_eq!(lock.libs.len(), 5);
|
||||
assert_eq!(
|
||||
lock.libs
|
||||
.iter()
|
||||
.filter(|lib| lib.spec.name == "example.com/b")
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
validate_with(&lock, &fixture::verifier()).unwrap();
|
||||
for (name, version) in [("a", "1.2.0"), ("z", "1.0.0")] {
|
||||
let closure = selected(
|
||||
&lock.libs,
|
||||
&[format!("go:example.com/{name}@1.0.0").parse().unwrap()],
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
closure
|
||||
.iter()
|
||||
.find(|lib| lib.spec.name == "example.com/b")
|
||||
.unwrap()
|
||||
.spec
|
||||
.version,
|
||||
version
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolves_authenticated_mvs_graph_and_replays_locked_hashes() {
|
||||
let registry = fixture::graph();
|
||||
let cache = fixture::Cache::default();
|
||||
let mut lock = Lock::new(vec![]);
|
||||
let runtime = fixture::runtime();
|
||||
resolve_with(
|
||||
&["go:example.com/a@1.0.0".parse().unwrap()],
|
||||
BuildTarget::host().unwrap(),
|
||||
&runtime,
|
||||
®istry,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(lock.libs.len(), 4);
|
||||
assert_eq!(
|
||||
selected(&lock.libs, &["go:example.com/a@1.0.0".parse().unwrap()])
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|lib| lib.spec.name == "example.com/b")
|
||||
.unwrap()
|
||||
.spec
|
||||
.version,
|
||||
"1.2.0"
|
||||
);
|
||||
let records = evidence(&lock).unwrap();
|
||||
assert!(
|
||||
records[0]
|
||||
.records
|
||||
.iter()
|
||||
.any(|record| record.module == "example.com/b" && record.version == "1.0.0")
|
||||
);
|
||||
let checked = validate_with(&lock, &fixture::verifier()).unwrap();
|
||||
for lib in &lock.libs {
|
||||
let artifact = &lib.artifacts[0];
|
||||
let bytes = cache
|
||||
.get(&artifact.sha256, artifact.bytes)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
checked
|
||||
.verify_zip(&lib.spec.name, &lib.spec.version, &bytes)
|
||||
.unwrap();
|
||||
assert!(
|
||||
checked
|
||||
.verify_zip(&lib.spec.name, &lib.spec.version, &bytes[..bytes.len() / 2])
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
validate_lock(&lock).is_err(),
|
||||
"fixture signing key must never become a product trust root"
|
||||
);
|
||||
lock.libs[0].dependencies.clear();
|
||||
assert!(validate_with(&lock, &fixture::verifier()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mvs_keeps_requirements_from_unselected_versions() {
|
||||
let mut registry = fixture::Registry::default();
|
||||
for (name, version, requires) in [
|
||||
(
|
||||
"a",
|
||||
"1.0.0",
|
||||
"require example.com/b v1.0.0\nrequire example.com/c v1.0.0\n",
|
||||
),
|
||||
("b", "1.0.0", "require example.com/d v1.2.0\n"),
|
||||
("b", "1.1.0", "require example.com/d v1.0.0\n"),
|
||||
(
|
||||
"c",
|
||||
"1.0.0",
|
||||
"require example.com/b v1.1.0\nrequire example.com/d v1.0.0\n",
|
||||
),
|
||||
("d", "1.0.0", ""),
|
||||
("d", "1.2.0", ""),
|
||||
] {
|
||||
registry.module(
|
||||
&format!("example.com/{name}"),
|
||||
version,
|
||||
&format!("module example.com/{name}\ngo 1.16\n{requires}"),
|
||||
);
|
||||
}
|
||||
registry.seal();
|
||||
let roots = ["go:example.com/a@1.0.0".parse().unwrap()];
|
||||
let mut lock = Lock::new(vec![]);
|
||||
resolve_with(
|
||||
&roots,
|
||||
BuildTarget::host().unwrap(),
|
||||
&fixture::runtime(),
|
||||
®istry,
|
||||
&fixture::Cache::default(),
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(lock.libs.len(), 6);
|
||||
let versions = selected(&lock.libs, &roots)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|lib| (lib.spec.name.as_str(), lib.spec.version.as_str()))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
assert_eq!(versions["example.com/b"], "1.1.0");
|
||||
assert_eq!(versions["example.com/d"], "1.2.0");
|
||||
let older = lock
|
||||
.libs
|
||||
.iter_mut()
|
||||
.find(|lib| lib.spec.name == "example.com/b" && lib.spec.version == "1.0.0")
|
||||
.unwrap();
|
||||
older.dependencies[0].spec.version = "1.0.0".into();
|
||||
assert!(validate_with(&lock, &fixture::verifier()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_module_keeps_distinct_worker_selections() {
|
||||
let mut registry = fixture::Registry::default();
|
||||
for (name, version, requires) in [
|
||||
("x", "1.0.0", "require example.com/d v1.0.0\n"),
|
||||
("y", "1.0.0", "require example.com/d v1.1.0\n"),
|
||||
("d", "1.0.0", ""),
|
||||
("d", "1.1.0", ""),
|
||||
] {
|
||||
registry.module(
|
||||
&format!("example.com/{name}"),
|
||||
version,
|
||||
&format!("module example.com/{name}\n{requires}"),
|
||||
);
|
||||
}
|
||||
registry.seal();
|
||||
let first = vec!["go:example.com/x@1.0.0".parse().unwrap()];
|
||||
let second = vec![
|
||||
"go:example.com/x@1.0.0".parse().unwrap(),
|
||||
"go:example.com/y@1.0.0".parse().unwrap(),
|
||||
];
|
||||
let mut lock = Lock::new(vec![]);
|
||||
for roots in [&first, &second] {
|
||||
resolve_with(
|
||||
roots,
|
||||
BuildTarget::host().unwrap(),
|
||||
&fixture::runtime(),
|
||||
®istry,
|
||||
&fixture::Cache::default(),
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let restored: Lock = serde_json::from_str(&lock.encode().unwrap()).unwrap();
|
||||
validate_with(&restored, &fixture::verifier()).unwrap();
|
||||
assert_eq!(restored.libs.len(), 4);
|
||||
for (roots, expected) in [(&first, "1.0.0"), (&second, "1.1.0")] {
|
||||
let closure = selected(&restored.libs, roots).unwrap();
|
||||
assert_eq!(
|
||||
closure
|
||||
.iter()
|
||||
.filter(|lib| lib.spec.name == "example.com/d")
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
closure
|
||||
.iter()
|
||||
.find(|lib| lib.spec.name == "example.com/d")
|
||||
.unwrap()
|
||||
.spec
|
||||
.version,
|
||||
expected
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejected_metadata_archive_or_rollback_never_publishes_lock() {
|
||||
let registry = fixture::graph();
|
||||
let runtime = fixture::runtime();
|
||||
for suffix in ["mod", "zip"] {
|
||||
let mut changed = registry.clone();
|
||||
changed
|
||||
.0
|
||||
.get_mut(&format!(
|
||||
"https://proxy.golang.org/example.com/b/@v/v1.0.0.{suffix}"
|
||||
))
|
||||
.unwrap()
|
||||
.extend(b"changed");
|
||||
if suffix == "zip" {
|
||||
changed.0.insert(
|
||||
"https://proxy.golang.org/example.com/b/@v/v1.2.0.zip".into(),
|
||||
fixture::zip("example.com/b", "1.2.0", "changed"),
|
||||
);
|
||||
}
|
||||
let cache = fixture::Cache::default();
|
||||
let mut lock = Lock::new(vec![]);
|
||||
let before = lock.encode().unwrap();
|
||||
assert!(
|
||||
resolve_with(
|
||||
&["go:example.com/a@1.0.0".parse().unwrap()],
|
||||
BuildTarget::host().unwrap(),
|
||||
&runtime,
|
||||
&changed,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier()
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
assert_eq!(lock.encode().unwrap(), before);
|
||||
assert!(cache.0.borrow().is_empty());
|
||||
}
|
||||
let cache = fixture::Cache::default();
|
||||
let mut lock = Lock::new(vec![]);
|
||||
let mut first = fixture::Registry::default();
|
||||
first.module("example.com/a", "1.0.0", "module example.com/a\n");
|
||||
first.seal();
|
||||
let roots = ["go:example.com/a@1.0.0".parse().unwrap()];
|
||||
resolve_with(
|
||||
&roots,
|
||||
BuildTarget::host().unwrap(),
|
||||
&runtime,
|
||||
&first,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut next = first.clone();
|
||||
next.module("example.com/z", "1.0.0", "module example.com/z\n");
|
||||
next.seal();
|
||||
resolve_with(
|
||||
&roots,
|
||||
BuildTarget::host().unwrap(),
|
||||
&runtime,
|
||||
&next,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(lock.go_sumdb.len(), 2);
|
||||
let before = lock.encode().unwrap();
|
||||
let error = resolve_with(
|
||||
&roots,
|
||||
BuildTarget::host().unwrap(),
|
||||
&runtime,
|
||||
&first,
|
||||
&cache,
|
||||
&mut lock,
|
||||
&fixture::verifier(),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(error.contains("rollback"), "{error}");
|
||||
assert_eq!(lock.encode().unwrap(), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_directives_check_identity_toolchain_and_requirements() {
|
||||
let source = b"module example.com/a\ngo 1.25\nrequire (\nexample.com/b v1.2.0 // indirect\n)\n";
|
||||
let parsed = module::requirements(source, "example.com/a", "1.25.0").unwrap();
|
||||
assert_eq!(parsed["example.com/b"], "1.2.0");
|
||||
assert!(module::requirements(source, "example.com/other", "1.25.0").is_err());
|
||||
assert!(module::requirements(source, "example.com/a", "1.24.0").is_err());
|
||||
for directive in [
|
||||
"replace example.com/b => ../local",
|
||||
"exclude example.com/b v1.0.0",
|
||||
"require (\nexample.com/b v1.0.0",
|
||||
"module example.com/a",
|
||||
] {
|
||||
assert!(
|
||||
module::requirements(
|
||||
format!("module example.com/a\n{directive}\n").as_bytes(),
|
||||
"example.com/a",
|
||||
"1.25.0"
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
assert_eq!(module::escape("example.com/Mixed"), "example.com/!mixed");
|
||||
}
|
||||
Reference in new issue
Block a user