bitcoin/src/univalue/test/unitester.cpp

163 lines
4.4 KiB
C++

// Copyright 2014 BitPay Inc.
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or https://opensource.org/licenses/mit-license.php.
#include <univalue.h>
#include <cassert>
#include <cstdio>
#include <string>
#ifndef JSON_TEST_SRC
#error JSON_TEST_SRC must point to test source directory
#endif
std::string srcdir(JSON_TEST_SRC);
static std::string rtrim(std::string s)
{
s.erase(s.find_last_not_of(" \n\r\t")+1);
return s;
}
static void runtest(std::string filename, const std::string& jdata)
{
std::string prefix = filename.substr(0, 4);
bool wantPass = (prefix == "pass") || (prefix == "roun");
bool wantFail = (prefix == "fail");
bool wantRoundTrip = (prefix == "roun");
assert(wantPass || wantFail);
UniValue val;
bool testResult = val.read(jdata);
if (wantPass) {
assert(testResult == true);
} else {
assert(testResult == false);
}
if (wantRoundTrip) {
std::string odata = val.write(0, 0);
assert(odata == rtrim(jdata));
}
}
static void runtest_file(const char *filename_)
{
std::string basename(filename_);
std::string filename = srcdir + "/" + basename;
FILE *f = fopen(filename.c_str(), "r");
assert(f != nullptr);
std::string jdata;
char buf[4096];
while (!feof(f)) {
int bread = fread(buf, 1, sizeof(buf), f);
assert(!ferror(f));
std::string s(buf, bread);
jdata += s;
}
assert(!ferror(f));
fclose(f);
runtest(basename, jdata);
}
static const char *filenames[] = {
"fail10.json",
"fail11.json",
"fail12.json",
"fail13.json",
"fail14.json",
"fail15.json",
"fail16.json",
"fail17.json",
//"fail18.json", // investigate
"fail19.json",
"fail1.json",
"fail20.json",
"fail21.json",
"fail22.json",
"fail23.json",
"fail24.json",
"fail25.json",
"fail26.json",
"fail27.json",
"fail28.json",
"fail29.json",
"fail2.json",
"fail30.json",
"fail31.json",
"fail32.json",
"fail33.json",
"fail34.json",
"fail35.json",
"fail36.json",
"fail37.json",
"fail38.json", // invalid unicode: only first half of surrogate pair
"fail39.json", // invalid unicode: only second half of surrogate pair
"fail40.json", // invalid unicode: broken UTF-8
"fail41.json", // invalid unicode: unfinished UTF-8
"fail42.json", // valid json with garbage following a nul byte
"fail44.json", // unterminated string
"fail45.json", // nested beyond max depth
"fail3.json",
"fail4.json", // extra comma
"fail5.json",
"fail6.json",
"fail7.json",
"fail8.json",
"fail9.json", // extra comma
"pass1.json",
"pass2.json",
"pass3.json",
"pass4.json",
"round1.json", // round-trip test
"round2.json", // unicode
"round3.json", // bare string
"round4.json", // bare number
"round5.json", // bare true
"round6.json", // bare false
"round7.json", // bare null
};
// Test \u handling
void unescape_unicode_test()
{
UniValue val;
bool testResult;
// Escaped ASCII (quote)
testResult = val.read("[\"\\u0022\"]");
assert(testResult);
assert(val[0].get_str() == "\"");
// Escaped Basic Plane character, two-byte UTF-8
testResult = val.read("[\"\\u0191\"]");
assert(testResult);
assert(val[0].get_str() == "\xc6\x91");
// Escaped Basic Plane character, three-byte UTF-8
testResult = val.read("[\"\\u2191\"]");
assert(testResult);
assert(val[0].get_str() == "\xe2\x86\x91");
// Escaped Supplementary Plane character U+1d161
testResult = val.read("[\"\\ud834\\udd61\"]");
assert(testResult);
assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
}
int main (int argc, char *argv[])
{
for (const auto& f: filenames) {
runtest_file(f);
}
unescape_unicode_test();
return 0;
}