Files
shadowsocks-libev/tests/test_json_cpp.cpp
Max Lv 678a891ef9 tests: port remaining C unit tests to the C++ test harness
Convert acl, acl_literal, aead2022, base64, buffer, cache (legacy
reference), crypto, ipset, ipset_reference, json, netutils, ppbloom,
process, ref, ssurl and utils tests to test_helpers.hpp. ctest names are
unchanged; every assertion is kept. Build the ported sources with the
strict C++ warning set.
2026-10-15 01:33:51 +08:00

159 lines
4.7 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
// JSON parser (src/json.cpp): values, nesting and malformed input.
#include <cstdint>
#include <cstring>
#include "json.h"
#include "test_helpers.hpp"
namespace {
json_value *parse(const char *text)
{
return json_parse(text, std::strlen(text));
}
void test_parse_simple_object()
{
json_value *val = parse("{\"key\": \"value\", \"num\": 42}");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_object);
SS_CHECK(val->u.object.length == 2);
// First entry.
SS_CHECK(std::strcmp(val->u.object.values[0].name, "key") == 0);
SS_CHECK(val->u.object.values[0].value->type == json_string);
SS_CHECK(std::strcmp(val->u.object.values[0].value->u.string.ptr, "value") == 0);
// Second entry.
SS_CHECK(std::strcmp(val->u.object.values[1].name, "num") == 0);
SS_CHECK(val->u.object.values[1].value->type == json_integer);
SS_CHECK(val->u.object.values[1].value->u.integer == 42);
json_value_free(val);
}
void test_parse_array()
{
json_value *val = parse("[1, 2, 3]");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_array);
SS_CHECK(val->u.array.length == 3);
SS_CHECK(val->u.array.values[0]->type == json_integer);
SS_CHECK(val->u.array.values[0]->u.integer == 1);
SS_CHECK(val->u.array.values[1]->u.integer == 2);
SS_CHECK(val->u.array.values[2]->u.integer == 3);
json_value_free(val);
}
void test_parse_nested()
{
json_value *val = parse("{\"outer\": {\"inner\": true}}");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_object);
SS_CHECK(val->u.object.length == 1);
json_value *outer = val->u.object.values[0].value;
SS_CHECK(outer->type == json_object);
SS_CHECK(outer->u.object.length == 1);
SS_CHECK(outer->u.object.values[0].value->type == json_boolean);
SS_CHECK(outer->u.object.values[0].value->u.boolean != 0);
json_value_free(val);
}
void test_parse_types()
{
json_value *val = parse("{\"s\": \"hello\", \"i\": -5, \"d\": 3.14, \"b\": false, \"n\": null}");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_object);
SS_CHECK(val->u.object.length == 5);
SS_CHECK(val->u.object.values[0].value->type == json_string);
SS_CHECK(val->u.object.values[1].value->type == json_integer);
SS_CHECK(val->u.object.values[1].value->u.integer == -5);
SS_CHECK(val->u.object.values[2].value->type == json_double);
SS_CHECK(val->u.object.values[3].value->type == json_boolean);
SS_CHECK(val->u.object.values[3].value->u.boolean == 0);
SS_CHECK(val->u.object.values[4].value->type == json_null);
json_value_free(val);
}
void test_parse_invalid()
{
// Missing closing brace.
SS_CHECK(json_parse("{\"key\": 1", 9) == nullptr);
// Empty string.
SS_CHECK(json_parse("", 0) == nullptr);
// Just garbage.
SS_CHECK(json_parse("not json", 8) == nullptr);
}
void test_parse_truncated_escape_sequences()
{
// Four bytes remain after 'u', but the fourth hex read would hit EOF.
SS_CHECK(parse("\"\\uB2D") == nullptr);
// Six bytes remain after the high surrogate, but the sixth read would hit EOF.
SS_CHECK(parse("\"\\udfff\\ufff") == nullptr);
}
void test_parse_truncated_literals()
{
SS_CHECK(json_parse("tru", 3) == nullptr);
SS_CHECK(json_parse("fals", 4) == nullptr);
SS_CHECK(json_parse("nul", 3) == nullptr);
}
void test_parse_empty_object()
{
json_value *val = parse("{}");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_object);
SS_CHECK(val->u.object.length == 0);
json_value_free(val);
}
void test_parse_empty_array()
{
json_value *val = parse("[]");
SS_CHECK(val != nullptr);
SS_CHECK(val->type == json_array);
SS_CHECK(val->u.array.length == 0);
json_value_free(val);
}
void test_parse_wide_numbers()
{
json_value *wide = parse("[4294967296,9223372036854775807,-4294967296,0.4294967296]");
SS_CHECK(wide != nullptr && wide->type == json_array && wide->u.array.length == 4);
SS_CHECK(wide->u.array.values[0]->u.integer == INT64_C(4294967296));
SS_CHECK(wide->u.array.values[1]->u.integer == INT64_MAX);
SS_CHECK(wide->u.array.values[2]->u.integer == -INT64_C(4294967296));
SS_CHECK(wide->u.array.values[3]->u.dbl > 0.4294967295 && wide->u.array.values[3]->u.dbl < 0.4294967297);
json_value_free(wide);
SS_CHECK(json_parse("9223372036854775808", 19) == nullptr);
}
} // namespace
int main()
{
SS_RUN(test_parse_wide_numbers);
SS_RUN(test_parse_simple_object);
SS_RUN(test_parse_array);
SS_RUN(test_parse_nested);
SS_RUN(test_parse_types);
SS_RUN(test_parse_invalid);
SS_RUN(test_parse_truncated_escape_sequences);
SS_RUN(test_parse_truncated_literals);
SS_RUN(test_parse_empty_object);
SS_RUN(test_parse_empty_array);
return 0;
}