nx_fasta_test.nx source
↩ module page · 177 lines · 7086 B
1// nx_fasta_test.nx -- KAT for FASTA single-record parser + strip helper.
2//
3// expect_exit: 0
4//
5// license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_const.nx"
9import "nx_fasta.nx"
10
11func main() -> i64 {
12
13 let buf: *u8 = sys_mmap(256)
14 let dst: *u8 = sys_mmap(256)
15 let meta: *i64 = sys_mmap(128) as *i64
16
17 // ============================================================
18 // Section A -- nx_is_whitespace.
19 // ============================================================
20
21 if nx_is_whitespace(0x0A) != 1 { return 1 } // LF
22 if nx_is_whitespace(0x0D) != 1 { return 2 } // CR
23 if nx_is_whitespace(0x20) != 1 { return 3 } // space
24 if nx_is_whitespace(0x09) != 1 { return 4 } // tab
25 if nx_is_whitespace(0x41) != 0 { return 5 } // 'A'
26 if nx_is_whitespace(0x3E) != 0 { return 6 } // '>'
27
28 // ============================================================
29 // Section B -- fasta_strip_whitespace.
30 // src = "AC\nGT \n " (8 bytes)
31 // strip -> "ACGT" (4 bytes)
32 // ============================================================
33
34 buf[0]=0x41; buf[1]=0x43; buf[2]=0x0A; buf[3]=0x47
35 buf[4]=0x54; buf[5]=0x20; buf[6]=0x0A; buf[7]=0x20
36 let n_strip: i64 = fasta_strip_whitespace(buf, 0, 8, dst, 16)
37 if n_strip != 4 { return 10 }
38 if (dst[0] & 0xff) != 0x41 { return 11 }
39 if (dst[1] & 0xff) != 0x43 { return 12 }
40 if (dst[2] & 0xff) != 0x47 { return 13 }
41 if (dst[3] & 0xff) != 0x54 { return 14 }
42
43 // Empty source range returns 0.
44 if fasta_strip_whitespace(buf, 3, 3, dst, 16) != 0 { return 15 }
45
46 // Capacity exceeded returns -1.
47 if fasta_strip_whitespace(buf, 0, 8, dst, 2) != -1 { return 16 }
48
49 // Bad input.
50 if fasta_strip_whitespace(buf, -1, 8, dst, 16) != -1 { return 17 }
51 if fasta_strip_whitespace(buf, 5, 3, dst, 16) != -1 { return 18 } // end < start
52
53 // ============================================================
54 // Section C -- single record, single-line sequence.
55 // Buffer 10 bytes:
56 // 0 1 2 3 4 5 6 7 8 9
57 // > i d 1 \n A C G T \n
58 // Expected: header_start=1 header_len=3
59 // seq_start=5 seq_end_excl=10 next_offset=10
60 // ============================================================
61
62 buf[0]=NX_ASCII_GT & 0xff
63 buf[1]=0x69; buf[2]=0x64; buf[3]=0x31 // "id1"
64 buf[4]=NX_ASCII_LF & 0xff
65 buf[5]=0x41; buf[6]=0x43; buf[7]=0x47; buf[8]=0x54 // "ACGT"
66 buf[9]=NX_ASCII_LF & 0xff
67
68 if fasta_parse_one_record(buf, 10, 0, meta) != 0 { return 30 }
69 if meta[0] != 1 { return 31 }
70 if meta[1] != 3 { return 32 }
71 if meta[2] != 5 { return 33 }
72 if meta[3] != 10 { return 34 }
73 if meta[4] != 10 { return 35 }
74
75 // Strip seq region to get clean bases.
76 let n_clean: i64 = fasta_strip_whitespace(buf, meta[2], meta[3], dst, 16)
77 if n_clean != 4 { return 36 }
78 if (dst[0] & 0xff) != 0x41 { return 37 }
79 if (dst[3] & 0xff) != 0x54 { return 38 }
80
81 // ============================================================
82 // Section D -- single record, MULTI-LINE sequence.
83 // Buffer 14 bytes:
84 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
85 // > i d \n A C G T \n A C G T \n
86 // Seq region buf[4..14) = "ACGT\nACGT\n" -> after strip: "ACGTACGT" (8 bytes)
87 // Expected: header_start=1 header_len=2
88 // seq_start=4 seq_end_excl=14 next_offset=14
89 // ============================================================
90
91 buf[0]=NX_ASCII_GT & 0xff
92 buf[1]=0x69; buf[2]=0x64 // "id"
93 buf[3]=NX_ASCII_LF & 0xff
94 buf[4]=0x41; buf[5]=0x43; buf[6]=0x47; buf[7]=0x54
95 buf[8]=NX_ASCII_LF & 0xff
96 buf[9]=0x41; buf[10]=0x43; buf[11]=0x47; buf[12]=0x54
97 buf[13]=NX_ASCII_LF & 0xff
98
99 if fasta_parse_one_record(buf, 14, 0, meta) != 0 { return 40 }
100 if meta[0] != 1 { return 41 }
101 if meta[1] != 2 { return 42 }
102 if meta[2] != 4 { return 43 }
103 if meta[3] != 14 { return 44 }
104 if meta[4] != 14 { return 45 }
105
106 let n_clean2: i64 = fasta_strip_whitespace(buf, meta[2], meta[3], dst, 32)
107 if n_clean2 != 8 { return 46 }
108 if (dst[0] & 0xff) != 0x41 { return 47 } // first A
109 if (dst[7] & 0xff) != 0x54 { return 48 } // last T
110 if (dst[4] & 0xff) != 0x41 { return 49 } // start of second line
111
112 // ============================================================
113 // Section E -- two-record stream with multi-line first record.
114 // Buffer 22 bytes:
115 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
116 // > i d \n A C G T \n > i d 2 \n G C T A \n
117 // Hmm let me recount. 22 bytes:
118 // 0:'>' 1:'i' 2:'d' 3:'\n' 4:'A' 5:'C' 6:'G' 7:'T' 8:'\n'
119 // 9:'>' 10:'i' 11:'d' 12:'2' 13:'\n' 14:'G' 15:'C' 16:'T' 17:'A' 18:'\n'
120 // = 19 bytes
121 // First record: header_start=1 header_len=2 seq_start=4 seq_end_excl=9 next_offset=9
122 // Second record (offset=9): header_start=10 header_len=3
123 // seq_start=14 seq_end_excl=19 next_offset=19
124 // ============================================================
125
126 buf[0]=NX_ASCII_GT & 0xff
127 buf[1]=0x69; buf[2]=0x64
128 buf[3]=NX_ASCII_LF & 0xff
129 buf[4]=0x41; buf[5]=0x43; buf[6]=0x47; buf[7]=0x54
130 buf[8]=NX_ASCII_LF & 0xff
131 buf[9]=NX_ASCII_GT & 0xff
132 buf[10]=0x69; buf[11]=0x64; buf[12]=0x32
133 buf[13]=NX_ASCII_LF & 0xff
134 buf[14]=0x47; buf[15]=0x43; buf[16]=0x54; buf[17]=0x41
135 buf[18]=NX_ASCII_LF & 0xff
136
137 if fasta_parse_one_record(buf, 19, 0, meta) != 0 { return 60 }
138 if meta[0] != 1 { return 61 }
139 if meta[1] != 2 { return 62 }
140 if meta[2] != 4 { return 63 }
141 if meta[3] != 9 { return 64 }
142 if meta[4] != 9 { return 65 }
143
144 if fasta_parse_one_record(buf, 19, 9, meta) != 0 { return 70 }
145 if meta[0] != 10 { return 71 }
146 if meta[1] != 3 { return 72 }
147 if meta[2] != 14 { return 73 }
148 if meta[3] != 19 { return 74 }
149 if meta[4] != 19 { return 75 }
150
151 // Third call at offset 19 -> EOF.
152 if fasta_parse_one_record(buf, 19, 19, meta) != 1 { return 80 }
153
154 // ============================================================
155 // Section F -- malformed: missing '>' at offset.
156 // ============================================================
157
158 buf[0]=0x41 // 'A' instead of '>'
159 if fasta_parse_one_record(buf, 19, 0, meta) != -1 { return 90 }
160 buf[0]=NX_ASCII_GT & 0xff
161
162 // ============================================================
163 // Section G -- header-only EOF (no LF after header).
164 // Buffer = ">id" only (3 bytes, no LF) -> nx_find_lf returns -1 -> -1.
165 // ============================================================
166
167 if fasta_parse_one_record(buf, 3, 0, meta) != -1 { return 100 }
168
169 // ============================================================
170 // Section H -- bad parameters.
171 // ============================================================
172
173 if fasta_parse_one_record(buf, -1, 0, meta) != -1 { return 110 }
174 if fasta_parse_one_record(buf, 19, -1, meta) != -1 { return 111 }
175
176 return 0
177}