source: branches/2.7x/libtransmission/json-test.c @ 13918

Last change on this file since 13918 was 13918, checked in by jordan, 8 years ago

(2.7x) #5249 'error parsing json in locales that use , as a decimal separator': backport unit tests and fix from trunk.

File size: 6.9 KB
Line 
1#include <string.h> /* strlen () */
2#include "transmission.h"
3#include "bencode.h"
4#include "json.h"
5#include "utils.h" /* tr_free */
6
7#undef VERBOSE
8#include "libtransmission-test.h"
9
10static int
11test_elements (void)
12{
13    const char * in;
14    tr_benc top;
15    const char * str;
16    bool f;
17    double d;
18    int64_t i;
19    int err = 0;
20
21    in = "{ \"string\": \"hello world\","
22         \"escaped\": \"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\","
23         \"int\": 5, "
24         \"float\": 6.5, "
25         \"true\": true, "
26         \"false\": false, "
27         \"null\": null }";
28
29    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
30    check_int_eq (0, err);
31    check (tr_bencIsDict (&top));
32    str = NULL;
33    check (tr_bencDictFindStr (&top, "string", &str));
34    check_streq ("hello world", str);
35    check (tr_bencDictFindStr (&top, "escaped", &str));
36    check_streq ("bell \b formfeed \f linefeed \n carriage return \r tab \t", str);
37    i = 0;
38    check (tr_bencDictFindInt (&top, "int", &i));
39    check_int_eq (5, i);
40    d = 0;
41    check (tr_bencDictFindReal (&top, "float", &d));
42    check_int_eq (65, ((int)(d*10)));
43    f = false;
44    check (tr_bencDictFindBool (&top, "true", &f));
45    check_int_eq (true, f);
46    check (tr_bencDictFindBool (&top, "false", &f));
47    check_int_eq (false, f);
48    check (tr_bencDictFindStr (&top, "null", &str));
49    check_streq ("", str);
50
51    if (!err)
52        tr_bencFree (&top);
53
54    return 0;
55}
56static int
57test_utf8 (void)
58{
59    const char      * in = "{ \"key\": \"Letöltések\" }";
60    tr_benc           top;
61    const char      * str;
62    char            * json;
63    int               err;
64
65    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
66    check (!err);
67    check (tr_bencIsDict (&top));
68    check (tr_bencDictFindStr (&top, "key", &str));
69    check_streq ("Letöltések", str);
70    if (!err)
71        tr_bencFree (&top);
72
73    in = "{ \"key\": \"\\u005C\" }";
74    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
75    check (!err);
76    check (tr_bencIsDict (&top));
77    check (tr_bencDictFindStr (&top, "key", &str));
78    check_streq ("\\", str);
79    if (!err)
80        tr_bencFree (&top);
81
82    /**
83     * 1. Feed it JSON-escaped nonascii to the JSON decoder.
84     * 2. Confirm that the result is UTF-8.
85     * 3. Feed the same UTF-8 back into the JSON encoder.
86     * 4. Confirm that the result is JSON-escaped.
87     * 5. Dogfood that result back into the parser.
88     * 6. Confirm that the result is UTF-8.
89     */
90    in = "{ \"key\": \"Let\\u00f6lt\\u00e9sek\" }";
91    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
92    check (!err);
93    check (tr_bencIsDict (&top));
94    check (tr_bencDictFindStr (&top, "key", &str));
95    check_streq ("Letöltések", str);
96    json = tr_bencToStr (&top, TR_FMT_JSON, NULL);
97    if (!err)
98        tr_bencFree (&top);
99    check (json);
100    check (strstr (json, "\\u00f6") != NULL);
101    check (strstr (json, "\\u00e9") != NULL);
102    err = tr_jsonParse (NULL, json, strlen (json), &top, NULL);
103    check (!err);
104    check (tr_bencIsDict (&top));
105    check (tr_bencDictFindStr (&top, "key", &str));
106    check_streq ("Letöltések", str);
107    if (!err)
108        tr_bencFree (&top);
109    tr_free (json);
110
111    return 0;
112}
113
114static int
115test1 (void)
116{
117    const char * in =
118        "{\n"
119        "    \"headers\": {\n"
120        "        \"type\": \"request\",\n"
121        "        \"tag\": 666\n"
122        "    },\n"
123        "    \"body\": {\n"
124        "        \"name\": \"torrent-info\",\n"
125        "        \"arguments\": {\n"
126        "            \"ids\": [ 7, 10 ]\n"
127        "        }\n"
128        "    }\n"
129        "}\n";
130    tr_benc      top, *headers, *body, *args, *ids;
131    const char * str;
132    int64_t      i;
133    const int    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
134
135    check (!err);
136    check (tr_bencIsDict (&top));
137    check ((headers = tr_bencDictFind (&top, "headers")));
138    check (tr_bencIsDict (headers));
139    check (tr_bencDictFindStr (headers, "type", &str));
140    check_streq ("request", str);
141    check (tr_bencDictFindInt (headers, "tag", &i));
142    check_int_eq (666, i);
143    check ((body = tr_bencDictFind (&top, "body")));
144    check (tr_bencDictFindStr (body, "name", &str));
145    check_streq ("torrent-info", str);
146    check ((args = tr_bencDictFind (body, "arguments")));
147    check (tr_bencIsDict (args));
148    check ((ids = tr_bencDictFind (args, "ids")));
149    check (tr_bencIsList (ids));
150    check_int_eq (2, tr_bencListSize (ids));
151    check (tr_bencGetInt (tr_bencListChild (ids, 0), &i));
152    check_int_eq (7, i);
153    check (tr_bencGetInt (tr_bencListChild (ids, 1), &i));
154    check_int_eq (10, i);
155
156    tr_bencFree (&top);
157    return 0;
158}
159
160static int
161test2 (void)
162{
163    tr_benc top;
164    const char * in = " ";
165    int err;
166
167    top.type = 0;
168    err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
169
170    check (err);
171    check (!tr_bencIsDict (&top));
172
173    return 0;
174}
175
176static int
177test3 (void)
178{
179    const char * in = "{ \"error\": 2,"
180                      \"errorString\": \"torrent not registered with this tracker 6UHsVW'*C\","
181                      \"eta\": 262792,"
182                      \"id\": 25,"
183                      \"leftUntilDone\": 2275655680 }";
184    tr_benc top;
185    const char * str;
186
187    const int err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
188    check (!err);
189    check (tr_bencDictFindStr (&top, "errorString", &str));
190    check_streq ("torrent not registered with this tracker 6UHsVW'*C", str);
191
192    tr_bencFree (&top);
193    return 0;
194}
195
196static int
197test_unescape (void)
198{
199    const char * in = "{ \"string-1\": \"\\/usr\\/lib\" }";
200    tr_benc top;
201    const char * str;
202
203    const int err = tr_jsonParse (NULL, in, strlen (in), &top, NULL);
204    check_int_eq (0, err);
205    check (tr_bencDictFindStr (&top, "string-1", &str));
206    check_streq ("/usr/lib", str);
207
208    tr_bencFree (&top);
209    return 0;
210}
211
212int
213main (void)
214{
215  int i;
216  int n;
217  int rv;
218
219  const char * comma_locales[] = { "da_DK.UTF-8",
220                                   "fr_FR.UTF-8",
221                                   "ru_RU.UTF-8"};
222
223  const testFunc tests[] = { test_elements,
224                             test_utf8,
225                             test1,
226                             test2,
227                             test3,
228                             test_unescape };
229
230  /* run the tests in a locale with a decimal point of '.' */
231  setlocale (LC_NUMERIC, "C");
232  if ((rv = runTests (tests, NUM_TESTS (tests))))
233    return rv;
234
235  /* run the tests in a locale with a decimal point of ',' */
236  n = sizeof(comma_locales) / sizeof(comma_locales[0]);
237  for (i=0; i<n; ++i)
238    if (setlocale (LC_NUMERIC, comma_locales[i]) != NULL)
239      break;
240  if (i==n)
241    fprintf (stderr, "WARNING: unable to run locale-specific json tests. add a locale like %s or %s\n",
242             comma_locales[0],
243             comma_locales[1]);
244  else if ((rv = runTests (tests, NUM_TESTS(tests))))
245    return rv;
246
247  /* success */
248  return 0;
249}
Note: See TracBrowser for help on using the repository browser.