1 /*
2 *
3 * Copyright 2015-2016 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <string.h>
20
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/log.h>
23 #include <grpc/support/string_util.h>
24 #include "src/core/lib/gpr/string.h"
25 #include "src/core/lib/gpr/useful.h"
26 #include "src/core/lib/json/json.h"
27
28 #include "test/core/util/test_config.h"
29
30 typedef struct testing_pair {
31 const char* input;
32 const char* output;
33 } testing_pair;
34
35 static testing_pair testing_pairs[] = {
36 /* Testing valid parsing. */
37 /* Testing trivial parses, with de-indentation. */
38 {" 0 ", "0"},
39 {" 1 ", "1"},
40 {" \" \" ", "\" \""},
41 {" \"a\" ", "\"a\""},
42 {" true ", "true"},
43 /* Testing the parser's ability to decode trivial UTF-16. */
44 {"\"\\u0020\\\\\\u0010\\u000a\\u000D\"", "\" \\\\\\u0010\\n\\r\""},
45 /* Testing various UTF-8 sequences. */
46 {"\"ßâñć௵⇒\"", "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""},
47 {"\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\"",
48 "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""},
49 /* Testing UTF-8 character "", U+11D1E. */
50 {"\"\xf0\x9d\x84\x9e\"", "\"\\ud834\\udd1e\""},
51 {"\"\\ud834\\udd1e\"", "\"\\ud834\\udd1e\""},
52 {"{\"\\ud834\\udd1e\":0}", "{\"\\ud834\\udd1e\":0}"},
53 /* Testing nested empty containers. */
54 {
55 " [ [ ] , { } , [ ] ] ",
56 "[[],{},[]]",
57 },
58 /* Testing escapes and control chars in key strings. */
59 {" { \"\\u007f\x7f\\n\\r\\\"\\f\\b\\\\a , b\": 1, \"\": 0 } ",
60 "{\"\\u007f\\u007f\\n\\r\\\"\\f\\b\\\\a , b\":1,\"\":0}"},
61 /* Testing the writer's ability to cut off invalid UTF-8 sequences. */
62 {"\"abc\xf0\x9d\x24\"", "\"abc\""},
63 {"\"\xff\"", "\"\""},
64 /* Testing valid number parsing. */
65 {"[0, 42 , 0.0123, 123.456]", "[0,42,0.0123,123.456]"},
66 {"[1e4,-53.235e-31, 0.3e+3]", "[1e4,-53.235e-31,0.3e+3]"},
67 /* Testing keywords parsing. */
68 {"[true, false, null]", "[true,false,null]"},
69
70 /* Testing invalid parsing. */
71
72 /* Testing plain invalid things, exercising the state machine. */
73 {"\\", nullptr},
74 {"nu ll", nullptr},
75 {"{\"foo\": bar}", nullptr},
76 {"{\"foo\": bar\"x\"}", nullptr},
77 {"fals", nullptr},
78 {"0,0 ", nullptr},
79 {"\"foo\",[]", nullptr},
80 /* Testing unterminated string. */
81 {"\"\\x", nullptr},
82 /* Testing invalid UTF-16 number. */
83 {"\"\\u123x", nullptr},
84 {"{\"\\u123x", nullptr},
85 /* Testing imbalanced surrogate pairs. */
86 {"\"\\ud834f", nullptr},
87 {"{\"\\ud834f\":0}", nullptr},
88 {"\"\\ud834\\n", nullptr},
89 {"{\"\\ud834\\n\":0}", nullptr},
90 {"\"\\udd1ef", nullptr},
91 {"{\"\\udd1ef\":0}", nullptr},
92 {"\"\\ud834\\ud834\"", nullptr},
93 {"{\"\\ud834\\ud834\"\":0}", nullptr},
94 {"\"\\ud834\\u1234\"", nullptr},
95 {"{\"\\ud834\\u1234\"\":0}", nullptr},
96 {"\"\\ud834]\"", nullptr},
97 {"{\"\\ud834]\"\":0}", nullptr},
98 {"\"\\ud834 \"", nullptr},
99 {"{\"\\ud834 \"\":0}", nullptr},
100 {"\"\\ud834\\\\\"", nullptr},
101 {"{\"\\ud834\\\\\"\":0}", nullptr},
102 /* Testing embedded invalid whitechars. */
103 {"\"\n\"", nullptr},
104 {"\"\t\"", nullptr},
105 /* Testing empty json data. */
106 {"", nullptr},
107 /* Testing extra characters after end of parsing. */
108 {"{},", nullptr},
109 /* Testing imbalanced containers. */
110 {"{}}", nullptr},
111 {"[]]", nullptr},
112 {"{{}", nullptr},
113 {"[[]", nullptr},
114 {"[}", nullptr},
115 {"{]", nullptr},
116 /* Testing bad containers. */
117 {"{x}", nullptr},
118 {"{x=0,y}", nullptr},
119 /* Testing trailing comma. */
120 {"{,}", nullptr},
121 {"[1,2,3,4,]", nullptr},
122 {"{\"a\": 1, }", nullptr},
123 /* Testing after-ending characters. */
124 {"{}x", nullptr},
125 /* Testing having a key syntax in an array. */
126 {"[\"x\":0]", nullptr},
127 /* Testing invalid numbers. */
128 {"1.", nullptr},
129 {"1e", nullptr},
130 {".12", nullptr},
131 {"1.x", nullptr},
132 {"1.12x", nullptr},
133 {"1ex", nullptr},
134 {"1e12x", nullptr},
135 {".12x", nullptr},
136 {"000", nullptr},
137 };
138
test_pairs()139 static void test_pairs() {
140 unsigned i;
141
142 for (i = 0; i < GPR_ARRAY_SIZE(testing_pairs); i++) {
143 testing_pair* pair = testing_pairs + i;
144 char* scratchpad = gpr_strdup(pair->input);
145 grpc_json* json;
146
147 gpr_log(GPR_INFO, "parsing string %i - should %s", i,
148 pair->output ? "succeed" : "fail");
149 json = grpc_json_parse_string(scratchpad);
150
151 if (pair->output) {
152 char* output;
153
154 GPR_ASSERT(json);
155 output = grpc_json_dump_to_string(json, 0);
156 GPR_ASSERT(output);
157 gpr_log(GPR_INFO, "succeeded with output = %s", output);
158 GPR_ASSERT(strcmp(output, pair->output) == 0);
159
160 grpc_json_destroy(json);
161 gpr_free(output);
162 } else {
163 gpr_log(GPR_INFO, "failed");
164 GPR_ASSERT(!json);
165 }
166
167 gpr_free(scratchpad);
168 }
169 }
170
test_atypical()171 static void test_atypical() {
172 char* scratchpad = gpr_strdup("[[],[],[]]");
173 grpc_json* json = grpc_json_parse_string(scratchpad);
174 grpc_json* brother;
175
176 GPR_ASSERT(json);
177 GPR_ASSERT(json->child);
178 brother = json->child->next;
179 grpc_json_destroy(json->child);
180 GPR_ASSERT(json->child == brother);
181 grpc_json_destroy(json->child->next);
182 grpc_json_destroy(json);
183 gpr_free(scratchpad);
184 }
185
main(int argc,char ** argv)186 int main(int argc, char** argv) {
187 grpc_test_init(argc, argv);
188 test_pairs();
189 test_atypical();
190 gpr_log(GPR_INFO, "json_test success");
191 return 0;
192 }
193