#[test]
fn run_strings_mode_succeeds_on_regular_file() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(b"Hello\x00World\x00teststring\x00ab\x00longword")
.expect("write");
let result = run(file.path(), false, false, true, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_hex_mode_file_not_found() {
let result = run(
Path::new("/nonexistent/file.bin"),
false,
true,
false,
256,
false,
false,
);
assert!(result.is_err());
}
#[test]
fn run_strings_mode_file_not_found() {
let result = run(
Path::new("/nonexistent/file.bin"),
false,
false,
true,
256,
false,
false,
);
assert!(result.is_err());
}
#[test]
fn run_basic_mode_with_valid_header_size_file() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1; buf[5] = 0; file.write_all(&buf).expect("write");
let result = run(file.path(), false, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_drama_mode_with_valid_header() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1;
buf[5] = 0;
file.write_all(&buf).expect("write");
let result = run(file.path(), true, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_drama_mode_with_invalid_magic() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"XXXX");
buf[4] = 1;
file.write_all(&buf).expect("write");
let result = run(file.path(), true, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_drama_mode_with_flags_set() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1;
buf[21] = 0b00100111;
file.write_all(&buf).expect("write");
let result = run(file.path(), true, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_drama_mode_version_non_one() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APR2");
buf[4] = 2; buf[5] = 1;
file.write_all(&buf).expect("write");
let result = run(file.path(), true, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_basic_mode_with_invalid_magic() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"ZZZZ");
file.write_all(&buf).expect("write");
let result = run(file.path(), false, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_basic_mode_with_flags_shows_flag_line() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[21] = 0x02; file.write_all(&buf).expect("write");
let result = run(file.path(), false, false, false, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_strings_mode_with_limit_one() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(b"firststring\x00secondstring\x00thirdstring")
.expect("write");
let result = run(file.path(), false, false, true, 1, false, false);
assert!(result.is_ok());
}
#[test]
fn run_hex_mode_with_small_limit() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(&[0u8; 256]).expect("write");
let result = run(file.path(), false, true, false, 32, false, false);
assert!(result.is_ok());
}
#[test]
fn run_directory_rejected() {
let dir = tempdir().expect("create dir");
let result = run(dir.path(), false, false, false, 100, false, false);
assert!(matches!(result, Err(CliError::NotAFile(_))));
}
#[test]
fn parse_header_compression_none_is_zero() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 0; let info = parse_header(&header);
assert!(!info.compressed);
}
#[test]
fn parse_header_compression_zstd_default() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 1; let info = parse_header(&header);
assert!(info.compressed);
}
#[test]
fn parse_header_compression_zstd_max() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 2; let info = parse_header(&header);
assert!(info.compressed);
}
#[test]
fn parse_header_compression_lz4() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 3; let info = parse_header(&header);
assert!(info.compressed);
}
#[test]
fn parse_header_compression_out_of_range() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 4; let info = parse_header(&header);
assert!(!info.compressed);
}
#[test]
fn parse_header_compression_255() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[20] = 255;
let info = parse_header(&header);
assert!(!info.compressed);
}
#[test]
fn parse_header_flags_byte_zero_no_flags() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x00;
let info = parse_header(&header);
assert!(!info.signed);
assert!(!info.encrypted);
}
#[test]
fn parse_header_flags_signed_bit_only() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x02; let info = parse_header(&header);
assert!(info.signed);
assert!(!info.encrypted);
}
#[test]
fn parse_header_flags_encrypted_bit_only() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x04; let info = parse_header(&header);
assert!(!info.signed);
assert!(info.encrypted);
}
#[test]
fn parse_header_flags_signed_and_encrypted() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x06; let info = parse_header(&header);
assert!(info.signed);
assert!(info.encrypted);
}
#[test]
fn parse_header_flags_high_bits_set_garbage() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0xFF; let info = parse_header(&header);
assert!(!info.signed);
assert!(!info.encrypted);
}
#[test]
fn parse_header_flags_just_below_garbage_threshold() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x07; let info = parse_header(&header);
assert!(info.signed);
assert!(info.encrypted);
}
#[test]
fn parse_header_flags_at_garbage_threshold() {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
header[21] = 0x08; let info = parse_header(&header);
assert!(!info.signed);
assert!(!info.encrypted);
}
#[test]
fn collect_flags_compressed_and_signed() {
let info = HeaderInfo {
magic_valid: true,
magic_str: "APRN".to_string(),
version: (1, 0),
model_type: 0x0001,
compressed: true,
signed: true,
encrypted: false,
};
let flags = collect_flags(&info);
assert_eq!(flags, vec!["compressed", "signed"]);
}
#[test]
fn collect_flags_compressed_and_encrypted() {
let info = HeaderInfo {
magic_valid: true,
magic_str: "APRN".to_string(),
version: (1, 0),
model_type: 0x0001,
compressed: true,
signed: false,
encrypted: true,
};
let flags = collect_flags(&info);
assert_eq!(flags, vec!["compressed", "encrypted"]);
}
#[test]
fn format_model_type_gap_between_svm_and_ngram() {
assert_eq!(format_model_type(0x000B), "Unknown(0x000B)");
assert_eq!(format_model_type(0x000C), "Unknown(0x000C)");
assert_eq!(format_model_type(0x000F), "Unknown(0x000F)");
}
#[test]
fn format_model_type_gap_between_count_vec_and_neural() {
assert_eq!(format_model_type(0x0013), "Unknown(0x0013)");
assert_eq!(format_model_type(0x001F), "Unknown(0x001F)");
}
#[test]
fn format_model_type_gap_between_neural_custom_and_recommender() {
assert_eq!(format_model_type(0x0022), "Unknown(0x0022)");
assert_eq!(format_model_type(0x002F), "Unknown(0x002F)");
}
#[test]
fn run_basic_mode_no_flags_shows_none() {
let info = HeaderInfo {
magic_valid: true,
magic_str: "APRN".to_string(),
version: (1, 0),
model_type: 0x0001,
compressed: false,
signed: false,
encrypted: false,
};
let flag_list = collect_flags(&info);
let flags_str = if flag_list.is_empty() {
"none".to_string()
} else {
flag_list.join(", ")
};
assert_eq!(flags_str, "none");
}
#[test]
fn run_basic_mode_flags_join_with_comma() {
let info = HeaderInfo {
magic_valid: true,
magic_str: "APRN".to_string(),
version: (1, 0),
model_type: 0x0001,
compressed: true,
signed: true,
encrypted: true,
};
let flag_list = collect_flags(&info);
let flags_str = flag_list.join(", ");
assert_eq!(flags_str, "compressed, signed, encrypted");
}
#[test]
fn run_json_mode_with_gguf_file() {
let mut file = NamedTempFile::with_suffix(".gguf").expect("create file");
file.write_all(b"GGUF").expect("write");
file.write_all(&[0u8; 100]).expect("write padding");
let result = run(file.path(), false, false, false, 100, true, false);
let _ = result;
}
#[test]
fn run_json_mode_with_apr_file() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1;
file.write_all(&buf).expect("write");
let result = run(file.path(), false, false, false, 100, true, false);
let _ = result;
}
#[test]
fn run_verbose_with_apr_file() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1;
buf[5] = 0;
file.write_all(&buf).expect("write");
let result = run(file.path(), false, false, false, 100, false, true);
assert!(result.is_ok());
}
#[test]
fn run_verbose_with_drama_mode() {
let mut file = NamedTempFile::with_suffix(".apr").expect("create file");
let mut buf = vec![0u8; HEADER_SIZE];
buf[0..4].copy_from_slice(b"APRN");
buf[4] = 1;
file.write_all(&buf).expect("write");
let result = run(file.path(), true, false, false, 100, false, true);
assert!(result.is_ok());
}
#[test]
fn run_hex_mode_with_empty_file() {
let file = NamedTempFile::new().expect("create file");
let result = run(file.path(), false, true, false, 256, false, false);
assert!(result.is_ok());
}
#[test]
fn run_hex_mode_limit_zero() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(&[0xAB; 100]).expect("write");
let result = run(file.path(), false, true, false, 0, false, false);
assert!(result.is_ok());
}
#[test]
fn run_hex_mode_limit_exceeds_file() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(b"short").expect("write");
let result = run(file.path(), false, true, false, 8192, false, false);
assert!(result.is_ok());
}
#[test]
fn run_strings_mode_all_printable() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(b"abcdefghijklmnop").expect("write");
let result = run(file.path(), false, false, true, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_strings_mode_all_binary() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(&[0x01, 0x02, 0x03, 0x80, 0xFF]).expect("write");
let result = run(file.path(), false, false, true, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_strings_mode_mixed_short_strings() {
let mut file = NamedTempFile::new().expect("create file");
file.write_all(b"ab\x00cd\x00efgh\x00").expect("write");
let result = run(file.path(), false, false, true, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn run_strings_mode_empty_file() {
let file = NamedTempFile::new().expect("create file");
let result = run(file.path(), false, false, true, 100, false, false);
assert!(result.is_ok());
}
#[test]
fn parse_header_all_known_model_types() {
let known_types: Vec<(u16, &str)> = vec![
(0x0001, "LinearRegression"),
(0x0002, "LogisticRegression"),
(0x0003, "DecisionTree"),
(0x0004, "RandomForest"),
(0x0005, "GradientBoosting"),
(0x0006, "KMeans"),
(0x0007, "PCA"),
(0x0008, "NaiveBayes"),
(0x0009, "KNN"),
(0x000A, "SVM"),
(0x0010, "NgramLM"),
(0x0011, "TfIdf"),
(0x0012, "CountVectorizer"),
(0x0020, "NeuralSequential"),
(0x0021, "NeuralCustom"),
(0x0030, "ContentRecommender"),
(0x0040, "MixtureOfExperts"),
(0x00FF, "Custom"),
];
for (type_id, expected_name) in known_types {
let mut header = [0u8; HEADER_SIZE];
header[0..4].copy_from_slice(b"APRN");
let bytes = type_id.to_le_bytes();
header[6] = bytes[0];
header[7] = bytes[1];
let info = parse_header(&header);
assert_eq!(info.model_type, type_id);
assert_eq!(format_model_type(info.model_type), expected_name);
}
}
#[test]
fn validate_path_with_symlink_to_file() {
let file = NamedTempFile::new().expect("create file");
assert!(validate_path(file.path()).is_ok());
}
#[test]
fn validate_path_empty_path() {
let result = validate_path(Path::new(""));
assert!(result.is_err());
}