1 /*
2 Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "unity/examples/unity_config.h"
28 #include "unity/src/unity.h"
29 #include "common.h"
30
31
cjson_array_foreach_should_loop_over_arrays(void)32 static void cjson_array_foreach_should_loop_over_arrays(void)
33 {
34 cJSON array[1];
35 cJSON elements[10];
36 cJSON *element_pointer = NULL;
37 size_t i = 0;
38
39 memset(array, 0, sizeof(array));
40 memset(elements, 0, sizeof(elements));
41
42 /* create array */
43 array[0].child = &elements[0];
44 elements[0].prev = NULL;
45 elements[9].next = NULL;
46 for (i = 0; i < 9; i++)
47 {
48 elements[i].next = &elements[i + 1];
49 elements[i + 1].prev = &elements[i];
50 }
51
52 i = 0;
53 cJSON_ArrayForEach(element_pointer, array)
54 {
55 TEST_ASSERT_TRUE_MESSAGE(element_pointer == &elements[i], "Not iterating over array properly");
56 i++;
57 }
58 }
59
cjson_array_foreach_should_not_dereference_null_pointer(void)60 static void cjson_array_foreach_should_not_dereference_null_pointer(void)
61 {
62 cJSON *array = NULL;
63 cJSON *element = NULL;
64 cJSON_ArrayForEach(element, array);
65 }
66
cjson_get_object_item_should_get_object_items(void)67 static void cjson_get_object_item_should_get_object_items(void)
68 {
69 cJSON *item = NULL;
70 cJSON *found = NULL;
71
72 item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
73
74 found = cJSON_GetObjectItem(NULL, "test");
75 TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
76
77 found = cJSON_GetObjectItem(item, NULL);
78 TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
79
80
81 found = cJSON_GetObjectItem(item, "one");
82 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
83 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
84
85 found = cJSON_GetObjectItem(item, "tWo");
86 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
87 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
88
89 found = cJSON_GetObjectItem(item, "three");
90 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
91 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
92
93 found = cJSON_GetObjectItem(item, "four");
94 TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
95
96 cJSON_Delete(item);
97 }
98
cjson_get_object_item_case_sensitive_should_get_object_items(void)99 static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
100 {
101 cJSON *item = NULL;
102 cJSON *found = NULL;
103
104 item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
105
106 found = cJSON_GetObjectItemCaseSensitive(NULL, "test");
107 TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
108
109 found = cJSON_GetObjectItemCaseSensitive(item, NULL);
110 TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
111
112 found = cJSON_GetObjectItemCaseSensitive(item, "one");
113 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
114 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
115
116 found = cJSON_GetObjectItemCaseSensitive(item, "Two");
117 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
118 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
119
120 found = cJSON_GetObjectItemCaseSensitive(item, "tHree");
121 TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
122 TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
123
124 found = cJSON_GetObjectItemCaseSensitive(item, "One");
125 TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
126
127 cJSON_Delete(item);
128 }
129
cjson_get_object_item_should_not_crash_with_array(void)130 static void cjson_get_object_item_should_not_crash_with_array(void) {
131 cJSON *array = NULL;
132 cJSON *found = NULL;
133 array = cJSON_Parse("[1]");
134
135 found = cJSON_GetObjectItem(array, "name");
136 TEST_ASSERT_NULL(found);
137
138 cJSON_Delete(array);
139 }
140
cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)141 static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
142 cJSON *array = NULL;
143 cJSON *found = NULL;
144 array = cJSON_Parse("[1]");
145
146 found = cJSON_GetObjectItemCaseSensitive(array, "name");
147 TEST_ASSERT_NULL(found);
148
149 cJSON_Delete(array);
150 }
151
typecheck_functions_should_check_type(void)152 static void typecheck_functions_should_check_type(void)
153 {
154 cJSON invalid[1];
155 cJSON item[1];
156 invalid->type = cJSON_Invalid;
157 invalid->type |= cJSON_StringIsConst;
158 item->type = cJSON_False;
159 item->type |= cJSON_StringIsConst;
160
161 TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
162 TEST_ASSERT_FALSE(cJSON_IsInvalid(item));
163 TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid));
164
165 item->type = cJSON_False | cJSON_StringIsConst;
166 TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
167 TEST_ASSERT_FALSE(cJSON_IsFalse(invalid));
168 TEST_ASSERT_TRUE(cJSON_IsFalse(item));
169 TEST_ASSERT_TRUE(cJSON_IsBool(item));
170
171 item->type = cJSON_True | cJSON_StringIsConst;
172 TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
173 TEST_ASSERT_FALSE(cJSON_IsTrue(invalid));
174 TEST_ASSERT_TRUE(cJSON_IsTrue(item));
175 TEST_ASSERT_TRUE(cJSON_IsBool(item));
176
177 item->type = cJSON_NULL | cJSON_StringIsConst;
178 TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
179 TEST_ASSERT_FALSE(cJSON_IsNull(invalid));
180 TEST_ASSERT_TRUE(cJSON_IsNull(item));
181
182 item->type = cJSON_Number | cJSON_StringIsConst;
183 TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
184 TEST_ASSERT_FALSE(cJSON_IsNumber(invalid));
185 TEST_ASSERT_TRUE(cJSON_IsNumber(item));
186
187 item->type = cJSON_String | cJSON_StringIsConst;
188 TEST_ASSERT_FALSE(cJSON_IsString(NULL));
189 TEST_ASSERT_FALSE(cJSON_IsString(invalid));
190 TEST_ASSERT_TRUE(cJSON_IsString(item));
191
192 item->type = cJSON_Array | cJSON_StringIsConst;
193 TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
194 TEST_ASSERT_FALSE(cJSON_IsArray(invalid));
195 TEST_ASSERT_TRUE(cJSON_IsArray(item));
196
197 item->type = cJSON_Object | cJSON_StringIsConst;
198 TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
199 TEST_ASSERT_FALSE(cJSON_IsObject(invalid));
200 TEST_ASSERT_TRUE(cJSON_IsObject(item));
201
202 item->type = cJSON_Raw | cJSON_StringIsConst;
203 TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
204 TEST_ASSERT_FALSE(cJSON_IsRaw(invalid));
205 TEST_ASSERT_TRUE(cJSON_IsRaw(item));
206 }
207
cjson_should_not_parse_to_deeply_nested_jsons(void)208 static void cjson_should_not_parse_to_deeply_nested_jsons(void)
209 {
210 char deep_json[CJSON_NESTING_LIMIT + 1];
211 size_t position = 0;
212
213 for (position = 0; position < sizeof(deep_json); position++)
214 {
215 deep_json[position] = '[';
216 }
217 deep_json[sizeof(deep_json) - 1] = '\0';
218
219 TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(deep_json), "To deep JSONs should not be parsed.");
220 }
221
cjson_set_number_value_should_set_numbers(void)222 static void cjson_set_number_value_should_set_numbers(void)
223 {
224 cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
225
226 cJSON_SetNumberValue(number, 1.5);
227 TEST_ASSERT_EQUAL(1, number->valueint);
228 TEST_ASSERT_EQUAL_DOUBLE(1.5, number->valuedouble);
229
230 cJSON_SetNumberValue(number, -1.5);
231 TEST_ASSERT_EQUAL(-1, number->valueint);
232 TEST_ASSERT_EQUAL_DOUBLE(-1.5, number->valuedouble);
233
234 cJSON_SetNumberValue(number, 1 + (double)INT_MAX);
235 TEST_ASSERT_EQUAL(INT_MAX, number->valueint);
236 TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble);
237
238 cJSON_SetNumberValue(number, -1 + (double)INT_MIN);
239 TEST_ASSERT_EQUAL(INT_MIN, number->valueint);
240 TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
241 }
242
cjson_detach_item_via_pointer_should_detach_items(void)243 static void cjson_detach_item_via_pointer_should_detach_items(void)
244 {
245 cJSON list[4];
246 cJSON parent[1];
247
248 memset(list, '\0', sizeof(list));
249
250 /* link the list */
251 list[0].next = &(list[1]);
252 list[1].next = &(list[2]);
253 list[2].next = &(list[3]);
254
255 list[3].prev = &(list[2]);
256 list[2].prev = &(list[1]);
257 list[1].prev = &(list[0]);
258 list[0].prev = &(list[3]);
259
260 parent->child = &list[0];
261
262 /* detach in the middle (list[1]) */
263 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle.");
264 TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL.");
265 TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0])));
266
267 /* detach beginning (list[0]) */
268 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
269 TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
270 TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
271
272 /* detach end (list[3])*/
273 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
274 TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL.");
275 TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end");
276
277 /* detach single item (list[2]) */
278 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item.");
279 TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL.");
280 TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
281 }
282
cjson_replace_item_via_pointer_should_replace_items(void)283 static void cjson_replace_item_via_pointer_should_replace_items(void)
284 {
285 cJSON replacements[3];
286 cJSON *beginning = NULL;
287 cJSON *middle = NULL;
288 cJSON *end = NULL;
289 cJSON *array = NULL;
290
291 beginning = cJSON_CreateNull();
292 TEST_ASSERT_NOT_NULL(beginning);
293 middle = cJSON_CreateNull();
294 TEST_ASSERT_NOT_NULL(middle);
295 end = cJSON_CreateNull();
296 TEST_ASSERT_NOT_NULL(end);
297
298 array = cJSON_CreateArray();
299 TEST_ASSERT_NOT_NULL(array);
300
301 cJSON_AddItemToArray(array, beginning);
302 cJSON_AddItemToArray(array, middle);
303 cJSON_AddItemToArray(array, end);
304
305
306 memset(replacements, '\0', sizeof(replacements));
307
308 /* replace beginning */
309 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
310 TEST_ASSERT_TRUE(replacements[0].prev == end);
311 TEST_ASSERT_TRUE(replacements[0].next == middle);
312 TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
313 TEST_ASSERT_TRUE(array->child == &(replacements[0]));
314
315 /* replace middle */
316 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1])));
317 TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0]));
318 TEST_ASSERT_TRUE(replacements[1].next == end);
319 TEST_ASSERT_TRUE(end->prev == &(replacements[1]));
320
321 /* replace end */
322 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2])));
323 TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1]));
324 TEST_ASSERT_NULL(replacements[2].next);
325 TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2]));
326
327 cJSON_free(array);
328 }
329
cjson_replace_item_in_object_should_preserve_name(void)330 static void cjson_replace_item_in_object_should_preserve_name(void)
331 {
332 cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }};
333 cJSON *child = NULL;
334 cJSON *replacement = NULL;
335 cJSON_bool flag = false;
336
337 child = cJSON_CreateNumber(1);
338 TEST_ASSERT_NOT_NULL(child);
339 replacement = cJSON_CreateNumber(2);
340 TEST_ASSERT_NOT_NULL(replacement);
341
342 flag = cJSON_AddItemToObject(root, "child", child);
343 TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
344 cJSON_ReplaceItemInObject(root, "child", replacement);
345
346 TEST_ASSERT_TRUE(root->child == replacement);
347 TEST_ASSERT_EQUAL_STRING("child", replacement->string);
348
349 cJSON_Delete(replacement);
350 }
351
cjson_functions_should_not_crash_with_null_pointers(void)352 static void cjson_functions_should_not_crash_with_null_pointers(void)
353 {
354 char buffer[10];
355 cJSON *item = cJSON_CreateString("item");
356
357 cJSON_InitHooks(NULL);
358 TEST_ASSERT_NULL(cJSON_Parse(NULL));
359 TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true));
360 TEST_ASSERT_NULL(cJSON_Print(NULL));
361 TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL));
362 TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true));
363 TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true));
364 TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true));
365 cJSON_Delete(NULL);
366 cJSON_GetArraySize(NULL);
367 TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0));
368 TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item"));
369 TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL));
370 TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item"));
371 TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL));
372 TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item"));
373 TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL));
374 TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
375 TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
376 TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
377 TEST_ASSERT_FALSE(cJSON_IsBool(NULL));
378 TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
379 TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
380 TEST_ASSERT_FALSE(cJSON_IsString(NULL));
381 TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
382 TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
383 TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
384 TEST_ASSERT_NULL(cJSON_CreateString(NULL));
385 TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
386 TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
387 TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
388 TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
389 TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10));
390 cJSON_AddItemToArray(NULL, item);
391 cJSON_AddItemToArray(item, NULL);
392 cJSON_AddItemToObject(item, "item", NULL);
393 cJSON_AddItemToObject(item, NULL, item);
394 cJSON_AddItemToObject(NULL, "item", item);
395 cJSON_AddItemToObjectCS(item, "item", NULL);
396 cJSON_AddItemToObjectCS(item, NULL, item);
397 cJSON_AddItemToObjectCS(NULL, "item", item);
398 cJSON_AddItemReferenceToArray(NULL, item);
399 cJSON_AddItemReferenceToArray(item, NULL);
400 cJSON_AddItemReferenceToObject(item, "item", NULL);
401 cJSON_AddItemReferenceToObject(item, NULL, item);
402 cJSON_AddItemReferenceToObject(NULL, "item", item);
403 TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item));
404 TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL));
405 TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0));
406 cJSON_DeleteItemFromArray(NULL, 0);
407 TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item"));
408 TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL));
409 TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item"));
410 TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL));
411 cJSON_DeleteItemFromObject(NULL, "item");
412 cJSON_DeleteItemFromObject(item, NULL);
413 cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
414 cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
415 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
416 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
417 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
418 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
419 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
420 TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
421 TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
422 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
423 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
424 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
425 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
426 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
427 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
428 TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
429 TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
430 TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
431 cJSON_Minify(NULL);
432 /* skipped because it is only used via a macro that checks for NULL */
433 /* cJSON_SetNumberHelper(NULL, 0); */
434
435 cJSON_Delete(item);
436 }
437
failing_realloc(void * pointer,size_t size)438 static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
439 {
440 (void)size;
441 (void)pointer;
442 return NULL;
443 }
444
ensure_should_fail_on_failed_realloc(void)445 static void ensure_should_fail_on_failed_realloc(void)
446 {
447 printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
448 buffer.buffer = (unsigned char*)malloc(100);
449 TEST_ASSERT_NOT_NULL(buffer.buffer);
450
451 TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
452 }
453
skip_utf8_bom_should_skip_bom(void)454 static void skip_utf8_bom_should_skip_bom(void)
455 {
456 const unsigned char string[] = "\xEF\xBB\xBF{}";
457 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
458 buffer.content = string;
459 buffer.length = sizeof(string);
460 buffer.hooks = global_hooks;
461
462 TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
463 TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
464 }
465
skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)466 static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
467 {
468 const unsigned char string[] = " \xEF\xBB\xBF{}";
469 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
470 buffer.content = string;
471 buffer.length = sizeof(string);
472 buffer.hooks = global_hooks;
473 buffer.offset = 1;
474
475 TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
476 }
477
cjson_get_string_value_should_get_a_string(void)478 static void cjson_get_string_value_should_get_a_string(void)
479 {
480 cJSON *string = cJSON_CreateString("test");
481 cJSON *number = cJSON_CreateNumber(1);
482
483 TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
484 TEST_ASSERT_NULL(cJSON_GetStringValue(number));
485 TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
486
487 cJSON_Delete(number);
488 cJSON_Delete(string);
489 }
490
cjson_get_number_value_should_get_a_number(void)491 static void cjson_get_number_value_should_get_a_number(void)
492 {
493 cJSON *string = cJSON_CreateString("test");
494 cJSON *number = cJSON_CreateNumber(1);
495
496 TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
497 TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
498 TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
499
500 cJSON_Delete(number);
501 cJSON_Delete(string);
502 }
503
cjson_create_string_reference_should_create_a_string_reference(void)504 static void cjson_create_string_reference_should_create_a_string_reference(void) {
505 const char *string = "I am a string!";
506
507 cJSON *string_reference = cJSON_CreateStringReference(string);
508 TEST_ASSERT_TRUE(string_reference->valuestring == string);
509 TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
510
511 cJSON_Delete(string_reference);
512 }
513
cjson_create_object_reference_should_create_an_object_reference(void)514 static void cjson_create_object_reference_should_create_an_object_reference(void) {
515 cJSON *number_reference = NULL;
516 cJSON *number_object = cJSON_CreateObject();
517 cJSON *number = cJSON_CreateNumber(42);
518 const char key[] = "number";
519
520 TEST_ASSERT_TRUE(cJSON_IsNumber(number));
521 TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
522 cJSON_AddItemToObjectCS(number_object, key, number);
523
524 number_reference = cJSON_CreateObjectReference(number);
525 TEST_ASSERT_TRUE(number_reference->child == number);
526 TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
527
528 cJSON_Delete(number_object);
529 cJSON_Delete(number_reference);
530 }
531
cjson_create_array_reference_should_create_an_array_reference(void)532 static void cjson_create_array_reference_should_create_an_array_reference(void) {
533 cJSON *number_reference = NULL;
534 cJSON *number_array = cJSON_CreateArray();
535 cJSON *number = cJSON_CreateNumber(42);
536
537 TEST_ASSERT_TRUE(cJSON_IsNumber(number));
538 TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
539 cJSON_AddItemToArray(number_array, number);
540
541 number_reference = cJSON_CreateArrayReference(number);
542 TEST_ASSERT_TRUE(number_reference->child == number);
543 TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
544
545 cJSON_Delete(number_array);
546 cJSON_Delete(number_reference);
547 }
548
cjson_add_item_to_object_or_array_should_not_add_itself(void)549 static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
550 {
551 cJSON *object = cJSON_CreateObject();
552 cJSON *array = cJSON_CreateArray();
553 cJSON_bool flag = false;
554
555 flag = cJSON_AddItemToObject(object, "key", object);
556 TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
557
558 flag = cJSON_AddItemToArray(array, array);
559 TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
560
561 cJSON_Delete(object);
562 cJSON_Delete(array);
563 }
564
cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)565 static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
566 {
567 cJSON *object = cJSON_CreateObject();
568 cJSON *number = cJSON_CreateNumber(42);
569 char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
570
571 TEST_ASSERT_NOT_NULL(object);
572 TEST_ASSERT_NOT_NULL(number);
573 TEST_ASSERT_NOT_NULL(name);
574
575 number->string = name;
576
577 /* The following should not have a use after free
578 * that would show up in valgrind or with AddressSanitizer */
579 cJSON_AddItemToObject(object, number->string, number);
580
581 cJSON_Delete(object);
582 }
583
cjson_delete_item_from_array_should_not_broken_list_structure(void)584 static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
585 {
586 const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
587 const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
588 const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
589 char *str1 = NULL;
590 char *str2 = NULL;
591 char *str3 = NULL;
592
593 cJSON *root = cJSON_Parse("{}");
594
595 cJSON *array = cJSON_AddArrayToObject(root, "rd");
596 cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
597 cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
598
599 cJSON_AddItemToArray(array, item1);
600 str1 = cJSON_PrintUnformatted(root);
601 TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
602 free(str1);
603
604 cJSON_AddItemToArray(array, item2);
605 str2 = cJSON_PrintUnformatted(root);
606 TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
607 free(str2);
608
609 /* this should not broken list structure */
610 cJSON_DeleteItemFromArray(array, 0);
611 str3 = cJSON_PrintUnformatted(root);
612 TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
613 free(str3);
614
615 cJSON_Delete(root);
616 }
617
cjson_set_valuestring_to_object_should_not_leak_memory(void)618 static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
619 {
620 cJSON *root = cJSON_Parse("{}");
621 const char *stringvalue = "valuestring could be changed safely";
622 const char *reference_valuestring = "reference item should be freed by yourself";
623 const char *short_valuestring = "shorter valuestring";
624 const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
625 cJSON *item1 = cJSON_CreateString(stringvalue);
626 cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
627 char *ptr1 = NULL;
628 char *return_value = NULL;
629
630 cJSON_AddItemToObject(root, "one", item1);
631 cJSON_AddItemToObject(root, "two", item2);
632
633 ptr1 = item1->valuestring;
634 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
635 TEST_ASSERT_NOT_NULL(return_value);
636 TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
637 TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
638
639 /* we needn't to free the original valuestring manually */
640 ptr1 = item1->valuestring;
641 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
642 TEST_ASSERT_NOT_NULL(return_value);
643 TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
644 TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
645
646 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
647 TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
648 TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
649
650 cJSON_Delete(root);
651 }
652
main(void)653 int CJSON_CDECL main(void)
654 {
655 UNITY_BEGIN();
656
657 RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
658 RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
659 RUN_TEST(cjson_get_object_item_should_get_object_items);
660 RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
661 RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
662 RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
663 RUN_TEST(typecheck_functions_should_check_type);
664 RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
665 RUN_TEST(cjson_set_number_value_should_set_numbers);
666 RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
667 RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
668 RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
669 RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
670 RUN_TEST(ensure_should_fail_on_failed_realloc);
671 RUN_TEST(skip_utf8_bom_should_skip_bom);
672 RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
673 RUN_TEST(cjson_get_string_value_should_get_a_string);
674 RUN_TEST(cjson_get_number_value_should_get_a_number);
675 RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
676 RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
677 RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
678 RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
679 RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
680 RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
681 RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
682
683 return UNITY_END();
684 }
685