use qualifier::annotation::{self, Annotation, AnnotationBody, Kind, Record};
use qualifier::compact::{self, filter_superseded};
use qualifier::qual_file::{self, QualFile};
use chrono::Utc;
use std::path::PathBuf;
fn make_att(subject: &str, kind: Kind, summary: &str) -> Annotation {
annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: subject.into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T10:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: summary.into(),
supersedes: None,
tags: vec![],
},
})
}
fn make_record(subject: &str, kind: Kind, summary: &str) -> Record {
Record::Annotation(Box::new(make_att(subject, kind, summary)))
}
#[test]
fn test_golden_annotation_id() {
let att = annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "src/parser.rs".into(),
issuer: "mailto:alice@example.com".into(),
issuer_type: None,
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T10:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Concern,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "Panics on malformed input".into(),
supersedes: None,
tags: vec![],
},
});
assert_eq!(annotation::generate_id(&att), att.id);
assert_eq!(att.id.len(), 64);
}
#[test]
fn test_golden_epoch_id() {
use qualifier::annotation::{self, Epoch, EpochBody, IssuerType};
let epoch = annotation::finalize_epoch(Epoch {
metabox: "1".into(),
record_type: "epoch".into(),
subject: "src/parser.rs".into(),
issuer: "urn:qualifier:compact".into(),
issuer_type: Some(IssuerType::Tool),
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-25T12:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: EpochBody {
refs: vec!["aaa".into(), "bbb".into(), "ccc".into()],
span: None,
summary: "Compacted from 3 annotations".into(),
},
});
assert_eq!(epoch.id.len(), 64);
}
#[test]
fn test_golden_dependency_id() {
use qualifier::annotation::{self, DependencyBody, DependencyRecord};
let dep = annotation::finalize_record(Record::Dependency(DependencyRecord {
metabox: "1".into(),
record_type: "dependency".into(),
subject: "bin/server".into(),
issuer: "https://build.example.com".into(),
issuer_type: None,
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-25T10:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: DependencyBody {
depends_on: vec!["lib/auth".into(), "lib/http".into()],
},
}));
assert_eq!(
dep.id(),
"dc97e9f3fa9b8d1f0c70e1a8aae30ddf305dba6f6c1d9720ef7e9d5db57eacfe",
"Golden dependency ID changed! Canonical form or hashing is broken."
);
}
#[test]
fn test_annotation_lifecycle_write_parse_roundtrip() {
let dir = tempfile::tempdir().unwrap();
let qual_path = dir.path().join("src/parser.rs.qual");
std::fs::create_dir_all(qual_path.parent().unwrap()).unwrap();
let r1 = make_record("src/parser.rs", Kind::Concern, "Panics on bad input");
let r2 = make_record("src/parser.rs", Kind::Praise, "Good test coverage");
qual_file::append(&qual_path, &r1).unwrap();
qual_file::append(&qual_path, &r2).unwrap();
let qf = qual_file::parse(&qual_path).unwrap();
assert_eq!(qf.records.len(), 2);
assert_eq!(qf.records[0].id(), r1.id());
assert_eq!(qf.records[1].id(), r2.id());
let att1 = r1.as_annotation().unwrap();
let att2 = r2.as_annotation().unwrap();
assert_eq!(annotation::generate_id(att1), att1.id);
assert_eq!(annotation::generate_id(att2), att2.id);
}
#[test]
fn test_annotation_id_is_content_addressed() {
let att1 = make_att("foo.rs", Kind::Pass, "ok");
let att2 = make_att("foo.rs", Kind::Pass, "ok");
assert_eq!(att1.id, att2.id);
let att3 = make_att("foo.rs", Kind::Pass, "ok with extra commentary");
assert_ne!(att1.id, att3.id);
}
#[test]
fn test_compaction_prune_removes_superseded() {
let original = make_record("mod.rs", Kind::Concern, "bad");
let fix = Record::Annotation(Box::new(annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "mod.rs".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T11:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Pass,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "fixed".into(),
supersedes: Some(original.id().to_string()),
tags: vec![],
},
})));
let extra = make_record("mod.rs", Kind::Praise, "nice");
let qf = QualFile {
path: PathBuf::from("mod.rs.qual"),
subject: "mod.rs".into(),
records: vec![original, fix.clone(), extra.clone()],
};
let (pruned, _) = compact::prune(&qf);
assert_eq!(pruned.records.len(), 2);
assert!(pruned.records.iter().any(|r| r.id() == fix.id()));
assert!(pruned.records.iter().any(|r| r.id() == extra.id()));
let (snapped, _) = compact::snapshot(&qf);
assert_eq!(snapped.records.len(), 1);
assert!(snapped.records[0].as_epoch().is_some());
}
#[test]
fn test_discovery_walks_tree() {
let dir = tempfile::tempdir().unwrap();
let paths = [
"src/lib.rs.qual",
"src/parser.rs.qual",
"src/util/helpers.rs.qual",
];
for p in &paths {
let full = dir.path().join(p);
std::fs::create_dir_all(full.parent().unwrap()).unwrap();
std::fs::write(&full, "").unwrap();
}
let hidden = dir.path().join(".git/objects/foo.qual");
std::fs::create_dir_all(hidden.parent().unwrap()).unwrap();
std::fs::write(&hidden, "").unwrap();
let found = qual_file::discover(dir.path(), true).unwrap();
assert_eq!(found.len(), 3);
let subjects: Vec<&str> = found.iter().map(|qf| qf.subject.as_str()).collect();
assert!(subjects.iter().any(|a| a.ends_with("src/lib.rs")));
assert!(subjects.iter().any(|a| a.ends_with("src/parser.rs")));
assert!(subjects.iter().any(|a| a.ends_with("src/util/helpers.rs")));
}
#[test]
fn test_supersession_cycle_detected() {
let now = Utc::now();
let a = Record::Annotation(Box::new(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "x".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: now,
id: "aaa".into(),
body: AnnotationBody {
detail: None,
kind: Kind::Pass,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "a".into(),
supersedes: Some("bbb".into()),
tags: vec![],
},
}));
let b = Record::Annotation(Box::new(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "x".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: now,
id: "bbb".into(),
body: AnnotationBody {
detail: None,
kind: Kind::Pass,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "b".into(),
supersedes: Some("aaa".into()),
tags: vec![],
},
}));
let result = annotation::check_supersession_cycles(&[a, b]);
assert!(result.is_err());
}
#[test]
fn test_cross_artifact_supersession_rejected() {
let a = make_record("foo.rs", Kind::Concern, "issue in foo");
let b = Record::Annotation(Box::new(annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "bar.rs".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T11:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Pass,
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "fix in bar".into(),
supersedes: Some(a.id().to_string()),
tags: vec![],
},
})));
let result = annotation::validate_supersession_targets(&[a, b]);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("cross-subject"));
}
#[test]
fn test_kind_typo_detected_in_validation() {
let att = annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "x.rs".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: None,
created_at: Utc::now(),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Custom("pss".into()),
r#ref: None,
references: None,
span: None,
suggested_fix: None,
summary: "oops".into(),
supersedes: None,
tags: vec![],
},
});
let errors = annotation::validate(&att);
assert!(
errors.iter().any(|e| e.contains("did you mean 'pass'")),
"expected typo warning, got: {:?}",
errors
);
}
#[test]
fn test_parse_qual_file_only_comments() {
let content = "// This is a comment\n// Another comment\n\n";
let records = qual_file::parse_str(content).unwrap();
assert!(records.is_empty());
}
#[test]
fn test_metabox_roundtrip() {
use qualifier::annotation::IssuerType;
let dir = tempfile::tempdir().unwrap();
let qual_path = dir.path().join("test.rs.qual");
let att = annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "test.rs".into(),
issuer: "mailto:alice@example.com".into(),
issuer_type: Some(IssuerType::Human),
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T10:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Praise,
r#ref: Some("git:3aba500".into()),
references: None,
span: None,
suggested_fix: None,
summary: "Great code".into(),
supersedes: None,
tags: vec!["quality".into()],
},
});
assert_eq!(att.metabox, "1");
qual_file::append(&qual_path, &Record::Annotation(Box::new(att.clone()))).unwrap();
let qf = qual_file::parse(&qual_path).unwrap();
assert_eq!(qf.records.len(), 1);
let parsed = qf.records[0].as_annotation().unwrap();
assert_eq!(parsed.metabox, "1");
assert_eq!(parsed.issuer_type, Some(IssuerType::Human));
assert_eq!(parsed.body.r#ref.as_deref(), Some("git:3aba500"));
assert_eq!(parsed.id, att.id);
}
#[test]
fn test_compact_snapshot_produces_epoch() {
use qualifier::annotation::IssuerType;
let records = vec![
make_record("src/a.rs", Kind::Praise, "good"),
make_record("src/a.rs", Kind::Concern, "meh"),
];
let qf = QualFile {
path: PathBuf::from("src/.qual"),
subject: "src/".into(),
records,
};
let (snapped, _) = compact::snapshot(&qf);
assert_eq!(snapped.records.len(), 1);
let epoch = snapped.records[0].as_epoch().unwrap();
assert_eq!(epoch.metabox, "1");
assert_eq!(epoch.issuer_type, Some(IssuerType::Tool));
assert_eq!(epoch.body.refs.len(), 2);
}
#[test]
fn test_supersession_filter() {
let original = make_record("mod.rs", Kind::Concern, "problem");
let replacement = Record::Annotation(Box::new(annotation::finalize(Annotation {
metabox: "1".into(),
record_type: "annotation".into(),
subject: "mod.rs".into(),
issuer: "mailto:test@test.com".into(),
issuer_type: Some(qualifier::annotation::IssuerType::Human),
created_at: chrono::DateTime::parse_from_rfc3339("2026-02-24T11:00:00Z")
.unwrap()
.with_timezone(&Utc),
id: String::new(),
body: AnnotationBody {
detail: None,
kind: Kind::Pass,
r#ref: Some("git:abc123".into()),
references: None,
span: None,
suggested_fix: None,
summary: "fixed it".into(),
supersedes: Some(original.id().to_string()),
tags: vec![],
},
})));
let all = vec![original.clone(), replacement.clone()];
let active = filter_superseded(&all);
assert_eq!(active.len(), 1);
assert_eq!(active[0].id(), replacement.id());
}