diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 091348a6b..c3eeaa277 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -347,6 +347,15 @@ pub(crate) fn adding_fonts() -> std::sync::MutexGuard<'static, ()> { FONTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner) } +/// Whether the tests that run every command with `{}` run command `id`. `plugin.clearCache` is +/// left out: without an id it empties the cache of every plug-in installed in the process, which +/// includes the caches that the plug-in storage tests check while they run. +/// `tests/plugin_clear_cache.rs` runs it with `{}` in a test binary of its own. +#[cfg(test)] +pub(crate) fn runs_with_empty_params(id: &str) -> bool { + id != "plugin.clearCache" +} + #[cfg(test)] use tests::{ adjust as tests_adjust, clip as tests_clip, colormgmt as tests_colormgmt, expand as tests_expand, large_edits as tests_large_edits, diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index ca0501c8f..2cf0031a3 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -3160,7 +3160,7 @@ fn every_command_survives_empty_params() { // The view toggles among them flip the process-wide proof view. let _proof_view = crate::tests_colormgmt::GLOBAL.lock().unwrap_or_else(|e| e.into_inner()); for sel in [false, true] { - for c in command_specs() { + for c in command_specs().iter().filter(|c| crate::runs_with_empty_params(c.id)) { let mut s = session(); let a = rect(&mut s, 0.0, 0.0, 10.0, 10.0); rect(&mut s, 20.0, 0.0, 10.0, 10.0); diff --git a/crates/engine/src/tests/dynamic_symbols.rs b/crates/engine/src/tests/dynamic_symbols.rs index f4ae97bb1..278d979ef 100644 --- a/crates/engine/src/tests/dynamic_symbols.rs +++ b/crates/engine/src/tests/dynamic_symbols.rs @@ -1309,7 +1309,7 @@ fn a_lent_selection_tool_moves_the_instance_of_a_picked_object() { #[test] fn read_only_commands_read_the_instance_of_a_picked_object() { let mut failures = Vec::new(); - for spec in crate::cmd::command_specs().iter().filter(|c| !c.journal) { + for spec in crate::cmd::command_specs().iter().filter(|c| !c.journal && crate::runs_with_empty_params(c.id)) { let mut s = session(); let inst = pair(&mut s, "dynamic"); s.execute("symbol.instance.selectPart", &json!({"id": inst.0, "path": [1]})).unwrap(); diff --git a/crates/engine/src/tests/plugins.rs b/crates/engine/src/tests/plugins.rs index a4be6e554..dc52243e3 100644 --- a/crates/engine/src/tests/plugins.rs +++ b/crates/engine/src/tests/plugins.rs @@ -3242,6 +3242,40 @@ fn removing_an_id_that_is_not_installed_deletes_its_storage() { assert!(s.execute("plugin.remove", &json!({"id": id})).is_err(), "nothing left to remove"); } +/// The `plugin.*` commands that the tests running every command with `{}` run +/// ([`crate::runs_with_empty_params`]) leave the cache of an installed plug-in as it is, so +/// those tests can run beside the ones here that check a cache. Each command runs with `{}` in a +/// document with two rectangles, one or both selected, as `every_command_survives_empty_params` +/// runs it. +#[test] +fn plugin_commands_run_with_empty_params_keep_other_plugins_caches() { + let folder = crate::tests_links::Folder::new("plugin-storage-empty-params"); + let id = "test.engine.storageemptyparams"; + let mut s = session(); + s.attach_plugin_store(folder.0.clone()); + 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)); + let mut ran = vec![]; + for all in [false, true] { + for c in crate::cmd::command_specs().iter().filter(|c| c.id.starts_with("plugin.") && crate::runs_with_empty_params(c.id)) { + let mut other = session(); + let a = rect(&mut other, 10.0, "#ff0000"); + rect(&mut other, 40.0, "#0000ff"); + if all { + run(&mut other, "select.all", json!({})); + } else { + run(&mut other, "select.set", json!({"ids": [a.0]})); + } + let _ = other.execute(c.id, &json!({})); + ran.push(c.id); + assert_eq!(run(&mut s, "plugin.info", json!({"id": id}))["cacheBytes"], json!(3), "after {}", c.id); + } + } + assert!(ran.contains(&"plugin.list"), "{ran:?}"); + run(&mut s, "plugin.remove", json!({"id": id})); +} + /// The settings file and the cache are checked: a file that doesn't read is moved aside and the /// settings start empty; a write past a cap fails and changes nothing; cache entries whose names /// differ only in case are two files; a removed plug-in's storage takes no more writes.