2 * Copyright (c) 2015, Vsevolod Stakhov
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.
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.
26 #include "ucl_internal.h"
29 static const int niter = 20;
30 static const int ntests = 10;
31 static const int nelt = 20;
33 static int recursion = 0;
35 typedef ucl_object_t* (*ucl_msgpack_test)(void);
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);
47 ucl_msgpack_test tests[] = {
56 #define NTESTS (sizeof(tests) / sizeof(tests[0]))
67 * From http://www.pcg-random.org/
72 uint64_t oldstate = rng.state;
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));
81 random_key (size_t *lenptr)
83 static char keybuf[512];
87 keylen = pcg32_random () % (sizeof (keybuf) - 1) + 1;
89 for (i = 0; i < keylen; i ++) {
91 c = pcg32_random () & 0xFF;
92 } while (!isgraph (c));
102 main (int argc, char **argv)
106 ucl_object_t *obj, *elt;
107 struct ucl_parser *parser;
108 size_t klen, elen, elen2;
110 unsigned char *emitted, *emitted2;
112 const char *fname_out = NULL;
121 fd = open ("/dev/urandom", O_RDONLY);
123 assert (read (fd, &rng, sizeof (rng)) == sizeof (rng));
126 for (i = 0; i < niter; i ++) {
127 if (fname_out != NULL) {
128 out = fopen (fname_out, "w");
138 obj = ucl_object_typed_new (UCL_OBJECT);
140 for (j = 0; j < ntests; j ++) {
141 sel = pcg32_random () % NTESTS;
143 key = random_key (&klen);
146 assert (elt != NULL);
149 ucl_object_insert_key (obj, elt, key, klen, true);
152 key = random_key (&klen);
153 elt = ucl_test_large_array ();
154 ucl_object_insert_key (obj, elt, key, klen, true);
156 key = random_key (&klen);
157 elt = ucl_test_large_map ();
158 ucl_object_insert_key (obj, elt, key, klen, true);
160 key = random_key (&klen);
161 elt = ucl_test_large_string ();
162 ucl_object_insert_key (obj, elt, key, klen, true);
164 emitted = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen);
166 assert (emitted != NULL);
169 fprintf (out, "%*.s\n", (int)elen, emitted);
173 ucl_object_unref (obj);
175 parser = ucl_parser_new (0);
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));
184 obj = ucl_parser_get_object (parser);
185 assert (obj != NULL);
187 emitted2 = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen2);
189 assert (emitted2 != NULL);
190 assert (elen2 == elen);
191 assert (memcmp (emitted, emitted2, elen) == 0);
193 ucl_parser_free (parser);
194 ucl_object_unref (obj);
204 ucl_test_integer (void)
211 res = ucl_object_typed_new (UCL_ARRAY);
212 count = pcg32_random () % nelt;
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));
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));
250 ucl_test_string (void)
252 ucl_object_t *res, *elt;
257 res = ucl_object_typed_new (UCL_ARRAY);
258 count = pcg32_random () % nelt;
260 for (i = 0; i < count; i ++) {
261 while ((cur_len = pcg32_random ()) % 128 == 0);
263 str = malloc (cur_len % 128);
264 ucl_array_append (res, ucl_object_fromstring_common (str, cur_len % 128,
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,
274 while ((cur_len = pcg32_random ()) % 128 == 0);
275 str = malloc (cur_len % 128);
276 elt = ucl_object_fromstring_common (str, cur_len % 128,
278 elt->flags |= UCL_OBJECT_BINARY;
279 ucl_array_append (res, elt);
282 while ((cur_len = pcg32_random ()) % 512 == 0);
283 str = malloc (cur_len % 512);
284 elt = ucl_object_fromstring_common (str, cur_len % 512,
286 elt->flags |= UCL_OBJECT_BINARY;
287 ucl_array_append (res, elt);
291 /* One large string */
292 str = malloc (65537);
293 elt = ucl_object_fromstring_common (str, 65537,
295 elt->flags |= UCL_OBJECT_BINARY;
296 ucl_array_append (res, elt);
303 ucl_test_boolean (void)
308 res = ucl_object_typed_new (UCL_ARRAY);
309 count = pcg32_random () % nelt;
311 for (i = 0; i < count; i ++) {
312 ucl_array_append (res, ucl_object_frombool (pcg32_random () % 2));
321 ucl_object_t *res, *cur;
323 uint32_t cur_len, sel;
327 res = ucl_object_typed_new (UCL_OBJECT);
328 count = pcg32_random () % nelt;
332 for (i = 0; i < count; i ++) {
334 if (recursion > 10) {
336 sel = pcg32_random () % NTESTS;
337 if (tests[sel] != ucl_test_map &&
338 tests[sel] != ucl_test_array) {
344 sel = pcg32_random () % NTESTS;
347 key = random_key (&klen);
349 assert (cur != NULL);
352 ucl_object_insert_key (res, cur, key, klen, true);
354 /* Multi value key */
356 assert (cur != NULL);
358 ucl_object_insert_key (res, cur, key, klen, true);
365 ucl_test_large_map (void)
367 ucl_object_t *res, *cur;
373 res = ucl_object_typed_new (UCL_OBJECT);
378 for (i = 0; i < count; i ++) {
379 key = random_key (&klen);
380 cur = ucl_test_boolean ();
381 assert (cur != NULL);
384 ucl_object_insert_key (res, cur, key, klen, true);
391 ucl_test_array (void)
393 ucl_object_t *res, *cur;
395 uint32_t cur_len, sel;
397 res = ucl_object_typed_new (UCL_ARRAY);
398 count = pcg32_random () % nelt;
402 for (i = 0; i < count; i ++) {
403 if (recursion > 10) {
405 sel = pcg32_random () % NTESTS;
406 if (tests[sel] != ucl_test_map &&
407 tests[sel] != ucl_test_array) {
413 sel = pcg32_random () % NTESTS;
417 assert (cur != NULL);
419 ucl_array_append (res, cur);
426 ucl_test_large_array (void)
428 ucl_object_t *res, *cur;
432 res = ucl_object_typed_new (UCL_ARRAY);
437 for (i = 0; i < count; i ++) {
438 cur = ucl_test_boolean ();
439 assert (cur != NULL);
441 ucl_array_append (res, cur);
448 ucl_test_large_string (void)
454 while ((cur_len = pcg32_random ()) % 100000 == 0);
455 str = malloc (cur_len % 100000);
456 res = ucl_object_fromstring_common (str, cur_len % 100000,
458 res->flags |= UCL_OBJECT_BINARY;
466 return ucl_object_typed_new (UCL_NULL);