const TARGET_EXE_PATH: &str = env!(concat!("CARGO_BIN_EXE_", env!("CARGO_PKG_NAME")));
#[macro_use]
mod helper;
#[macro_use]
mod helper_e;
mod test_0_e {
use exec_target::exec_target;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_help() {
let oup = exec_target(TARGET_EXE_PATH, ["-H"]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, help_msg!());
assert!(oup.status.success());
}
#[test]
fn test_help_long() {
let oup = exec_target(TARGET_EXE_PATH, ["--help"]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, help_msg!());
assert!(oup.status.success());
}
#[test]
fn test_version() {
let oup = exec_target(TARGET_EXE_PATH, ["-V"]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, version_msg!());
assert!(oup.status.success());
}
#[test]
fn test_version_long() {
let oup = exec_target(TARGET_EXE_PATH, ["--version"]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, version_msg!());
assert!(oup.status.success());
}
#[test]
fn test_non_option() {
let oup = exec_target(TARGET_EXE_PATH, [""]);
assert_eq!(
oup.stderr,
concat!(
program_name!(),
": Unexpected argument: \n",
try_help_msg!()
)
);
assert_eq!(oup.stdout, "");
assert!(!oup.status.success());
}
#[test]
fn test_invalid_regex() {
let oup = exec_target(TARGET_EXE_PATH, ["-e", "["]);
assert_eq!(
oup.stderr,
concat!(
program_name!(),
": regex parse error:\n [\n ^\nerror: unclosed character class\n",
)
);
assert_eq!(oup.stdout, "");
assert!(!oup.status.success());
}
}
mod test_0_x_options_e {
use exec_target::exec_target;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_x_option_help() {
let oup = exec_target(TARGET_EXE_PATH, ["-X", "help"]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, x_help_msg!());
assert!(oup.status.success());
}
#[test]
fn test_x_option_rust_version_info() {
let oup = exec_target(TARGET_EXE_PATH, ["-X", "rust-version-info"]);
assert_eq!(oup.stderr, "");
assert!(oup.stdout.contains("rustc"));
assert!(oup.status.success());
}
#[test]
fn test_multiple_x_options() {
let oup = exec_target(TARGET_EXE_PATH, ["-X", "help", "-X", "rust-version-info"]);
assert_eq!(oup.stderr, "");
assert!(oup.stdout.contains("Options:"));
assert!(!oup.stdout.contains("rustc"));
assert!(oup.status.success());
}
}
mod test_1_e {
use exec_target::exec_target_with_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_invalid_utf8() {
let v = std::fs::read(fixture_invalid_utf8!()).unwrap();
let oup = exec_target_with_in(TARGET_EXE_PATH, ["-e", "."], &v);
assert_eq!(
oup.stderr,
concat!(program_name!(), ": stream did not contain valid UTF-8\n",)
);
assert_eq!(oup.stdout, "");
assert!(!oup.status.success());
}
}
mod test_2_regex_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_abc_1() {
let in_put: &[u8] = b"abcdefg";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "a"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>a<E>bcdefg\n");
assert!(oup.status.success());
}
#[test]
fn test_abc_2() {
let in_put: &[u8] = b"abcdefg\nhiajklnm\n";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "a"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>a<E>bcdefg\nhi<R>a<E>jklnm\n");
assert!(oup.status.success());
}
#[test]
fn test_abc_3() {
let in_put: &[u8] = b"ab1cdefg\nhi2jklnm\nhi1jklnm\n";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "[0-9]"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(
oup.stdout,
"ab<R>1<E>cdefg\nhi<G>2<E>jklnm\nhi<R>1<E>jklnm\n"
);
assert!(oup.status.success());
}
#[test]
fn test_abc_4() {
let in_put: &[u8] = b"ab1cdefg\nhi2jklnm\nhi1jklnm\n";
let oup = exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "[a-z][0-9]([a-z])"],
env_1!(),
in_put,
);
assert_eq!(oup.stderr, "");
assert_eq!(
oup.stdout,
"ab1<R>c<E>defg\nhi2<G>j<E>klnm\nhi1<G>j<E>klnm\n"
);
assert!(oup.status.success());
}
#[test]
fn test_regex_multiple_capture_groups() {
let in_put: &[u8] = b"abc123def";
let oup = exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "([a-z]+)([0-9]+)"],
env_1!(),
in_put,
);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>abc<E>123def\n");
assert!(oup.status.success());
}
#[test]
fn test_regex_overlapping_matches() {
let in_put: &[u8] = b"abababa";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "aba"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>aba<E>b<R>aba<E>\n");
assert!(oup.status.success());
}
#[test]
fn test_regex_zero_length_match() {
let in_put: &[u8] = b"abc";
let oup =
exec_target::exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "a*"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>a<E>bc\n");
assert!(oup.status.success());
}
}
mod test_3_e {
use exec_target::exec_target;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_output_broken_pipe() {
let cmdstr = format!(
"cat \"{}\" | \"{}\" -e \"A\" | head -n 2",
fixture_text10k!(),
TARGET_EXE_PATH
);
let oup = exec_target("sh", ["-c", &cmdstr]);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "\u{1b}[31mA\u{1b}[0mBCDEFG\nHIJKLMN\n");
assert!(oup.status.success());
}
}
mod test_4_color_cycling_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_color_reuse() {
let in_put: &[u8] = b"apple\nbanana\napple";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "[a-z]+"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>apple<E>\n<G>banana<E>\n<R>apple<E>\n");
assert!(oup.status.success());
}
#[test]
fn test_color_cycle_wrap_around() {
let in_put: &[u8] = b"a\nb\nc\nd\ne\nf\ng\na";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "[a-z]"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(
oup.stdout,
"<R>a<E>\n<G>b<E>\n<B>c<E>\n<C>d<E>\n<M>e<E>\n<Y>f<E>\n<R>g<E>\n<R>a<E>\n"
);
assert!(oup.status.success());
}
}
mod test_4_input_edge_cases_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_long_line() {
let long_line = "a".repeat(10000);
let in_put = long_line.as_bytes();
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "a+"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
let expected_output = format!("<R>{long_line}<E>\n");
assert_eq!(oup.stdout, expected_output);
assert!(oup.status.success());
}
#[test]
fn test_mixed_line_endings() {
let in_put: &[u8] = b"line1\r\nline2\nline3";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "line[0-9]"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>line1<E>\n<G>line2<E>\n<B>line3<E>\n");
assert!(oup.status.success());
}
}
mod test_4_color_env_vars_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_custom_color_sequences() {
let in_put: &[u8] = b"abc";
let mut env = env_1!();
env.push(("AKI_MCYCLE_COLOR_SEQ_RED_ST", "[RED]"));
env.push(("AKI_MCYCLE_COLOR_SEQ_ED", "[/RED]"));
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "b"], env, in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "a[RED]b[/RED]c\n");
assert!(oup.status.success());
}
#[test]
fn test_empty_color_sequences() {
let in_put: &[u8] = b"abc";
let mut env = env_1!();
env.push(("AKI_MCYCLE_COLOR_SEQ_RED_ST", ""));
env.push(("AKI_MCYCLE_COLOR_SEQ_ED", ""));
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "b"], env, in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "abc\n");
assert!(oup.status.success());
}
}
mod test_4_cycle_cleaning_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_cycle_vec_cleaning() {
let mut input = String::new();
for i in 0..96 {
input.push_str(&format!("word{i}\n"));
}
input.push_str("word0\n");
let oup = exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "word[0-9]+"],
env_1!(),
input.as_bytes(),
);
assert_eq!(oup.stderr, "");
let stdout = oup.stdout.as_str();
let lines: Vec<&str> = stdout.lines().collect();
assert!(lines[0].starts_with("<R>word0<E>"));
assert!(lines[1].starts_with("<G>word1<E>"));
assert!(lines[6].starts_with("<R>word6<E>"));
assert!(lines[96].starts_with("<R>word0<E>"));
assert!(oup.status.success());
}
}
mod test_4_capture_groups_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_regex_with_capture_group() {
let in_put: &[u8] = b"abc123def";
let oup = exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "[a-z]+([0-9]+)[a-z]+"],
env_1!(),
in_put,
);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "abc<R>123<E>def\n");
assert!(oup.status.success());
}
#[test]
fn test_regex_with_multiple_capture_groups() {
let in_put: &[u8] = b"abc123def";
let oup = exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "([a-z]+)([0-9]+)([a-z]+)"],
env_1!(),
in_put,
);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>abc<E>123def\n");
assert!(oup.status.success());
}
#[test]
fn test_regex_with_no_capture_group() {
let in_put: &[u8] = b"abc123def";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "[0-9]+"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "abc<R>123<E>def\n");
assert!(oup.status.success());
}
}
mod test_4_invalid_env_vars_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_malformed_color_sequence() {
let in_put: &[u8] = b"abc";
let mut env = env_1!();
env.push(("AKI_MCYCLE_COLOR_SEQ_RED_ST", "\x1b[31m"));
env.push(("AKI_MCYCLE_COLOR_SEQ_ED", "\x1b[0m"));
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "b"], env, in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "a\u{1b}[31mb\u{1b}[0mc\n");
assert!(oup.status.success());
}
}
mod test_4_unicode_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_unicode_matching() {
let in_put: &[u8] = "こんにちは世界".as_bytes();
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "世界"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "こんにちは<R>世界<E>\n");
assert!(oup.status.success());
}
#[test]
fn test_unicode_non_matching() {
let in_put: &[u8] = "こんにちは世界".as_bytes();
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "さようなら"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "こんにちは世界\n");
assert!(oup.status.success());
}
}
mod test_4_edge_cases_e {
use exec_target::exec_target_with_env_in;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_empty_input() {
let in_put: &[u8] = b"";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "."], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "");
assert!(oup.status.success());
}
#[test]
fn test_no_matches() {
let in_put: &[u8] = b"abc\ndef\nghi";
let oup = exec_target_with_env_in(TARGET_EXE_PATH, ["-e", "xyz"], env_1!(), in_put);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "abc\ndef\nghi\n");
assert!(oup.status.success());
}
#[test]
fn test_catastrophic_backtracking_regex() {
let in_put: &[u8] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaab".as_bytes();
let oup = exec_target::exec_target_with_env_in(
TARGET_EXE_PATH,
["-e", "(a+)+"],
env_1!(),
in_put,
);
assert_eq!(oup.stderr, "");
assert_eq!(oup.stdout, "<R>aaaaaaaaaaaaaaaaaaaaaaaaaaaaa<E>b\n");
assert!(oup.status.success());
}
}
#[cfg(not(windows))]
mod test_5_integration_e {
use exec_target::exec_target;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_pipe_to_grep() {
let cmdstr = format!(
"cat \"{}\" | \"{}\" -e \"[A-Z]+\" | grep '\\[31m'",
fixture_text10k!(),
TARGET_EXE_PATH
);
let oup = exec_target("sh", ["-c", &cmdstr]);
assert_eq!(oup.stderr, "");
assert!(oup.stdout.contains("\u{1b}[31mABCDEFG\u{1b}[0m"));
assert!(oup.status.success());
}
}
#[cfg(not(windows))]
mod test_5_performance_e {
use exec_target::exec_target;
use std::time::Instant;
const TARGET_EXE_PATH: &str = super::TARGET_EXE_PATH;
#[test]
fn test_large_file_performance() {
let start = Instant::now();
let cmdstr = format!(
"cat \"{}\" | \"{}\" -e \"[A-Z]+\" > /dev/null",
fixture_text10k!(),
TARGET_EXE_PATH
);
let oup = exec_target("sh", ["-c", &cmdstr]);
let duration = start.elapsed();
assert_eq!(oup.stderr, "");
assert!(oup.status.success());
assert!(
duration.as_secs() < 5,
"Processing a 10k file took too long: {duration:?}"
);
}
}