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: */ 33static 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 52static 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 88static 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 138static 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 168static 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 192static 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 214int 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