unitester.cpp raw

   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  }
 200