#[cfg(test)]
mod golden_path_tests {
use crate::clang::lexer::Lexer;
use crate::clang::token::TokenKind;
use crate::clang::preprocessor::Preprocessor;
use crate::clang::parser::Parser;
use crate::clang::sema::Sema;
use crate::clang::codegen::ClangCodeGen;
use crate::clang::CLangStandard;
use crate::context::LLVMContext;
#[test]
fn golden_empty_program() {
let source = "";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all();
assert!(tokens.is_empty() || tokens.iter().all(|t| t.kind == TokenKind::Eof));
}
#[test]
fn golden_lexer_keywords() {
let source = "int return if else while for void char float double struct union enum";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
assert!(tokens.len() >= 15, "Expected at least 15 tokens, got {}", tokens.len());
let kinds: Vec<&TokenKind> = tokens.iter().map(|t| &t.kind).collect();
assert!(kinds.contains(&&TokenKind::KwInt));
assert!(kinds.contains(&&TokenKind::KwReturn));
assert!(kinds.contains(&&TokenKind::KwIf));
assert!(kinds.contains(&&TokenKind::KwElse));
assert!(kinds.contains(&&TokenKind::KwWhile));
assert!(kinds.contains(&&TokenKind::KwFor));
assert!(kinds.contains(&&TokenKind::KwVoid));
assert!(kinds.contains(&&TokenKind::KwChar));
assert!(kinds.contains(&&TokenKind::KwFloat));
assert!(kinds.contains(&&TokenKind::KwDouble));
assert!(kinds.contains(&&TokenKind::KwStruct));
assert!(kinds.contains(&&TokenKind::KwUnion));
assert!(kinds.contains(&&TokenKind::KwEnum));
}
#[test]
fn golden_lexer_integers() {
let source = "0 42 0xFF 0777 0b1010 1234567890";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let nums: Vec<_> = tokens.iter()
.filter(|t| t.kind == TokenKind::NumericLiteral)
.collect();
assert_eq!(nums.len(), 6, "Expected 6 numeric literals");
}
#[test]
fn golden_lexer_strings() {
let source = r#""hello" 'a' "world\n" '\x41' L"wide" u8"utf8""#;
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let strings: Vec<_> = tokens.iter()
.filter(|t| matches!(&t.kind,
TokenKind::StringLiteral | TokenKind::CharLiteral |
TokenKind::WideStringLiteral | TokenKind::UTF8StringLiteral |
TokenKind::WideCharLiteral | TokenKind::UTF8CharLiteral))
.collect();
assert!(strings.len() >= 5, "Expected at least 5 string/char literals, got {}", strings.len());
}
#[test]
fn golden_lexer_operators() {
let source = "+ - * / % ++ -- == != < > <= >= && || ! & | ^ ~ << >> += -= *= /= &= |= ^=";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
assert!(tokens.len() >= 30, "Expected at least 30 operator tokens, got {}", tokens.len());
}
#[test]
fn golden_lexer_minimal_function() {
let source = "int main(void) { return 0; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
assert!(tokens.len() >= 10, "Expected at least 10 tokens for main(), got {}", tokens.len());
let kinds: Vec<&TokenKind> = tokens.iter().map(|t| &t.kind).collect();
assert!(kinds.contains(&&TokenKind::KwInt), "Missing 'int' keyword");
assert!(kinds.contains(&&TokenKind::Identifier), "Missing identifier 'main'");
assert!(kinds.contains(&&TokenKind::KwVoid), "Missing 'void' keyword");
assert!(kinds.contains(&&TokenKind::KwReturn), "Missing 'return' keyword");
assert!(kinds.contains(&&TokenKind::NumericLiteral), "Missing '0' literal");
}
#[test]
fn golden_parser_empty() {
let source = "";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept empty input: {:?}", result.err());
}
#[test]
fn golden_parser_function_decl() {
let source = "int foo(int a, int b);";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept function declaration: {:?}", result.err());
}
#[test]
fn golden_parser_function_def() {
let source = "int add(int a, int b) { return a + b; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept function definition: {:?}", result.err());
}
#[test]
fn golden_parser_global_var() {
let source = "int x = 42;";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept global variable: {:?}", result.err());
}
#[test]
fn golden_parser_struct() {
let source = "struct Point { int x; int y; };";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept struct definition: {:?}", result.err());
}
#[test]
fn golden_sema_empty() {
let source = "";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let tu = parser.parse().expect("Parse failed");
let mut sema = Sema::new(CLangStandard::C17);
let result = sema.analyze(&tu);
assert!(result.is_ok(), "Sema should accept empty TU: {:?}", result.err());
}
#[test]
fn golden_sema_simple_function() {
let source = "int main(void) { return 0; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let tu = parser.parse().expect("Parse failed");
let mut sema = Sema::new(CLangStandard::C17);
let result = sema.analyze(&tu);
match result {
Ok(_) => {},
Err(errors) => {
eprintln!("Sema warnings (expected for simple case): {:?}", errors);
}
}
}
#[test]
fn golden_codegen_simple_function() {
let source = "int add(int a, int b) { return a + b; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let tu = parser.parse().expect("Parse failed");
let mut sema = Sema::new(CLangStandard::C17);
sema.analyze(&tu).ok();
let mut cg = ClangCodeGen::new("test", "x86_64-unknown-linux-gnu");
let result = cg.compile(&tu);
match result {
Ok(_) => eprintln!("CodeGen SUCCESS for add()"),
Err(errors) => {
eprintln!("CodeGen errors (may be expected): {:?}", errors);
}
}
}
#[test]
fn golden_full_pipeline_main() {
let source = "int main(void) { return 0; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
eprintln!(" [1] Lexed {} tokens", tokens.len());
let mut parser = Parser::new(tokens, CLangStandard::C17);
let tu = match parser.parse() {
Ok(tu) => { eprintln!(" [2] Parse OK"); tu }
Err(e) => { eprintln!(" [2] Parse FAILED: {:?}", e); return; }
};
let mut sema = Sema::new(CLangStandard::C17);
match sema.analyze(&tu) {
Ok(_) => eprintln!(" [3] Sema OK"),
Err(e) => eprintln!(" [3] Sema warnings/errors: {} issues", e.len()),
}
let mut cg = ClangCodeGen::new("main", "x86_64-unknown-linux-gnu");
match cg.compile(&tu) {
Ok(_) => eprintln!(" [4] CodeGen OK — GOLDEN PATH WORKS!"),
Err(e) => eprintln!(" [4] CodeGen errors: {} issues", e.len()),
}
eprintln!(" [5] Pipeline complete!");
}
#[test]
fn golden_variable_init() {
let source = "int count = 100; float pi = 3.14; char c = 'a';";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept variable initializers: {:?}", result.err());
}
#[test]
fn golden_if_statement() {
let source = "int test(int x) { if (x > 0) { return 1; } else { return 0; } }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept if/else: {:?}", result.err());
}
#[test]
fn golden_while_loop() {
let source = "void loop(int n) { while (n > 0) { n = n - 1; } }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept while loop: {:?}", result.err());
}
#[test]
fn golden_for_loop() {
let source = "int sum(int n) { int s = 0; for (int i = 0; i < n; i++) { s += i; } return s; }";
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let mut parser = Parser::new(tokens, CLangStandard::C17);
let result = parser.parse();
assert!(result.is_ok(), "Parser should accept for loop: {:?}", result.err());
}
#[test]
fn golden_stress_lexer() {
let mut source = String::new();
for i in 0..100 {
source.push_str(&format!("int var{} = {};\n", i, i * 7));
}
source.push_str("int main(void) { return 0; }");
let mut lexer = Lexer::new(&source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
assert!(tokens.len() > 500, "Expected >500 tokens, got {}", tokens.len());
}
#[test]
fn golden_oracle_comparison_lexer() {
let source = "int main(void) { return 42; }";
let oracle_sequence = vec![
TokenKind::KwInt,
TokenKind::Identifier, TokenKind::LParen,
TokenKind::KwVoid,
TokenKind::RParen,
TokenKind::LBrace,
TokenKind::KwReturn,
TokenKind::NumericLiteral, TokenKind::Semicolon,
TokenKind::RBrace,
TokenKind::Eof,
];
let mut lexer = Lexer::new(source, CLangStandard::C17);
let tokens = lexer.lex_all().to_vec();
let actual_kinds: Vec<&TokenKind> = tokens.iter()
.filter(|t| t.kind != TokenKind::Newline && t.kind != TokenKind::Comment)
.map(|t| &t.kind)
.collect();
eprintln!("Oracle sequence: {:?}", oracle_sequence);
eprintln!("Actual sequence: {:?}", actual_kinds);
assert_eq!(
actual_kinds.len(),
oracle_sequence.len(),
"Token count mismatch"
);
for (i, (expected, actual)) in oracle_sequence.iter().zip(actual_kinds.iter()).enumerate() {
assert_eq!(
std::mem::discriminant(expected),
std::mem::discriminant(*actual),
"Token mismatch at position {}: expected {:?}, got {:?}",
i, expected, actual
);
}
eprintln!(" ✅ Oracle comparison PASSED — all token kinds match!");
}
}