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}