unitester.cpp raw

   1  // Copyright 2014 BitPay Inc.
   2  // Copyright (c) 2015-present The Limenka 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 <cstdio>
  67  #include <string>
  68  
  69  static std::string rtrim(std::string s)
  70  {
  71      s.erase(s.find_last_not_of(" \n\r\t") + 1);
  72      return s;
  73  }
  74  
  75  static void runtest(std::string filename, const std::string& jdata)
  76  {
  77      std::string prefix = filename.substr(0, 4);
  78  
  79      bool wantPass = (prefix == "pass") || (prefix == "roun");
  80      bool wantFail = (prefix == "fail");
  81      bool wantRoundTrip = (prefix == "roun");
  82      assert(wantPass || wantFail);
  83  
  84      UniValue val;
  85      bool testResult = val.read(jdata);
  86  
  87      if (wantPass) {
  88          assert(testResult == true);
  89      } else {
  90          assert(testResult == false);
  91      }
  92  
  93      if (wantRoundTrip) {
  94          std::string odata = val.write(0, 0);
  95          assert(odata == rtrim(jdata));
  96      }
  97  }
  98  
  99  #define TEST_FILE(name) {#name, json_tests::name}
 100  inline constexpr std::array tests{std::to_array<std::tuple<std::string_view, std::string_view>>({
 101      TEST_FILE(fail1),
 102      TEST_FILE(fail10),
 103      TEST_FILE(fail11),
 104      TEST_FILE(fail12),
 105      TEST_FILE(fail13),
 106      TEST_FILE(fail14),
 107      TEST_FILE(fail15),
 108      TEST_FILE(fail16),
 109      TEST_FILE(fail17),
 110      TEST_FILE(fail18),
 111      TEST_FILE(fail19),
 112      TEST_FILE(fail2),
 113      TEST_FILE(fail20),
 114      TEST_FILE(fail21),
 115      TEST_FILE(fail22),
 116      TEST_FILE(fail23),
 117      TEST_FILE(fail24),
 118      TEST_FILE(fail25),
 119      TEST_FILE(fail26),
 120      TEST_FILE(fail27),
 121      TEST_FILE(fail28),
 122      TEST_FILE(fail29),
 123      TEST_FILE(fail3),
 124      TEST_FILE(fail30),
 125      TEST_FILE(fail31),
 126      TEST_FILE(fail32),
 127      TEST_FILE(fail33),
 128      TEST_FILE(fail34),
 129      TEST_FILE(fail35),
 130      TEST_FILE(fail36),
 131      TEST_FILE(fail37),
 132      TEST_FILE(fail38), // invalid unicode: only first half of surrogate pair
 133      TEST_FILE(fail39), // invalid unicode: only second half of surrogate pair
 134      TEST_FILE(fail4),  // extra comma
 135      TEST_FILE(fail40), // invalid unicode: broken UTF-8
 136      TEST_FILE(fail41), // invalid unicode: unfinished UTF-8
 137      TEST_FILE(fail42), // valid json with garbage following a nul byte
 138      TEST_FILE(fail44), // unterminated string
 139      TEST_FILE(fail45), // nested beyond max depth
 140      TEST_FILE(fail5),
 141      TEST_FILE(fail6),
 142      TEST_FILE(fail7),
 143      TEST_FILE(fail8),
 144      TEST_FILE(fail9), // extra comma
 145      TEST_FILE(pass1),
 146      TEST_FILE(pass2),
 147      TEST_FILE(pass3),
 148      TEST_FILE(pass4),
 149      TEST_FILE(round1), // round-trip test
 150      TEST_FILE(round2), // unicode
 151      TEST_FILE(round3), // bare string
 152      TEST_FILE(round4), // bare number
 153      TEST_FILE(round5), // bare true
 154      TEST_FILE(round6), // bare false
 155      TEST_FILE(round7), // bare null
 156  })};
 157  
 158  // Test \u handling
 159  void unescape_unicode_test()
 160  {
 161      UniValue val;
 162      bool testResult;
 163      // Escaped ASCII (quote)
 164      testResult = val.read("[\"\\u0022\"]");
 165      assert(testResult);
 166      assert(val[0].get_str() == "\"");
 167      // Escaped Basic Plane character, two-byte UTF-8
 168      testResult = val.read("[\"\\u0191\"]");
 169      assert(testResult);
 170      assert(val[0].get_str() == "\xc6\x91");
 171      // Escaped Basic Plane character, three-byte UTF-8
 172      testResult = val.read("[\"\\u2191\"]");
 173      assert(testResult);
 174      assert(val[0].get_str() == "\xe2\x86\x91");
 175      // Escaped Supplementary Plane character U+1d161
 176      testResult = val.read("[\"\\ud834\\udd61\"]");
 177      assert(testResult);
 178      assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
 179  }
 180  
 181  void no_nul_test()
 182  {
 183      char buf[] = "___[1,2,3]___";
 184      UniValue val;
 185      assert(val.read({buf + 3, 7}));
 186  }
 187  
 188  int main(int argc, char* argv[])
 189  {
 190      for (const auto& [file, json] : tests) {
 191          runtest(std::string{file}, std::string{json});
 192      }
 193  
 194      unescape_unicode_test();
 195      no_nul_test();
 196  
 197      return 0;
 198  }
 199