Files
vectorcraft/crates/engine/tests/plugin_clear_cache.rs
dotCooCoo fe7b71b857 Plug-ins: the clear-cache test installs with request grants allowed
plugin.install refuses grant from a request unless the session was started
to allow it, so the test from main that installs with grant turns that on.
The install dialog's comment names OK's Sense::click.
2026-11-08 19:26:55 -08:00

67 lines
3.4 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! `plugin.clearCache` without an id empties the cache of every installed plug-in and leaves their
//! settings.
//!
//! A test binary of its own: installed plug-ins are process-wide, so clearing every plug-in's cache
//! in the engine's other tests would empty the caches those tests check.
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness).
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use serde_json::{Value, json};
use vectorcraft_engine::Session;
use vectorcraft_plugins::wat as tpl;
/// Sets "zoom" to "hello" and writes "hel" to the cache entry "tile".
const WRITES: &str = "(if (call $vc_settings_set (i32.const 0x2000) (i32.const 4) (i32.const 0x2100) (i32.const 5)) (then unreachable))
(if (call $vc_cache_write (i32.const 0x2004) (i32.const 4) (i32.const 0x2100) (i32.const 3)) (then unreachable))";
/// Traps unless "zoom" is "hello".
const READS: &str =
"(if (i32.ne (call $vc_settings_get (i32.const 0x2000) (i32.const 4) (i32.const 0x3000) (i32.const 16)) (i32.const 5)) (then unreachable))
(if (i32.ne (i32.load (i32.const 0x3000)) (i32.load (i32.const 0x2100))) (then unreachable))";
fn run(s: &mut Session, cmd: &str, p: Value) -> Value {
s.execute(cmd, &p).unwrap_or_else(|e| panic!("{cmd}: {e}"))
}
/// Installs a filter `id` of API level 2 that lists `settings` and `cache` and whose `vc_run` runs
/// `first`, in place of any module installed with its id (`replace: true`).
fn install_storing(s: &mut Session, id: &str, first: &str) {
let manifest = format!(r#"{{"id":"{id}","name":"Test {id}","kind":"filter","api":2,"permissions":["settings","cache"]}}"#);
let data = format!(r#"{} (data (i32.const 0x2000) "zoomtile") (data (i32.const 0x2100) "hello")"#, tpl::STORAGE_IMPORTS);
let wasm = wat::parse_str(tpl::with_imports(&manifest, &data, first, r#"{"objects":[]}"#)).unwrap();
let data = vectorcraft_format::base64_encode(&wasm);
run(s, "plugin.install", json!({"dataBase64": data, "grant": ["settings", "cache"], "replace": true}));
}
#[test]
fn clearing_every_cache_empties_each_plugins_cache_and_keeps_its_settings() {
let folder = std::env::temp_dir().join(format!("vc-plugin-clear-cache-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&folder);
std::fs::create_dir_all(&folder).unwrap();
let ids = ["test.clearcache.a", "test.clearcache.b"];
let mut s = Session::new();
s.allow_plugin_grants_from_requests();
s.execute("file.new", &json!({"width": 400, "height": 200})).unwrap();
s.attach_plugin_store(folder.clone());
for id in ids {
install_storing(&mut s, id, WRITES);
run(&mut s, "plugin.run", json!({"id": id, "ids": []}));
assert_eq!(run(&mut s, "plugin.info", json!({"id": id}))["cacheBytes"], json!(3));
}
assert_eq!(run(&mut s, "plugin.clearCache", json!({})), json!({"cleared": ids, "bytesFreed": 6}));
for id in ids {
assert_eq!(run(&mut s, "plugin.info", json!({"id": id}))["cacheBytes"], json!(0));
// The settings stay: a module that reads them runs.
install_storing(&mut s, id, READS);
run(&mut s, "plugin.run", json!({"id": id, "ids": []}));
}
// Nothing is left to clear.
assert_eq!(run(&mut s, "plugin.clearCache", json!({})), json!({"cleared": ids, "bytesFreed": 0}));
for id in ids {
run(&mut s, "plugin.remove", json!({"id": id}));
}
let _ = std::fs::remove_dir_all(&folder);
}