#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use super::lexer::{Lexer, LexerError, Token};
fn lex(input: &str) -> Vec<Token> {
let mut lexer = Lexer::new(input);
lexer.tokenize().unwrap_or_default()
}
fn lex_ok(input: &str) -> Vec<Token> {
let mut lexer = Lexer::new(input);
lexer.tokenize().expect("tokenization should succeed")
}
#[test]
fn test_LEX_OP_EXT_001_at_glob_pattern() {
let tokens = lex("echo @(foo|bar)");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s == "@(foo|bar)")),
"Expected @(foo|bar) extended glob, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_EXT_002_plus_glob_pattern() {
let tokens = lex("echo +(abc|def)");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s == "+(abc|def)")),
"Expected +(abc|def) extended glob, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_EXT_003_question_glob_pattern() {
let tokens = lex("echo ?(opt1|opt2)");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s == "?(opt1|opt2)")),
"Expected ?(opt1|opt2) extended glob, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_EXT_004_at_glob_nested_parens() {
let tokens = lex("@(a|(b|c))");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s == "@(a|(b|c))")),
"Expected nested @(a|(b|c)), got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_EXT_005_plus_glob_single_pattern() {
let tokens = lex("+(single)");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s == "+(single)")),
"Expected +(single), got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_REGEX_001_basic_regex_match() {
let tokens = lex("[[ $str =~ ^[0-9]+$ ]]");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s.starts_with("=~ "))),
"Expected =~ regex match operator, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_REGEX_002_regex_pattern_content() {
let tokens = lex("[[ $var =~ foo.*bar ]]");
let regex_tok = tokens
.iter()
.find(|t| matches!(t, Token::Identifier(s) if s.starts_with("=~ ")));
assert!(regex_tok.is_some(), "Expected =~ token, got: {:?}", tokens);
if let Some(Token::Identifier(s)) = regex_tok {
assert!(
s.contains("foo.*bar"),
"Regex pattern should contain 'foo.*bar', got: {}",
s
);
}
}
#[test]
fn test_LEX_OP_REGEX_003_regex_with_bracket_class() {
let tokens = lex("[[ $x =~ [[:alpha:]]+ ]]");
let regex_tok = tokens
.iter()
.find(|t| matches!(t, Token::Identifier(s) if s.starts_with("=~ ")));
assert!(
regex_tok.is_some(),
"Expected =~ regex token with bracket class, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_ARITH_001_standalone_arithmetic() {
let tokens = lex("((x + 1))");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::ArithmeticExpansion(_))),
"Expected ArithmeticExpansion token, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_ARITH_002_standalone_arithmetic_content() {
let tokens = lex("((i++))");
let arith = tokens
.iter()
.find(|t| matches!(t, Token::ArithmeticExpansion(_)));
assert!(
arith.is_some(),
"Expected ArithmeticExpansion, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_ARITH_003_arithmetic_nested_parens() {
let tokens = lex("((a * (b + c)))");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::ArithmeticExpansion(_))),
"Expected ArithmeticExpansion with nested parens, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_BRACE_001_comma_expansion() {
let tokens = lex("echo {a,b,c}");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s.contains(","))),
"Expected brace expansion with commas, got: {:?}",
tokens
);
}
#[test]
fn test_LEX_OP_BRACE_002_range_expansion() {
let tokens = lex("echo {1..10}");
assert!(
tokens
.iter()
.any(|t| matches!(t, Token::Identifier(s) if s.contains(".."))),
"Expected brace expansion with range, got: {:?}",
tokens
);
}
#[test]
include!("lexer_operator_tests_tests_LEX.rs");