#![allow(
dead_code,
unused_imports,
unused_variables,
deprecated,
clippy::all,
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
unused_mut
)]
use assert_cmd::Command;
use std::fs;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
fn ggen() -> Command {
Command::cargo_bin("ggen").expect("ggen binary not found")
}
struct World {
home: TempDir,
project: TempDir,
registry: TempDir,
}
impl World {
fn new() -> Self {
let project = TempDir::new().expect("project tempdir");
fs::create_dir_all(project.path().join(".ggen")).expect("create .ggen");
World {
home: TempDir::new().expect("home tempdir"),
project,
registry: TempDir::new().expect("registry tempdir"),
}
}
fn project_path(&self) -> &Path {
self.project.path()
}
fn registry_pack_path(&self, id: &str) -> PathBuf {
self.registry.path().join(format!("{id}.toml"))
}
fn install_dir(&self, id: &str) -> PathBuf {
self.home.path().join(".ggen").join("packs").join(id)
}
fn lock_path(&self) -> PathBuf {
self.project.path().join(".ggen").join("packs.lock")
}
fn write_pack(&self, id: &str, version: &str) {
let toml = format!(
r#"[pack]
id = "{id}"
name = "Reverify Pack {id}"
version = "{version}"
description = "Real pack fixture for proof_digest_reverify_test"
category = "test"
author = "proof-test"
license = "MIT"
production_ready = true
packages = ["{id}-core"]
tags = ["proof", "test"]
keywords = ["{id}"]
"#
);
let path = self.registry_pack_path(id);
fs::write(&path, toml).expect("write pack toml");
assert!(path.exists(), "registry pack file must exist after write");
}
fn pack(&self) -> Command {
let mut cmd = ggen();
cmd.arg("pack")
.current_dir(self.project.path())
.env("HOME", self.home.path())
.env("GGEN_PACKS_DIR", self.registry.path())
.env(
"GGEN_PACK_CACHE_DIR",
self.home.path().join(".ggen").join("packs"),
);
cmd
}
fn sync(&self) -> Command {
let mut cmd = ggen();
cmd.arg("sync")
.current_dir(self.project.path())
.env("HOME", self.home.path())
.env("GGEN_PACKS_DIR", self.registry.path())
.env(
"GGEN_PACK_CACHE_DIR",
self.home.path().join(".ggen").join("packs"),
);
cmd
}
fn install(&self, id: &str, version: &str) {
self.write_pack(id, version);
self.pack().arg("add").arg(id).assert().success();
assert!(
self.lock_path().exists(),
"precondition: `pack add` must write .ggen/packs.lock"
);
assert!(
self.install_dir(id).exists(),
"precondition: `pack add` must create the install dir under $HOME"
);
}
}
fn combined_output(cmd: &mut Command) -> (Option<i32>, String) {
let output = cmd.assert().get_output().clone();
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
(output.status.code(), format!("{stdout}{stderr}"))
}
#[test]
fn test_sync_locked_passes_for_unmodified_pack() {
let world = World::new();
world.install("io.ggen.happy", "1.0.0");
let (_code, combined) =
combined_output(world.sync().arg("--locked").arg("--dry-run").arg("true"));
assert!(
!combined.contains("digest mismatch"),
"unmodified pack must NOT trip digest-mismatch re-verification; output: {combined}"
);
assert!(
!combined.contains("missing pack"),
"unmodified pack must NOT trip missing-pack re-verification; output: {combined}"
);
assert!(
!combined.contains("digest re-verification failed"),
"unmodified pack must pass --locked re-verification; output: {combined}"
);
}
#[test]
fn test_sync_locked_fails_on_digest_mismatch_after_mutation() {
let world = World::new();
world.install("io.ggen.drift", "1.0.0");
world.write_pack("io.ggen.drift", "2.0.0");
let (code, combined) =
combined_output(world.sync().arg("--locked").arg("--dry-run").arg("true"));
assert_ne!(
code,
Some(0),
"FAIL-OPEN DEFECT: `ggen sync --locked` must exit non-zero when a locked \
pack was mutated on disk. Got exit {code:?}, output: {combined}"
);
assert!(
combined.contains("digest mismatch"),
"error must reference 'digest mismatch'; output: {combined}"
);
assert!(
combined.contains("io.ggen.drift"),
"error must name the drifted pack; output: {combined}"
);
}
#[test]
fn test_sync_locked_fails_when_pack_definition_removed() {
let world = World::new();
world.install("io.ggen.gone", "1.0.0");
fs::remove_file(world.registry_pack_path("io.ggen.gone")).expect("remove registry pack toml");
assert!(!world.registry_pack_path("io.ggen.gone").exists());
let (code, combined) =
combined_output(world.sync().arg("--locked").arg("--dry-run").arg("true"));
assert_ne!(
code,
Some(0),
"FAIL-OPEN DEFECT: `ggen sync --locked` must exit non-zero when a locked \
pack's definition is missing on disk. Got exit {code:?}, output: {combined}"
);
assert!(
combined.contains("missing pack"),
"error must reference 'missing pack'; output: {combined}"
);
assert!(
combined.contains("io.ggen.gone"),
"error must name the missing pack; output: {combined}"
);
}