89 lines
3.4 KiB
Rust
89 lines
3.4 KiB
Rust
//! Linked files changing while their document is open (`link_watch`): `links.updateChanged`,
|
|
//! and the background look following Preferences → File Handling → Update Links.
|
|
|
|
use serde_json::{Value, json};
|
|
|
|
use super::*;
|
|
use crate::tests_links::{BLUE, Folder, RED, centre_colour, place, png, session};
|
|
|
|
/// Write `bytes` to `path` so its modification time moves even on coarse file systems.
|
|
fn save(path: &str, bytes: &[u8]) {
|
|
std::thread::sleep(std::time::Duration::from_millis(30));
|
|
std::fs::write(path, bytes).unwrap();
|
|
}
|
|
|
|
fn colour(s: &Session) -> [u8; 3] {
|
|
centre_colour(&s.doc().unwrap().doc)
|
|
}
|
|
|
|
/// One background look, waited for.
|
|
fn look(s: &mut Session) -> Value {
|
|
s.start_link_scan();
|
|
let t0 = std::time::Instant::now();
|
|
loop {
|
|
if let Some(r) = s.poll_link_scan() {
|
|
return r.unwrap();
|
|
}
|
|
assert!(t0.elapsed().as_secs() < 10, "the look never finished");
|
|
std::thread::yield_now();
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn update_changed_reads_changed_files_again_once() {
|
|
let dir = Folder::new("watch-update");
|
|
let path = dir.file("art.png");
|
|
std::fs::write(&path, png(40, 40, RED)).unwrap();
|
|
let mut s = session();
|
|
let id = place(&mut s, &path);
|
|
// First look: remembered, nothing to read.
|
|
assert_eq!(s.execute("links.updateChanged", &json!({})).unwrap()["updated"], json!([]));
|
|
save(&path, &png(40, 40, BLUE));
|
|
assert_eq!(s.execute("links.updateChanged", &json!({})).unwrap()["updated"], json!([id.0]));
|
|
assert_eq!(colour(&s), BLUE);
|
|
// Undoing it is respected: the link stays modified until the file changes again.
|
|
s.execute("edit.undo", &json!({})).unwrap();
|
|
assert_eq!(colour(&s), RED);
|
|
assert_eq!(s.execute("links.updateChanged", &json!({})).unwrap()["updated"], json!([]));
|
|
assert_eq!(s.execute("links.check", &json!({})).unwrap()["modified"], 1);
|
|
}
|
|
|
|
#[test]
|
|
fn a_background_look_follows_update_links() {
|
|
for (mode, key) in [("automatically", "updated"), ("askWhenModified", "ask"), ("manually", "modified")] {
|
|
let dir = Folder::new(&format!("watch-{mode}"));
|
|
let path = dir.file("art.png");
|
|
std::fs::write(&path, png(40, 40, RED)).unwrap();
|
|
let mut s = session();
|
|
s.prefs.update_links = mode.into();
|
|
let id = place(&mut s, &path);
|
|
assert_eq!(look(&mut s), json!({"updated": [], "ask": [], "modified": []}), "{mode}");
|
|
save(&path, &png(40, 40, BLUE));
|
|
let r = look(&mut s);
|
|
assert_eq!(r[key], json!([id.0]), "{mode}: {r}");
|
|
assert_eq!(colour(&s), if mode == "automatically" { BLUE } else { RED }, "{mode}");
|
|
// Acted on once: the next look finds nothing new.
|
|
assert_eq!(look(&mut s), json!({"updated": [], "ask": [], "modified": []}), "{mode}");
|
|
assert!(s.link_scan.is_none());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn a_file_still_being_written_is_tried_again() {
|
|
let dir = Folder::new("watch-partial");
|
|
let path = dir.file("art.png");
|
|
std::fs::write(&path, png(40, 40, RED)).unwrap();
|
|
let mut s = session();
|
|
s.prefs.update_links = "automatically".into();
|
|
let id = place(&mut s, &path);
|
|
look(&mut s);
|
|
// Another app has only written the start of the file so far.
|
|
let full = png(40, 40, BLUE);
|
|
save(&path, &full[..16]);
|
|
assert_eq!(look(&mut s)["updated"], json!([]));
|
|
assert_eq!(colour(&s), RED, "the last good pixels stay");
|
|
save(&path, &full);
|
|
assert_eq!(look(&mut s)["updated"], json!([id.0]));
|
|
assert_eq!(colour(&s), BLUE);
|
|
}
|