Branch data Line data Source code
1 : : // Copyright 2014 BitPay Inc.
2 : : // Distributed under the MIT/X11 software license, see the accompanying
3 : : // file COPYING or https://opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <univalue.h>
6 : :
7 : : #include <cassert>
8 : : #include <cstdio>
9 : : #include <string>
10 : :
11 : : #ifndef JSON_TEST_SRC
12 : : #error JSON_TEST_SRC must point to test source directory
13 : : #endif
14 : :
15 : 0 : std::string srcdir(JSON_TEST_SRC);
16 : :
17 : 0 : static std::string rtrim(std::string s)
18 : : {
19 : 0 : s.erase(s.find_last_not_of(" \n\r\t")+1);
20 : 0 : return s;
21 : : }
22 : :
23 : 0 : static void runtest(std::string filename, const std::string& jdata)
24 : : {
25 : 0 : std::string prefix = filename.substr(0, 4);
26 : :
27 : 0 : bool wantPass = (prefix == "pass") || (prefix == "roun");
28 : 0 : bool wantFail = (prefix == "fail");
29 : 0 : bool wantRoundTrip = (prefix == "roun");
30 : 0 : assert(wantPass || wantFail);
31 : :
32 : 0 : UniValue val;
33 : 0 : bool testResult = val.read(jdata);
34 : :
35 : 0 : if (wantPass) {
36 : 0 : assert(testResult == true);
37 : 0 : } else {
38 : 0 : assert(testResult == false);
39 : : }
40 : :
41 : 0 : if (wantRoundTrip) {
42 : 0 : std::string odata = val.write(0, 0);
43 : 0 : assert(odata == rtrim(jdata));
44 : 0 : }
45 : 0 : }
46 : :
47 : 0 : static void runtest_file(const char *filename_)
48 : : {
49 : 0 : std::string basename(filename_);
50 : 0 : std::string filename = srcdir + "/" + basename;
51 : 0 : FILE *f = fopen(filename.c_str(), "r");
52 : 0 : assert(f != nullptr);
53 : :
54 : 0 : std::string jdata;
55 : :
56 : : char buf[4096];
57 : 0 : while (!feof(f)) {
58 : 0 : int bread = fread(buf, 1, sizeof(buf), f);
59 : 0 : assert(!ferror(f));
60 : :
61 : 0 : std::string s(buf, bread);
62 : 0 : jdata += s;
63 : 0 : }
64 : :
65 : 0 : assert(!ferror(f));
66 : 0 : fclose(f);
67 : :
68 : 0 : runtest(basename, jdata);
69 : 0 : }
70 : :
71 : : static const char *filenames[] = {
72 : : "fail10.json",
73 : : "fail11.json",
74 : : "fail12.json",
75 : : "fail13.json",
76 : : "fail14.json",
77 : : "fail15.json",
78 : : "fail16.json",
79 : : "fail17.json",
80 : : //"fail18.json", // investigate
81 : : "fail19.json",
82 : : "fail1.json",
83 : : "fail20.json",
84 : : "fail21.json",
85 : : "fail22.json",
86 : : "fail23.json",
87 : : "fail24.json",
88 : : "fail25.json",
89 : : "fail26.json",
90 : : "fail27.json",
91 : : "fail28.json",
92 : : "fail29.json",
93 : : "fail2.json",
94 : : "fail30.json",
95 : : "fail31.json",
96 : : "fail32.json",
97 : : "fail33.json",
98 : : "fail34.json",
99 : : "fail35.json",
100 : : "fail36.json",
101 : : "fail37.json",
102 : : "fail38.json", // invalid unicode: only first half of surrogate pair
103 : : "fail39.json", // invalid unicode: only second half of surrogate pair
104 : : "fail40.json", // invalid unicode: broken UTF-8
105 : : "fail41.json", // invalid unicode: unfinished UTF-8
106 : : "fail42.json", // valid json with garbage following a nul byte
107 : : "fail44.json", // unterminated string
108 : : "fail45.json", // nested beyond max depth
109 : : "fail3.json",
110 : : "fail4.json", // extra comma
111 : : "fail5.json",
112 : : "fail6.json",
113 : : "fail7.json",
114 : : "fail8.json",
115 : : "fail9.json", // extra comma
116 : : "pass1.json",
117 : : "pass2.json",
118 : : "pass3.json",
119 : : "pass4.json",
120 : : "round1.json", // round-trip test
121 : : "round2.json", // unicode
122 : : "round3.json", // bare string
123 : : "round4.json", // bare number
124 : : "round5.json", // bare true
125 : : "round6.json", // bare false
126 : : "round7.json", // bare null
127 : : };
128 : :
129 : : // Test \u handling
130 : 0 : void unescape_unicode_test()
131 : : {
132 : 0 : UniValue val;
133 : : bool testResult;
134 : : // Escaped ASCII (quote)
135 : 0 : testResult = val.read("[\"\\u0022\"]");
136 : 0 : assert(testResult);
137 : 0 : assert(val[0].get_str() == "\"");
138 : : // Escaped Basic Plane character, two-byte UTF-8
139 : 0 : testResult = val.read("[\"\\u0191\"]");
140 : 0 : assert(testResult);
141 : 0 : assert(val[0].get_str() == "\xc6\x91");
142 : : // Escaped Basic Plane character, three-byte UTF-8
143 : 0 : testResult = val.read("[\"\\u2191\"]");
144 : 0 : assert(testResult);
145 : 0 : assert(val[0].get_str() == "\xe2\x86\x91");
146 : : // Escaped Supplementary Plane character U+1d161
147 : 0 : testResult = val.read("[\"\\ud834\\udd61\"]");
148 : 0 : assert(testResult);
149 : 0 : assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
150 : 0 : }
151 : :
152 : 0 : void no_nul_test()
153 : : {
154 : 0 : char buf[] = "___[1,2,3]___";
155 : 0 : UniValue val;
156 : 0 : assert(val.read({buf + 3, 7}));
157 : 0 : }
158 : :
159 : 0 : int main (int argc, char *argv[])
160 : : {
161 : 0 : for (const auto& f: filenames) {
162 : 0 : runtest_file(f);
163 : : }
164 : :
165 : 0 : unescape_unicode_test();
166 : 0 : no_nul_test();
167 : :
168 : 0 : return 0;
169 : : }
170 : :
|