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