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