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 #include "../cJSON_Utils.h"
31
32 /* JSON Apply Merge tests: */
33 static const char *merges[15][3] =
34 {
35 {"{\"a\":\"b\"}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
36 {"{\"a\":\"b\"}", "{\"b\":\"c\"}", "{\"a\":\"b\",\"b\":\"c\"}"},
37 {"{\"a\":\"b\"}", "{\"a\":null}", "{}"},
38 {"{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":null}", "{\"b\":\"c\"}"},
39 {"{\"a\":[\"b\"]}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
40 {"{\"a\":\"c\"}", "{\"a\":[\"b\"]}", "{\"a\":[\"b\"]}"},
41 {"{\"a\":{\"b\":\"c\"}}", "{\"a\":{\"b\":\"d\",\"c\":null}}", "{\"a\":{\"b\":\"d\"}}"},
42 {"{\"a\":[{\"b\":\"c\"}]}", "{\"a\":[1]}", "{\"a\":[1]}"},
43 {"[\"a\",\"b\"]", "[\"c\",\"d\"]", "[\"c\",\"d\"]"},
44 {"{\"a\":\"b\"}", "[\"c\"]", "[\"c\"]"},
45 {"{\"a\":\"foo\"}", "null", "null"},
46 {"{\"a\":\"foo\"}", "\"bar\"", "\"bar\""},
47 {"{\"e\":null}", "{\"a\":1}", "{\"e\":null,\"a\":1}"},
48 {"[1,2]", "{\"a\":\"b\",\"c\":null}", "{\"a\":\"b\"}"},
49 {"{}","{\"a\":{\"bb\":{\"ccc\":null}}}", "{\"a\":{\"bb\":{}}}"}
50 };
51
json_pointer_tests(void)52 static void json_pointer_tests(void)
53 {
54 cJSON *root = NULL;
55 const char *json=
56 "{"
57 "\"foo\": [\"bar\", \"baz\"],"
58 "\"\": 0,"
59 "\"a/b\": 1,"
60 "\"c%d\": 2,"
61 "\"e^f\": 3,"
62 "\"g|h\": 4,"
63 "\"i\\\\j\": 5,"
64 "\"k\\\"l\": 6,"
65 "\" \": 7,"
66 "\"m~n\": 8"
67 "}";
68
69 root = cJSON_Parse(json);
70
71 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, ""), root);
72 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo"), cJSON_GetObjectItem(root, "foo"));
73 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo/0"), cJSON_GetObjectItem(root, "foo")->child);
74 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/foo/0"), cJSON_GetObjectItem(root, "foo")->child);
75 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/"), cJSON_GetObjectItem(root, ""));
76 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/a~1b"), cJSON_GetObjectItem(root, "a/b"));
77 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c%d"), cJSON_GetObjectItem(root, "c%d"));
78 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c^f"), cJSON_GetObjectItem(root, "c^f"));
79 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/c|f"), cJSON_GetObjectItem(root, "c|f"));
80 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/i\\j"), cJSON_GetObjectItem(root, "i\\j"));
81 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/k\"l"), cJSON_GetObjectItem(root, "k\"l"));
82 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/ "), cJSON_GetObjectItem(root, " "));
83 TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(root, "/m~0n"), cJSON_GetObjectItem(root, "m~n"));
84
85 cJSON_Delete(root);
86 }
87
misc_tests(void)88 static void misc_tests(void)
89 {
90 /* Misc tests */
91 int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
92 cJSON *object = NULL;
93 cJSON *object1 = NULL;
94 cJSON *object2 = NULL;
95 cJSON *object3 = NULL;
96 cJSON *object4 = NULL;
97 cJSON *nums = NULL;
98 cJSON *num6 = NULL;
99 char *pointer = NULL;
100
101 printf("JSON Pointer construct\n");
102 object = cJSON_CreateObject();
103 nums = cJSON_CreateIntArray(numbers, 10);
104 num6 = cJSON_GetArrayItem(nums, 6);
105 cJSON_AddItemToObject(object, "numbers", nums);
106
107 pointer = cJSONUtils_FindPointerFromObjectTo(object, num6);
108 TEST_ASSERT_EQUAL_STRING("/numbers/6", pointer);
109 free(pointer);
110
111 pointer = cJSONUtils_FindPointerFromObjectTo(object, nums);
112 TEST_ASSERT_EQUAL_STRING("/numbers", pointer);
113 free(pointer);
114
115 pointer = cJSONUtils_FindPointerFromObjectTo(object, object);
116 TEST_ASSERT_EQUAL_STRING("", pointer);
117 free(pointer);
118
119 object1 = cJSON_CreateObject();
120 object2 = cJSON_CreateString("m~n");
121 cJSON_AddItemToObject(object1, "m~n", object2);
122 pointer = cJSONUtils_FindPointerFromObjectTo(object1, object2);
123 TEST_ASSERT_EQUAL_STRING("/m~0n",pointer);
124 free(pointer);
125
126 object3 = cJSON_CreateObject();
127 object4 = cJSON_CreateString("m/n");
128 cJSON_AddItemToObject(object3, "m/n", object4);
129 pointer = cJSONUtils_FindPointerFromObjectTo(object3, object4);
130 TEST_ASSERT_EQUAL_STRING("/m~1n",pointer);
131 free(pointer);
132
133 cJSON_Delete(object);
134 cJSON_Delete(object1);
135 cJSON_Delete(object3);
136 }
137
sort_tests(void)138 static void sort_tests(void)
139 {
140 /* Misc tests */
141 const char *random = "QWERTYUIOPASDFGHJKLZXCVBNM";
142 char buf[2] = {'\0', '\0'};
143 cJSON *sortme = NULL;
144 size_t i = 0;
145 cJSON *current_element = NULL;
146
147 /* JSON Sort test: */
148 sortme = cJSON_CreateObject();
149 for (i = 0; i < 26; i++)
150 {
151 buf[0] = random[i];
152 cJSON_AddItemToObject(sortme, buf, cJSON_CreateNumber(1));
153 }
154
155 cJSONUtils_SortObject(sortme);
156
157 /* check sorting */
158 current_element = sortme->child->next;
159 for (i = 1; (i < 26) && (current_element != NULL) && (current_element->prev != NULL); i++)
160 {
161 TEST_ASSERT_TRUE(current_element->string[0] >= current_element->prev->string[0]);
162 current_element = current_element->next;
163 }
164
165 cJSON_Delete(sortme);
166 }
167
merge_tests(void)168 static void merge_tests(void)
169 {
170 size_t i = 0;
171 char *patchtext = NULL;
172 char *after = NULL;
173
174 /* Merge tests: */
175 printf("JSON Merge Patch tests\n");
176 for (i = 0; i < 15; i++)
177 {
178 cJSON *object_to_be_merged = cJSON_Parse(merges[i][0]);
179 cJSON *patch = cJSON_Parse(merges[i][1]);
180 patchtext = cJSON_PrintUnformatted(patch);
181 object_to_be_merged = cJSONUtils_MergePatch(object_to_be_merged, patch);
182 after = cJSON_PrintUnformatted(object_to_be_merged);
183 TEST_ASSERT_EQUAL_STRING(merges[i][2], after);
184
185 free(patchtext);
186 free(after);
187 cJSON_Delete(object_to_be_merged);
188 cJSON_Delete(patch);
189 }
190 }
191
generate_merge_tests(void)192 static void generate_merge_tests(void)
193 {
194 size_t i = 0;
195 char *patchedtext = NULL;
196
197 /* Generate Merge tests: */
198 for (i = 0; i < 15; i++)
199 {
200 cJSON *from = cJSON_Parse(merges[i][0]);
201 cJSON *to = cJSON_Parse(merges[i][2]);
202 cJSON *patch = cJSONUtils_GenerateMergePatch(from,to);
203 from = cJSONUtils_MergePatch(from,patch);
204 patchedtext = cJSON_PrintUnformatted(from);
205 TEST_ASSERT_EQUAL_STRING(merges[i][2], patchedtext);
206
207 cJSON_Delete(from);
208 cJSON_Delete(to);
209 cJSON_Delete(patch);
210 free(patchedtext);
211 }
212 }
213
main(void)214 int main(void)
215 {
216 UNITY_BEGIN();
217
218 RUN_TEST(json_pointer_tests);
219 RUN_TEST(misc_tests);
220 RUN_TEST(sort_tests);
221 RUN_TEST(merge_tests);
222 RUN_TEST(generate_merge_tests);
223
224 return UNITY_END();
225 }
226