/ src / univalue / test / unitester.cpp
unitester.cpp
  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  static std::string rtrim(std::string s)
 71  {
 72      s.erase(s.find_last_not_of(" \n\r\t") + 1);
 73      return s;
 74  }
 75  
 76  static void runtest(std::string filename, const std::string& jdata)
 77  {
 78      std::string prefix = filename.substr(0, 4);
 79  
 80      bool wantPass = (prefix == "pass") || (prefix == "roun");
 81      bool wantFail = (prefix == "fail");
 82      bool wantRoundTrip = (prefix == "roun");
 83      assert(wantPass || wantFail);
 84  
 85      UniValue val;
 86      bool testResult = val.read(jdata);
 87  
 88      if (wantPass) {
 89          assert(testResult == true);
 90      } else {
 91          assert(testResult == false);
 92      }
 93  
 94      if (wantRoundTrip) {
 95          std::string odata = val.write(0, 0);
 96          assert(odata == rtrim(jdata));
 97      }
 98  }
 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  void unescape_unicode_test()
161  {
162      UniValue val;
163      bool testResult;
164      // Escaped ASCII (quote)
165      testResult = val.read("[\"\\u0022\"]");
166      assert(testResult);
167      assert(val[0].get_str() == "\"");
168      // Escaped Basic Plane character, two-byte UTF-8
169      testResult = val.read("[\"\\u0191\"]");
170      assert(testResult);
171      assert(val[0].get_str() == "\xc6\x91");
172      // Escaped Basic Plane character, three-byte UTF-8
173      testResult = val.read("[\"\\u2191\"]");
174      assert(testResult);
175      assert(val[0].get_str() == "\xe2\x86\x91");
176      // Escaped Supplementary Plane character U+1d161
177      testResult = val.read("[\"\\ud834\\udd61\"]");
178      assert(testResult);
179      assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
180  }
181  
182  void no_nul_test()
183  {
184      char buf[] = "___[1,2,3]___";
185      UniValue val;
186      assert(val.read({buf + 3, 7}));
187  }
188  
189  int main(int argc, char* argv[])
190  {
191      for (const auto& [file, json] : tests) {
192          runtest(std::string{file}, std::string{json});
193      }
194  
195      unescape_unicode_test();
196      no_nul_test();
197  
198      return 0;
199  }