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