You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
8.0KB

  1. /*
  2. * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
  3. *
  4. * Jansson is free software; you can redistribute it and/or modify
  5. * it under the terms of the MIT license. See LICENSE for details.
  6. */
  7. #include "jansson_private_config.h"
  8. #include <jansson.h>
  9. #include <string.h>
  10. #ifdef HAVE_UNISTD_H
  11. #include <unistd.h>
  12. #endif
  13. #include "util.h"
  14. static int encode_null_callback(const char *buffer, size_t size, void *data)
  15. {
  16. (void)buffer;
  17. (void)size;
  18. (void)data;
  19. return 0;
  20. }
  21. static void encode_null()
  22. {
  23. if(json_dumps(NULL, JSON_ENCODE_ANY) != NULL)
  24. fail("json_dumps didn't fail for NULL");
  25. if(json_dumpb(NULL, NULL, 0, JSON_ENCODE_ANY) != 0)
  26. fail("json_dumps didn't fail for NULL");
  27. if(json_dumpf(NULL, stderr, JSON_ENCODE_ANY) != -1)
  28. fail("json_dumpf didn't fail for NULL");
  29. #ifdef HAVE_UNISTD_H
  30. if(json_dumpfd(NULL, STDERR_FILENO, JSON_ENCODE_ANY) != -1)
  31. fail("json_dumpfd didn't fail for NULL");
  32. #endif
  33. /* Don't test json_dump_file to avoid creating a file */
  34. if(json_dump_callback(NULL, encode_null_callback, NULL, JSON_ENCODE_ANY) != -1)
  35. fail("json_dump_callback didn't fail for NULL");
  36. }
  37. static void encode_twice()
  38. {
  39. /* Encode an empty object/array, add an item, encode again */
  40. json_t *json;
  41. char *result;
  42. json = json_object();
  43. result = json_dumps(json, 0);
  44. if(!result || strcmp(result, "{}"))
  45. fail("json_dumps failed");
  46. free(result);
  47. json_object_set_new(json, "foo", json_integer(5));
  48. result = json_dumps(json, 0);
  49. if(!result || strcmp(result, "{\"foo\": 5}"))
  50. fail("json_dumps failed");
  51. free(result);
  52. json_decref(json);
  53. json = json_array();
  54. result = json_dumps(json, 0);
  55. if(!result || strcmp(result, "[]"))
  56. fail("json_dumps failed");
  57. free(result);
  58. json_array_append_new(json, json_integer(5));
  59. result = json_dumps(json, 0);
  60. if(!result || strcmp(result, "[5]"))
  61. fail("json_dumps failed");
  62. free(result);
  63. json_decref(json);
  64. }
  65. static void circular_references()
  66. {
  67. /* Construct a JSON object/array with a circular reference:
  68. object: {"a": {"b": {"c": <circular reference to $.a>}}}
  69. array: [[[<circular reference to the $[0] array>]]]
  70. Encode it, remove the circular reference and encode again.
  71. */
  72. json_t *json;
  73. char *result;
  74. json = json_object();
  75. json_object_set_new(json, "a", json_object());
  76. json_object_set_new(json_object_get(json, "a"), "b", json_object());
  77. json_object_set(json_object_get(json_object_get(json, "a"), "b"), "c",
  78. json_object_get(json, "a"));
  79. if(json_dumps(json, 0))
  80. fail("json_dumps encoded a circular reference!");
  81. json_object_del(json_object_get(json_object_get(json, "a"), "b"), "c");
  82. result = json_dumps(json, 0);
  83. if(!result || strcmp(result, "{\"a\": {\"b\": {}}}"))
  84. fail("json_dumps failed!");
  85. free(result);
  86. json_decref(json);
  87. json = json_array();
  88. json_array_append_new(json, json_array());
  89. json_array_append_new(json_array_get(json, 0), json_array());
  90. json_array_append(json_array_get(json_array_get(json, 0), 0),
  91. json_array_get(json, 0));
  92. if(json_dumps(json, 0))
  93. fail("json_dumps encoded a circular reference!");
  94. json_array_remove(json_array_get(json_array_get(json, 0), 0), 0);
  95. result = json_dumps(json, 0);
  96. if(!result || strcmp(result, "[[[]]]"))
  97. fail("json_dumps failed!");
  98. free(result);
  99. json_decref(json);
  100. }
  101. static void encode_other_than_array_or_object()
  102. {
  103. /* Encoding anything other than array or object should only
  104. * succeed if the JSON_ENCODE_ANY flag is used */
  105. json_t *json;
  106. char *result;
  107. json = json_string("foo");
  108. if(json_dumps(json, 0) != NULL)
  109. fail("json_dumps encoded a string!");
  110. if(json_dumpf(json, NULL, 0) == 0)
  111. fail("json_dumpf encoded a string!");
  112. if(json_dumpfd(json, -1, 0) == 0)
  113. fail("json_dumpfd encoded a string!");
  114. result = json_dumps(json, JSON_ENCODE_ANY);
  115. if(!result || strcmp(result, "\"foo\"") != 0)
  116. fail("json_dumps failed to encode a string with JSON_ENCODE_ANY");
  117. free(result);
  118. json_decref(json);
  119. json = json_integer(42);
  120. if(json_dumps(json, 0) != NULL)
  121. fail("json_dumps encoded an integer!");
  122. if(json_dumpf(json, NULL, 0) == 0)
  123. fail("json_dumpf encoded an integer!");
  124. if(json_dumpfd(json, -1, 0) == 0)
  125. fail("json_dumpfd encoded an integer!");
  126. result = json_dumps(json, JSON_ENCODE_ANY);
  127. if(!result || strcmp(result, "42") != 0)
  128. fail("json_dumps failed to encode an integer with JSON_ENCODE_ANY");
  129. free(result);
  130. json_decref(json);
  131. }
  132. static void escape_slashes()
  133. {
  134. /* Test dump escaping slashes */
  135. json_t *json;
  136. char *result;
  137. json = json_object();
  138. json_object_set_new(json, "url", json_string("https://github.com/akheron/jansson"));
  139. result = json_dumps(json, 0);
  140. if(!result || strcmp(result, "{\"url\": \"https://github.com/akheron/jansson\"}"))
  141. fail("json_dumps failed to not escape slashes");
  142. free(result);
  143. result = json_dumps(json, JSON_ESCAPE_SLASH);
  144. if(!result || strcmp(result, "{\"url\": \"https:\\/\\/github.com\\/akheron\\/jansson\"}"))
  145. fail("json_dumps failed to escape slashes");
  146. free(result);
  147. json_decref(json);
  148. }
  149. static void encode_nul_byte()
  150. {
  151. json_t *json;
  152. char *result;
  153. json = json_stringn("nul byte \0 in string", 20);
  154. result = json_dumps(json, JSON_ENCODE_ANY);
  155. if(!result || memcmp(result, "\"nul byte \\u0000 in string\"", 27))
  156. fail("json_dumps failed to dump an embedded NUL byte");
  157. free(result);
  158. json_decref(json);
  159. }
  160. static void dump_file()
  161. {
  162. json_t *json;
  163. int result;
  164. result = json_dump_file(NULL, "", 0);
  165. if (result != -1)
  166. fail("json_dump_file succeeded with invalid args");
  167. json = json_object();
  168. result = json_dump_file(json, "json_dump_file.json", 0);
  169. if (result != 0)
  170. fail("json_dump_file failed");
  171. json_decref(json);
  172. remove("json_dump_file.json");
  173. }
  174. static void dumpb()
  175. {
  176. char buf[2];
  177. json_t *obj;
  178. size_t size;
  179. obj = json_object();
  180. size = json_dumpb(obj, buf, sizeof(buf), 0);
  181. if(size != 2 || strncmp(buf, "{}", 2))
  182. fail("json_dumpb failed");
  183. json_decref(obj);
  184. obj = json_pack("{s:s}", "foo", "bar");
  185. size = json_dumpb(obj, buf, sizeof(buf), JSON_COMPACT);
  186. if(size != 13)
  187. fail("json_dumpb size check failed");
  188. json_decref(obj);
  189. }
  190. static void dumpfd()
  191. {
  192. #ifdef HAVE_UNISTD_H
  193. int fds[2] = {-1, -1};
  194. json_t *a, *b;
  195. if(pipe(fds))
  196. fail("pipe() failed");
  197. a = json_pack("{s:s}", "foo", "bar");
  198. if(json_dumpfd(a, fds[1], 0))
  199. fail("json_dumpfd() failed");
  200. close(fds[1]);
  201. b = json_loadfd(fds[0], 0, NULL);
  202. if (!b)
  203. fail("json_loadfd() failed");
  204. close(fds[0]);
  205. if (!json_equal(a, b))
  206. fail("json_equal() failed for fd test");
  207. json_decref(a);
  208. json_decref(b);
  209. #endif
  210. }
  211. static void embed()
  212. {
  213. static const char *plains[] = {
  214. "{\"bar\":[],\"foo\":{}}",
  215. "[[],{}]",
  216. "{}",
  217. "[]",
  218. NULL
  219. };
  220. size_t i;
  221. for(i = 0; plains[i]; i++) {
  222. const char *plain = plains[i];
  223. json_t *parse = NULL;
  224. char *embed = NULL;
  225. size_t psize = 0;
  226. size_t esize = 0;
  227. psize = strlen(plain) - 2;
  228. embed = calloc(1, psize);
  229. parse = json_loads(plain, 0, NULL);
  230. esize = json_dumpb(parse, embed, psize,
  231. JSON_COMPACT | JSON_SORT_KEYS | JSON_EMBED);
  232. json_decref(parse);
  233. if(esize != psize)
  234. fail("json_dumpb(JSON_EMBED) returned an invalid size");
  235. if(strncmp(plain + 1, embed, esize) != 0)
  236. fail("json_dumps(JSON_EMBED) returned an invalid value");
  237. free(embed);
  238. }
  239. }
  240. static void run_tests()
  241. {
  242. encode_null();
  243. encode_twice();
  244. circular_references();
  245. encode_other_than_array_or_object();
  246. escape_slashes();
  247. encode_nul_byte();
  248. dump_file();
  249. dumpb();
  250. dumpfd();
  251. embed();
  252. }