use async_trait::async_trait;
use std::fs;
use std::path::PathBuf;
use agent_ask::{
cid_of, pull_from_peer, verify_artifact, FetchResponse, Fetcher, Store,
};
use chrono::DateTime;
use serde_json::Value;
fn vectors_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("vectors")
}
#[test]
fn c1_roundtrip_vectors_all_verify() {
let dir = vectors_dir().join("C1-roundtrip");
let mut count = 0;
for entry in fs::read_dir(&dir).unwrap() {
let path = entry.unwrap().path();
if path.extension().and_then(|s| s.to_str()) != Some("json") {
continue;
}
let raw: Value = serde_json::from_slice(&fs::read(&path).unwrap()).unwrap();
let v = verify_artifact(&raw);
assert!(v.ok, "{}: {:?}", path.display(), v.errors);
count += 1;
}
assert!(count > 0);
}
#[test]
fn c2_tamper_vectors_all_fail() {
let dir = vectors_dir().join("C2-tamper");
let mut count = 0;
for entry in fs::read_dir(&dir).unwrap() {
let path = entry.unwrap().path();
if path.extension().and_then(|s| s.to_str()) != Some("json") {
continue;
}
let raw: Value = serde_json::from_slice(&fs::read(&path).unwrap()).unwrap();
let v = verify_artifact(&raw);
assert!(!v.ok, "{}: expected verification to fail", path.display());
count += 1;
}
assert!(count > 0);
}
struct StaticFetcher(String);
#[async_trait]
impl Fetcher for StaticFetcher {
async fn fetch(&self, _url: &str) -> Result<FetchResponse, agent_ask::Error> {
Ok(FetchResponse { status: 200, text: self.0.clone() })
}
}
#[tokio::test]
async fn c3_pull_import_byte_identical() {
let path = vectors_dir().join("C3-federation").join("feed.ndjson");
let feed = fs::read_to_string(&path).unwrap();
let expected: Vec<Value> = feed.split('\n')
.filter(|l| !l.is_empty())
.map(|l| serde_json::from_str(l).unwrap())
.collect();
let newest = expected.iter()
.max_by_key(|a| a["created_at"].as_str().unwrap_or("").to_string())
.unwrap();
let iso = newest["created_at"].as_str().unwrap();
let now = DateTime::parse_from_rfc3339(iso).unwrap().with_timezone(&chrono::Utc);
let store = Store::open(":memory:").unwrap();
let fetcher = StaticFetcher(feed);
let res = pull_from_peer("http://peer", &store, None, &fetcher, now).await.unwrap();
assert_eq!(res.count, expected.len(), "rejected: {:?}", res.reasons);
for art in &expected {
let cid = cid_of(art).unwrap();
assert!(store.has_artifact(&cid).unwrap(), "{cid} not ingested");
let got = store.get_artifact(&cid).unwrap().unwrap();
assert_eq!(got, *art, "byte mismatch for {cid}");
}
}