1290067Sbapt/* 2290067Sbapt * Copyright (c) 2015, Vsevolod Stakhov 3290067Sbapt * All rights reserved. 4290067Sbapt * 5290067Sbapt * Redistribution and use in source and binary forms, with or without 6290067Sbapt * modification, are permitted provided that the following conditions are met: 7290067Sbapt * * Redistributions of source code must retain the above copyright 8290067Sbapt * notice, this list of conditions and the following disclaimer. 9290067Sbapt * * Redistributions in binary form must reproduce the above copyright 10290067Sbapt * notice, this list of conditions and the following disclaimer in the 11290067Sbapt * documentation and/or other materials provided with the distribution. 12290067Sbapt * 13290067Sbapt * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY 14290067Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15290067Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16290067Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 17290067Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18290067Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19290067Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20290067Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21290067Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22290067Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23290067Sbapt */ 24290067Sbapt 25290067Sbapt#include "ucl.h" 26290067Sbapt#include "ucl_internal.h" 27290067Sbapt#include <ctype.h> 28290067Sbapt 29298166Sbaptstatic const int niter = 20; 30298166Sbaptstatic const int ntests = 10; 31298166Sbaptstatic const int nelt = 20; 32290067Sbapt 33290067Sbaptstatic int recursion = 0; 34290067Sbapt 35290067Sbapttypedef ucl_object_t* (*ucl_msgpack_test)(void); 36290067Sbapt 37290067Sbaptstatic ucl_object_t* ucl_test_integer (void); 38290067Sbaptstatic ucl_object_t* ucl_test_string (void); 39290067Sbaptstatic ucl_object_t* ucl_test_boolean (void); 40290067Sbaptstatic ucl_object_t* ucl_test_map (void); 41290067Sbaptstatic ucl_object_t* ucl_test_array (void); 42298166Sbaptstatic ucl_object_t* ucl_test_large_map (void); 43298166Sbaptstatic ucl_object_t* ucl_test_large_array (void); 44298166Sbaptstatic ucl_object_t* ucl_test_large_string (void); 45298166Sbaptstatic ucl_object_t* ucl_test_null (void); 46290067Sbapt 47290067Sbaptucl_msgpack_test tests[] = { 48290067Sbapt ucl_test_integer, 49290067Sbapt ucl_test_string, 50290067Sbapt ucl_test_boolean, 51290067Sbapt ucl_test_map, 52290067Sbapt ucl_test_array, 53298166Sbapt ucl_test_null 54290067Sbapt}; 55290067Sbapt 56290067Sbapt#define NTESTS (sizeof(tests) / sizeof(tests[0])) 57290067Sbapt 58290067Sbapttypedef struct 59290067Sbapt{ 60290067Sbapt uint64_t state; 61290067Sbapt uint64_t inc; 62290067Sbapt} pcg32_random_t; 63290067Sbapt 64290067Sbaptpcg32_random_t rng; 65290067Sbapt 66290067Sbapt/* 67290067Sbapt * From http://www.pcg-random.org/ 68290067Sbapt */ 69290067Sbaptstatic uint32_t 70290067Sbaptpcg32_random (void) 71290067Sbapt{ 72290067Sbapt uint64_t oldstate = rng.state; 73290067Sbapt 74290067Sbapt rng.state = oldstate * 6364136223846793005ULL + (rng.inc | 1); 75290067Sbapt uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; 76290067Sbapt uint32_t rot = oldstate >> 59u; 77290067Sbapt return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); 78290067Sbapt} 79290067Sbapt 80290067Sbaptstatic const char * 81290067Sbaptrandom_key (size_t *lenptr) 82290067Sbapt{ 83290067Sbapt static char keybuf[512]; 84290067Sbapt int keylen, i; 85290067Sbapt char c; 86290067Sbapt 87290067Sbapt keylen = pcg32_random () % (sizeof (keybuf) - 1) + 1; 88290067Sbapt 89290067Sbapt for (i = 0; i < keylen; i ++) { 90290067Sbapt do { 91290067Sbapt c = pcg32_random () & 0xFF; 92290067Sbapt } while (!isgraph (c)); 93290067Sbapt 94290067Sbapt keybuf[i] = c; 95290067Sbapt } 96290067Sbapt 97290067Sbapt *lenptr = keylen; 98290067Sbapt return keybuf; 99290067Sbapt} 100290067Sbapt 101290067Sbaptint 102290067Sbaptmain (int argc, char **argv) 103290067Sbapt{ 104290067Sbapt int fd, i, j; 105290067Sbapt uint32_t sel; 106290067Sbapt ucl_object_t *obj, *elt; 107290067Sbapt struct ucl_parser *parser; 108290067Sbapt size_t klen, elen, elen2; 109290067Sbapt const char *key; 110290067Sbapt unsigned char *emitted, *emitted2; 111290067Sbapt FILE *out; 112290067Sbapt const char *fname_out = NULL; 113290067Sbapt 114290067Sbapt switch (argc) { 115290067Sbapt case 2: 116290067Sbapt fname_out = argv[1]; 117290067Sbapt break; 118290067Sbapt } 119290067Sbapt 120290067Sbapt /* Seed prng */ 121290067Sbapt fd = open ("/dev/urandom", O_RDONLY); 122290067Sbapt assert (fd != -1); 123290067Sbapt assert (read (fd, &rng, sizeof (rng)) == sizeof (rng)); 124290067Sbapt close (fd); 125290067Sbapt 126290067Sbapt for (i = 0; i < niter; i ++) { 127290067Sbapt if (fname_out != NULL) { 128290067Sbapt out = fopen (fname_out, "w"); 129290067Sbapt if (out == NULL) { 130290067Sbapt exit (-errno); 131290067Sbapt } 132290067Sbapt } 133290067Sbapt else { 134290067Sbapt out = NULL; 135290067Sbapt } 136290067Sbapt 137290067Sbapt /* Generate phase */ 138290067Sbapt obj = ucl_object_typed_new (UCL_OBJECT); 139290067Sbapt 140290067Sbapt for (j = 0; j < ntests; j ++) { 141290067Sbapt sel = pcg32_random () % NTESTS; 142290067Sbapt 143290067Sbapt key = random_key (&klen); 144290067Sbapt recursion = 0; 145290067Sbapt elt = tests[sel](); 146290067Sbapt assert (elt != NULL); 147290067Sbapt assert (klen != 0); 148290067Sbapt 149290067Sbapt ucl_object_insert_key (obj, elt, key, klen, true); 150290067Sbapt } 151290067Sbapt 152298166Sbapt key = random_key (&klen); 153298166Sbapt elt = ucl_test_large_array (); 154298166Sbapt ucl_object_insert_key (obj, elt, key, klen, true); 155298166Sbapt 156298166Sbapt key = random_key (&klen); 157298166Sbapt elt = ucl_test_large_map (); 158298166Sbapt ucl_object_insert_key (obj, elt, key, klen, true); 159298166Sbapt 160298166Sbapt key = random_key (&klen); 161298166Sbapt elt = ucl_test_large_string (); 162298166Sbapt ucl_object_insert_key (obj, elt, key, klen, true); 163298166Sbapt 164290067Sbapt emitted = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen); 165290067Sbapt 166290067Sbapt assert (emitted != NULL); 167290067Sbapt 168290067Sbapt if (out) { 169290067Sbapt fprintf (out, "%*.s\n", (int)elen, emitted); 170290067Sbapt 171290067Sbapt fclose (out); 172290067Sbapt } 173290067Sbapt ucl_object_unref (obj); 174290067Sbapt 175290067Sbapt parser = ucl_parser_new (0); 176290067Sbapt 177290067Sbapt if (!ucl_parser_add_chunk_full (parser, emitted, elen, 0, 178290067Sbapt UCL_DUPLICATE_APPEND, UCL_PARSE_MSGPACK)) { 179290067Sbapt fprintf (stderr, "error parsing input: %s", 180290067Sbapt ucl_parser_get_error (parser)); 181290067Sbapt assert (0); 182290067Sbapt } 183290067Sbapt 184290067Sbapt obj = ucl_parser_get_object (parser); 185290067Sbapt assert (obj != NULL); 186290067Sbapt 187290067Sbapt emitted2 = ucl_object_emit_len (obj, UCL_EMIT_MSGPACK, &elen2); 188290067Sbapt 189290067Sbapt assert (emitted2 != NULL); 190290067Sbapt assert (elen2 == elen); 191290067Sbapt assert (memcmp (emitted, emitted2, elen) == 0); 192290067Sbapt 193290067Sbapt ucl_parser_free (parser); 194290067Sbapt ucl_object_unref (obj); 195290067Sbapt free (emitted); 196290067Sbapt free (emitted2); 197290067Sbapt } 198290067Sbapt 199290067Sbapt return 0; 200290067Sbapt} 201290067Sbapt 202290067Sbapt 203290067Sbaptstatic ucl_object_t* 204290067Sbaptucl_test_integer (void) 205290067Sbapt{ 206290067Sbapt ucl_object_t *res; 207290067Sbapt int count, i; 208290067Sbapt uint64_t cur; 209298166Sbapt double curf; 210290067Sbapt 211290067Sbapt res = ucl_object_typed_new (UCL_ARRAY); 212290067Sbapt count = pcg32_random () % nelt; 213290067Sbapt 214290067Sbapt for (i = 0; i < count; i ++) { 215290067Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 216290067Sbapt ucl_array_append (res, ucl_object_fromint (cur % 128)); 217298166Sbapt ucl_array_append (res, ucl_object_fromint (-(cur % 128))); 218290067Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 219298166Sbapt ucl_array_append (res, ucl_object_fromint (cur % UINT16_MAX)); 220298166Sbapt ucl_array_append (res, ucl_object_fromint (-(cur % INT16_MAX))); 221290067Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 222298166Sbapt ucl_array_append (res, ucl_object_fromint (cur % UINT32_MAX)); 223298166Sbapt ucl_array_append (res, ucl_object_fromint (-(cur % INT32_MAX))); 224290067Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 225298166Sbapt ucl_array_append (res, ucl_object_fromint (cur)); 226298166Sbapt ucl_array_append (res, ucl_object_fromint (-cur)); 227298166Sbapt /* Double version */ 228290067Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 229298166Sbapt curf = (cur % 128) / 19 * 16; 230298166Sbapt ucl_array_append (res, ucl_object_fromdouble (curf)); 231298166Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 232298166Sbapt curf = -(cur % 128) / 19 * 16; 233298166Sbapt ucl_array_append (res, ucl_object_fromdouble (curf)); 234298166Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 235298166Sbapt curf = (cur % 65536) / 19 * 16; 236298166Sbapt ucl_array_append (res, ucl_object_fromdouble (curf)); 237298166Sbapt ucl_array_append (res, ucl_object_fromdouble (-curf)); 238298166Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 239298166Sbapt curf = (cur % INT32_MAX) / 19 * 16; 240298166Sbapt ucl_array_append (res, ucl_object_fromdouble (curf)); 241298166Sbapt cur = ((uint64_t)pcg32_random ()) << 32 | pcg32_random (); 242298166Sbapt memcpy (&curf, &cur, sizeof (curf)); 243290067Sbapt ucl_array_append (res, ucl_object_fromint (cur)); 244290067Sbapt } 245290067Sbapt 246290067Sbapt return res; 247290067Sbapt} 248290067Sbapt 249290067Sbaptstatic ucl_object_t* 250290067Sbaptucl_test_string (void) 251290067Sbapt{ 252290067Sbapt ucl_object_t *res, *elt; 253290067Sbapt int count, i; 254290067Sbapt uint32_t cur_len; 255290067Sbapt char *str; 256290067Sbapt 257290067Sbapt res = ucl_object_typed_new (UCL_ARRAY); 258290067Sbapt count = pcg32_random () % nelt; 259290067Sbapt 260290067Sbapt for (i = 0; i < count; i ++) { 261290067Sbapt while ((cur_len = pcg32_random ()) % 128 == 0); 262290067Sbapt 263290067Sbapt str = malloc (cur_len % 128); 264290067Sbapt ucl_array_append (res, ucl_object_fromstring_common (str, cur_len % 128, 265290067Sbapt UCL_STRING_RAW)); 266290067Sbapt free (str); 267290067Sbapt 268290067Sbapt while ((cur_len = pcg32_random ()) % 512 == 0); 269290067Sbapt str = malloc (cur_len % 512); 270290067Sbapt ucl_array_append (res, ucl_object_fromstring_common (str, cur_len % 512, 271290067Sbapt UCL_STRING_RAW)); 272290067Sbapt free (str); 273290067Sbapt 274290067Sbapt while ((cur_len = pcg32_random ()) % 128 == 0); 275290067Sbapt str = malloc (cur_len % 128); 276290067Sbapt elt = ucl_object_fromstring_common (str, cur_len % 128, 277290067Sbapt UCL_STRING_RAW); 278290067Sbapt elt->flags |= UCL_OBJECT_BINARY; 279290067Sbapt ucl_array_append (res, elt); 280290067Sbapt free (str); 281290067Sbapt 282290067Sbapt while ((cur_len = pcg32_random ()) % 512 == 0); 283290067Sbapt str = malloc (cur_len % 512); 284290067Sbapt elt = ucl_object_fromstring_common (str, cur_len % 512, 285290067Sbapt UCL_STRING_RAW); 286290067Sbapt elt->flags |= UCL_OBJECT_BINARY; 287290067Sbapt ucl_array_append (res, elt); 288290067Sbapt free (str); 289290067Sbapt } 290290067Sbapt 291298166Sbapt /* One large string */ 292298166Sbapt str = malloc (65537); 293298166Sbapt elt = ucl_object_fromstring_common (str, 65537, 294298166Sbapt UCL_STRING_RAW); 295298166Sbapt elt->flags |= UCL_OBJECT_BINARY; 296298166Sbapt ucl_array_append (res, elt); 297298166Sbapt free (str); 298298166Sbapt 299290067Sbapt return res; 300290067Sbapt} 301290067Sbapt 302290067Sbaptstatic ucl_object_t* 303290067Sbaptucl_test_boolean (void) 304290067Sbapt{ 305290067Sbapt ucl_object_t *res; 306290067Sbapt int count, i; 307290067Sbapt 308290067Sbapt res = ucl_object_typed_new (UCL_ARRAY); 309290067Sbapt count = pcg32_random () % nelt; 310290067Sbapt 311290067Sbapt for (i = 0; i < count; i ++) { 312290067Sbapt ucl_array_append (res, ucl_object_frombool (pcg32_random () % 2)); 313290067Sbapt } 314290067Sbapt 315290067Sbapt return res; 316290067Sbapt} 317290067Sbapt 318290067Sbaptstatic ucl_object_t* 319290067Sbaptucl_test_map (void) 320290067Sbapt{ 321290067Sbapt ucl_object_t *res, *cur; 322290067Sbapt int count, i; 323290067Sbapt uint32_t cur_len, sel; 324290067Sbapt size_t klen; 325290067Sbapt const char *key; 326290067Sbapt 327290067Sbapt res = ucl_object_typed_new (UCL_OBJECT); 328290067Sbapt count = pcg32_random () % nelt; 329290067Sbapt 330290067Sbapt recursion ++; 331290067Sbapt 332290067Sbapt for (i = 0; i < count; i ++) { 333290067Sbapt 334290067Sbapt if (recursion > 10) { 335298166Sbapt for (;;) { 336298166Sbapt sel = pcg32_random () % NTESTS; 337298166Sbapt if (tests[sel] != ucl_test_map && 338298166Sbapt tests[sel] != ucl_test_array) { 339298166Sbapt break; 340298166Sbapt } 341298166Sbapt } 342290067Sbapt } 343290067Sbapt else { 344290067Sbapt sel = pcg32_random () % NTESTS; 345290067Sbapt } 346290067Sbapt 347290067Sbapt key = random_key (&klen); 348290067Sbapt cur = tests[sel](); 349290067Sbapt assert (cur != NULL); 350290067Sbapt assert (klen != 0); 351290067Sbapt 352290067Sbapt ucl_object_insert_key (res, cur, key, klen, true); 353290067Sbapt 354290067Sbapt /* Multi value key */ 355290067Sbapt cur = tests[sel](); 356290067Sbapt assert (cur != NULL); 357290067Sbapt 358290067Sbapt ucl_object_insert_key (res, cur, key, klen, true); 359290067Sbapt } 360290067Sbapt 361290067Sbapt return res; 362290067Sbapt} 363290067Sbapt 364290067Sbaptstatic ucl_object_t* 365298166Sbaptucl_test_large_map (void) 366298166Sbapt{ 367298166Sbapt ucl_object_t *res, *cur; 368298166Sbapt int count, i; 369298166Sbapt uint32_t cur_len; 370298166Sbapt size_t klen; 371298166Sbapt const char *key; 372298166Sbapt 373298166Sbapt res = ucl_object_typed_new (UCL_OBJECT); 374298166Sbapt count = 65537; 375298166Sbapt 376298166Sbapt recursion ++; 377298166Sbapt 378298166Sbapt for (i = 0; i < count; i ++) { 379298166Sbapt key = random_key (&klen); 380298166Sbapt cur = ucl_test_boolean (); 381298166Sbapt assert (cur != NULL); 382298166Sbapt assert (klen != 0); 383298166Sbapt 384298166Sbapt ucl_object_insert_key (res, cur, key, klen, true); 385298166Sbapt } 386298166Sbapt 387298166Sbapt return res; 388298166Sbapt} 389298166Sbapt 390298166Sbaptstatic ucl_object_t* 391290067Sbaptucl_test_array (void) 392290067Sbapt{ 393290067Sbapt ucl_object_t *res, *cur; 394290067Sbapt int count, i; 395290067Sbapt uint32_t cur_len, sel; 396290067Sbapt 397290067Sbapt res = ucl_object_typed_new (UCL_ARRAY); 398290067Sbapt count = pcg32_random () % nelt; 399290067Sbapt 400290067Sbapt recursion ++; 401290067Sbapt 402290067Sbapt for (i = 0; i < count; i ++) { 403290067Sbapt if (recursion > 10) { 404298166Sbapt for (;;) { 405298166Sbapt sel = pcg32_random () % NTESTS; 406298166Sbapt if (tests[sel] != ucl_test_map && 407298166Sbapt tests[sel] != ucl_test_array) { 408298166Sbapt break; 409298166Sbapt } 410298166Sbapt } 411290067Sbapt } 412290067Sbapt else { 413290067Sbapt sel = pcg32_random () % NTESTS; 414290067Sbapt } 415290067Sbapt 416290067Sbapt cur = tests[sel](); 417290067Sbapt assert (cur != NULL); 418290067Sbapt 419290067Sbapt ucl_array_append (res, cur); 420290067Sbapt } 421290067Sbapt 422290067Sbapt return res; 423290067Sbapt} 424298166Sbapt 425298166Sbaptstatic ucl_object_t* 426298166Sbaptucl_test_large_array (void) 427298166Sbapt{ 428298166Sbapt ucl_object_t *res, *cur; 429298166Sbapt int count, i; 430298166Sbapt uint32_t cur_len; 431298166Sbapt 432298166Sbapt res = ucl_object_typed_new (UCL_ARRAY); 433298166Sbapt count = 65537; 434298166Sbapt 435298166Sbapt recursion ++; 436298166Sbapt 437298166Sbapt for (i = 0; i < count; i ++) { 438298166Sbapt cur = ucl_test_boolean (); 439298166Sbapt assert (cur != NULL); 440298166Sbapt 441298166Sbapt ucl_array_append (res, cur); 442298166Sbapt } 443298166Sbapt 444298166Sbapt return res; 445298166Sbapt} 446298166Sbapt 447298166Sbaptstatic ucl_object_t* 448298166Sbaptucl_test_large_string (void) 449298166Sbapt{ 450298166Sbapt ucl_object_t *res; 451298166Sbapt char *str; 452298166Sbapt uint32_t cur_len; 453298166Sbapt 454298166Sbapt while ((cur_len = pcg32_random ()) % 100000 == 0); 455298166Sbapt str = malloc (cur_len % 100000); 456298166Sbapt res = ucl_object_fromstring_common (str, cur_len % 100000, 457298166Sbapt UCL_STRING_RAW); 458298166Sbapt res->flags |= UCL_OBJECT_BINARY; 459298166Sbapt 460298166Sbapt return res; 461298166Sbapt} 462298166Sbapt 463298166Sbaptstatic ucl_object_t* 464298166Sbaptucl_test_null (void) 465298166Sbapt{ 466298166Sbapt return ucl_object_typed_new (UCL_NULL); 467298166Sbapt} 468