Skip to content

Commit

Permalink
- test: add json native diff tests
Browse files Browse the repository at this point in the history
  • Loading branch information
oknenavin committed Jul 6, 2024
1 parent 21a3234 commit 94842a3
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 91 deletions.
8 changes: 4 additions & 4 deletions src/cxon/lang/common/cio/char.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -505,15 +505,15 @@ namespace cxon { namespace cio { namespace chr {
__m128i const v4 = _mm_set1_epi8('\'');
std::size_t n = l - f;
while (n >= 16) {
__m128i r0 = _mm_loadu_si128((__m128i const*)f);
__m128i const r0 = _mm_loadu_si128((__m128i const*)f);
__m128i r1;
CXON_IF_CONSTEXPR (is_quoted_key_context<X>::value || X::string::del == '\"')
r1 = _mm_cmpeq_epi8(r0, v1);
else CXON_IF_CONSTEXPR (is_quoted_key_context<X>::value || X::string::del == '\'')
r1 = _mm_cmpeq_epi8(r0, v4);
__m128i r2 = _mm_cmpeq_epi8(r0, v2);
__m128i r3 = _mm_cmpeq_epi8(_mm_min_epu8(r0, v3), r0);
__m128i r4 = _mm_or_si128(_mm_or_si128(r1, r2), r3);
__m128i const r2 = _mm_cmpeq_epi8(r0, v2);
__m128i const r3 = _mm_cmpeq_epi8(r0, _mm_min_epu8(r0, v3));
__m128i const r4 = _mm_or_si128(_mm_or_si128(r1, r2), r3);
if (int r = _mm_movemask_epi8(r4)) {
int e = ffs(r);
if (a != (f += e) && !poke<Y>(o, a, f, cx)) return false;
Expand Down
56 changes: 50 additions & 6 deletions test/data/json/tests.cf
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ tests = {
label = "time-native"
group = ["set-time-4"]
}
diff = {
label = "diff"
group = ["set-diff-1" "set-diff-2" "set-diff-3"]
diff-node = {
label = "diff-node"
group = ["set-diff-node-1" "set-diff-node-2" "set-diff-node-3"]
}
diff-native = {
label = "diff-native"
group = ["set-diff-native-1" "set-diff-native-2" "set-diff-native-3"]
}
}

Expand Down Expand Up @@ -458,19 +462,19 @@ sets = {
"set.6/random-object.json"
]
}
set-diff-1 = {
set-diff-node-1 = {
label = "https://github.com/minimaxir/big-list-of-naughty-strings"
group = [
"set.3/blns.json"
]
}
set-diff-2 = {
set-diff-node-2 = {
label = "https://github.com/github/gemoji"
group = [
"set.4/emoji.json"
]
}
set-diff-3 = {
set-diff-node-3 = {
label = "https://github.com/lemire/simdjson"
group = [
"set.5/apache_builds.json"
Expand All @@ -496,4 +500,44 @@ sets = {
//"set.5/update-center.json"
]
}
set-diff-native-1 = {
label = "https://github.com/minimaxir/big-list-of-naughty-strings"
group = [
"set.3/blns.json"
]
}
set-diff-native-2 = {
label = "https://github.com/github/gemoji"
group = [
// redundant default value
//"set.4/emoji.json"
]
}
set-diff-native-3 = {
label = "https://github.com/lemire/simdjson"
group = [
"set.5/apache_builds.json"
"set.5/canada.json"
"set.5/citm_catalog.json"
// different key order for same objects
//"set.5/github_events.json"
// redundant escapes
//"set.5/gsoc-2018.json"
"set.5/instruments.json"
// number precision
//"set.5/marine_ik.json"
// number precision
//"set.5/mesh.json"
//"set.5/mesh.pretty.json"
// number precision
//"set.5/numbers.json"
"set.5/random.json"
// number precision
//"set.5/twitter.json"
// redundant escapes + number precision
//"set.5/twitterescaped.json"
// redundant escapes
//"set.5/update-center.json"
]
}
}
8 changes: 5 additions & 3 deletions test/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@ check-all: build-json build-json-node build-cbor build-cbor-node
@(cd $(outdir) && ./check-json)
@(cd $(outdir) && ./check-json-node)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf pass fail)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff | xargs -n2 diff -q)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff-node | xargs -n2 diff -q)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff-native | xargs -n2 diff -q)
@(cd $(outdir) && ./check-cbor)
@(cd $(outdir) && ./check-cbor-node)
@(cd $(outdir) && ./check-cbor-node $(datdir)/cbor/tests.cf test-vector)
@(cd $(outdir) && ./check-cbor-node $(datdir)/cbor/tests.cf round-trip | xargs -n2 diff -q)
@(cd $(outdir) && ./check-cbor-node $(datdir)/cbor/tests.cf round-trip | xargs -n2 diff -q)
check-json: build-json
@(cd $(outdir) && ./check-json)
check-json-node: build-json-node
@(cd $(outdir) && ./check-json-node)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf pass fail)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff | xargs -n2 diff -q)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff-node | xargs -n2 diff -q)
@(cd $(outdir) && ./check-json-node $(datdir)/json/tests.cf diff-native | xargs -n2 diff -q)
check-cbor: build-cbor
@(cd $(outdir) && ./check-cbor)
check-cbor-node: build-cbor-node
Expand Down
4 changes: 2 additions & 2 deletions test/src/cbor/cbor.node-main.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ namespace test { namespace kind { // round-trip
++err, std::fprintf(stderr, "error: cannot be opened: '%s'\n", file.c_str());
continue;
}
std::string const f0 = name(file) + ".ct(0).json";
std::string const f1 = name(file) + ".ct(1).json";
std::string const f0 = "cbor.round-trip." + name(file) + ".(0).json";
std::string const f1 = "cbor.round-trip." + name(file) + ".(1).json";
{ // 0
std::ofstream os(f0, std::ofstream::binary);
if (!os) {
Expand Down
165 changes: 165 additions & 0 deletions test/src/json/json.node-diff.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright (c) 2017-2024 oknenavin.
// Licensed under the MIT license. See LICENSE file in the library root for full license information.
//
// SPDX-License-Identifier: MIT

#ifndef CXON_TIME_ONLY

#include "json.node.hxx"
#include "json.node-time.native.hxx"

#include "cxon/json.hxx"
#include "cxon/lib/node.ordered.hxx"
#include "cxon/lang/json/tidy.hxx"

#include <string>
#include <map>
#include <fstream>

////////////////////////////////////////////////////////////////////////////////

namespace test { namespace kind {

using node = cxon::json::ordered_node;

static std::string name(const std::string& p) {
auto f = p.find_last_of("/\\"); f = f != p.npos ? f + 1 : 0;
auto l = p.rfind('.'); if (l == p.npos) l = p.size();
return std::string(p, f, l - f);
};

template <typename T>
int diff(test& test, const char* prefix) {
std::string json;
{ // read
std::ifstream is(test.source, std::ifstream::binary);
if (!is) {
test.error = "cannot be opened";
return 1;
}
json.assign(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>());
}
{ // tidy
std::ofstream os(prefix + name(test.source) + ".(0).json", std::ofstream::binary);
if (!os) {
test.error = prefix + name(test.source) + ".(0).json" + ": cannot be opened";
return 1;
}
cxon::json::tidy(std::ostreambuf_iterator<char>(os), json);
}
T result;
{ // from
auto const r = cxon::from_bytes(result, json);
if (!r) {
test.error = format_error(r, json.cbegin());
return 1;
}
}
{ // to
std::ofstream os(prefix + name(test.source) + ".(1).json", std::ofstream::binary);
if (!os) {
test.error = prefix + name(test.source) + ".(1).json" + "cannot be opened";
return 1;
}
auto const w = cxon::to_bytes(cxon::json::make_indenter(std::ostreambuf_iterator<char>(os)), result);
if (!w) {
test.error += w.ec.category().name(),
test.error += ": " + w.ec.message();
}
}
return 0;
}

int diff_node(cases& cases) {
int err = 0;

char const*const prefix = "json.node.";

for (auto& c : cases) {
err += diff<node>(c, prefix);
}
std::size_t fc = 0;
for (auto& c : cases) {
if (!c.error.empty()) {
++fc, std::fprintf(stderr, "%s:\n\tfailed: %s\n", c.source.c_str(), c.error.c_str()), std::fflush(stderr);
}
}
if (!fc) {
for (auto& c : cases) {
std::fprintf(stdout, "%s %s ", (prefix + name(c.source) + ".(0).json").c_str(), (prefix + name(c.source) + ".(1).json").c_str()), std::fflush(stdout);
}
std::fputc('\n', stdout);
}
else {
std::fprintf(stdout, "%-21s: %zu of %4zu failed\n", "cxon/json/node/diff", fc, cases.size()), std::fflush(stdout);
}

return err;
}

using executor = int (*)(test&, const char*);

static std::map<std::string, executor> executors_ = {
{ "blns.json", &diff<blns::object> },
{ "emoji.json", &diff<emoji::object> },
{ "apache_builds.json", &diff<apache_builds::object> },
{ "canada.json", &diff<canada::object> },
# ifdef CXON_HAS_LIB_STD_OPTIONAL
{ "citm_catalog.json", &diff<citm_catalog::object> },
# endif
# ifdef CXON_HAS_LIB_STD_OPTIONAL
{ "github_events.json", &diff<github_events::object> },
# endif
{ "gsoc-2018.json", &diff<gsoc_2018::object> },
# ifdef CXON_HAS_LIB_STD_OPTIONAL
{ "instruments.json", &diff<instruments::object> },
# endif
{ "marine_ik.json", &diff<marine_ik::object> },
{ "mesh.json", &diff<mesh::object> },
{ "mesh.pretty.json", &diff<mesh::object> },
{ "numbers.json", &diff<numbers::object> },
{ "random.json", &diff<random::object> },
# ifdef CXON_HAS_LIB_STD_OPTIONAL
{ "twitter.json", &diff<twitter::object> },
{ "twitterescaped.json", &diff<twitter::object> },
# endif
{ "update-center.json", &diff<update_center::object> }
};

int diff_native(cases& cases) {
int err = 0;

char const*const prefix = "json.native.";

for (auto& c : cases) {

auto i = executors_.find(c.source.substr(c.source.rfind('/') + 1));
if (i == executors_.end()) {
++err, c.error = name(c.source) + ": unknown format";
continue;
}
else
err += i->second(c, prefix);
}
std::size_t fc = 0;
for (auto& c : cases) {
if (!c.error.empty()) {
++fc, std::fprintf(stderr, "%s:\n\tfailed: %s\n", c.source.c_str(), c.error.c_str()), std::fflush(stderr);
}
}
if (!fc) {
for (auto& c : cases) {
std::fprintf(stdout, "%s %s ", (prefix + name(c.source) + ".(0).json").c_str(), (prefix + name(c.source) + ".(1).json").c_str()), std::fflush(stdout);
}
std::fputc('\n', stdout);
}
else {
std::fprintf(stdout, "%-21s: %zu of %4zu failed\n", "cxon/json/node/diff", fc, cases.size()), std::fflush(stdout);
}

return err;
}

}}

#endif // CXON_TIME_ONLY
Loading

0 comments on commit 94842a3

Please sign in to comment.