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 : std::string srcdir(JSON_TEST_SRC);
16 :
17 7 : static std::string rtrim(std::string s)
18 : {
19 7 : s.erase(s.find_last_not_of(" \n\r\t")+1);
20 7 : return s;
21 : }
22 :
23 54 : static void runtest(std::string filename, const std::string& jdata)
24 : {
25 54 : std::string prefix = filename.substr(0, 4);
26 :
27 54 : bool wantPass = (prefix == "pass") || (prefix == "roun");
28 54 : bool wantFail = (prefix == "fail");
29 54 : bool wantRoundTrip = (prefix == "roun");
30 54 : assert(wantPass || wantFail);
31 :
32 54 : UniValue val;
33 54 : bool testResult = val.read(jdata);
34 :
35 54 : if (wantPass) {
36 11 : assert(testResult == true);
37 11 : } else {
38 43 : assert(testResult == false);
39 : }
40 :
41 54 : if (wantRoundTrip) {
42 7 : std::string odata = val.write(0, 0);
43 7 : assert(odata == rtrim(jdata));
44 7 : }
45 54 : }
46 :
47 54 : static void runtest_file(const char *filename_)
48 : {
49 54 : std::string basename(filename_);
50 54 : std::string filename = srcdir + "/" + basename;
51 54 : FILE *f = fopen(filename.c_str(), "r");
52 54 : assert(f != nullptr);
53 :
54 54 : std::string jdata;
55 :
56 : char buf[4096];
57 108 : while (!feof(f)) {
58 54 : int bread = fread(buf, 1, sizeof(buf), f);
59 54 : assert(!ferror(f));
60 :
61 54 : std::string s(buf, bread);
62 54 : jdata += s;
63 54 : }
64 :
65 54 : assert(!ferror(f));
66 54 : fclose(f);
67 :
68 54 : runtest(basename, jdata);
69 54 : }
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 1 : void unescape_unicode_test()
131 : {
132 1 : UniValue val;
133 : bool testResult;
134 : // Escaped ASCII (quote)
135 1 : testResult = val.read("[\"\\u0022\"]");
136 1 : assert(testResult);
137 1 : assert(val[0].get_str() == "\"");
138 : // Escaped Basic Plane character, two-byte UTF-8
139 1 : testResult = val.read("[\"\\u0191\"]");
140 1 : assert(testResult);
141 1 : assert(val[0].get_str() == "\xc6\x91");
142 : // Escaped Basic Plane character, three-byte UTF-8
143 1 : testResult = val.read("[\"\\u2191\"]");
144 1 : assert(testResult);
145 1 : assert(val[0].get_str() == "\xe2\x86\x91");
146 : // Escaped Supplementary Plane character U+1d161
147 1 : testResult = val.read("[\"\\ud834\\udd61\"]");
148 1 : assert(testResult);
149 1 : assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
150 1 : }
151 :
152 1 : void no_nul_test()
153 : {
154 1 : char buf[] = "___[1,2,3]___";
155 1 : UniValue val;
156 1 : assert(val.read(buf + 3, 7));
157 1 : }
158 :
159 1 : int main (int argc, char *argv[])
160 : {
161 55 : for (const auto& f: filenames) {
162 54 : runtest_file(f);
163 : }
164 :
165 1 : unescape_unicode_test();
166 1 : no_nul_test();
167 :
168 1 : return 0;
169 : }
170 :
|