Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libucl/tests/test_msgpack.c
2066 views
1
/*
2
* Copyright (c) 2015, Vsevolod Stakhov
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
7
* * Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* * Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
17
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
*/
24
25
#include "ucl.h"
26
#include "ucl_internal.h"
27
#include <ctype.h>
28
29
static const int niter = 20;
30
static const int ntests = 10;
31
static const int nelt = 20;
32
33
static int recursion = 0;
34
35
typedef ucl_object_t* (*ucl_msgpack_test)(void);
36
37
static ucl_object_t* ucl_test_integer (void);
38
static ucl_object_t* ucl_test_string (void);
39
static ucl_object_t* ucl_test_boolean (void);
40
static ucl_object_t* ucl_test_map (void);
41
static ucl_object_t* ucl_test_array (void);
42
static ucl_object_t* ucl_test_large_map (void);
43
static ucl_object_t* ucl_test_large_array (void);
44
static ucl_object_t* ucl_test_large_string (void);
45
static ucl_object_t* ucl_test_null (void);
46
47
ucl_msgpack_test tests[] = {
48
ucl_test_integer,
49
ucl_test_string,
50
ucl_test_boolean,
51
ucl_test_map,
52
ucl_test_array,
53
ucl_test_null
54
};
55
56
#define NTESTS (sizeof(tests) / sizeof(tests[0]))
57
58
typedef struct
59
{
60
uint64_t state;
61
uint64_t inc;
62
} pcg32_random_t;
63
64
pcg32_random_t rng;
65
66
/*
67
* From http://www.pcg-random.org/
68
*/
69
static uint32_t
70
pcg32_random (void)
71
{
72
uint64_t oldstate = rng.state;
73
74
rng.state = oldstate * 6364136223846793005ULL + (rng.inc | 1);
75
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
76
uint32_t rot = oldstate >> 59u;
77
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
78
}
79
80
static const char *
81
random_key (size_t *lenptr)
82
{
83
static char keybuf[512];
84
int keylen, i;
85
char c;
86
87
keylen = pcg32_random () % (sizeof (keybuf) - 1) + 1;
88
89
for (i = 0; i < keylen; i ++) {
90
do {
91
c = pcg32_random () & 0xFF;
92
} while (!isgraph (c));
93
94
keybuf[i] = c;
95
}
96
97
*lenptr = keylen;
98
return keybuf;
99
}
100
101
int
102
main (int argc, char **argv)
103
{
104
int fd, i, j;
105
uint32_t sel;
106
ucl_object_t *obj, *elt;
107
struct ucl_parser *parser;
108
size_t klen, elen, elen2;
109
const char *key;
110
unsigned char *emitted, *emitted2;
111
FILE *out;
112
const char *fname_out = NULL;
113
114
switch (argc) {
115
case 2:
116
fname_out = argv[1];
117
break;
118
}
119
120
/* Seed prng */
121
fd = open ("/dev/urandom", O_RDONLY);
122
assert (fd != -1);
123
assert (read (fd, &rng, sizeof (rng)) == sizeof (rng));
124
close (fd);
125
126
for (i = 0; i < niter; i ++) {
127
if (fname_out != NULL) {
128
out = fopen (fname_out, "w");
129
if (out == NULL) {
130
exit (-errno);
131
}
132
}
133
else {
134
out = NULL;
135
}
136
137
/* Generate phase */
138
obj = ucl_object_typed_new (UCL_OBJECT);
139
140
for (j = 0; j < ntests; j ++) {
141
sel = pcg32_random () % NTESTS;
142
143
key = random_key (&klen);
144
recursion = 0;
145
elt = tests[sel]();
146
assert (elt != NULL);
147
assert (klen != 0);
148
149
ucl_object_insert_key (obj, elt, key, klen, true);
150
}
151
152
key = random_key (&klen);
153
elt = ucl_test_large_array ();
154
ucl_object_insert_key (obj, elt, key, klen, true);
155
156
key = random_key (&klen);
157
elt = ucl_test_large_map ();
158
ucl_object_insert_key (obj, elt, key, klen, true);
159
160
key = random_key (&klen);
161
elt = ucl_test_large_string ();
162
ucl_object_insert_key (obj, elt, key, klen, true);
163
164
emitted = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen);
165
166
assert (emitted != NULL);
167
168
if (out) {
169
fprintf (out, "%*.s\n", (int)elen, emitted);
170
171
fclose (out);
172
}
173
ucl_object_unref (obj);
174
175
parser = ucl_parser_new (0);
176
177
if (!ucl_parser_add_chunk_full (parser, emitted, elen, 0,
178
UCL_DUPLICATE_APPEND, UCL_PARSE_MSGPACK)) {
179
fprintf (stderr, "error parsing input: %s",
180
ucl_parser_get_error (parser));
181
assert (0);
182
}
183
184
obj = ucl_parser_get_object (parser);
185
assert (obj != NULL);
186
187
emitted2 = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen2);
188
189
assert (emitted2 != NULL);
190
assert (elen2 == elen);
191
assert (memcmp (emitted, emitted2, elen) == 0);
192
193
ucl_parser_free (parser);
194
ucl_object_unref (obj);
195
free (emitted);
196
free (emitted2);
197
}
198
199
return 0;
200
}
201
202
203
static ucl_object_t*
204
ucl_test_integer (void)
205
{
206
ucl_object_t *res;
207
int count, i;
208
uint64_t cur;
209
double curf;
210
211
res = ucl_object_typed_new (UCL_ARRAY);
212
count = pcg32_random () % nelt;
213
214
for (i = 0; i < count; i ++) {
215
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
216
ucl_array_append (res, ucl_object_fromint (cur % 128));
217
ucl_array_append (res, ucl_object_fromint (-(cur % 128)));
218
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
219
ucl_array_append (res, ucl_object_fromint (cur % UINT16_MAX));
220
ucl_array_append (res, ucl_object_fromint (-(cur % INT16_MAX)));
221
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
222
ucl_array_append (res, ucl_object_fromint (cur % UINT32_MAX));
223
ucl_array_append (res, ucl_object_fromint (-(cur % INT32_MAX)));
224
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
225
ucl_array_append (res, ucl_object_fromint (cur));
226
ucl_array_append (res, ucl_object_fromint (-cur));
227
/* Double version */
228
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
229
curf = (cur % 128) / 19 * 16;
230
ucl_array_append (res, ucl_object_fromdouble (curf));
231
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
232
curf = -(cur % 128) / 19 * 16;
233
ucl_array_append (res, ucl_object_fromdouble (curf));
234
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
235
curf = (cur % 65536) / 19 * 16;
236
ucl_array_append (res, ucl_object_fromdouble (curf));
237
ucl_array_append (res, ucl_object_fromdouble (-curf));
238
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
239
curf = (cur % INT32_MAX) / 19 * 16;
240
ucl_array_append (res, ucl_object_fromdouble (curf));
241
cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random ();
242
memcpy (&curf, &cur, sizeof (curf));
243
ucl_array_append (res, ucl_object_fromint (cur));
244
}
245
246
return res;
247
}
248
249
static ucl_object_t*
250
ucl_test_string (void)
251
{
252
ucl_object_t *res, *elt;
253
int count, i;
254
uint32_t cur_len;
255
char *str;
256
257
res = ucl_object_typed_new (UCL_ARRAY);
258
count = pcg32_random () % nelt;
259
260
for (i = 0; i < count; i ++) {
261
while ((cur_len = pcg32_random ()) % 128 == 0);
262
263
str = malloc (cur_len % 128);
264
ucl_array_append (res, ucl_object_fromstring_common (str, cur_len % 128,
265
UCL_STRING_RAW));
266
free (str);
267
268
while ((cur_len = pcg32_random ()) % 512 == 0);
269
str = malloc (cur_len % 512);
270
ucl_array_append (res, ucl_object_fromstring_common (str, cur_len % 512,
271
UCL_STRING_RAW));
272
free (str);
273
274
while ((cur_len = pcg32_random ()) % 128 == 0);
275
str = malloc (cur_len % 128);
276
elt = ucl_object_fromstring_common (str, cur_len % 128,
277
UCL_STRING_RAW);
278
elt->flags |= UCL_OBJECT_BINARY;
279
ucl_array_append (res, elt);
280
free (str);
281
282
while ((cur_len = pcg32_random ()) % 512 == 0);
283
str = malloc (cur_len % 512);
284
elt = ucl_object_fromstring_common (str, cur_len % 512,
285
UCL_STRING_RAW);
286
elt->flags |= UCL_OBJECT_BINARY;
287
ucl_array_append (res, elt);
288
free (str);
289
}
290
291
/* One large string */
292
str = malloc (65537);
293
elt = ucl_object_fromstring_common (str, 65537,
294
UCL_STRING_RAW);
295
elt->flags |= UCL_OBJECT_BINARY;
296
ucl_array_append (res, elt);
297
free (str);
298
299
return res;
300
}
301
302
static ucl_object_t*
303
ucl_test_boolean (void)
304
{
305
ucl_object_t *res;
306
int count, i;
307
308
res = ucl_object_typed_new (UCL_ARRAY);
309
count = pcg32_random () % nelt;
310
311
for (i = 0; i < count; i ++) {
312
ucl_array_append (res, ucl_object_frombool (pcg32_random () % 2));
313
}
314
315
return res;
316
}
317
318
static ucl_object_t*
319
ucl_test_map (void)
320
{
321
ucl_object_t *res, *cur;
322
int count, i;
323
uint32_t cur_len, sel;
324
size_t klen;
325
const char *key;
326
327
res = ucl_object_typed_new (UCL_OBJECT);
328
count = pcg32_random () % nelt;
329
330
recursion ++;
331
332
for (i = 0; i < count; i ++) {
333
334
if (recursion > 10) {
335
for (;;) {
336
sel = pcg32_random () % NTESTS;
337
if (tests[sel] != ucl_test_map &&
338
tests[sel] != ucl_test_array) {
339
break;
340
}
341
}
342
}
343
else {
344
sel = pcg32_random () % NTESTS;
345
}
346
347
key = random_key (&klen);
348
cur = tests[sel]();
349
assert (cur != NULL);
350
assert (klen != 0);
351
352
ucl_object_insert_key (res, cur, key, klen, true);
353
354
/* Multi value key */
355
cur = tests[sel]();
356
assert (cur != NULL);
357
358
ucl_object_insert_key (res, cur, key, klen, true);
359
}
360
361
return res;
362
}
363
364
static ucl_object_t*
365
ucl_test_large_map (void)
366
{
367
ucl_object_t *res, *cur;
368
int count, i;
369
uint32_t cur_len;
370
size_t klen;
371
const char *key;
372
373
res = ucl_object_typed_new (UCL_OBJECT);
374
count = 65537;
375
376
recursion ++;
377
378
for (i = 0; i < count; i ++) {
379
key = random_key (&klen);
380
cur = ucl_test_boolean ();
381
assert (cur != NULL);
382
assert (klen != 0);
383
384
ucl_object_insert_key (res, cur, key, klen, true);
385
}
386
387
return res;
388
}
389
390
static ucl_object_t*
391
ucl_test_array (void)
392
{
393
ucl_object_t *res, *cur;
394
int count, i;
395
uint32_t cur_len, sel;
396
397
res = ucl_object_typed_new (UCL_ARRAY);
398
count = pcg32_random () % nelt;
399
400
recursion ++;
401
402
for (i = 0; i < count; i ++) {
403
if (recursion > 10) {
404
for (;;) {
405
sel = pcg32_random () % NTESTS;
406
if (tests[sel] != ucl_test_map &&
407
tests[sel] != ucl_test_array) {
408
break;
409
}
410
}
411
}
412
else {
413
sel = pcg32_random () % NTESTS;
414
}
415
416
cur = tests[sel]();
417
assert (cur != NULL);
418
419
ucl_array_append (res, cur);
420
}
421
422
return res;
423
}
424
425
static ucl_object_t*
426
ucl_test_large_array (void)
427
{
428
ucl_object_t *res, *cur;
429
int count, i;
430
uint32_t cur_len;
431
432
res = ucl_object_typed_new (UCL_ARRAY);
433
count = 65537;
434
435
recursion ++;
436
437
for (i = 0; i < count; i ++) {
438
cur = ucl_test_boolean ();
439
assert (cur != NULL);
440
441
ucl_array_append (res, cur);
442
}
443
444
return res;
445
}
446
447
static ucl_object_t*
448
ucl_test_large_string (void)
449
{
450
ucl_object_t *res;
451
char *str;
452
uint32_t cur_len;
453
454
while ((cur_len = pcg32_random ()) % 100000 == 0);
455
str = malloc (cur_len % 100000);
456
res = ucl_object_fromstring_common (str, cur_len % 100000,
457
UCL_STRING_RAW);
458
res->flags |= UCL_OBJECT_BINARY;
459
free (str);
460
461
return res;
462
}
463
464
static ucl_object_t*
465
ucl_test_null (void)
466
{
467
return ucl_object_typed_new (UCL_NULL);
468
}
469
470