• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 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 <stdio.h>
20 #include <stdlib.h>
21 
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24 #include "test/core/util/test_config.h"
25 
26 #include "src/core/lib/gpr/useful.h"
27 #include "src/core/lib/json/json_reader.h"
28 #include "src/core/lib/json/json_writer.h"
29 
30 typedef struct json_writer_userdata {
31   FILE* cmp;
32 } json_writer_userdata;
33 
34 typedef struct stacked_container {
35   grpc_json_type type;
36   struct stacked_container* next;
37 } stacked_container;
38 
39 typedef struct json_reader_userdata {
40   FILE* in;
41   grpc_json_writer* writer;
42   char* scratchpad;
43   char* ptr;
44   size_t free_space;
45   size_t allocated;
46   size_t string_len;
47   stacked_container* top;
48   int did_eagain;
49 } json_reader_userdata;
50 
json_writer_output_char(void * userdata,char c)51 static void json_writer_output_char(void* userdata, char c) {
52   json_writer_userdata* state = static_cast<json_writer_userdata*>(userdata);
53   int cmp = fgetc(state->cmp);
54 
55   /* treat CRLF as LF */
56   if (cmp == '\r' && c == '\n') {
57     cmp = fgetc(state->cmp);
58   }
59   GPR_ASSERT(cmp == c);
60 }
61 
json_writer_output_string(void * userdata,const char * str)62 static void json_writer_output_string(void* userdata, const char* str) {
63   while (*str) {
64     json_writer_output_char(userdata, *str++);
65   }
66 }
67 
json_writer_output_string_with_len(void * userdata,const char * str,size_t len)68 static void json_writer_output_string_with_len(void* userdata, const char* str,
69                                                size_t len) {
70   size_t i;
71   for (i = 0; i < len; i++) {
72     json_writer_output_char(userdata, str[i]);
73   }
74 }
75 
76 grpc_json_writer_vtable writer_vtable = {json_writer_output_char,
77                                          json_writer_output_string,
78                                          json_writer_output_string_with_len};
79 
check_string(json_reader_userdata * state,size_t needed)80 static void check_string(json_reader_userdata* state, size_t needed) {
81   if (state->free_space >= needed) return;
82   needed -= state->free_space;
83   needed = (needed + 0xffu) & ~0xffu;
84   state->scratchpad = static_cast<char*>(
85       gpr_realloc(state->scratchpad, state->allocated + needed));
86   state->free_space += needed;
87   state->allocated += needed;
88 }
89 
json_reader_string_clear(void * userdata)90 static void json_reader_string_clear(void* userdata) {
91   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
92   state->free_space = state->allocated;
93   state->string_len = 0;
94 }
95 
json_reader_string_add_char(void * userdata,uint32_t c)96 static void json_reader_string_add_char(void* userdata, uint32_t c) {
97   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
98   check_string(state, 1);
99   GPR_ASSERT(c <= 256);
100   state->scratchpad[state->string_len++] = static_cast<char>(c);
101 }
102 
json_reader_string_add_utf32(void * userdata,uint32_t c)103 static void json_reader_string_add_utf32(void* userdata, uint32_t c) {
104   if (c <= 0x7f) {
105     json_reader_string_add_char(userdata, c);
106   } else if (c <= 0x7ffu) {
107     uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu);
108     uint32_t b2 = 0x80u | (c & 0x3fu);
109     json_reader_string_add_char(userdata, b1);
110     json_reader_string_add_char(userdata, b2);
111   } else if (c <= 0xffffu) {
112     uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu);
113     uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu);
114     uint32_t b3 = 0x80u | (c & 0x3fu);
115     json_reader_string_add_char(userdata, b1);
116     json_reader_string_add_char(userdata, b2);
117     json_reader_string_add_char(userdata, b3);
118   } else if (c <= 0x1fffffu) {
119     uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u);
120     uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu);
121     uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu);
122     uint32_t b4 = 0x80u | (c & 0x3fu);
123     json_reader_string_add_char(userdata, b1);
124     json_reader_string_add_char(userdata, b2);
125     json_reader_string_add_char(userdata, b3);
126     json_reader_string_add_char(userdata, b4);
127   }
128 }
129 
json_reader_read_char(void * userdata)130 static uint32_t json_reader_read_char(void* userdata) {
131   int r;
132   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
133 
134   if (!state->did_eagain) {
135     state->did_eagain = 1;
136     return GRPC_JSON_READ_CHAR_EAGAIN;
137   }
138 
139   state->did_eagain = 0;
140 
141   r = fgetc(state->in);
142   if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF;
143   return static_cast<uint32_t>(r);
144 }
145 
json_reader_container_begins(void * userdata,grpc_json_type type)146 static void json_reader_container_begins(void* userdata, grpc_json_type type) {
147   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
148   stacked_container* container =
149       static_cast<stacked_container*>(gpr_malloc(sizeof(stacked_container)));
150 
151   container->type = type;
152   container->next = state->top;
153   state->top = container;
154 
155   grpc_json_writer_container_begins(state->writer, type);
156 }
157 
json_reader_container_ends(void * userdata)158 static grpc_json_type json_reader_container_ends(void* userdata) {
159   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
160   stacked_container* container = state->top;
161 
162   grpc_json_writer_container_ends(state->writer, container->type);
163   state->top = container->next;
164   gpr_free(container);
165   return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL;
166 }
167 
json_reader_set_key(void * userdata)168 static void json_reader_set_key(void* userdata) {
169   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
170   json_reader_string_add_char(userdata, 0);
171 
172   grpc_json_writer_object_key(state->writer, state->scratchpad);
173 }
174 
json_reader_set_string(void * userdata)175 static void json_reader_set_string(void* userdata) {
176   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
177   json_reader_string_add_char(userdata, 0);
178 
179   grpc_json_writer_value_string(state->writer, state->scratchpad);
180 }
181 
json_reader_set_number(void * userdata)182 static int json_reader_set_number(void* userdata) {
183   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
184 
185   grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad,
186                                       state->string_len);
187 
188   return 1;
189 }
190 
json_reader_set_true(void * userdata)191 static void json_reader_set_true(void* userdata) {
192   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
193 
194   grpc_json_writer_value_raw_with_len(state->writer, "true", 4);
195 }
196 
json_reader_set_false(void * userdata)197 static void json_reader_set_false(void* userdata) {
198   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
199 
200   grpc_json_writer_value_raw_with_len(state->writer, "false", 5);
201 }
202 
json_reader_set_null(void * userdata)203 static void json_reader_set_null(void* userdata) {
204   json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
205 
206   grpc_json_writer_value_raw_with_len(state->writer, "null", 4);
207 }
208 
209 static grpc_json_reader_vtable reader_vtable = {
210     json_reader_string_clear,     json_reader_string_add_char,
211     json_reader_string_add_utf32, json_reader_read_char,
212     json_reader_container_begins, json_reader_container_ends,
213     json_reader_set_key,          json_reader_set_string,
214     json_reader_set_number,       json_reader_set_true,
215     json_reader_set_false,        json_reader_set_null};
216 
rewrite_and_compare(FILE * in,FILE * cmp,int indent)217 int rewrite_and_compare(FILE* in, FILE* cmp, int indent) {
218   grpc_json_writer writer;
219   grpc_json_reader reader;
220   grpc_json_reader_status status;
221   json_writer_userdata writer_user;
222   json_reader_userdata reader_user;
223 
224   GPR_ASSERT(in);
225   GPR_ASSERT(cmp);
226 
227   reader_user.writer = &writer;
228   reader_user.in = in;
229   reader_user.top = nullptr;
230   reader_user.scratchpad = nullptr;
231   reader_user.string_len = 0;
232   reader_user.free_space = 0;
233   reader_user.allocated = 0;
234   reader_user.did_eagain = 0;
235 
236   writer_user.cmp = cmp;
237 
238   grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user);
239   grpc_json_reader_init(&reader, &reader_vtable, &reader_user);
240 
241   do {
242     status = grpc_json_reader_run(&reader);
243   } while (status == GRPC_JSON_EAGAIN);
244 
245   free(reader_user.scratchpad);
246   while (reader_user.top) {
247     stacked_container* container = reader_user.top;
248     reader_user.top = container->next;
249     free(container);
250   }
251 
252   return status == GRPC_JSON_DONE;
253 }
254 
255 typedef struct test_file {
256   const char* input;
257   const char* cmp;
258   int indent;
259 } test_file;
260 
261 static test_file test_files[] = {
262     {"test/core/json/rewrite_test_input.json",
263      "test/core/json/rewrite_test_output_condensed.json", 0},
264     {"test/core/json/rewrite_test_input.json",
265      "test/core/json/rewrite_test_output_indented.json", 2},
266     {"test/core/json/rewrite_test_output_indented.json",
267      "test/core/json/rewrite_test_output_condensed.json", 0},
268     {"test/core/json/rewrite_test_output_condensed.json",
269      "test/core/json/rewrite_test_output_indented.json", 2},
270 };
271 
test_rewrites()272 void test_rewrites() {
273   unsigned i;
274 
275   for (i = 0; i < GPR_ARRAY_SIZE(test_files); i++) {
276     test_file* test = test_files + i;
277     FILE* input = fopen(test->input, "rb");
278     FILE* cmp = fopen(test->cmp, "rb");
279     int status;
280     gpr_log(GPR_INFO, "Testing file %s against %s using indent=%i", test->input,
281             test->cmp, test->indent);
282     status = rewrite_and_compare(input, cmp, test->indent);
283     GPR_ASSERT(status);
284     fclose(input);
285     fclose(cmp);
286   }
287 }
288 
main(int argc,char ** argv)289 int main(int argc, char** argv) {
290   grpc_test_init(argc, argv);
291   test_rewrites();
292   gpr_log(GPR_INFO, "json_rewrite_test success");
293   return 0;
294 }
295