1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_cunit.h" 37 38 #include "json_write.c" 39 40 #include "spdk/util.h" 41 42 static uint8_t g_buf[1000]; 43 static uint8_t *g_write_pos; 44 45 static int 46 write_cb(void *cb_ctx, const void *data, size_t size) 47 { 48 size_t buf_free = g_buf + sizeof(g_buf) - g_write_pos; 49 50 if (size > buf_free) { 51 return -1; 52 } 53 54 memcpy(g_write_pos, data, size); 55 g_write_pos += size; 56 57 return 0; 58 } 59 60 #define BEGIN() \ 61 memset(g_buf, 0, sizeof(g_buf)); \ 62 g_write_pos = g_buf; \ 63 w = spdk_json_write_begin(write_cb, NULL, 0); \ 64 CU_ASSERT_FATAL(w != NULL) 65 66 #define END(json) \ 67 CU_ASSERT(spdk_json_write_end(w) == 0); \ 68 CU_ASSERT(g_write_pos - g_buf == sizeof(json) - 1); \ 69 CU_ASSERT(memcmp(json, g_buf, sizeof(json) - 1) == 0) 70 71 #define END_NOCMP() \ 72 CU_ASSERT(spdk_json_write_end(w) == 0) 73 74 #define END_FAIL() \ 75 CU_ASSERT(spdk_json_write_end(w) < 0) 76 77 #define VAL_STRING(str) \ 78 CU_ASSERT(spdk_json_write_string_raw(w, str, sizeof(str) - 1) == 0) 79 80 #define VAL_STRING_FAIL(str) \ 81 CU_ASSERT(spdk_json_write_string_raw(w, str, sizeof(str) - 1) < 0) 82 83 #define STR_PASS(in, out) \ 84 BEGIN(); VAL_STRING(in); END("\"" out "\"") 85 86 #define STR_FAIL(in) \ 87 BEGIN(); VAL_STRING_FAIL(in); END_FAIL() 88 89 #define VAL_NAME(name) \ 90 CU_ASSERT(spdk_json_write_name_raw(w, name, sizeof(name) - 1) == 0) 91 92 #define VAL_NULL() CU_ASSERT(spdk_json_write_null(w) == 0) 93 #define VAL_TRUE() CU_ASSERT(spdk_json_write_bool(w, true) == 0) 94 #define VAL_FALSE() CU_ASSERT(spdk_json_write_bool(w, false) == 0) 95 96 #define VAL_INT32(i) CU_ASSERT(spdk_json_write_int32(w, i) == 0); 97 #define VAL_UINT32(u) CU_ASSERT(spdk_json_write_uint32(w, u) == 0); 98 99 #define VAL_ARRAY_BEGIN() CU_ASSERT(spdk_json_write_array_begin(w) == 0) 100 #define VAL_ARRAY_END() CU_ASSERT(spdk_json_write_array_end(w) == 0) 101 102 #define VAL_OBJECT_BEGIN() CU_ASSERT(spdk_json_write_object_begin(w) == 0) 103 #define VAL_OBJECT_END() CU_ASSERT(spdk_json_write_object_end(w) == 0) 104 105 #define VAL(v) CU_ASSERT(spdk_json_write_val(w, v) == 0) 106 107 static void 108 test_write_literal(void) 109 { 110 struct spdk_json_write_ctx *w; 111 112 BEGIN(); 113 VAL_NULL(); 114 END("null"); 115 116 BEGIN(); 117 VAL_TRUE(); 118 END("true"); 119 120 BEGIN(); 121 VAL_FALSE(); 122 END("false"); 123 } 124 125 static void 126 test_write_string_simple(void) 127 { 128 struct spdk_json_write_ctx *w; 129 130 STR_PASS("hello world", "hello world"); 131 STR_PASS(" ", " "); 132 STR_PASS("~", "~"); 133 } 134 135 static void 136 test_write_string_escapes(void) 137 { 138 struct spdk_json_write_ctx *w; 139 140 /* Two-character escapes */ 141 STR_PASS("\b", "\\b"); 142 STR_PASS("\f", "\\f"); 143 STR_PASS("\n", "\\n"); 144 STR_PASS("\r", "\\r"); 145 STR_PASS("\t", "\\t"); 146 STR_PASS("\"", "\\\""); 147 STR_PASS("\\", "\\\\"); 148 149 /* JSON defines an escape for forward slash, but it is optional */ 150 STR_PASS("/", "/"); 151 152 STR_PASS("hello\nworld", "hello\\nworld"); 153 154 STR_PASS("\x00", "\\u0000"); 155 STR_PASS("\x01", "\\u0001"); 156 STR_PASS("\x02", "\\u0002"); 157 158 STR_PASS("\xC3\xB6", "\\u00F6"); 159 STR_PASS("\xE2\x88\x9A", "\\u221A"); 160 STR_PASS("\xEA\xAA\xAA", "\\uAAAA"); 161 162 /* Surrogate pairs */ 163 STR_PASS("\xF0\x9D\x84\x9E", "\\uD834\\uDD1E"); 164 STR_PASS("\xF0\xA0\x9C\x8E", "\\uD841\\uDF0E"); 165 166 /* Examples from RFC 3629 */ 167 STR_PASS("\x41\xE2\x89\xA2\xCE\x91\x2E", "A\\u2262\\u0391."); 168 STR_PASS("\xED\x95\x9C\xEA\xB5\xAD\xEC\x96\xB4", "\\uD55C\\uAD6D\\uC5B4"); 169 STR_PASS("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E", "\\u65E5\\u672C\\u8A9E"); 170 STR_PASS("\xEF\xBB\xBF\xF0\xA3\x8E\xB4", "\\uFEFF\\uD84C\\uDFB4"); 171 172 /* UTF-8 edge cases */ 173 STR_PASS("\x7F", "\\u007F"); 174 STR_FAIL("\x80"); 175 STR_FAIL("\xC1"); 176 STR_FAIL("\xC2"); 177 STR_PASS("\xC2\x80", "\\u0080"); 178 STR_PASS("\xC2\xBF", "\\u00BF"); 179 STR_PASS("\xDF\x80", "\\u07C0"); 180 STR_PASS("\xDF\xBF", "\\u07FF"); 181 STR_FAIL("\xDF"); 182 STR_FAIL("\xE0\x80"); 183 STR_FAIL("\xE0\x1F"); 184 STR_FAIL("\xE0\x1F\x80"); 185 STR_FAIL("\xE0"); 186 STR_FAIL("\xE0\xA0"); 187 STR_PASS("\xE0\xA0\x80", "\\u0800"); 188 STR_PASS("\xE0\xA0\xBF", "\\u083F"); 189 STR_FAIL("\xE0\xA0\xC0"); 190 STR_PASS("\xE0\xBF\x80", "\\u0FC0"); 191 STR_PASS("\xE0\xBF\xBF", "\\u0FFF"); 192 STR_FAIL("\xE0\xC0\x80"); 193 STR_FAIL("\xE1"); 194 STR_FAIL("\xE1\x80"); 195 STR_FAIL("\xE1\x7F\x80"); 196 STR_FAIL("\xE1\x80\x7F"); 197 STR_PASS("\xE1\x80\x80", "\\u1000"); 198 STR_PASS("\xE1\x80\xBF", "\\u103F"); 199 STR_PASS("\xE1\xBF\x80", "\\u1FC0"); 200 STR_PASS("\xE1\xBF\xBF", "\\u1FFF"); 201 STR_FAIL("\xE1\xC0\x80"); 202 STR_FAIL("\xE1\x80\xC0"); 203 STR_PASS("\xEF\x80\x80", "\\uF000"); 204 STR_PASS("\xEF\xBF\xBF", "\\uFFFF"); 205 STR_FAIL("\xF0"); 206 STR_FAIL("\xF0\x90"); 207 STR_FAIL("\xF0\x90\x80"); 208 STR_FAIL("\xF0\x80\x80\x80"); 209 STR_FAIL("\xF0\x8F\x80\x80"); 210 STR_PASS("\xF0\x90\x80\x80", "\\uD800\\uDC00"); 211 STR_PASS("\xF0\x90\x80\xBF", "\\uD800\\uDC3F"); 212 STR_PASS("\xF0\x90\xBF\x80", "\\uD803\\uDFC0"); 213 STR_PASS("\xF0\xBF\x80\x80", "\\uD8BC\\uDC00"); 214 STR_FAIL("\xF0\xC0\x80\x80"); 215 STR_FAIL("\xF1"); 216 STR_FAIL("\xF1\x80"); 217 STR_FAIL("\xF1\x80\x80"); 218 STR_FAIL("\xF1\x80\x80\x7F"); 219 STR_PASS("\xF1\x80\x80\x80", "\\uD8C0\\uDC00"); 220 STR_PASS("\xF1\x80\x80\xBF", "\\uD8C0\\uDC3F"); 221 STR_PASS("\xF1\x80\xBF\x80", "\\uD8C3\\uDFC0"); 222 STR_PASS("\xF1\xBF\x80\x80", "\\uD9BC\\uDC00"); 223 STR_PASS("\xF3\x80\x80\x80", "\\uDAC0\\uDC00"); 224 STR_FAIL("\xF3\xC0\x80\x80"); 225 STR_FAIL("\xF3\x80\xC0\x80"); 226 STR_FAIL("\xF3\x80\x80\xC0"); 227 STR_FAIL("\xF4"); 228 STR_FAIL("\xF4\x80"); 229 STR_FAIL("\xF4\x80\x80"); 230 STR_PASS("\xF4\x80\x80\x80", "\\uDBC0\\uDC00"); 231 STR_PASS("\xF4\x8F\x80\x80", "\\uDBFC\\uDC00"); 232 STR_PASS("\xF4\x8F\xBF\xBF", "\\uDBFF\\uDFFF"); 233 STR_FAIL("\xF4\x90\x80\x80"); 234 STR_FAIL("\xF5"); 235 STR_FAIL("\xF5\x80"); 236 STR_FAIL("\xF5\x80\x80"); 237 STR_FAIL("\xF5\x80\x80\x80"); 238 STR_FAIL("\xF5\x80\x80\x80\x80"); 239 240 /* Overlong encodings */ 241 STR_FAIL("\xC0\x80"); 242 243 /* Surrogate pairs */ 244 STR_FAIL("\xED\xA0\x80"); /* U+D800 First high surrogate */ 245 STR_FAIL("\xED\xAF\xBF"); /* U+DBFF Last high surrogate */ 246 STR_FAIL("\xED\xB0\x80"); /* U+DC00 First low surrogate */ 247 STR_FAIL("\xED\xBF\xBF"); /* U+DFFF Last low surrogate */ 248 STR_FAIL("\xED\xA1\x8C\xED\xBE\xB4"); /* U+233B4 (invalid surrogate pair encoding) */ 249 } 250 251 static void 252 test_write_number_int32(void) 253 { 254 struct spdk_json_write_ctx *w; 255 256 BEGIN(); 257 VAL_INT32(0); 258 END("0"); 259 260 BEGIN(); 261 VAL_INT32(1); 262 END("1"); 263 264 BEGIN(); 265 VAL_INT32(123); 266 END("123"); 267 268 BEGIN(); 269 VAL_INT32(-123); 270 END("-123"); 271 272 BEGIN(); 273 VAL_INT32(2147483647); 274 END("2147483647"); 275 276 BEGIN(); 277 VAL_INT32(-2147483648); 278 END("-2147483648"); 279 } 280 281 static void 282 test_write_number_uint32(void) 283 { 284 struct spdk_json_write_ctx *w; 285 286 BEGIN(); 287 VAL_UINT32(0); 288 END("0"); 289 290 BEGIN(); 291 VAL_UINT32(1); 292 END("1"); 293 294 BEGIN(); 295 VAL_UINT32(123); 296 END("123"); 297 298 BEGIN(); 299 VAL_UINT32(2147483647); 300 END("2147483647"); 301 302 BEGIN(); 303 VAL_UINT32(4294967295); 304 END("4294967295"); 305 } 306 307 static void 308 test_write_array(void) 309 { 310 struct spdk_json_write_ctx *w; 311 312 BEGIN(); 313 VAL_ARRAY_BEGIN(); 314 VAL_ARRAY_END(); 315 END("[]"); 316 317 BEGIN(); 318 VAL_ARRAY_BEGIN(); 319 VAL_INT32(0); 320 VAL_ARRAY_END(); 321 END("[0]"); 322 323 BEGIN(); 324 VAL_ARRAY_BEGIN(); 325 VAL_INT32(0); 326 VAL_INT32(1); 327 VAL_ARRAY_END(); 328 END("[0,1]"); 329 330 BEGIN(); 331 VAL_ARRAY_BEGIN(); 332 VAL_INT32(0); 333 VAL_INT32(1); 334 VAL_INT32(2); 335 VAL_ARRAY_END(); 336 END("[0,1,2]"); 337 338 BEGIN(); 339 VAL_ARRAY_BEGIN(); 340 VAL_STRING("a"); 341 VAL_ARRAY_END(); 342 END("[\"a\"]"); 343 344 BEGIN(); 345 VAL_ARRAY_BEGIN(); 346 VAL_STRING("a"); 347 VAL_STRING("b"); 348 VAL_ARRAY_END(); 349 END("[\"a\",\"b\"]"); 350 351 BEGIN(); 352 VAL_ARRAY_BEGIN(); 353 VAL_STRING("a"); 354 VAL_STRING("b"); 355 VAL_STRING("c"); 356 VAL_ARRAY_END(); 357 END("[\"a\",\"b\",\"c\"]"); 358 359 BEGIN(); 360 VAL_ARRAY_BEGIN(); 361 VAL_TRUE(); 362 VAL_ARRAY_END(); 363 END("[true]"); 364 365 BEGIN(); 366 VAL_ARRAY_BEGIN(); 367 VAL_TRUE(); 368 VAL_FALSE(); 369 VAL_ARRAY_END(); 370 END("[true,false]"); 371 372 BEGIN(); 373 VAL_ARRAY_BEGIN(); 374 VAL_TRUE(); 375 VAL_FALSE(); 376 VAL_TRUE(); 377 VAL_ARRAY_END(); 378 END("[true,false,true]"); 379 } 380 381 static void 382 test_write_object(void) 383 { 384 struct spdk_json_write_ctx *w; 385 386 BEGIN(); 387 VAL_OBJECT_BEGIN(); 388 VAL_OBJECT_END(); 389 END("{}"); 390 391 BEGIN(); 392 VAL_OBJECT_BEGIN(); 393 VAL_NAME("a"); 394 VAL_INT32(0); 395 VAL_OBJECT_END(); 396 END("{\"a\":0}"); 397 398 BEGIN(); 399 VAL_OBJECT_BEGIN(); 400 VAL_NAME("a"); 401 VAL_INT32(0); 402 VAL_NAME("b"); 403 VAL_INT32(1); 404 VAL_OBJECT_END(); 405 END("{\"a\":0,\"b\":1}"); 406 407 BEGIN(); 408 VAL_OBJECT_BEGIN(); 409 VAL_NAME("a"); 410 VAL_INT32(0); 411 VAL_NAME("b"); 412 VAL_INT32(1); 413 VAL_NAME("c"); 414 VAL_INT32(2); 415 VAL_OBJECT_END(); 416 END("{\"a\":0,\"b\":1,\"c\":2}"); 417 } 418 419 static void 420 test_write_nesting(void) 421 { 422 struct spdk_json_write_ctx *w; 423 424 BEGIN(); 425 VAL_ARRAY_BEGIN(); 426 VAL_ARRAY_BEGIN(); 427 VAL_ARRAY_END(); 428 VAL_ARRAY_END(); 429 END("[[]]"); 430 431 BEGIN(); 432 VAL_ARRAY_BEGIN(); 433 VAL_ARRAY_BEGIN(); 434 VAL_ARRAY_BEGIN(); 435 VAL_ARRAY_END(); 436 VAL_ARRAY_END(); 437 VAL_ARRAY_END(); 438 END("[[[]]]"); 439 440 BEGIN(); 441 VAL_ARRAY_BEGIN(); 442 VAL_INT32(0); 443 VAL_ARRAY_BEGIN(); 444 VAL_ARRAY_END(); 445 VAL_ARRAY_END(); 446 END("[0,[]]"); 447 448 BEGIN(); 449 VAL_ARRAY_BEGIN(); 450 VAL_ARRAY_BEGIN(); 451 VAL_ARRAY_END(); 452 VAL_INT32(0); 453 VAL_ARRAY_END(); 454 END("[[],0]"); 455 456 BEGIN(); 457 VAL_ARRAY_BEGIN(); 458 VAL_INT32(0); 459 VAL_ARRAY_BEGIN(); 460 VAL_INT32(1); 461 VAL_ARRAY_END(); 462 VAL_INT32(2); 463 VAL_ARRAY_END(); 464 END("[0,[1],2]"); 465 466 BEGIN(); 467 VAL_ARRAY_BEGIN(); 468 VAL_INT32(0); 469 VAL_INT32(1); 470 VAL_ARRAY_BEGIN(); 471 VAL_INT32(2); 472 VAL_INT32(3); 473 VAL_ARRAY_END(); 474 VAL_INT32(4); 475 VAL_INT32(5); 476 VAL_ARRAY_END(); 477 END("[0,1,[2,3],4,5]"); 478 479 BEGIN(); 480 VAL_OBJECT_BEGIN(); 481 VAL_NAME("a"); 482 VAL_OBJECT_BEGIN(); 483 VAL_OBJECT_END(); 484 VAL_OBJECT_END(); 485 END("{\"a\":{}}"); 486 487 BEGIN(); 488 VAL_OBJECT_BEGIN(); 489 VAL_NAME("a"); 490 VAL_OBJECT_BEGIN(); 491 VAL_NAME("b"); 492 VAL_INT32(0); 493 VAL_OBJECT_END(); 494 VAL_OBJECT_END(); 495 END("{\"a\":{\"b\":0}}"); 496 497 BEGIN(); 498 VAL_OBJECT_BEGIN(); 499 VAL_NAME("a"); 500 VAL_ARRAY_BEGIN(); 501 VAL_INT32(0); 502 VAL_ARRAY_END(); 503 VAL_OBJECT_END(); 504 END("{\"a\":[0]}"); 505 506 BEGIN(); 507 VAL_ARRAY_BEGIN(); 508 VAL_OBJECT_BEGIN(); 509 VAL_NAME("a"); 510 VAL_INT32(0); 511 VAL_OBJECT_END(); 512 VAL_ARRAY_END(); 513 END("[{\"a\":0}]"); 514 515 BEGIN(); 516 VAL_ARRAY_BEGIN(); 517 VAL_OBJECT_BEGIN(); 518 VAL_NAME("a"); 519 VAL_OBJECT_BEGIN(); 520 VAL_NAME("b"); 521 VAL_ARRAY_BEGIN(); 522 VAL_OBJECT_BEGIN(); 523 VAL_NAME("c"); 524 VAL_INT32(1); 525 VAL_OBJECT_END(); 526 VAL_INT32(2); 527 VAL_ARRAY_END(); 528 VAL_NAME("d"); 529 VAL_INT32(3); 530 VAL_OBJECT_END(); 531 VAL_NAME("e"); 532 VAL_INT32(4); 533 VAL_OBJECT_END(); 534 VAL_INT32(5); 535 VAL_ARRAY_END(); 536 END("[{\"a\":{\"b\":[{\"c\":1},2],\"d\":3},\"e\":4},5]"); 537 538 /* Examples from RFC 7159 */ 539 BEGIN(); 540 VAL_OBJECT_BEGIN(); 541 VAL_NAME("Image"); 542 VAL_OBJECT_BEGIN(); 543 VAL_NAME("Width"); 544 VAL_INT32(800); 545 VAL_NAME("Height"); 546 VAL_INT32(600); 547 VAL_NAME("Title"); 548 VAL_STRING("View from 15th Floor"); 549 VAL_NAME("Thumbnail"); 550 VAL_OBJECT_BEGIN(); 551 VAL_NAME("Url"); 552 VAL_STRING("http://www.example.com/image/481989943"); 553 VAL_NAME("Height"); 554 VAL_INT32(125); 555 VAL_NAME("Width"); 556 VAL_INT32(100); 557 VAL_OBJECT_END(); 558 VAL_NAME("Animated"); 559 VAL_FALSE(); 560 VAL_NAME("IDs"); 561 VAL_ARRAY_BEGIN(); 562 VAL_INT32(116); 563 VAL_INT32(943); 564 VAL_INT32(234); 565 VAL_INT32(38793); 566 VAL_ARRAY_END(); 567 VAL_OBJECT_END(); 568 VAL_OBJECT_END(); 569 END( 570 "{\"Image\":" 571 "{" 572 "\"Width\":800," 573 "\"Height\":600," 574 "\"Title\":\"View from 15th Floor\"," 575 "\"Thumbnail\":{" 576 "\"Url\":\"http://www.example.com/image/481989943\"," 577 "\"Height\":125," 578 "\"Width\":100" 579 "}," 580 "\"Animated\":false," 581 "\"IDs\":[116,943,234,38793]" 582 "}" 583 "}"); 584 } 585 586 /* Round-trip parse and write test */ 587 static void 588 test_write_val(void) 589 { 590 struct spdk_json_write_ctx *w; 591 struct spdk_json_val values[100]; 592 char src[] = "{\"a\":[1,2,3],\"b\":{\"c\":\"d\"},\"e\":true,\"f\":false,\"g\":null}"; 593 594 CU_ASSERT(spdk_json_parse(src, strlen(src), values, SPDK_COUNTOF(values), NULL, 595 SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE) == 19); 596 597 BEGIN(); 598 VAL(values); 599 END("{\"a\":[1,2,3],\"b\":{\"c\":\"d\"},\"e\":true,\"f\":false,\"g\":null}"); 600 } 601 602 int main(int argc, char **argv) 603 { 604 CU_pSuite suite = NULL; 605 unsigned int num_failures; 606 607 if (CU_initialize_registry() != CUE_SUCCESS) { 608 return CU_get_error(); 609 } 610 611 suite = CU_add_suite("json", NULL, NULL); 612 if (suite == NULL) { 613 CU_cleanup_registry(); 614 return CU_get_error(); 615 } 616 617 if ( 618 CU_add_test(suite, "write_literal", test_write_literal) == NULL || 619 CU_add_test(suite, "write_string_simple", test_write_string_simple) == NULL || 620 CU_add_test(suite, "write_string_escapes", test_write_string_escapes) == NULL || 621 CU_add_test(suite, "write_number_int32", test_write_number_int32) == NULL || 622 CU_add_test(suite, "write_number_uint32", test_write_number_uint32) == NULL || 623 CU_add_test(suite, "write_array", test_write_array) == NULL || 624 CU_add_test(suite, "write_object", test_write_object) == NULL || 625 CU_add_test(suite, "write_nesting", test_write_nesting) == NULL || 626 CU_add_test(suite, "write_val", test_write_val) == NULL) { 627 CU_cleanup_registry(); 628 return CU_get_error(); 629 } 630 631 CU_basic_set_mode(CU_BRM_VERBOSE); 632 633 CU_basic_run_tests(); 634 635 num_failures = CU_get_number_of_failures(); 636 CU_cleanup_registry(); 637 638 return num_failures; 639 } 640