code wiki / (root) / prop_lex_number_test.nx

prop_lex_number_test.nx source

↩ module page · 86 lines · 2734 B

1// prop_lex_number_test.nx -- property test for lex_source on numbers. 2// 3// Property: for every random decimal digit sequence D with value V, 4// lex_source(D) produces exactly one TK_INT with int_val == V. 5// 6// Catches: 7// * Overflow in the digit accumulator (V doesn't match hand math) 8// * Off-by-one in digit iteration 9// * Mis-tokenising legal digit chars as something else 10// * Crash on edge cases (leading zeros, max i64 magnitude, etc.) 11// 12// Runs 2000 iterations. Each iteration picks a random number of 13// digits (1..18 -- safely under i64 range for uniform digits). 14 15import "syscalls.nx" 16import "types.nx" 17import "lex_kinds.nx" 18import "lex.nx" 19import "prop_test.nx" 20 21// Compute the value of `buf[0..n]` interpreted as ASCII decimal. 22// Matches the lexer's integer path for validation. 23func ascii_to_i64(buf: *u8, n: i64) -> i64 { 24 var v: i64 = 0 25 var i: i64 = 0 26 while i < n { 27 v = v * 10 + (buf[i] - 0x30) 28 i = i + 1 29 } 30 return v 31} 32 33func main() -> i64 { 34 let g: *PropGen = prop_gen_new(0xC0FFEE) 35 let src: *u8 = sys_mmap(64) 36 37 var iter: i64 = 0 38 while iter < 2000 { 39 g.iter = iter 40 41 // Pick a digit count in [1, 18]. 42 let n_digits: i64 = prop_gen_range(g, 1, 18) 43 44 // Generate n_digits random decimal digits. First digit 45 // must be non-zero unless n_digits==1 (else we're testing 46 // leading zeros which is a separate property). 47 var d: i64 = 0 48 while d < n_digits { 49 var digit: i64 = prop_gen_range(g, 0, 9) 50 if d == 0 { 51 if n_digits > 1 { 52 if digit == 0 { digit = 1 } 53 } 54 } 55 src[d] = 0x30 + digit 56 d = d + 1 57 } 58 src[n_digits] = 0 59 60 let expected: i64 = ascii_to_i64(src, n_digits) 61 62 let toks: *Tok = lex_source(src, 64) 63 if toks == (0 as *Tok) { 64 prop_report(g, "lex_source returned null" as *u8) 65 return __syscall(93, 10, 0, 0, 0, 0, 0) 66 } 67 if toks.kind != TK_INT { 68 prop_report(g, "first tok not TK_INT" as *u8) 69 return __syscall(93, 11, 0, 0, 0, 0, 0) 70 } 71 if toks.int_val != expected { 72 prop_report(g, "int_val != expected" as *u8) 73 sys_write(2, " input: " as *u8, 9) 74 sys_write(2, src, n_digits) 75 sys_write(2, "\n expected: " as *u8, 13) 76 nx_puti_err(expected) 77 sys_write(2, " got: " as *u8, 7) 78 nx_puti_err(toks.int_val) 79 return __syscall(93, 12, 0, 0, 0, 0, 0) 80 } 81 82 iter = iter + 1 83 } 84 85 return 0 86}