use super::tests::{syncer, write};
use super::*;
use flint_store::memory::MemoryStore;
use flint_store::RequestCounts;
use std::sync::Arc;
fn names(r: &barrier::BarrierReport) -> Vec<&'static str> {
r.steps.iter().map(|s| s.step).collect()
}
fn charged(r: &barrier::BarrierReport) -> RequestCounts {
let mut c = RequestCounts::default();
for s in &r.steps {
let q = s.requests.expect("the memory double counts requests");
c.get += q.get;
c.head += q.head;
c.put += q.put;
c.copy += q.copy;
c.delete += q.delete;
c.list += q.list;
c.multipart += q.multipart;
}
c
}
fn sent(before: RequestCounts, after: RequestCounts) -> RequestCounts {
RequestCounts {
get: after.get - before.get,
head: after.head - before.head,
put: after.put - before.put,
copy: after.copy - before.copy,
delete: after.delete - before.delete,
list: after.list - before.list,
multipart: after.multipart - before.multipart,
}
}
const COMMIT: [&str; 24] = [
"cell",
"rescope_replay",
"consume",
"baseline_load",
"walk",
"classify",
"intent",
"upload",
"claim",
"verify",
"load",
"fence",
"merge",
"cas",
"retire_set",
"surface",
"retire_ledger",
"reap",
"orphan_sweep",
"baseline",
"generation_sweep",
"chunk_sweep",
"free",
"release",
];
#[tokio::test]
async fn a_publishing_barrier_charges_every_request_to_one_of_its_steps() {
let store = Arc::new(MemoryStore::new());
let dir = tempfile::tempdir().unwrap();
let mut a = syncer(&store, dir.path()).await;
a.checkout().await.unwrap();
write(dir.path(), "a.txt", "v1");
write(dir.path(), "b.txt", "v1");
a.run_barrier().await.unwrap();
write(dir.path(), "a.txt", "v2, longer");
let before = store.request_counts().unwrap();
let started = std::time::Instant::now();
let r = a.run_barrier().await.unwrap();
let wall = started.elapsed().as_micros() as u64;
let after = store.request_counts().unwrap();
assert_eq!(r.uploaded, vec!["a.txt".to_string()]);
assert_eq!(names(&r), COMMIT.to_vec(), "{:#?}", r.steps);
assert_eq!(charged(&r), sent(before, after), "a request no step was charged for: {:#?}", r.steps);
let timed: u64 = r.steps.iter().map(|s| s.us).sum();
assert!(timed <= wall, "the steps ({timed} us) outlast the barrier ({wall} us)");
let step = |n: &str| r.steps.iter().find(|s| s.step == n).unwrap().requests.unwrap();
assert!(step("upload").put >= 1, "the one changed file's PUT is the upload step's");
assert_eq!(step("verify").head, 1, "the commit re-reads its one upload");
assert!(step("cas").put >= 1, "the pointer CAS is the cas step's");
assert!(step("reap").delete >= 1, "the replaced version is the reap step's DELETE");
}
#[tokio::test]
async fn a_barrier_with_nothing_to_publish_takes_no_step_of_the_commit_section() {
let store = Arc::new(MemoryStore::new());
let dir = tempfile::tempdir().unwrap();
let mut a = syncer(&store, dir.path()).await;
a.checkout().await.unwrap();
write(dir.path(), "a.txt", "v1");
a.run_barrier().await.unwrap();
let before = store.request_counts().unwrap();
let r = a.run_barrier().await.unwrap();
let after = store.request_counts().unwrap();
assert!(r.no_change);
assert_eq!(names(&r), vec!["cell", "rescope_replay", "consume", "baseline_load", "walk", "classify", "idle_check"]);
assert_eq!(charged(&r), sent(before, after), "{:#?}", r.steps);
}