| 20 | |
| 21 | #[test] |
| 22 | fn test_cases() { |
| 23 | let cases: Vec<Case> = |
| 24 | serde_json::from_str(include_str!("cases/parser.json")).expect("invalid JSON"); |
| 25 | |
| 26 | for case in cases { |
| 27 | let (tokens, lex_errs) = lex(&case.src); |
| 28 | let mut parser = Parser::new(&case.src, tokens.into_iter()); |
| 29 | for e in lex_errs { parser.errors.push(Diagnostic { start: e.start, end: e.end, msg: e.msg.into() }); } |
| 30 | let (chunk, diagnostics) = parser.parse(); |
| 31 | |
| 32 | let constants: Vec<String> = chunk |
| 33 | .constants |
| 34 | .iter() |
| 35 | .map(|v| match v { |
| 36 | Value::Str(s) => s.clone(), |
| 37 | Value::Bytes(b) => format!("b{:?}", |
| 38 | String::from_utf8_lossy(b).to_string()), |
| 39 | Value::Int(i) => i.to_string(), |
| 40 | Value::LongInt(i) => i.to_string(), |
| 41 | Value::Float(f) => f.to_string(), |
| 42 | Value::Bool(b) => b.to_string(), |
| 43 | Value::None => "None".to_string(), |
| 44 | }) |
| 45 | .collect(); |
| 46 | |
| 47 | let instructions: Vec<(String, u16)> = chunk |
| 48 | .instructions |
| 49 | .iter() |
| 50 | // Debug-format opcodes for snapshot comparison (test-only). |
| 51 | .map(|i| (format!("{:?}", i.opcode), i.operand)) |
| 52 | .collect(); |
| 53 | |
| 54 | assert_eq!( |
| 55 | constants, case.constants, |
| 56 | "constants mismatch on: {:?}", |
| 57 | case.src |
| 58 | ); |
| 59 | assert_eq!(chunk.names, case.names, "names mismatch on: {:?}", case.src); |
| 60 | assert_eq!( |
| 61 | instructions, case.instructions, |
| 62 | "bytecode mismatch on: {:?}", |
| 63 | case.src |
| 64 | ); |
| 65 | assert_eq!( |
| 66 | chunk.functions.len(), |
| 67 | case.functions, |
| 68 | "functions mismatch on: {:?}", |
| 69 | case.src |
| 70 | ); |
| 71 | assert_eq!( |
| 72 | chunk.classes.len(), |
| 73 | case.classes, |
| 74 | "classes mismatch on: {:?}", |
| 75 | case.src |
| 76 | ); |
| 77 | |
| 78 | if !case.errors.is_empty() { |
| 79 | let actual: Vec<String> = diagnostics.iter().map(|e| e.msg.clone()).collect(); |