nx_quality_grade_test.nx source
↩ module page · 281 lines · 12108 B
1// nx_quality_grade_test.nx -- smoke: synthesize a tiny Module IR and
2// grade it via every Layer-0 rule. Asserts:
3//
4// license_tier: ORIGINAL
5//
6// 1. Sealed-enum validity predicates accept all in-range values and
7// reject out-of-range.
8// 2. A clean synthetic Module (1 main function, 0 BR_COND, 5 instrs,
9// no dead funcs) grades A.
10// 3. A messy synthetic Module (1 function with CCN > 25, 1 dead
11// function) grades D or worse.
12// 4. The grader correctly counts findings per category.
13//
14// We hand-build Module + Function structs in mmap'd memory instead of
15// running the self-host parser. This isolates the grader logic from
16// any parser bugs and lets the smoke run in milliseconds.
17
18import "nx_syscalls.nx"
19import "nx_runtime.nx"
20import "nx_types.nx"
21import "nx_tier.nx"
22import "nx_quality_grade.nx"
23
24// Build a single Function with the given name + instruction count +
25// BR_COND count. Returns *Function (allocated via sys_mmap).
26func _build_function(name: *u8, name_len: nx_int,
27 n_instrs: nx_int, n_br_cond: nx_int) -> *Function {
28 let f_raw: *u8 = sys_mmap(NX_GRADE_FUNCTION_STRIDE + 16)
29 let f: *Function = f_raw as *Function
30 f.name_start = name as nx_int
31 f.name_len = name_len
32 f.n_params = 0
33 f.values = 0 as *Value
34 f.n_values = 0
35 f.values_cap = 0
36 f.blocks = 0 as *BasicBlock
37 f.n_blocks = 1
38 f.blocks_cap = 0
39 let instrs_raw: *u8 = sys_mmap(NX_GRADE_INSTR_STRIDE * n_instrs + 32)
40 f.instrs = instrs_raw as *Instr
41 f.n_instrs = n_instrs
42 f.instrs_cap = n_instrs
43
44 // Populate instructions: first n_br_cond are BR_COND, the last one
45 // is OP_RETURN (so the Layer-1 reliability rule sees an explicit
46 // return path), the rest are ADD.
47 var i: nx_int = 0
48 while i < n_instrs {
49 let inst: *Instr = (instrs_raw as nx_int + i * NX_GRADE_INSTR_STRIDE) as *Instr
50 if i == n_instrs - 1 {
51 inst.op = OP_RETURN
52 } else {
53 if i < n_br_cond {
54 inst.op = OP_BR_COND
55 } else {
56 inst.op = OP_ADD
57 }
58 }
59 inst.result = 0
60 inst.n_operands = 0
61 inst.op0 = 0
62 inst.op1 = 0
63 inst.callee = 0 as *Function
64 i = i + 1
65 }
66 return f
67}
68
69// Build a Module with a single Function (passed in). Returns *Module.
70func _build_module_1fn(f0: *Function) -> *Module {
71 let m_raw: *u8 = sys_mmap(256)
72 let m: *Module = m_raw as *Module
73 // Module.functions is an array; lay one Function at base.
74 let fns_raw: *u8 = sys_mmap(NX_GRADE_FUNCTION_STRIDE + 32)
75 let fns_base: nx_int = fns_raw as nx_int
76 // Memcpy via 22 i64 slots (Function is 176 bytes = 22 nx_int).
77 let dst: *i64 = fns_raw as *i64
78 let src: *i64 = f0 as *i64
79 var j: nx_int = 0
80 while j < 22 {
81 let s_addr: nx_int = (src as nx_int) + j * 8
82 let d_addr: nx_int = (dst as nx_int) + j * 8
83 let sp: *i64 = s_addr as *i64
84 let dp: *i64 = d_addr as *i64
85 dp[0] = sp[0]
86 j = j + 1
87 }
88 m.functions = fns_raw as *Function
89 m.n_functions = 1
90 return m
91}
92
93// Build a Module with two Functions, second is dead.
94func _build_module_2fns(f0: *Function, f1: *Function) -> *Module {
95 let m_raw: *u8 = sys_mmap(256)
96 let m: *Module = m_raw as *Module
97 let fns_raw: *u8 = sys_mmap(NX_GRADE_FUNCTION_STRIDE * 2 + 32)
98 // Copy f0 at slot 0, f1 at slot 1.
99 var k: nx_int = 0
100 while k < 2 {
101 let src_fn: *Function = f0
102 if k == 1 { let s2: *Function = f1; let src_addr: nx_int = s2 as nx_int; let dst_addr: nx_int = (fns_raw as nx_int) + k * NX_GRADE_FUNCTION_STRIDE; var j: nx_int = 0; while j < 22 { let sp: *i64 = (src_addr + j * 8) as *i64; let dp: *i64 = (dst_addr + j * 8) as *i64; dp[0] = sp[0]; j = j + 1 } }
103 if k == 0 { let src_addr: nx_int = f0 as nx_int; let dst_addr: nx_int = (fns_raw as nx_int) + k * NX_GRADE_FUNCTION_STRIDE; var j: nx_int = 0; while j < 22 { let sp: *i64 = (src_addr + j * 8) as *i64; let dp: *i64 = (dst_addr + j * 8) as *i64; dp[0] = sp[0]; j = j + 1 } }
104 k = k + 1
105 }
106 m.functions = fns_raw as *Function
107 m.n_functions = 2
108 return m
109}
110
111func main() -> nx_int {
112 // ---- Test 1: sealed-enum validity predicates ---------------------
113 if nx_grade_severity_is_valid(NX_SEV_INFO) != 1 { return 1 }
114 if nx_grade_severity_is_valid(NX_SEV_SECURITY) != 1 { return 2 }
115 if nx_grade_severity_is_valid(NX_SEV_N) != 0 { return 3 }
116 if nx_grade_severity_is_valid(-1) != 0 { return 4 }
117 if nx_grade_kind_is_valid(NX_KIND_COMPLEXITY) != 1 { return 5 }
118 if nx_grade_kind_is_valid(NX_KIND_API_MISUSE) != 1 { return 6 }
119 if nx_grade_kind_is_valid(NX_KIND_N) != 0 { return 7 }
120 if nx_grade_verdict_is_valid(NX_QV_WIN) != 1 { return 8 }
121 if nx_grade_verdict_is_valid(NX_QV_N) != 0 { return 9 }
122 if nx_grade_letter_is_valid(NX_GRADE_A) != 1 { return 10 }
123 if nx_grade_letter_is_valid(NX_GRADE_N) != 0 { return 11 }
124
125 // ---- Test 2: clean module grades well ----------------------------
126 //
127 // One function "main" (4 chars), 5 instructions, 0 BR_COND. Expect:
128 // - complexity: CCN=1 -> WIN
129 // - maintain: fn_len=5 -> WIN
130 // - deadcode: main is the only fn and main is excluded -> WIN
131 // - 5 categories UNMEASURED
132 // - grade: A (4 WIN + 0 LOSE >= 4 WIN, 0 LOSE)
133 let main_name: *u8 = "main" as *u8
134 let f_clean: *Function = _build_function(main_name, 4, 5, 0)
135 let m_clean: *Module = _build_module_1fn(f_clean)
136
137 let prof_raw: *u8 = sys_mmap(128)
138 let prof_sq: *GradeProfile = prof_raw as *GradeProfile
139 nx_grade_profile_sonarqube(prof_sq)
140
141 let card1: *GradeCard = nx_grade_card_alloc()
142 nx_grade_card_init(card1)
143 nx_grade_card_scan(card1, m_clean, prof_sq)
144 nx_grade_card_compute(card1, prof_sq)
145
146 if card1.cat_complexity.verdict != NX_QV_WIN { return 20 }
147 if card1.cat_maintain.verdict != NX_QV_WIN { return 21 }
148 if card1.cat_deadcode.verdict != NX_QV_WIN { return 22 }
149 // Layers 1 + 2 add 5 more measurable categories (reliability,
150 // portability, performance, security, api_misuse). Synthetic
151 // main: OP_RETURN present, under 8 KiB, no OP_CALL (fanout=0),
152 // no OP_SYSCALL, no sys_open/close imbalance. All 8 categories WIN.
153 if card1.n_wins != 8 { return 23 }
154 if card1.n_losses != 0 { return 24 }
155 if card1.grade != NX_GRADE_S { return 25 }
156
157 // ---- Test 3: messy module grades poorly ----------------------------
158 //
159 // Two functions:
160 // "main" - 200 instructions, 30 BR_COND (CCN=31, fn_len=200)
161 // "dead" - 5 instructions, 0 BR_COND (no callers)
162 // Expect:
163 // - complexity: CCN=31 > 25 -> ERROR -> LOSE
164 // - maintain: fn_len=200 > 150 -> ERROR -> LOSE
165 // - deadcode: 1 dead fn -> LOSE
166 // - grade: D or worse
167 let f_messy: *Function = _build_function(main_name, 4, 200, 30)
168 let dead_name: *u8 = "dead" as *u8
169 let f_dead: *Function = _build_function(dead_name, 4, 5, 0)
170 let m_messy: *Module = _build_module_2fns(f_messy, f_dead)
171
172 let card2: *GradeCard = nx_grade_card_alloc()
173 nx_grade_card_init(card2)
174 nx_grade_card_scan(card2, m_messy, prof_sq)
175 nx_grade_card_compute(card2, prof_sq)
176
177 if card2.cat_complexity.verdict != NX_QV_LOSE { return 30 }
178 if card2.cat_complexity.worst_value != 31 { return 31 }
179 if card2.cat_complexity.n_error < 1 { return 32 }
180 if card2.cat_maintain.verdict != NX_QV_LOSE { return 33 }
181 if card2.cat_maintain.worst_value != 200 { return 34 }
182 if card2.cat_deadcode.verdict != NX_QV_LOSE { return 35 }
183 if card2.cat_deadcode.worst_value != 1 { return 36 }
184 // Tightened rubric: >=3 LOSE => D (no longer hideable by more
185 // measured WINs). Messy module hits exactly D.
186 if card2.n_losses < 3 { return 37 }
187 if card2.grade != NX_GRADE_D { return 38 }
188
189 // ---- Test 4: emit summary (smoke that print path works) -----------
190 nx_grade_card_emit(card1)
191
192 // ---- Test 5: TRIANGULATION across SonarQube + clippy + Elm --------
193 //
194 // Synthesise a Module that all three graders should AGREE on as
195 // a clean WIN. CCN=1, fn_len=5 instructions, 0 dead funcs. Even
196 // Elm's strictest thresholds (CCN<=7, fn_len<=24) are cleared.
197 let prof_cl_raw: *u8 = sys_mmap(128)
198 let prof_cl: *GradeProfile = prof_cl_raw as *GradeProfile
199 nx_grade_profile_clippy(prof_cl)
200 let prof_el_raw: *u8 = sys_mmap(128)
201 let prof_el: *GradeProfile = prof_el_raw as *GradeProfile
202 nx_grade_profile_elm(prof_el)
203
204 let card_sq: *GradeCard = nx_grade_card_alloc()
205 nx_grade_card_init(card_sq)
206 nx_grade_card_scan(card_sq, m_clean, prof_sq)
207 nx_grade_card_compute(card_sq, prof_sq)
208
209 let card_cl: *GradeCard = nx_grade_card_alloc()
210 nx_grade_card_init(card_cl)
211 nx_grade_card_scan(card_cl, m_clean, prof_cl)
212 nx_grade_card_compute(card_cl, prof_cl)
213
214 let card_el: *GradeCard = nx_grade_card_alloc()
215 nx_grade_card_init(card_el)
216 nx_grade_card_scan(card_el, m_clean, prof_el)
217 nx_grade_card_compute(card_el, prof_el)
218
219 let tri: *GradeTriangulation = nx_grade_triangulation_alloc()
220 nx_grade_triangulate(tri, card_sq, card_cl, card_el)
221
222 // All three should WIN on complexity + deadcode + maintain +
223 // reliability; portability: sq+el WIN, cl UNMEASURED (clippy has no
224 // Tier-0 lens) -- one outlier, triangulated still WIN.
225 if tri.cat_complexity.triangulated != NX_QV_WIN { return 40 }
226 if tri.cat_complexity.disagreement_count != 0 { return 41 }
227 if tri.cat_deadcode.triangulated != NX_QV_WIN { return 42 }
228 if tri.cat_maintain.triangulated != NX_QV_WIN { return 43 }
229 if tri.cat_portability.triangulated != NX_QV_WIN { return 44 }
230 if tri.cat_portability.disagreement_count != 1 { return 45 }
231 if tri.n_fully_controversial != 0 { return 46 }
232
233 // ---- Test 6: DISAGREEMENT case ------------------------------------
234 //
235 // Build a Module that scores WIN on SonarQube + clippy but LOSE
236 // on Elm. CCN=12 sits between Elm's win_max=7 and SonarQube's
237 // win_max=14. fn_len=60 sits between Elm's 24 and SonarQube's 79.
238 //
239 // SonarQube: CCN=12 <= 14 -> WIN. fn_len=60 <= 79 -> WIN.
240 // clippy: CCN=12 > 11 -> TIE (12 == ccn_warn, not > error).
241 // fn_len=60 <= 119 -> WIN.
242 // Elm: CCN=12 > 7 -> LOSE (since 12 > 7 win_max but > 8 warn,
243 // and > 12 is the error threshold; 12 == 12 so n_error
244 // stays 0, CCN==12 > 8 warn -> n_warn=1, verdict TIE).
245 // Actually CCN=12 means n_error=0 (12 is NOT > 12), so
246 // verdict is checked via worst_value: 12 > 7 win_max,
247 // 12 <= 8 warn? no, 12 > 8 -> LOSE.
248 //
249 // So we expect complexity disagreement.
250 let f_middling: *Function = _build_function(main_name, 4, 60, 11)
251 let m_middling: *Module = _build_module_1fn(f_middling)
252
253 let mid_sq: *GradeCard = nx_grade_card_alloc()
254 nx_grade_card_init(mid_sq)
255 nx_grade_card_scan(mid_sq, m_middling, prof_sq)
256 nx_grade_card_compute(mid_sq, prof_sq)
257
258 let mid_cl: *GradeCard = nx_grade_card_alloc()
259 nx_grade_card_init(mid_cl)
260 nx_grade_card_scan(mid_cl, m_middling, prof_cl)
261 nx_grade_card_compute(mid_cl, prof_cl)
262
263 let mid_el: *GradeCard = nx_grade_card_alloc()
264 nx_grade_card_init(mid_el)
265 nx_grade_card_scan(mid_el, m_middling, prof_el)
266 nx_grade_card_compute(mid_el, prof_el)
267
268 let mid_tri: *GradeTriangulation = nx_grade_triangulation_alloc()
269 nx_grade_triangulate(mid_tri, mid_sq, mid_cl, mid_el)
270
271 // At least one category should show non-zero disagreement -- the
272 // graders DO have meaningfully different thresholds. If all 8
273 // categories were unanimous, our 3 graders would be redundant.
274 if mid_tri.n_with_outlier + mid_tri.n_fully_controversial == 0 {
275 return 50
276 }
277
278 nx_grade_triangulation_emit(mid_tri)
279
280 return 0
281}