test(commands): schema and Lua script validation for resources/commands/

Three unit tests catch the kind of bug that broke weather/set_city (a
phrases array instead of lang→array map silently dropped the whole pack):

- every_command_toml_parses: every resources/commands/*/command.toml round-
  trips through toml::from_str::<JCommandsList>. Reports all failures at
  once instead of failing on the first.
- lua_command_scripts_exist: for every type="lua" command, the named (or
  default script.lua) script file exists in the pack dir.
- every_command_has_phrases: structural commands (terminate/stop_chaining)
  excluded, every other command has ≥1 phrase across all languages.

Tests use env!("CARGO_MANIFEST_DIR") -> ../.. -> resources/commands so they
work from any cwd.

NB: cargo test does not run on this machine right now — aws-lc-sys needs
cl.exe (MSVC Build Tools missing). The release binary was built earlier
with MSVC available; toolchain install is a follow-up. The tests are still
valid for CI / a re-armed dev box.
This commit is contained in:
Bossiara13 2026-05-15 00:55:01 +03:00
parent 9c25108356
commit 85a004e263

View file

@ -266,6 +266,112 @@ pub fn list_paths(commands: &[JCommandsList]) -> Vec<&Path> {
commands.iter().map(|x| x.path.as_path()).collect() commands.iter().map(|x| x.path.as_path()).collect()
} }
#[cfg(test)]
mod tests {
use super::*;
fn resources_commands_dir() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent().unwrap()
.parent().unwrap()
.join("resources/commands")
}
#[test]
fn every_command_toml_parses() {
let cmds_dir = resources_commands_dir();
assert!(cmds_dir.is_dir(), "missing {}", cmds_dir.display());
let mut failures = Vec::new();
let mut packs_seen = 0;
for entry in fs::read_dir(&cmds_dir).expect("read_dir") {
let entry = entry.expect("entry");
let toml_file = entry.path().join("command.toml");
if !toml_file.exists() {
continue;
}
packs_seen += 1;
let body = fs::read_to_string(&toml_file).expect("read");
if let Err(e) = toml::from_str::<JCommandsList>(&body) {
failures.push(format!("{}: {}", toml_file.display(), e));
}
}
assert!(packs_seen > 0, "no command packs found in {}", cmds_dir.display());
assert!(
failures.is_empty(),
"parse failures ({}):\n{}",
failures.len(),
failures.join("\n")
);
}
#[test]
fn lua_command_scripts_exist() {
let cmds_dir = resources_commands_dir();
let mut missing = Vec::new();
for entry in fs::read_dir(&cmds_dir).expect("read_dir") {
let entry = entry.expect("entry");
let pack_path = entry.path();
let toml_file = pack_path.join("command.toml");
if !toml_file.exists() {
continue;
}
let body = fs::read_to_string(&toml_file).expect("read");
let pack: JCommandsList = toml::from_str(&body).expect("parse");
for cmd in &pack.commands {
if cmd.cmd_type != "lua" {
continue;
}
let script = if cmd.script.is_empty() {
"script.lua".to_string()
} else {
cmd.script.clone()
};
let script_path = pack_path.join(&script);
if !script_path.exists() {
missing.push(format!(
"{} -> {} (missing)",
cmd.id,
script_path.display()
));
}
}
}
assert!(missing.is_empty(), "missing Lua scripts:\n{}", missing.join("\n"));
}
#[test]
fn every_command_has_phrases() {
let cmds_dir = resources_commands_dir();
let mut empty = Vec::new();
for entry in fs::read_dir(&cmds_dir).expect("read_dir") {
let toml_file = entry.expect("entry").path().join("command.toml");
if !toml_file.exists() {
continue;
}
let body = fs::read_to_string(&toml_file).expect("read");
let pack: JCommandsList = toml::from_str(&body).expect("parse");
for cmd in &pack.commands {
// structural commands (terminate, stop_chaining) may omit phrases
if cmd.cmd_type == "terminate" || cmd.cmd_type == "stop_chaining" {
continue;
}
let total: usize = cmd.phrases.values().map(|v| v.len()).sum();
if total == 0 {
empty.push(cmd.id.clone());
}
}
}
assert!(empty.is_empty(), "commands with no phrases: {:?}", empty);
}
}
#[cfg(feature = "lua")] #[cfg(feature = "lua")]
fn execute_lua_command( fn execute_lua_command(
cmd_path: &PathBuf, cmd_path: &PathBuf,