|
|
@@ -0,0 +1,104 @@
|
|
|
+#include <cassert>
|
|
|
+#include <cstring>
|
|
|
+#include <iostream>
|
|
|
+#include <string>
|
|
|
+#include <nlohmann/json.hpp>
|
|
|
+#include "json_parse.hpp"
|
|
|
+
|
|
|
+using nlohmann::json;
|
|
|
+using smartbotic::db::parse_to_nlohmann;
|
|
|
+
|
|
|
+namespace {
|
|
|
+
|
|
|
+void check(bool cond, const char* msg) {
|
|
|
+ if (!cond) {
|
|
|
+ std::cerr << "FAIL: " << msg << "\n";
|
|
|
+ std::abort();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void test_empty_object() {
|
|
|
+ auto j = parse_to_nlohmann("{}");
|
|
|
+ check(j.is_object() && j.empty(), "empty object");
|
|
|
+}
|
|
|
+
|
|
|
+void test_empty_array() {
|
|
|
+ auto j = parse_to_nlohmann("[]");
|
|
|
+ check(j.is_array() && j.empty(), "empty array");
|
|
|
+}
|
|
|
+
|
|
|
+void test_primitives() {
|
|
|
+ check(parse_to_nlohmann("true").get<bool>() == true, "true");
|
|
|
+ check(parse_to_nlohmann("false").get<bool>() == false, "false");
|
|
|
+ check(parse_to_nlohmann("null").is_null(), "null");
|
|
|
+ check(parse_to_nlohmann("42").get<int64_t>() == 42, "int");
|
|
|
+ check(parse_to_nlohmann("-7").get<int64_t>() == -7, "negative int");
|
|
|
+ check(parse_to_nlohmann("3.14").get<double>() == 3.14, "double");
|
|
|
+ check(parse_to_nlohmann("\"hello\"").get<std::string>() == "hello", "string");
|
|
|
+}
|
|
|
+
|
|
|
+void test_nested() {
|
|
|
+ std::string s = R"({"a":1,"b":[2,3,{"c":"x"}],"d":null,"e":true})";
|
|
|
+ auto y = parse_to_nlohmann(s);
|
|
|
+ auto n = json::parse(s);
|
|
|
+ check(y == n, "nested equality with nlohmann");
|
|
|
+}
|
|
|
+
|
|
|
+void test_unicode_string() {
|
|
|
+ std::string s = R"({"name":"Árvíztűrő tükörfúrógép","emoji":"🚀"})";
|
|
|
+ auto y = parse_to_nlohmann(s);
|
|
|
+ auto n = json::parse(s);
|
|
|
+ check(y == n, "unicode equality");
|
|
|
+}
|
|
|
+
|
|
|
+void test_large_int() {
|
|
|
+ auto j = parse_to_nlohmann("9223372036854775807");
|
|
|
+ check(j.get<int64_t>() == 9223372036854775807LL, "int64 max");
|
|
|
+}
|
|
|
+
|
|
|
+void test_string_view_overload() {
|
|
|
+ std::string s = "{\"k\":1}";
|
|
|
+ auto j = parse_to_nlohmann(std::string_view(s));
|
|
|
+ check(j["k"].get<int>() == 1, "string_view overload");
|
|
|
+}
|
|
|
+
|
|
|
+void test_invalid_json_throws() {
|
|
|
+ bool threw = false;
|
|
|
+ try {
|
|
|
+ (void)parse_to_nlohmann("{not json");
|
|
|
+ } catch (const std::exception&) {
|
|
|
+ threw = true;
|
|
|
+ }
|
|
|
+ check(threw, "invalid json throws");
|
|
|
+}
|
|
|
+
|
|
|
+void test_corpus_equivalence() {
|
|
|
+ // Sample of doc shapes the production service sees.
|
|
|
+ const char* corpus[] = {
|
|
|
+ R"({"_id":"abc","name":"x","tags":["a","b"],"count":0})",
|
|
|
+ R"({"_id":"xyz","_vector":[0.1,-0.2,0.3,0.4],"meta":{"k":"v"}})",
|
|
|
+ R"({"_id":"e1","_event":"call.ended","at":1731628800123})",
|
|
|
+ R"([])",
|
|
|
+ R"([1,2,3,4,5,6,7,8,9,10])",
|
|
|
+ R"({"deeply":{"nested":{"object":{"is":{"fine":true}}}}})",
|
|
|
+ };
|
|
|
+ for (const char* s : corpus) {
|
|
|
+ check(parse_to_nlohmann(s) == json::parse(s), s);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace
|
|
|
+
|
|
|
+int main() {
|
|
|
+ test_empty_object();
|
|
|
+ test_empty_array();
|
|
|
+ test_primitives();
|
|
|
+ test_nested();
|
|
|
+ test_unicode_string();
|
|
|
+ test_large_int();
|
|
|
+ test_string_view_overload();
|
|
|
+ test_invalid_json_throws();
|
|
|
+ test_corpus_equivalence();
|
|
|
+ std::cout << "test_json_parse: all passed\n";
|
|
|
+ return 0;
|
|
|
+}
|