mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
251 lines
6.5 KiB
Plaintext
251 lines
6.5 KiB
Plaintext
module json_test @test;
|
|
import std::collections::object;
|
|
import std::io;
|
|
import std::encoding::json;
|
|
|
|
fn void simple_test()
|
|
{
|
|
ByteReader reader;
|
|
reader.init(`{ "b": 123, "c": [ { "d": 66 }, null, "hello\tworld", false, { "id": "xyz" } ] }`);
|
|
Object* o = json::parse(mem, &reader)!!;
|
|
defer o.free();
|
|
assert(o.get_int("b")!! == 123);
|
|
assert(o.get("c").get_len()!! == 5);
|
|
assert(o.get("c").get_at(0).get_int("d")!! == 66);
|
|
assert(o.get("c").get_at(1).is_null()!!);
|
|
assert(o.get("c").get_string_at(2)!! == "hello\tworld");
|
|
assert(o.get("c").get_bool_at(3)!! == false);
|
|
assert(o.get("c").get_at(4).get_string("id")!! == "xyz");
|
|
}
|
|
|
|
fn void simple_test2()
|
|
{
|
|
ByteReader reader;
|
|
reader.init(`{"jsonrpc":"2.0","id":null,"method":"initialize"}`);
|
|
Object* o = json::parse(mem, &reader)!!;
|
|
defer o.free();
|
|
}
|
|
|
|
|
|
fn void test_string()
|
|
{
|
|
Object* o = json::parse_string(mem, `{"jsonrpc":"2","id":null,"method":"initialize"}`)!!;
|
|
defer o.free();
|
|
String s = string::tformat("%s", *o);
|
|
Object* o2 = json::parse_string(mem, s)!!;
|
|
defer o2.free();
|
|
String s2 = string::tformat("%s", *o2);
|
|
assert(s2 == s, "Unexpectedly got %s and not %s", s2, s);
|
|
}
|
|
|
|
fn void test_temp_string()
|
|
{
|
|
@pool()
|
|
{
|
|
Object* o = json::tparse_string(`{"jsonrpc":"2","id":null,"method":"initialize"}`)!!;
|
|
defer o.free();
|
|
String s = string::tformat("%s", *o);
|
|
Object* o2 = json::tparse_string(s)!!;
|
|
defer o2.free();
|
|
String s2 = string::tformat("%s", *o2);
|
|
assert(s2 == s, "Unexpectedly got %s and not %s", s2, s);
|
|
};
|
|
}
|
|
|
|
fn void test_valid_numbers()
|
|
{
|
|
// Test valid integer
|
|
Object* o1 = json::parse_string(mem, "123")!!;
|
|
defer o1.free();
|
|
assert(o1.f == 123.0);
|
|
|
|
// Test valid negative integer
|
|
Object* o2 = json::parse_string(mem, "-456")!!;
|
|
defer o2.free();
|
|
assert(o2.f == -456.0);
|
|
|
|
// Test valid decimal
|
|
Object* o3 = json::parse_string(mem, "123.456")!!;
|
|
defer o3.free();
|
|
assert(o3.f == 123.456);
|
|
|
|
// Test valid negative decimal
|
|
Object* o4 = json::parse_string(mem, "-123.456")!!;
|
|
defer o4.free();
|
|
assert(o4.f == -123.456);
|
|
|
|
// Test valid scientific notation
|
|
Object* o5 = json::parse_string(mem, "1.23e10")!!;
|
|
defer o5.free();
|
|
assert(o5.f == 1.23e10);
|
|
|
|
// Test valid scientific notation with negative exponent
|
|
Object* o6 = json::parse_string(mem, "1.23e-10")!!;
|
|
defer o6.free();
|
|
assert(o6.f == 1.23e-10);
|
|
|
|
// Test valid scientific notation with positive exponent
|
|
Object* o7 = json::parse_string(mem, "1.23e+10")!!;
|
|
defer o7.free();
|
|
assert(o7.f == 1.23e+10);
|
|
|
|
// Test zero
|
|
Object* o8 = json::parse_string(mem, "0")!!;
|
|
defer o8.free();
|
|
assert(o8.f == 0.0);
|
|
|
|
// Test zero with decimal
|
|
Object* o9 = json::parse_string(mem, "0.0")!!;
|
|
defer o9.free();
|
|
assert(o9.f == 0.0);
|
|
|
|
// Test negative zero
|
|
Object* o10 = json::parse_string(mem, "-0")!!;
|
|
defer o10.free();
|
|
assert(o10.f == 0.0);
|
|
|
|
// Test zero with scientific notation
|
|
Object* o11 = json::parse_string(mem, "0e10")!!;
|
|
defer o11.free();
|
|
assert(o11.f == 0.0);
|
|
|
|
// Test zero with decimal and scientific notation
|
|
Object* o12 = json::parse_string(mem, "0.0e10")!!;
|
|
defer o12.free();
|
|
assert(o12.f == 0.0);
|
|
}
|
|
|
|
fn void test_duplicate_keys()
|
|
{
|
|
// Test that duplicate keys are now allowed (should not fail)
|
|
Object* o1 = json::parse_string(mem, `{"a":"first","a":"second"}`)!!;
|
|
defer o1.free();
|
|
assert(o1.has_key("a"));
|
|
assert(o1.get_string("a")!! == "second"); // Last value wins
|
|
|
|
// Test multiple duplicate keys with different types
|
|
Object* o2 = json::parse_string(mem, `{"x":1,"x":"string","x":true}`)!!;
|
|
defer o2.free();
|
|
assert(o2.get_bool("x")!! == true); // Last value wins
|
|
|
|
// Test duplicate keys in nested objects
|
|
Object* o3 = json::parse_string(mem, `{"obj":{"a":1},"obj":{"b":2}}`)!!;
|
|
defer o3.free();
|
|
Object* nested = o3.get("obj")!!;
|
|
assert(nested.has_key("b"));
|
|
assert(nested.get_int("b")!! == 2);
|
|
// The first object should be completely replaced
|
|
assert(!nested.has_key("a"));
|
|
}
|
|
|
|
fn void test_invalid_numbers()
|
|
{
|
|
// Test invalid: leading decimal point
|
|
if (catch err = json::parse_string(mem, "[.5]"))
|
|
{
|
|
assert(err == json::UNEXPECTED_CHARACTER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected UNEXPECTED_CHARACTER error for [.5]");
|
|
}
|
|
|
|
// Test invalid: multiple decimal points
|
|
if (catch err = json::parse_string(mem, "[1.2.3]"))
|
|
{
|
|
assert(err == json::UNEXPECTED_CHARACTER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected UNEXPECTED_CHARACTER error for [1.2.3]");
|
|
}
|
|
|
|
// Test invalid: scientific notation without digits after e
|
|
if (catch err = json::parse_string(mem, "[1e]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [1e]");
|
|
}
|
|
|
|
// Test invalid: scientific notation with only sign after e
|
|
if (catch err = json::parse_string(mem, "[1e+]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [1e+]");
|
|
}
|
|
|
|
// Test invalid: scientific notation with only sign after e
|
|
if (catch err = json::parse_string(mem, "[1e-]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [1e-]");
|
|
}
|
|
|
|
// Test invalid: leading zeros
|
|
if (catch err = json::parse_string(mem, "[012]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [012]");
|
|
}
|
|
|
|
// Test invalid: negative leading zeros
|
|
if (catch err = json::parse_string(mem, "[-012]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [-012]");
|
|
}
|
|
|
|
// Test invalid: leading zeros with decimal
|
|
if (catch err = json::parse_string(mem, "[012.5]"))
|
|
{
|
|
assert(err == json::INVALID_NUMBER);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected INVALID_NUMBER error for [012.5]");
|
|
}
|
|
}
|
|
|
|
fn void test_depth_limit()
|
|
{
|
|
// Test that deeply nested arrays with 150 opening brackets exceed the depth limit of 128
|
|
String deep_json = "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]";
|
|
|
|
if (catch err = json::parse_string(mem, deep_json))
|
|
{
|
|
assert(err == json::MAX_DEPTH_REACHED);
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected MAX_DEPTH_REACHED error for deeply nested array with 150 brackets");
|
|
}
|
|
}
|
|
|
|
fn void test_comments_rejected()
|
|
{
|
|
// Test that just a slash is rejected
|
|
if (catch err = json::parse_string(mem, "/"))
|
|
{
|
|
// Should fail with some error - slash is not valid JSON
|
|
}
|
|
else
|
|
{
|
|
assert(false, "Expected error for single slash but parsing succeeded");
|
|
}
|
|
}
|