1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2016 Arun Raghavan <mail@arunraghavan.net>
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <check.h>
25
26 #include <pulse/json.h>
27 #include <pulsecore/core-util.h>
28
START_TEST(string_test)29 START_TEST (string_test) {
30 pa_json_object *o;
31 unsigned int i;
32 const char *strings_parse[] = {
33 "\"\"", "\"test\"", "\"test123\"", "\"123\"", "\"newline\\n\"", "\" spaces \"",
34 " \"lots of spaces\" ", "\"esc\\nape\"", "\"escape a \\\" quote\"",
35 };
36 const char *strings_compare[] = {
37 "", "test", "test123", "123", "newline\n", " spaces ",
38 "lots of spaces", "esc\nape", "escape a \" quote",
39 };
40
41 for (i = 0; i < PA_ELEMENTSOF(strings_parse); i++) {
42 o = pa_json_parse(strings_parse[i]);
43
44 fail_unless(o != NULL);
45 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_STRING);
46 fail_unless(pa_streq(pa_json_object_get_string(o), strings_compare[i]));
47
48 pa_json_object_free(o);
49 }
50 }
51 END_TEST
52
START_TEST(int_test)53 START_TEST(int_test) {
54 pa_json_object *o;
55 unsigned int i;
56 const char *ints_parse[] = { "1", "-1", "1234", "0" };
57 const int ints_compare[] = { 1, -1, 1234, 0 };
58
59 for (i = 0; i < PA_ELEMENTSOF(ints_parse); i++) {
60 o = pa_json_parse(ints_parse[i]);
61
62 fail_unless(o != NULL);
63 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_INT);
64 fail_unless(pa_json_object_get_int(o) == ints_compare[i]);
65
66 pa_json_object_free(o);
67 }
68 }
69 END_TEST
70
START_TEST(double_test)71 START_TEST(double_test) {
72 pa_json_object *o;
73 unsigned int i;
74 const char *doubles_parse[] = {
75 "1.0", "-1.1", "1234e2", "1234e0", "0.1234", "-0.1234", "1234e-1", "1234.5e-1", "1234.5e+2",
76 };
77 const double doubles_compare[] = {
78 1.0, -1.1, 123400.0, 1234.0, 0.1234, -0.1234, 123.4, 123.45, 123450.0,
79 };
80
81 for (i = 0; i < PA_ELEMENTSOF(doubles_parse); i++) {
82 o = pa_json_parse(doubles_parse[i]);
83
84 fail_unless(o != NULL);
85 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_DOUBLE);
86 fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(o), doubles_compare[i]));
87
88 pa_json_object_free(o);
89 }
90 }
91 END_TEST
92
START_TEST(null_test)93 START_TEST(null_test) {
94 pa_json_object *o;
95
96 o = pa_json_parse("null");
97
98 fail_unless(o != NULL);
99 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_NULL);
100
101 pa_json_object_free(o);
102 }
103 END_TEST
104
START_TEST(bool_test)105 START_TEST(bool_test) {
106 pa_json_object *o;
107
108 o = pa_json_parse("true");
109
110 fail_unless(o != NULL);
111 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL);
112 fail_unless(pa_json_object_get_bool(o) == true);
113
114 pa_json_object_free(o);
115
116 o = pa_json_parse("false");
117
118 fail_unless(o != NULL);
119 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL);
120 fail_unless(pa_json_object_get_bool(o) == false);
121
122 pa_json_object_free(o);
123 }
124 END_TEST
125
START_TEST(object_test)126 START_TEST(object_test) {
127 pa_json_object *o;
128 const pa_json_object *v;
129
130 o = pa_json_parse(" { \"name\" : \"A Person\" } ");
131
132 fail_unless(o != NULL);
133 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
134
135 v = pa_json_object_get_object_member(o, "name");
136 fail_unless(v != NULL);
137 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
138 fail_unless(pa_streq(pa_json_object_get_string(v), "A Person"));
139
140 pa_json_object_free(o);
141
142 o = pa_json_parse(" { \"age\" : -45.3e-0 } ");
143
144 fail_unless(o != NULL);
145 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
146
147 v = pa_json_object_get_object_member(o, "age");
148 fail_unless(v != NULL);
149 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
150 fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), -45.3));
151
152 pa_json_object_free(o);
153
154 o = pa_json_parse("{\"person\":true}");
155
156 fail_unless(o != NULL);
157 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
158
159 v = pa_json_object_get_object_member(o, "person");
160 fail_unless(v != NULL);
161 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
162 fail_unless(pa_json_object_get_bool(v) == true);
163
164 pa_json_object_free(o);
165
166 o = pa_json_parse("{ \"parent\": { \"child\": false } }");
167 fail_unless(o != NULL);
168 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
169
170 v = pa_json_object_get_object_member(o, "parent");
171 fail_unless(v != NULL);
172 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
173 v = pa_json_object_get_object_member(v, "child");
174 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
175 fail_unless(pa_json_object_get_bool(v) == false);
176
177 pa_json_object_free(o);
178 }
179 END_TEST
180
START_TEST(array_test)181 START_TEST(array_test) {
182 pa_json_object *o;
183 const pa_json_object *v, *v2;
184
185 o = pa_json_parse(" [ ] ");
186
187 fail_unless(o != NULL);
188 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
189 fail_unless(pa_json_object_get_array_length(o) == 0);
190
191 pa_json_object_free(o);
192
193 o = pa_json_parse("[\"a member\"]");
194
195 fail_unless(o != NULL);
196 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
197 fail_unless(pa_json_object_get_array_length(o) == 1);
198
199 v = pa_json_object_get_array_member(o, 0);
200 fail_unless(v != NULL);
201 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
202 fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
203
204 pa_json_object_free(o);
205
206 o = pa_json_parse("[\"a member\", 1234.5, { \"another\": true } ]");
207
208 fail_unless(o != NULL);
209 fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
210 fail_unless(pa_json_object_get_array_length(o) == 3);
211
212 v = pa_json_object_get_array_member(o, 0);
213 fail_unless(v != NULL);
214 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
215 fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
216 v = pa_json_object_get_array_member(o, 1);
217 fail_unless(v != NULL);
218 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
219 fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), 1234.5));
220 v = pa_json_object_get_array_member(o, 2);
221 fail_unless(v != NULL);
222 fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
223 v2 =pa_json_object_get_object_member(v, "another");
224 fail_unless(v2 != NULL);
225 fail_unless(pa_json_object_get_type(v2) == PA_JSON_TYPE_BOOL);
226 fail_unless(pa_json_object_get_bool(v2) == true);
227
228 pa_json_object_free(o);
229 }
230 END_TEST
231
START_TEST(bad_test)232 START_TEST(bad_test) {
233 unsigned int i;
234 const char *bad_parse[] = {
235 "\"" /* Quote not closed */,
236 "123456789012345678901234567890" /* Overflow */,
237 "0.123456789012345678901234567890" /* Overflow */,
238 "1e123456789012345678901234567890" /* Overflow */,
239 "1e" /* Bad number string */,
240 "1." /* Bad number string */,
241 "1.e3" /* Bad number string */,
242 "-" /* Bad number string */,
243 "{ \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { } } } } } } } } } } } } } } } } } } } } } }" /* Nested too deep */,
244 "[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ { \"a\": \"b\" } ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]" /* Nested too deep */,
245 "asdf" /* Unquoted string */,
246 "{ a: true }" /* Unquoted key in object */,
247 "\" \a\"" /* Alarm is not a valid character */
248 };
249
250 for (i = 0; i < PA_ELEMENTSOF(bad_parse); i++) {
251 pa_json_object *obj;
252
253 fail_unless((obj = pa_json_parse(bad_parse[i])) == NULL);
254 if (obj)
255 pa_json_object_free(obj);
256 }
257 }
258 END_TEST
259
main(int argc,char * argv[])260 int main(int argc, char *argv[]) {
261 int failed = 0;
262 Suite *s;
263 TCase *tc;
264 SRunner *sr;
265
266 s = suite_create("JSON");
267 tc = tcase_create("json");
268 tcase_add_test(tc, string_test);
269 tcase_add_test(tc, int_test);
270 tcase_add_test(tc, double_test);
271 tcase_add_test(tc, null_test);
272 tcase_add_test(tc, bool_test);
273 tcase_add_test(tc, object_test);
274 tcase_add_test(tc, array_test);
275 tcase_add_test(tc, bad_test);
276 suite_add_tcase(s, tc);
277
278 sr = srunner_create(s);
279 srunner_run_all(sr, CK_NORMAL);
280 failed = srunner_ntests_failed(sr);
281 srunner_free(sr);
282
283 return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
284 }
285