#![allow(clippy::unwrap_used)]
use bashrs::linter::rules::lint_shell;
use jugar_probar::gui_coverage;
use std::panic::{self, AssertUnwindSafe};
fn lint_safely(code: &str) -> bool {
let result = panic::catch_unwind(AssertUnwindSafe(|| lint_shell(code)));
result.is_ok()
}
#[test]
fn test_simulation_unicode_encoding() {
let mut gui = gui_coverage! {
buttons: ["S101", "S102", "S103", "S104", "S105", "S106", "S107", "S108", "S109", "S110"],
screens: ["pass", "fail"]
};
let tests = [
("S101", "echo 'héllo wörld'", "Latin extended chars"),
("S102", "echo '日本語テスト'", "Japanese characters"),
("S103", "echo '🚀🔥💻'", "Emoji in string"),
("S104", "var='Ù…Ø±ØØ¨Ø§'; echo $var", "RTL Arabic text"),
("S105", "echo 'Ω≈ç√∫'", "Math symbols"),
("S106", "echo '\u{0000}'", "Null byte in string"),
("S107", "echo $'\\xc0\\xc1'", "Invalid UTF-8 sequence"),
("S108", "x='a\u{200B}b'; echo $x", "Zero-width space"),
("S109", "echo '\u{200B}'", "Zero-width char only"),
("S110", "echo 'A\u{0308}'", "Combining diacritical"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, code, desc);
}
let report = gui.generate_report();
println!(
"\nS1xx Unicode: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All unicode tests must pass"
);
}
#[test]
fn test_simulation_boundary_conditions() {
let mut gui = gui_coverage! {
buttons: ["S201", "S202", "S203", "S204", "S205", "S206", "S207", "S208", "S209", "S210"],
screens: ["pass", "fail"]
};
let s201 = format!("x={}", "a".repeat(10000));
let s202 = format!("echo {}", "word ".repeat(100));
let s203 = format!("{}echo test", " ".repeat(100));
let s204 = format!("echo test{}", " ".repeat(100));
let s210 = format!("# {}", "x".repeat(500));
let tests: [(&str, &str, &str); 10] = [
("S201", &s201, "10KB variable"),
("S202", &s202, "100 word echo"),
("S203", &s203, "100 leading spaces"),
("S204", &s204, "100 trailing spaces"),
("S205", "\n\n\n\n\necho test", "5 leading newlines"),
(
"S206",
"echo test; echo test; echo test; echo test; echo test",
"5 chained commands",
),
(
"S207",
"cat << EOF\nline1\nline2\nline3\nEOF",
"3 line heredoc",
),
(
"S208",
"echo ${x:-${y:-${z:-default}}}",
"3 nested expansions",
),
("S209", "arr=(a b c d e f g h i j)", "10 element array"),
("S210", &s210, "500 char comment"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, desc, desc);
}
let report = gui.generate_report();
println!(
"\nS2xx Boundary: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All boundary tests must pass"
);
}
#[test]
fn test_simulation_deep_nesting() {
let mut gui = gui_coverage! {
buttons: ["S301", "S302", "S303", "S304", "S305", "S306", "S307", "S308", "S309", "S310"],
screens: ["pass", "fail"]
};
let tests = [
(
"S301",
"if true; then if true; then echo deep; fi; fi",
"2 nested ifs",
),
("S302", "{ { { echo test; }; }; }", "3 nested blocks"),
("S303", "( ( ( echo test ) ) )", "3 nested subshells"),
(
"S304",
"case x in a) case y in b) echo z ;; esac ;; esac",
"2 nested case",
),
(
"S305",
"while true; do while true; do break 2; done; done",
"2 nested whiles",
),
(
"S306",
"for i in a; do for j in b; do echo $i$j; done; done",
"2 nested fors",
),
("S307", "echo $(echo $(echo test))", "2 nested cmd subs"),
("S308", "[[ true && true ]]", "Compound conditions"),
("S309", "echo $(( 1 + (2 + (3)) ))", "3 nested arithmetic"),
(
"S310",
"f() { g() { echo deep; }; g; }; f",
"2 nested functions",
),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, code, desc);
}
let report = gui.generate_report();
println!(
"\nS3xx Nesting: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All nesting tests must pass"
);
}
#[test]
fn test_simulation_special_characters() {
let mut gui = gui_coverage! {
buttons: ["S401", "S402", "S403", "S404", "S405", "S406", "S407", "S408", "S409", "S410"],
screens: ["pass", "fail"]
};
let tests = [
("S401", "echo 'test\ttest'", "Tab in string"),
("S402", "echo 'test\rtest'", "Carriage return"),
("S403", "echo 'line1\nline2'", "Newline in string"),
("S404", "echo $'\\a\\b\\e\\f'", "ANSI escapes"),
("S405", "echo 'test\\\\test'", "Backslash in string"),
("S406", "x='`'; echo $x", "Backtick in var"),
("S407", "echo '$()'", "Literal cmd sub"),
("S408", "echo '$((1+1))'", "Literal arithmetic"),
("S409", "echo '!!'", "History expansion chars"),
("S410", "echo '#not a comment'", "Hash in quotes"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, code, desc);
}
let report = gui.generate_report();
println!(
"\nS4xx Special Chars: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All special char tests must pass"
);
}
#[test]
fn test_simulation_malformed_syntax() {
let mut gui = gui_coverage! {
buttons: ["S501", "S502", "S503", "S504", "S505", "S506", "S507", "S508", "S509", "S510"],
screens: ["pass", "fail"]
};
let tests = [
("S501", "echo ${", "Unclosed brace"),
("S502", "echo $((1+)", "Unclosed arithmetic"),
("S503", "if true; then", "Missing fi"),
("S504", "case x in", "Missing esac"),
("S505", "while true; do", "Missing done"),
("S506", "echo \"unterminated", "Unclosed quote"),
("S507", "echo 'unterminated", "Unclosed single quote"),
("S508", "((", "Empty arithmetic"),
("S509", "[[", "Empty condition"),
("S510", "}", "Unmatched brace"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(
passed,
"{}: Must NOT panic on malformed: {} ({})",
id, code, desc
);
}
let report = gui.generate_report();
println!(
"\nS5xx Malformed: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All malformed tests must not panic"
);
}
#[test]
fn test_simulation_timing_order() {
let mut gui = gui_coverage! {
buttons: ["S601", "S602", "S603", "S604", "S605", "S606", "S607", "S608", "S609", "S610"],
screens: ["pass", "fail"]
};
let tests = [
("S601", "echo $$ $!", "PID variables"),
("S602", "echo ${RANDOM} ${RANDOM}", "Multiple RANDOM"),
("S603", "trap 'echo exit' EXIT; exit", "Trap on exit"),
("S604", "eval 'echo test'", "Eval command"),
("S605", "exec 3>&1", "FD manipulation"),
("S606", "wait", "Wait builtin"),
("S607", "jobs", "Jobs builtin"),
("S608", "bg 2>/dev/null", "Background builtin"),
("S609", "fg 2>/dev/null", "Foreground builtin"),
("S610", "disown 2>/dev/null", "Disown builtin"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, code, desc);
}
let report = gui.generate_report();
println!(
"\nS6xx Timing: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(report.element_coverage >= 1.0, "All timing tests must pass");
}
#[test]
fn test_simulation_resource_limits() {
let mut gui = gui_coverage! {
buttons: ["S701", "S702", "S703", "S704", "S705", "S706", "S707", "S708", "S709", "S710"],
screens: ["pass", "fail"]
};
let tests = [
("S701", "echo ${xxxxxxxxxx}", "Long variable name"),
("S702", "fxxxxxxxx() { :; }", "Long function name"),
("S703", "alias aaaaaaaaaa='echo'", "Long alias name"),
("S704", "export VVVVVVVVVV=value", "Long export name"),
("S705", "read vvvvv wwwww", "Multiple read vars"),
("S706", "f() { local vvvvvvvvvv=x; }", "Long local var"),
("S707", "declare -a arrarrarr", "Long array name"),
("S708", "printf '%s' 'x' 'y' 'z'", "Many printf args"),
("S709", "echo $1 $2 $3 $4 $5", "Many positional refs"),
("S710", "set -- arg1 arg2 arg3 arg4 arg5", "Many set args"),
];
for (id, code, desc) in tests {
let passed = lint_safely(code);
gui.click(id);
gui.visit(if passed { "pass" } else { "fail" });
assert!(passed, "{}: Must NOT panic on: {} ({})", id, code, desc);
}
let report = gui.generate_report();
println!(
"\nS7xx Resource: {:.1}% elements",
report.element_coverage * 100.0
);
assert!(
report.element_coverage >= 1.0,
"All resource tests must pass"
);
}
#[test]
include!("simulation_probar_testing_simulation_e.rs");