#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
#![allow(non_snake_case)]
use crate::bash_parser::ast::*;
use crate::bash_parser::codegen::generate_purified_bash;
use crate::bash_parser::parser::BashParser;
#[test]
fn test_issue_136_if_not_command_v_with_redirects() {
let script = "if ! command -v apr >/dev/null 2>&1; then\n echo \"ERROR: apr not found.\"\n exit 1\nfi";
let mut parser = BashParser::new(script).expect("Lexer should succeed");
let ast = parser.parse().unwrap_or_else(|e| {
panic!("Issue #136 REGRESSION: `if ! command -v` must parse. Error: {e:?}")
});
assert_eq!(ast.statements.len(), 1, "Should produce one If statement");
match &ast.statements[0] {
BashStmt::If {
condition,
then_block,
..
} => {
match condition {
BashExpr::CommandCondition(cmd) => {
assert!(
matches!(cmd.as_ref(), BashStmt::Negated { .. }),
"Condition should be Negated, got: {cmd:?}"
);
}
other => panic!("Expected CommandCondition, got: {other:?}"),
}
assert_eq!(then_block.len(), 2, "then block: echo + exit");
}
other => panic!("Expected If, got: {other:?}"),
}
}
#[test]
fn test_issue_136_if_not_command_v_no_redirects() {
let script = "if ! command -v foo; then echo missing; fi";
let mut parser = BashParser::new(script).expect("Lexer");
let ast = parser
.parse()
.unwrap_or_else(|e| panic!("Issue #136: no-redirect variant must parse. Error: {e:?}"));
assert_eq!(ast.statements.len(), 1);
assert!(matches!(&ast.statements[0], BashStmt::If { .. }));
}
#[test]
fn test_issue_136_if_not_command_v_with_variable() {
let script = "if ! command -v \"$bin\" >/dev/null 2>&1; then\n exit 1\nfi";
let mut parser = BashParser::new(script).expect("Lexer");
let ast = parser
.parse()
.unwrap_or_else(|e| panic!("Issue #136: variable arg variant must parse. Error: {e:?}"));
assert_eq!(ast.statements.len(), 1);
assert!(matches!(&ast.statements[0], BashStmt::If { .. }));
}
#[test]
fn test_issue_136_while_not_command_v() {
let script = "while ! command -v foo >/dev/null 2>&1; do sleep 1; done";
let mut parser = BashParser::new(script).expect("Lexer");
let ast = parser
.parse()
.unwrap_or_else(|e| panic!("Issue #136: while variant must parse. Error: {e:?}"));
assert_eq!(ast.statements.len(), 1);
assert!(matches!(&ast.statements[0], BashStmt::While { .. }));
}
#[test]
fn test_issue_136_negated_command_v_in_function() {
let script = "qualify() {\n if ! command -v \"$1\" >/dev/null 2>&1; then\n return 1\n fi\n}";
let mut parser = BashParser::new(script).expect("Lexer");
let ast = parser
.parse()
.unwrap_or_else(|e| panic!("Issue #136: function-body variant must parse. Error: {e:?}"));
assert!(!ast.statements.is_empty());
}
#[test]
fn test_issue_136_roundtrip_if_not_command_v() {
let input = "#!/bin/bash\nif ! command -v apr >/dev/null 2>&1; then\n echo 'not found'\n exit 1\nfi";
let mut parser = BashParser::new(input).expect("Lex");
let ast = parser.parse().expect("Issue #136: parse must succeed");
let output = generate_purified_bash(&ast);
assert!(
output.contains("if ! command -v apr"),
"negated command preserved: {output}"
);
assert!(output.contains("then"), "then keyword: {output}");
assert!(output.contains("fi"), "fi keyword: {output}");
}
#[test]
fn test_issue_136_roundtrip_negated_command_v_variable() {
let input = "#!/bin/bash\nif ! command -v \"$bin\" >/dev/null 2>&1; then\n exit 1\nfi";
let mut parser = BashParser::new(input).expect("Lex");
let ast = parser.parse().expect("Issue #136: parse must succeed");
let output = generate_purified_bash(&ast);
assert!(
output.contains("! command"),
"negated command preserved: {output}"
);
}