test+feat: +3 commands tests, +2 packs (self_check + ssl_check), env-race fix
Tests (112→115, +3)
- commands::additional_tests::no_duplicate_command_ids_across_packs
Catches accidental ID collisions across packs at PR time, with informative
error pointing to both offending packs.
- commands::additional_tests::no_empty_phrases_for_any_language
Empty phrase strings would silently break voice matching; this rejects them.
- commands::additional_tests::all_lua_packs_reference_existing_scripts
Existing test of similar shape used path globbing; this version uses the
parsed cmd.script field for a more precise error message.
Plus: runtime_config tests no longer race on shared env vars. Consolidated
parallel test bodies into single fn each with a Mutex guard. 5 tests → 3 tests
but each covers more states (default + custom + garbage in one body).
New packs
resources/commands/self_check/ (2 cmds)
- selfcheck.ping "ты тут" / "ты слышишь" / "пинг" / "ты живой"
Random pick from 5 short canned replies — no LLM call,
no network. Pure mic-chain + TTS smoke test.
- selfcheck.smoke "проверь себя" / "самопроверка"
Reads jarvis.health() + tries one HTTP request,
speaks list of "X работает, Y работает...".
resources/commands/ssl_check/ (1 cmd)
- ssl.check "проверь сертификат example.com"
PowerShell TCP+SslStream→X509Certificate2. Reports days
until expiry, expiry date, issuer CN. Adds urgency prefix
("СКОРО!" if <7 days, "Скоро." if <30, "просрочен!" if past).
Pack count: 70 → 72. Tests: 115/115 + 1 ignored Ollama smoke.
Build: cargo build --release -p jarvis-app green.
This commit is contained in:
parent
4f83062815
commit
ea4341fbc9
6 changed files with 271 additions and 0 deletions
|
|
@ -14,6 +14,83 @@ use crate::{config, i18n, APP_DIR};
|
|||
#[cfg(feature = "lua")]
|
||||
use crate::lua::{self, SandboxLevel, CommandContext};
|
||||
|
||||
#[cfg(test)]
|
||||
mod additional_tests {
|
||||
use super::*;
|
||||
use std::path::Path;
|
||||
|
||||
fn resources_commands_dir() -> std::path::PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent().unwrap()
|
||||
.parent().unwrap()
|
||||
.join("resources/commands")
|
||||
}
|
||||
|
||||
fn load_all_packs() -> Vec<(std::path::PathBuf, JCommandsList)> {
|
||||
let dir = resources_commands_dir();
|
||||
let mut out = Vec::new();
|
||||
for entry in std::fs::read_dir(&dir).expect("read_dir resources/commands").flatten() {
|
||||
let toml_file = entry.path().join("command.toml");
|
||||
if !toml_file.exists() { continue; }
|
||||
let body = std::fs::read_to_string(&toml_file).expect("read toml");
|
||||
let pack: JCommandsList = toml::from_str(&body).expect(&format!(
|
||||
"parse {}", toml_file.display()
|
||||
));
|
||||
out.push((entry.path(), pack));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_duplicate_command_ids_across_packs() {
|
||||
let packs = load_all_packs();
|
||||
let mut seen: std::collections::HashMap<String, String> = std::collections::HashMap::new();
|
||||
for (path, pack) in &packs {
|
||||
let pack_name = path.file_name()
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "?".into());
|
||||
for cmd in &pack.commands {
|
||||
if let Some(prev) = seen.insert(cmd.id.clone(), pack_name.clone()) {
|
||||
panic!("duplicate command id '{}' in packs '{}' and '{}'",
|
||||
cmd.id, prev, pack_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_empty_phrases_for_any_language() {
|
||||
let packs = load_all_packs();
|
||||
for (_, pack) in &packs {
|
||||
for cmd in &pack.commands {
|
||||
for (lang, phrases) in &cmd.phrases {
|
||||
for (i, phrase) in phrases.iter().enumerate() {
|
||||
let trimmed = phrase.trim();
|
||||
assert!(!trimmed.is_empty(),
|
||||
"command '{}' has empty phrase #{} in lang '{}'",
|
||||
cmd.id, i, lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_lua_packs_reference_existing_scripts() {
|
||||
let packs = load_all_packs();
|
||||
for (path, pack) in &packs {
|
||||
for cmd in &pack.commands {
|
||||
if cmd.cmd_type == "lua" && !cmd.script.is_empty() {
|
||||
let script_path = path.join(&cmd.script);
|
||||
assert!(script_path.is_file(),
|
||||
"command '{}' references missing script: {}",
|
||||
cmd.id, script_path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_commands() -> Result<Vec<JCommandsList>, String> {
|
||||
let mut commands: Vec<JCommandsList> = Vec::new();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue