/builds/xfbs/passgen/src/tests/generate.c
Line | Count | Source |
1 | | #include "passgen/generate.h" |
2 | | #include "passgen/container/stack.h" |
3 | | #include "passgen/parser/parser.h" |
4 | | #include "passgen/parser/token.h" |
5 | | #include "passgen/passgen.h" |
6 | | #include "passgen/pattern/group.h" |
7 | | #include "passgen/pattern/literal.h" |
8 | | #include "passgen/pattern/pattern.h" |
9 | | #include "passgen/pattern/range.h" |
10 | | #include "passgen/pattern/repeat.h" |
11 | | #include "passgen/pattern/segment.h" |
12 | | #include "passgen/pattern/segment_item.h" |
13 | | #include "passgen/pattern/set.h" |
14 | | #include "tests.h" |
15 | | |
16 | | // don't change this seed - that will break tests! |
17 | | #define SEED 320843200 |
18 | | |
19 | | #define PREAMBLE() \ |
20 | 7 | passgen_parser parser; \ |
21 | 7 | passgen_token_parser token_parser = {0}; \ |
22 | 7 | passgen_token token = {0}; \ |
23 | 7 | passgen_env env; \ |
24 | 7 | passgen_pattern parsed_pattern; \ |
25 | 7 | const char *pattern; \ |
26 | 7 | passgen_random random; \ |
27 | 7 | assert(passgen_random_open_xorshift(&random, SEED)); \ |
28 | 7 | passgen_env_init(&env, &random); |
29 | | |
30 | | #define GENERATE(output, pattern) \ |
31 | 28 | do { \ |
32 | 28 | passgen_parser_init(&parser, &parsed_pattern); \ |
33 | 28 | passgen_token_parser_init(&token_parser); \ |
34 | 28 | \ |
35 | 28 | int token_parser_state = PASSGEN_TOKEN_INIT; \ |
36 | 156 | for(size_t i = 0; pattern[i]; i++128 ) { \ |
37 | 128 | token_parser_state = \ |
38 | 128 | passgen_token_parse(&token_parser, &token, 1, pattern[i]); \ |
39 | 128 | if(token_parser_state == PASSGEN_TOKEN_INIT) { \ |
40 | 121 | assert(0 == passgen_parse_token(&parser, &token)); \ |
41 | 121 | } \ |
42 | 128 | } \ |
43 | 28 | \ |
44 | 28 | assert(token_parser_state == PASSGEN_TOKEN_INIT); \ |
45 | 28 | assert(0 == passgen_parse_finish(&parser)); \ |
46 | 28 | size_t len = passgen_generate_fill_unicode( \ |
47 | 28 | parser.pattern, \ |
48 | 28 | &env, \ |
49 | 28 | NULL, \ |
50 | 28 | output, \ |
51 | 28 | sizeof(output)); \ |
52 | 28 | output[len] = 0; \ |
53 | 28 | \ |
54 | 28 | passgen_parser_free(&parser); \ |
55 | 28 | passgen_pattern_free(&parsed_pattern); \ |
56 | 28 | } while(0) |
57 | | |
58 | 7 | #define POSTAMBLE() passgen_random_close(&random) |
59 | | |
60 | 1 | test_result test_generate_empty(void) { |
61 | 1 | PREAMBLE(); |
62 | 1 | uint32_t output[10]; |
63 | 1 | |
64 | 1 | pattern = ""; |
65 | 1 | GENERATE(output, pattern); |
66 | 1 | assert(output[0] == '\0'); |
67 | 1 | |
68 | 1 | POSTAMBLE(); |
69 | 1 | return test_ok; |
70 | 1 | } |
71 | | |
72 | 1 | test_result test_generate_chars(void) { |
73 | 1 | PREAMBLE(); |
74 | 1 | uint32_t output[10]; |
75 | 1 | |
76 | 1 | // single char |
77 | 1 | pattern = "a"; |
78 | 1 | GENERATE(output, pattern); |
79 | 1 | assert(output[0] == 'a'); |
80 | 1 | assert(output[1] == '\0'); |
81 | 1 | |
82 | 1 | // multiple chars |
83 | 1 | pattern = "abc"; |
84 | 1 | GENERATE(output, pattern); |
85 | 1 | assert(output[0] == 'a'); |
86 | 1 | assert(output[1] == 'b'); |
87 | 1 | assert(output[2] == 'c'); |
88 | 1 | assert(output[3] == '\0'); |
89 | 1 | |
90 | 1 | // escaped chars |
91 | 1 | pattern = "pass\\[\\{\\u{78}"; |
92 | 1 | GENERATE(output, pattern); |
93 | 1 | assert(output[0] == 'p'); |
94 | 1 | assert(output[1] == 'a'); |
95 | 1 | assert(output[2] == 's'); |
96 | 1 | assert(output[3] == 's'); |
97 | 1 | assert(output[4] == '['); |
98 | 1 | assert(output[5] == '{'); |
99 | 1 | assert(output[6] == 'x'); |
100 | 1 | assert(output[7] == '\0'); |
101 | 1 | |
102 | 1 | POSTAMBLE(); |
103 | 1 | return test_ok; |
104 | 1 | } |
105 | | |
106 | 1 | test_result test_generate_segments(void) { |
107 | 1 | PREAMBLE(); |
108 | 1 | uint32_t output[10]; |
109 | 1 | |
110 | 1 | // either a or b |
111 | 1 | pattern = "a|b"; |
112 | 1 | GENERATE(output, pattern); |
113 | 1 | assert(output[0] == 'b'); |
114 | 1 | assert(output[1] == '\0'); |
115 | 1 | |
116 | 1 | GENERATE(output, pattern); |
117 | 1 | assert(output[0] == 'b'); |
118 | 1 | assert(output[1] == '\0'); |
119 | 1 | |
120 | 1 | GENERATE(output, pattern); |
121 | 1 | assert(output[0] == 'a'); |
122 | 1 | assert(output[1] == '\0'); |
123 | 1 | |
124 | 1 | POSTAMBLE(); |
125 | 1 | return test_ok; |
126 | 1 | } |
127 | | |
128 | 1 | test_result test_generate_group(void) { |
129 | 1 | PREAMBLE(); |
130 | 1 | uint32_t output[10]; |
131 | 1 | |
132 | 1 | // "abc" |
133 | 1 | pattern = "(abc)"; |
134 | 1 | GENERATE(output, pattern); |
135 | 1 | assert(output[0] == 'a'); |
136 | 1 | assert(output[1] == 'b'); |
137 | 1 | assert(output[2] == 'c'); |
138 | 1 | assert(output[3] == '\0'); |
139 | 1 | |
140 | 1 | // either "a" or "b" |
141 | 1 | pattern = "(a|b)"; |
142 | 1 | GENERATE(output, pattern); |
143 | 1 | assert(output[0] == 'a'); |
144 | 1 | assert(output[1] == '\0'); |
145 | 1 | |
146 | 1 | passgen_random_u64(&random); |
147 | 1 | passgen_random_u64(&random); |
148 | 1 | passgen_random_u64(&random); |
149 | 1 | passgen_random_u64(&random); |
150 | 1 | |
151 | 1 | GENERATE(output, pattern); |
152 | 1 | assert(output[0] == 'b'); |
153 | 1 | assert(output[1] == '\0'); |
154 | 1 | |
155 | 1 | POSTAMBLE(); |
156 | 1 | return test_ok; |
157 | 1 | } |
158 | | |
159 | 1 | test_result test_generate_set(void) { |
160 | 1 | PREAMBLE(); |
161 | 1 | uint32_t output[10]; |
162 | 1 | |
163 | 1 | // "abc" |
164 | 1 | pattern = "[a]"; |
165 | 1 | GENERATE(output, pattern); |
166 | 1 | assert(output[0] == 'a'); |
167 | 1 | assert(output[1] == '\0'); |
168 | 1 | |
169 | 1 | // "a" or "b" or "c" |
170 | 1 | pattern = "[abc]"; |
171 | 1 | GENERATE(output, pattern); |
172 | 1 | assert(output[0] == 'a'); |
173 | 1 | assert(output[1] == '\0'); |
174 | 1 | |
175 | 1 | passgen_random_u64(&random); |
176 | 1 | GENERATE(output, pattern); |
177 | 1 | assert(output[0] == 'c'); |
178 | 1 | assert(output[1] == '\0'); |
179 | 1 | |
180 | 1 | GENERATE(output, pattern); |
181 | 1 | assert(output[0] == 'a'); |
182 | 1 | assert(output[1] == '\0'); |
183 | 1 | |
184 | 1 | pattern = "[a-c]"; |
185 | 1 | GENERATE(output, pattern); |
186 | 1 | assert(output[0] == 'c'); |
187 | 1 | assert(output[1] == '\0'); |
188 | 1 | |
189 | 1 | GENERATE(output, pattern); |
190 | 1 | assert(output[0] == 'c'); |
191 | 1 | assert(output[1] == '\0'); |
192 | 1 | |
193 | 1 | passgen_random_u64(&random); |
194 | 1 | passgen_random_u64(&random); |
195 | 1 | passgen_random_u64(&random); |
196 | 1 | passgen_random_u64(&random); |
197 | 1 | GENERATE(output, pattern); |
198 | 1 | assert(output[0] == 'b'); |
199 | 1 | assert(output[1] == '\0'); |
200 | 1 | |
201 | 1 | POSTAMBLE(); |
202 | 1 | return test_ok; |
203 | 1 | } |
204 | | |
205 | 1 | test_result test_generate_maybe(void) { |
206 | 1 | PREAMBLE(); |
207 | 1 | uint32_t output[10]; |
208 | 1 | |
209 | 1 | // char or not? |
210 | 1 | pattern = "a?"; |
211 | 1 | GENERATE(output, pattern); |
212 | 1 | assert(output[0] == 'a'); |
213 | 1 | assert(output[1] == '\0'); |
214 | 1 | |
215 | 1 | passgen_random_u64(&random); |
216 | 1 | passgen_random_u64(&random); |
217 | 1 | passgen_random_u64(&random); |
218 | 1 | |
219 | 1 | GENERATE(output, pattern); |
220 | 1 | assert(output[0] == '\0'); |
221 | 1 | |
222 | 1 | // group or not? |
223 | 1 | pattern = "(b)?"; |
224 | 1 | GENERATE(output, pattern); |
225 | 1 | assert(output[0] == 'b'); |
226 | 1 | assert(output[1] == '\0'); |
227 | 1 | |
228 | 1 | GENERATE(output, pattern); |
229 | 1 | assert(output[0] == 'b'); |
230 | 1 | assert(output[1] == '\0'); |
231 | 1 | |
232 | 1 | // set or not? |
233 | 1 | pattern = "[c]?"; |
234 | 1 | GENERATE(output, pattern); |
235 | 1 | assert(output[0] == 'c'); |
236 | 1 | assert(output[1] == '\0'); |
237 | 1 | |
238 | 1 | passgen_random_u64(&random); |
239 | 1 | |
240 | 1 | GENERATE(output, pattern); |
241 | 1 | assert(output[0] == 'c'); |
242 | 1 | assert(output[1] == '\0'); |
243 | 1 | |
244 | 1 | POSTAMBLE(); |
245 | 1 | return test_ok; |
246 | 1 | } |
247 | | |
248 | 1 | test_result test_generate_repeat(void) { |
249 | 1 | PREAMBLE(); |
250 | 1 | uint32_t output[10]; |
251 | 1 | |
252 | 1 | // char or not? |
253 | 1 | pattern = "a{5}"; |
254 | 1 | GENERATE(output, pattern); |
255 | 1 | assert(output[0] == 'a'); |
256 | 1 | assert(output[1] == 'a'); |
257 | 1 | assert(output[2] == 'a'); |
258 | 1 | assert(output[3] == 'a'); |
259 | 1 | assert(output[4] == 'a'); |
260 | 1 | assert(output[5] == '\0'); |
261 | 1 | |
262 | 1 | pattern = "b{2,3}"; |
263 | 1 | GENERATE(output, pattern); |
264 | 1 | assert(output[0] == 'b'); |
265 | 1 | assert(output[1] == 'b'); |
266 | 1 | assert(output[2] == '\0'); |
267 | 1 | |
268 | 1 | passgen_random_u64(&random); |
269 | 1 | GENERATE(output, pattern); |
270 | 1 | assert(output[0] == 'b'); |
271 | 1 | assert(output[1] == 'b'); |
272 | 1 | assert(output[2] == '\0'); |
273 | 1 | |
274 | 1 | pattern = "[abc]{3}"; |
275 | 1 | GENERATE(output, pattern); |
276 | 1 | assert(output[0] == 'c'); |
277 | 1 | assert(output[1] == 'c'); |
278 | 1 | assert(output[2] == 'c'); |
279 | 1 | assert(output[3] == '\0'); |
280 | 1 | |
281 | 1 | pattern = "(ab|x){3}"; |
282 | 1 | GENERATE(output, pattern); |
283 | 1 | assert(output[0] == 'x'); |
284 | 1 | assert(output[1] == 'x'); |
285 | 1 | assert(output[2] == 'a'); |
286 | 1 | assert(output[3] == 'b'); |
287 | 1 | assert(output[4] == '\0'); |
288 | 1 | |
289 | 1 | POSTAMBLE(); |
290 | 1 | return test_ok; |
291 | 1 | } |
292 | | |
293 | 5 | static int dummy_callback(void *data, uint32_t codepoint) { |
294 | 5 | (void) data; |
295 | 5 | (void) codepoint; |
296 | 5 | return 0; |
297 | 5 | } |
298 | | |
299 | 1 | test_result test_generate_depth_limit_zero(void) { |
300 | 1 | passgen_pattern pattern; |
301 | 1 | passgen_error error; |
302 | 1 | assert_eq(0, passgen_parse(&pattern, &error, "abc")); |
303 | 1 | |
304 | 1 | passgen_random random; |
305 | 1 | passgen_random_open(&random, NULL); |
306 | 1 | |
307 | 1 | passgen_env env; |
308 | 1 | passgen_env_init(&env, &random); |
309 | 1 | env.depth_limit = 0; |
310 | 1 | |
311 | 1 | int ret = passgen_generate(&pattern, &env, NULL, NULL, dummy_callback); |
312 | 1 | |
313 | 1 | // can't generate |
314 | 1 | assert(ret != 0); |
315 | 1 | |
316 | 1 | passgen_pattern_free(&pattern); |
317 | 1 | // FIXME: don't free random in env_free |
318 | 1 | env.random = NULL; |
319 | 1 | passgen_env_free(&env); |
320 | 1 | |
321 | 1 | return test_ok; |
322 | 1 | } |
323 | | |
324 | 1 | test_result test_generate_depth_limit_one(void) { |
325 | 1 | passgen_pattern pattern; |
326 | 1 | passgen_error error; |
327 | 1 | assert_eq(0, passgen_parse(&pattern, &error, "abc")); |
328 | 1 | |
329 | 1 | passgen_random random; |
330 | 1 | passgen_random_open(&random, NULL); |
331 | 1 | |
332 | 1 | passgen_env env; |
333 | 1 | passgen_env_init(&env, &random); |
334 | 1 | env.depth_limit = 1; |
335 | 1 | |
336 | 1 | int ret = passgen_generate(&pattern, &env, NULL, NULL, dummy_callback); |
337 | 1 | assert_eq(ret, 0); |
338 | 1 | |
339 | 1 | passgen_pattern_free(&pattern); |
340 | 1 | // FIXME: don't free random in env_free |
341 | 1 | env.random = NULL; |
342 | 1 | passgen_env_free(&env); |
343 | 1 | |
344 | 1 | return test_ok; |
345 | 1 | } |
346 | | |
347 | 1 | test_result test_generate_depth_limit_one_over(void) { |
348 | 1 | passgen_pattern pattern; |
349 | 1 | passgen_error error; |
350 | 1 | assert_eq(0, passgen_parse(&pattern, &error, "(abc)")); |
351 | 1 | |
352 | 1 | passgen_random random; |
353 | 1 | passgen_random_open(&random, NULL); |
354 | 1 | |
355 | 1 | passgen_env env; |
356 | 1 | passgen_env_init(&env, &random); |
357 | 1 | env.depth_limit = 1; |
358 | 1 | |
359 | 1 | int ret = passgen_generate(&pattern, &env, NULL, NULL, dummy_callback); |
360 | 1 | assert(ret != 0); |
361 | 1 | |
362 | 1 | passgen_pattern_free(&pattern); |
363 | 1 | // FIXME: don't free random in env_free |
364 | 1 | env.random = NULL; |
365 | 1 | passgen_env_free(&env); |
366 | 1 | |
367 | 1 | return test_ok; |
368 | 1 | } |
369 | | |
370 | 1 | test_result test_generate_depth_limit_two(void) { |
371 | 1 | passgen_pattern pattern; |
372 | 1 | passgen_error error; |
373 | 1 | assert_eq(0, passgen_parse(&pattern, &error, "(abc|def|[ghi]{2})")); |
374 | 1 | |
375 | 1 | passgen_random random; |
376 | 1 | passgen_random_open(&random, NULL); |
377 | 1 | |
378 | 1 | passgen_env env; |
379 | 1 | passgen_env_init(&env, &random); |
380 | 1 | env.depth_limit = 2; |
381 | 1 | |
382 | 1 | int ret = passgen_generate(&pattern, &env, NULL, NULL, dummy_callback); |
383 | 1 | assert(ret == 0); |
384 | 1 | |
385 | 1 | passgen_pattern_free(&pattern); |
386 | 1 | // FIXME: don't free random in env_free |
387 | 1 | env.random = NULL; |
388 | 1 | passgen_env_free(&env); |
389 | 1 | |
390 | 1 | return test_ok; |
391 | 1 | } |
392 | | |
393 | 1 | test_result test_generate_depth_limit_two_over(void) { |
394 | 1 | passgen_pattern pattern; |
395 | 1 | passgen_error error; |
396 | 1 | assert_eq(0, passgen_parse(&pattern, &error, "((abc)|(def|ghi))")); |
397 | 1 | |
398 | 1 | passgen_random random; |
399 | 1 | passgen_random_open(&random, NULL); |
400 | 1 | |
401 | 1 | passgen_env env; |
402 | 1 | passgen_env_init(&env, &random); |
403 | 1 | env.depth_limit = 2; |
404 | 1 | |
405 | 1 | int ret = passgen_generate(&pattern, &env, NULL, NULL, dummy_callback); |
406 | 1 | assert(ret != 0); |
407 | 1 | |
408 | 1 | passgen_pattern_free(&pattern); |
409 | 1 | // FIXME: don't free random in env_free |
410 | 1 | env.random = NULL; |
411 | 1 | passgen_env_free(&env); |
412 | 1 | |
413 | 1 | return test_ok; |
414 | 1 | } |
415 | | |
416 | | #undef SEED |
417 | | #undef PREAMBLE |
418 | | #undef POSTAMBLE |