//! The host API shares the journal that tags world mutations. use sausage::{ api::{Api, handle}, cred::{Caller, Cred}, process::{Runtime, default_script}, world::World, }; use sausage_vfs::{Open, journal::Tag}; use std::sync::Arc; #[tokio::test] async fn list_show_and_restore() { let temp = tempfile::tempdir().unwrap(); let world = World::open(temp.path()).unwrap(); let journal = world.root.journal().unwrap(); let tag = Tag { id: "A".into(), pid: 1, program: "/bin/test".into(), conversations: vec!["c".into()], }; journal .layer(tag) .open( "/file", Open { create: true, write: true, ..Default::default() }, ) .await .unwrap() .write(0, b"data".to_vec()) .await .unwrap(); let cred = Arc::new(Cred::open(&world.host_dir).unwrap()); let api = Arc::new( Api::open( cred.clone(), &world.host_dir, "localhost", "http://localhost:8081", ) .unwrap(), ); let _runtime = Runtime::new_with_hooks(world, cred, default_script(), Some(api.clone())).unwrap(); let request = |method, path, body: &'static str| { http::Request::builder() .method(method) .uri(path) .body(bytes::Bytes::from_static(body.as_bytes())) .unwrap() }; let caller = || Caller { pid: 1, program: "/bin/undo".into(), conversations: vec!["c".into()], }; let response = handle(&api, caller(), request("GET", "/undo?conversation=c", "")).await; assert_eq!(response.status(), 200); let entries: serde_json::Value = serde_json::from_slice(response.body()).unwrap(); assert_eq!(entries[0]["tag"], "A"); let response = handle(&api, caller(), request("GET", "/undo/show?tag=A", "")).await; assert_eq!(response.status(), 200); let snapshots: serde_json::Value = serde_json::from_slice(response.body()).unwrap(); assert_eq!(snapshots[0]["path"], "/file"); let response = handle(&api, caller(), request("POST", "/undo", r#"{"tag":"A"}"#)).await; assert_eq!(response.status(), 200); assert!(!temp.path().join("world/file").exists()); let response = handle(&api, caller(), request("POST", "/undo", "{}")).await; assert_eq!(response.status(), 400); }