test_chaos.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #ifndef _GNU_SOURCE
  2. #define _GNU_SOURCE
  3. #endif
  4. #include "util.h"
  5. #include <jansson.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. static int chaos_pos = 0;
  9. static int chaos_fail = 0;
  10. #define CHAOS_MAX_FAILURE 100
  11. void *chaos_malloc(size_t size) {
  12. if (chaos_pos == chaos_fail)
  13. return NULL;
  14. chaos_pos++;
  15. return malloc(size);
  16. }
  17. void chaos_free(void *obj) { free(obj); }
  18. /* Test all potential allocation failures. */
  19. #define chaos_loop(condition, code, cleanup) \
  20. { \
  21. chaos_pos = chaos_fail = 0; \
  22. while (condition) { \
  23. if (chaos_fail > CHAOS_MAX_FAILURE) \
  24. fail("too many chaos failures"); \
  25. code chaos_pos = 0; \
  26. chaos_fail++; \
  27. } \
  28. cleanup \
  29. }
  30. #define chaos_loop_new_value(json, initcall) \
  31. chaos_loop(!json, json = initcall;, json_decref(json); json = NULL;)
  32. int test_unpack() {
  33. int ret = -1;
  34. int v1;
  35. int v2;
  36. json_error_t error;
  37. json_t *root = json_pack("{s:i, s:i, s:i, s:i}", "n1", 1, "n2", 2, "n3", 3, "n4", 4);
  38. if (!root)
  39. return -1;
  40. if (!json_unpack_ex(root, &error, JSON_STRICT, "{s:i, s:i}", "n1", &v1, "n2", &v2))
  41. fail("Unexpected success");
  42. if (json_error_code(&error) != json_error_end_of_input_expected) {
  43. if (json_error_code(&error) != json_error_out_of_memory)
  44. fail("Unexpected error code");
  45. goto out;
  46. }
  47. if (strcmp(error.text, "2 object item(s) left unpacked: n3, n4"))
  48. goto out;
  49. ret = 0;
  50. out:
  51. json_decref(root);
  52. return ret;
  53. }
  54. int dump_chaos_callback(const char *buffer, size_t size, void *data) {
  55. json_t *obj = json_object();
  56. (void)buffer;
  57. (void)size;
  58. (void)data;
  59. if (!obj)
  60. return -1;
  61. json_decref(obj);
  62. return 0;
  63. }
  64. static void test_chaos() {
  65. json_malloc_t orig_malloc;
  66. json_free_t orig_free;
  67. json_t *json = NULL;
  68. json_t *obj = json_object();
  69. json_t *arr1 = json_array();
  70. json_t *arr2 = json_array();
  71. json_t *txt = json_string("test");
  72. json_t *intnum = json_integer(1);
  73. json_t *dblnum = json_real(0.5);
  74. char *dumptxt = NULL;
  75. json_t *dumpobj = json_pack("{s:[iiis], s:s}", "key1", 1, 2, 3, "txt", "key2", "v2");
  76. int keyno;
  77. if (!obj || !arr1 || !arr2 || !txt || !intnum || !dblnum || !dumpobj)
  78. fail("failed to allocate basic objects");
  79. json_get_alloc_funcs(&orig_malloc, &orig_free);
  80. json_set_alloc_funcs(chaos_malloc, chaos_free);
  81. chaos_loop_new_value(json, json_pack("{s:s}", "key", "value"));
  82. chaos_loop_new_value(json, json_pack("{s:[]}", "key"));
  83. chaos_loop_new_value(json, json_pack("[biIf]", 1, 1, (json_int_t)1, 1.0));
  84. chaos_loop_new_value(json, json_pack("[s*,s*]", "v1", "v2"));
  85. chaos_loop_new_value(json, json_pack("o", json_incref(txt)));
  86. chaos_loop_new_value(json, json_pack("O", txt));
  87. chaos_loop_new_value(json, json_pack("s++", "a", "long string to force realloc",
  88. "another long string to force yet another "
  89. "reallocation of the string because "
  90. "that's what we are testing."));
  91. chaos_loop(test_unpack(), , );
  92. chaos_loop(json_dump_callback(dumpobj, dump_chaos_callback, NULL, JSON_INDENT(1)),
  93. , );
  94. chaos_loop(json_dump_callback(dumpobj, dump_chaos_callback, NULL,
  95. JSON_INDENT(1) | JSON_SORT_KEYS),
  96. , );
  97. chaos_loop(!dumptxt, dumptxt = json_dumps(dumpobj, JSON_COMPACT);, free(dumptxt);
  98. dumptxt = NULL;);
  99. chaos_loop_new_value(json, json_copy(obj));
  100. chaos_loop_new_value(json, json_deep_copy(obj));
  101. chaos_loop_new_value(json, json_copy(arr1));
  102. chaos_loop_new_value(json, json_deep_copy(arr1));
  103. chaos_loop_new_value(json, json_copy(txt));
  104. chaos_loop_new_value(json, json_copy(intnum));
  105. chaos_loop_new_value(json, json_copy(dblnum));
  106. #define JSON_LOAD_TXT "{\"n\":[1,2,3,4,5,6,7,8,9,10]}"
  107. chaos_loop_new_value(json, json_loads(JSON_LOAD_TXT, 0, NULL));
  108. chaos_loop_new_value(json, json_loadb(JSON_LOAD_TXT, strlen(JSON_LOAD_TXT), 0, NULL));
  109. chaos_loop_new_value(json, json_sprintf("%s", "string"));
  110. for (keyno = 0; keyno < 100; ++keyno) {
  111. #if !defined(_MSC_VER) || _MSC_VER >= 1900
  112. /* Skip this test on old Windows compilers. */
  113. char testkey[10];
  114. snprintf(testkey, sizeof(testkey), "test%d", keyno);
  115. chaos_loop(json_object_set_new_nocheck(obj, testkey, json_object()), , );
  116. #endif
  117. chaos_loop(json_array_append_new(arr1, json_null()), , );
  118. chaos_loop(json_array_insert_new(arr2, 0, json_null()), , );
  119. }
  120. chaos_loop(json_array_extend(arr1, arr2), , );
  121. chaos_loop(json_string_set_nocheck(txt, "test"), , );
  122. json_set_alloc_funcs(orig_malloc, orig_free);
  123. json_decref(obj);
  124. json_decref(arr1);
  125. json_decref(arr2);
  126. json_decref(txt);
  127. json_decref(intnum);
  128. json_decref(dblnum);
  129. json_decref(dumpobj);
  130. }
  131. static void run_tests() { test_chaos(); }