Coverage Report

Created: 2024-03-29 06:04

/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