nx_cigar_test.nx source
↩ module page · 174 lines · 7647 B
1// nx_cigar_test.nx -- KAT for CIGAR compression + ASCII serialiser.
2//
3// expect_exit: 0
4//
5// license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_const.nx"
9import "nx_cigar.nx"
10
11func main() -> i64 {
12
13 let ops: *u8 = sys_mmap(64)
14 let codes: *u8 = sys_mmap(64)
15 let lens: *i64 = sys_mmap(128) as *i64
16 let ascii_buf: *u8 = sys_mmap(128)
17 let digits_buf: *u8 = sys_mmap(32)
18
19 // ============================================================
20 // Section A -- nx_i64_to_ascii_digits.
21 // ============================================================
22
23 if nx_i64_to_ascii_digits(0, digits_buf) != 1 { return 1 }
24 if (digits_buf[0] & 0xff) != 0x30 { return 2 } // '0'
25
26 if nx_i64_to_ascii_digits(7, digits_buf) != 1 { return 3 }
27 if (digits_buf[0] & 0xff) != 0x37 { return 4 } // '7'
28
29 if nx_i64_to_ascii_digits(42, digits_buf) != 2 { return 5 }
30 if (digits_buf[0] & 0xff) != 0x34 { return 6 } // '4'
31 if (digits_buf[1] & 0xff) != 0x32 { return 7 } // '2'
32
33 if nx_i64_to_ascii_digits(12345, digits_buf) != 5 { return 8 }
34 if (digits_buf[0] & 0xff) != 0x31 { return 9 } // '1'
35 if (digits_buf[1] & 0xff) != 0x32 { return 10 } // '2'
36 if (digits_buf[2] & 0xff) != 0x33 { return 11 } // '3'
37 if (digits_buf[3] & 0xff) != 0x34 { return 12 } // '4'
38 if (digits_buf[4] & 0xff) != 0x35 { return 13 } // '5'
39
40 if nx_i64_to_ascii_digits(-1, digits_buf) != 0 { return 14 } // refused
41
42 // ============================================================
43 // Section B -- nx_cigar_code_to_ascii.
44 // ============================================================
45
46 if nx_cigar_code_to_ascii(NX_CIGAR_M) != 0x4D { return 20 }
47 if nx_cigar_code_to_ascii(NX_CIGAR_I) != 0x49 { return 21 }
48 if nx_cigar_code_to_ascii(NX_CIGAR_D) != 0x44 { return 22 }
49 if nx_cigar_code_to_ascii(NX_CIGAR_N) != 0x4E { return 23 }
50 if nx_cigar_code_to_ascii(NX_CIGAR_S) != 0x53 { return 24 }
51 if nx_cigar_code_to_ascii(NX_CIGAR_EQ) != 0x3D { return 25 }
52 if nx_cigar_code_to_ascii(NX_CIGAR_X) != 0x58 { return 26 }
53 if nx_cigar_code_to_ascii(99) != 0x3F { return 27 } // '?' fallback
54
55 // ============================================================
56 // Section C -- cigar_compress: single-op run.
57 // "MMMM" (4 ops) -> [(M, 4)], 1 group.
58 // ============================================================
59
60 ops[0] = NX_CIGAR_M & 0xff
61 ops[1] = NX_CIGAR_M & 0xff
62 ops[2] = NX_CIGAR_M & 0xff
63 ops[3] = NX_CIGAR_M & 0xff
64 let n1: i64 = cigar_compress(ops, 4, codes, lens, 16)
65 if n1 != 1 { return 30 }
66 if (codes[0] & 0xff) != NX_CIGAR_M { return 31 }
67 if lens[0] != 4 { return 32 }
68
69 // ============================================================
70 // Section D -- cigar_compress: multi-op runs.
71 // "MMMIIIIDD" (9 ops) -> [(M,3), (I,4), (D,2)], 3 groups.
72 // ============================================================
73
74 ops[0]=NX_CIGAR_M & 0xff; ops[1]=NX_CIGAR_M & 0xff; ops[2]=NX_CIGAR_M & 0xff
75 ops[3]=NX_CIGAR_I & 0xff; ops[4]=NX_CIGAR_I & 0xff; ops[5]=NX_CIGAR_I & 0xff; ops[6]=NX_CIGAR_I & 0xff
76 ops[7]=NX_CIGAR_D & 0xff; ops[8]=NX_CIGAR_D & 0xff
77 let n2: i64 = cigar_compress(ops, 9, codes, lens, 16)
78 if n2 != 3 { return 40 }
79 if (codes[0] & 0xff) != NX_CIGAR_M { return 41 }
80 if lens[0] != 3 { return 42 }
81 if (codes[1] & 0xff) != NX_CIGAR_I { return 43 }
82 if lens[1] != 4 { return 44 }
83 if (codes[2] & 0xff) != NX_CIGAR_D { return 45 }
84 if lens[2] != 2 { return 46 }
85
86 // ============================================================
87 // Section E -- cigar_compress: alternating ops (worst case).
88 // "MIMDM" -> 5 groups each length 1.
89 // ============================================================
90
91 ops[0]=NX_CIGAR_M & 0xff
92 ops[1]=NX_CIGAR_I & 0xff
93 ops[2]=NX_CIGAR_M & 0xff
94 ops[3]=NX_CIGAR_D & 0xff
95 ops[4]=NX_CIGAR_M & 0xff
96 let n3: i64 = cigar_compress(ops, 5, codes, lens, 16)
97 if n3 != 5 { return 50 }
98 if lens[0] != 1 { return 51 }
99 if lens[4] != 1 { return 52 }
100 if (codes[0] & 0xff) != NX_CIGAR_M { return 53 }
101 if (codes[1] & 0xff) != NX_CIGAR_I { return 54 }
102 if (codes[2] & 0xff) != NX_CIGAR_M { return 55 }
103 if (codes[3] & 0xff) != NX_CIGAR_D { return 56 }
104 if (codes[4] & 0xff) != NX_CIGAR_M { return 57 }
105
106 // ============================================================
107 // Section F -- empty + capacity overflow.
108 // ============================================================
109
110 if cigar_compress(ops, 0, codes, lens, 16) != 0 { return 60 }
111 if cigar_compress(ops, -1, codes, lens, 16) != -1 { return 61 }
112 if cigar_compress(ops, 5, codes, lens, 0) != -1 { return 62 }
113 if cigar_compress(ops, 5, codes, lens, 2) != -1 { return 63 } // 5 alt groups need 5 cap
114
115 // ============================================================
116 // Section G -- cigar_serialize: single group.
117 // [(M, 4)] -> "4M" (2 bytes).
118 // ============================================================
119
120 codes[0] = NX_CIGAR_M & 0xff
121 lens[0] = 4
122 let s1: i64 = cigar_serialize(codes, lens, 1, ascii_buf, 64)
123 if s1 != 2 { return 70 }
124 if (ascii_buf[0] & 0xff) != 0x34 { return 71 } // '4'
125 if (ascii_buf[1] & 0xff) != 0x4D { return 72 } // 'M'
126
127 // ============================================================
128 // Section H -- cigar_serialize: multi-group + multi-digit lengths.
129 // [(M, 12), (I, 1), (D, 3)] -> "12M1I3D" (7 bytes).
130 // ============================================================
131
132 codes[0]=NX_CIGAR_M & 0xff; lens[0]=12
133 codes[1]=NX_CIGAR_I & 0xff; lens[1]=1
134 codes[2]=NX_CIGAR_D & 0xff; lens[2]=3
135 let s2: i64 = cigar_serialize(codes, lens, 3, ascii_buf, 64)
136 if s2 != 7 { return 80 }
137 if (ascii_buf[0] & 0xff) != 0x31 { return 81 } // '1'
138 if (ascii_buf[1] & 0xff) != 0x32 { return 82 } // '2'
139 if (ascii_buf[2] & 0xff) != 0x4D { return 83 } // 'M'
140 if (ascii_buf[3] & 0xff) != 0x31 { return 84 } // '1'
141 if (ascii_buf[4] & 0xff) != 0x49 { return 85 } // 'I'
142 if (ascii_buf[5] & 0xff) != 0x33 { return 86 } // '3'
143 if (ascii_buf[6] & 0xff) != 0x44 { return 87 } // 'D'
144
145 // ============================================================
146 // Section I -- end-to-end: "MIMM" (the G1.0c gap-path backtrace
147 // for AGCT/ACT) compresses to [(M,1),(I,1),(M,2)] = 3 groups
148 // and serialises to "1M1I2M" (6 bytes).
149 // ============================================================
150
151 ops[0]=NX_CIGAR_M & 0xff
152 ops[1]=NX_CIGAR_I & 0xff
153 ops[2]=NX_CIGAR_M & 0xff
154 ops[3]=NX_CIGAR_M & 0xff
155 let n4: i64 = cigar_compress(ops, 4, codes, lens, 16)
156 if n4 != 3 { return 90 }
157 let s3: i64 = cigar_serialize(codes, lens, n4, ascii_buf, 64)
158 if s3 != 6 { return 91 }
159 if (ascii_buf[0] & 0xff) != 0x31 { return 92 } // '1'
160 if (ascii_buf[1] & 0xff) != 0x4D { return 93 } // 'M'
161 if (ascii_buf[2] & 0xff) != 0x31 { return 94 } // '1'
162 if (ascii_buf[3] & 0xff) != 0x49 { return 95 } // 'I'
163 if (ascii_buf[4] & 0xff) != 0x32 { return 96 } // '2'
164 if (ascii_buf[5] & 0xff) != 0x4D { return 97 } // 'M'
165
166 // ============================================================
167 // Section J -- empty serialise + capacity overflow.
168 // ============================================================
169
170 if cigar_serialize(codes, lens, 0, ascii_buf, 64) != 0 { return 100 }
171 if cigar_serialize(codes, lens, 3, ascii_buf, 3) != -1 { return 101 } // "12M" alone is 3 bytes, can't fit "1I"
172
173 return 0
174}