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:
parent
9c25108356
commit
85a004e263
1 changed files with 106 additions and 0 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue