#[path = "oracle_helpers.rs"]
mod oracle_helpers;
use oracle_helpers::{
generate_corpus, generate_flags, generate_query, run_differential, run_differential_with_tier_c,
};
use proptest::prelude::*;
#[test]
fn golden_smoke_literal_basic() {
let corpus = vec![
("src/main.rs".to_string(), b"fn parse_query() {}\n".to_vec()),
("src/lib.rs".to_string(), b"fn reparse() {}\n".to_vec()),
];
run_differential(&corpus, "parse_query", &[]).unwrap();
}
#[test]
fn golden_smoke_anchored_literal() {
let corpus = vec![
(
"src/main.rs".to_string(),
b"fn _parse_query_() {}\n".to_vec(),
),
(
"src/lib.rs".to_string(),
b"fn reparse_query() {}\n".to_vec(),
),
];
run_differential(&corpus, "_parse_query_", &[]).unwrap();
}
#[test]
fn golden_smoke_crlf_line_endings() {
let corpus = vec![(
"src/main.rs".to_string(),
b"fn foo() {}\r\nfn bar() {}\r\n".to_vec(),
)];
run_differential(&corpus, "foo", &[]).unwrap();
run_differential(&corpus, "bar", &[]).unwrap();
}
#[test]
fn golden_smoke_cr_only_line_endings() {
let corpus = vec![(
"src/main.rs".to_string(),
b"fn foo() {}\rfn bar() {}\r".to_vec(),
)];
run_differential(&corpus, "foo", &[]).unwrap();
}
#[test]
fn golden_smoke_utf8_bom() {
let mut content = vec![0xEF, 0xBB, 0xBF];
content.extend_from_slice(b"fn parse_query() {}\n");
let corpus = vec![("src/main.rs".to_string(), content)];
run_differential(&corpus, "parse_query", &[]).unwrap();
}
#[test]
fn golden_smoke_utf16_le() {
let content_u16 = [
0xFF, 0xFE, b'f', 0, b'n', 0, b' ', 0, b'p', 0, b'a', 0, b'r', 0, b's', 0, b'e', 0, b'\n', 0,
];
let corpus = vec![("src/main.rs".to_string(), content_u16.to_vec())];
run_differential(&corpus, "parse", &[]).unwrap();
}
#[test]
fn golden_smoke_utf16_be() {
let content_u16 = [
0xFE, 0xFF, 0, b'f', 0, b'n', 0, b' ', 0, b'p', 0, b'a', 0, b'r', 0, b's', 0, b'e', 0, b'\n',
];
let corpus = vec![("src/main.rs".to_string(), content_u16.to_vec())];
run_differential(&corpus, "parse", &[]).unwrap();
}
#[test]
fn golden_smoke_binary_null_at_8191() {
let mut content = vec![b'a'; 8191];
content.push(0); content.extend_from_slice(b"fn parse_query() {}\n");
let corpus = vec![("src/main.rs".to_string(), content)];
run_differential(&corpus, "parse_query", &[]).unwrap();
}
#[test]
fn golden_smoke_long_token() {
let mut content = b"fn ".to_vec();
content.extend_from_slice(&[b'a'; 130]);
content.extend_from_slice(b"() {}\n");
let corpus = vec![("src/main.rs".to_string(), content)];
let query = String::from_utf8(vec![b'a'; 130]).unwrap();
run_differential(&corpus, &query, &[]).unwrap();
}
#[test]
fn golden_smoke_empty_file() {
let corpus = vec![("src/main.rs".to_string(), Vec::new())];
run_differential(&corpus, "parse", &[]).unwrap();
}
#[test]
fn golden_smoke_invalid_utf8_in_content() {
let corpus = vec![(
"src/main.rs".to_string(),
vec![
b'f', b'n', b' ', b'p', b'a', b'r', b's', b'e', 0xFF, 0xFE, b'\n',
],
)];
run_differential(&corpus, "parse", &[]).unwrap();
}
#[test]
fn golden_smoke_case_insensitive() {
let corpus = vec![("src/main.rs".to_string(), b"fn PARSE_QUERY() {}\n".to_vec())];
run_differential(&corpus, "parse_query", &["-i"]).unwrap();
}
#[test]
fn golden_smoke_alternation() {
let corpus = vec![(
"src/main.rs".to_string(),
b"fn parse() {}\nfn query() {}\n".to_vec(),
)];
run_differential(&corpus, "parse|query", &[]).unwrap();
}
#[test]
fn golden_smoke_char_class_mid_token() {
let corpus = vec![("src/main.rs".to_string(), b"fn parse_query() {}\n".to_vec())];
run_differential(&corpus, "parse_quer[yi]", &[]).unwrap();
}
#[test]
fn golden_smoke_fixed_multi_pattern() {
let corpus = vec![(
"src/main.rs".to_string(),
b"fn parse_query() {}\nfn reparse() {}\nfn query_all() {}\n".to_vec(),
)];
run_differential(&corpus, "parse_query", &["-F"]).unwrap();
run_differential(&corpus, "query_all", &["-F"]).unwrap();
}
#[test]
fn golden_smoke_word_regexp_alternation() {
let corpus = vec![(
"src/main.rs".to_string(),
b"foo bar foobar barfoo\n".to_vec(),
)];
run_differential(&corpus, "foo|bar", &["-w"]).unwrap();
}
#[test]
fn golden_smoke_only_matching_context() {
let corpus = vec![(
"src/main.rs".to_string(),
b"before\nfn parse_query() {}\nafter\n".to_vec(),
)];
run_differential(&corpus, "parse", &["-o"]).unwrap();
}
#[test]
fn golden_smoke_count_lines() {
let corpus = vec![
(
"src/main.rs".to_string(),
b"fn parse() {}\nfn parse_query() {}\nfn other() {}\n".to_vec(),
),
("src/lib.rs".to_string(), b"fn parse_all() {}\n".to_vec()),
];
run_differential_with_tier_c(&corpus, "parse", &["-c"]).unwrap();
}
#[test]
fn golden_smoke_files_with_matches() {
let corpus = vec![
("src/main.rs".to_string(), b"fn parse_query() {}\n".to_vec()),
("src/lib.rs".to_string(), b"fn reparse() {}\n".to_vec()),
("src/util.rs".to_string(), b"fn helper() {}\n".to_vec()),
];
run_differential_with_tier_c(&corpus, "parse", &["-l"]).unwrap();
}
#[test]
fn golden_smoke_vimgrep() {
let corpus = vec![(
"src/main.rs".to_string(),
b"fn parse_query() {}\nfn reparse() {}\n".to_vec(),
)];
run_differential_with_tier_c(&corpus, "parse", &["--vimgrep"]).unwrap();
}
#[test]
fn golden_smoke_line_regexp() {
let corpus = vec![(
"src/main.rs".to_string(),
b"parse\nfn parse_query() {}\nparse_all\n".to_vec(),
)];
run_differential(&corpus, "parse", &["-x"]).unwrap();
}
#[test]
fn golden_smoke_word_regexp() {
let corpus = vec![(
"src/main.rs".to_string(),
b"parse parse_query reparse\n".to_vec(),
)];
run_differential(&corpus, "parse", &["-w"]).unwrap();
}
fn generate_cli_run() -> impl Strategy<Value = (Vec<(String, Vec<u8>)>, String, Vec<&'static str>)>
{
generate_corpus().prop_flat_map(|corpus| {
let query_strat = generate_query(&corpus);
let flags_strat = generate_flags();
(Just(corpus), query_strat, flags_strat)
})
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(20))]
#[test]
fn test_cli_differential((corpus, query, flags) in generate_cli_run()) {
let has_regex_meta = query.chars().any(|c| matches!(c, '.' | '*' | '+' | '?' | '[' | ']' | '{' | '}' | '(' | ')' | '|' | '^' | '$' | '\\'));
let effective_flags: Vec<&str> = flags.iter()
.filter(|&&f| !(f == "-F" && has_regex_meta))
.copied()
.collect();
let res = run_differential_with_tier_c(&corpus, &query, &effective_flags);
assert!(res.is_ok(), "differential test failed: {:?}", res);
}
}
#[test]
fn test_regression_fixtures() {
use serde::Deserialize;
use std::fs;
#[derive(Deserialize)]
struct RegressionFixture {
r#type: String,
corpus: Vec<FileEntry>,
query: String,
flags: Vec<String>,
}
#[derive(Deserialize)]
struct FileEntry {
path: String,
content_b64: String,
}
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let regressions_dir = std::path::Path::new(manifest_dir)
.join("tests")
.join("oracle")
.join("regressions");
if !regressions_dir.exists() {
return;
}
let entries = fs::read_dir(regressions_dir).unwrap();
let mut count = 0;
for entry in entries {
let entry = entry.unwrap();
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("json") {
count += 1;
println!("Running regression fixture: {:?}", path);
let content = fs::read_to_string(&path).unwrap();
let fixture: RegressionFixture = serde_json::from_str(&content).unwrap();
let corpus: Vec<(String, Vec<u8>)> = fixture
.corpus
.iter()
.map(|fe| {
let bytes = oracle_helpers::base64_decode(&fe.content_b64)
.unwrap_or_else(|e| panic!("invalid base64 in fixture {:?}: {}", path, e));
(fe.path.clone(), bytes)
})
.collect();
let flags_refs: Vec<&str> = fixture.flags.iter().map(|s| s.as_str()).collect();
if fixture.r#type == "cli" {
if let Err(e) = run_differential_with_tier_c(&corpus, &fixture.query, &flags_refs) {
panic!("Regression fixture failed: {:?}\nError: {}", path, e);
}
} else {
panic!("Unknown regression fixture type: {}", fixture.r#type);
}
}
}
println!("Successfully ran {} regression fixtures", count);
}