179 lines
5.2 KiB
C++
179 lines
5.2 KiB
C++
#include "json.hpp"
|
|
#include <iostream>
|
|
#include <cassert>
|
|
|
|
void test_basic_types() {
|
|
JsonParser parser;
|
|
|
|
// Test null
|
|
auto null_val = parser.parse("null");
|
|
assert(null_val.is<JsonParser::JsonNull>());
|
|
|
|
// Test boolean
|
|
auto true_val = parser.parse("true");
|
|
assert(true_val.is<JsonParser::JsonBool>() && true_val.as<JsonParser::JsonBool>() == true);
|
|
|
|
auto false_val = parser.parse("false");
|
|
assert(false_val.is<JsonParser::JsonBool>() && false_val.as<JsonParser::JsonBool>() == false);
|
|
|
|
// Test numbers
|
|
auto int_val = parser.parse("42");
|
|
assert(int_val.is<JsonParser::JsonNumber>() && int_val.as<JsonParser::JsonNumber>() == 42.0);
|
|
|
|
auto float_val = parser.parse("3.14159");
|
|
assert(float_val.is<JsonParser::JsonNumber>() && abs(float_val.as<JsonParser::JsonNumber>() - 3.14159) < 0.00001);
|
|
|
|
auto neg_val = parser.parse("-123.45");
|
|
assert(neg_val.is<JsonParser::JsonNumber>() && neg_val.as<JsonParser::JsonNumber>() == -123.45);
|
|
|
|
auto exp_val = parser.parse("1.5e3");
|
|
assert(exp_val.is<JsonParser::JsonNumber>() && exp_val.as<JsonParser::JsonNumber>() == 1500.0);
|
|
|
|
// Test string
|
|
auto str_val = parser.parse("\"hello world\"");
|
|
assert(str_val.is<JsonParser::JsonString>() && str_val.as<JsonParser::JsonString>() == "hello world");
|
|
|
|
std::cout << "✓ Basic types test passed\n";
|
|
}
|
|
|
|
void test_string_escapes() {
|
|
JsonParser parser;
|
|
|
|
auto escaped = parser.parse("\"line1\\nline2\\ttab\\\"quote\\\\backslash\"");
|
|
assert(escaped.is<JsonParser::JsonString>());
|
|
assert(escaped.as<JsonParser::JsonString>() == "line1\nline2\ttab\"quote\\backslash");
|
|
|
|
auto unicode = parser.parse("\"\\u0048\\u0065\\u006c\\u006c\\u006f\"");
|
|
assert(unicode.is<JsonParser::JsonString>());
|
|
assert(unicode.as<JsonParser::JsonString>() == "Hello");
|
|
|
|
std::cout << "✓ String escapes test passed\n";
|
|
}
|
|
|
|
void test_arrays() {
|
|
JsonParser parser;
|
|
|
|
// Empty array
|
|
auto empty_arr = parser.parse("[]");
|
|
assert(empty_arr.is<JsonParser::JsonArray>());
|
|
assert(empty_arr.as<JsonParser::JsonArray>().empty());
|
|
|
|
// Mixed array
|
|
auto mixed_arr = parser.parse("[1, \"hello\", true, null, [2, 3]]");
|
|
assert(mixed_arr.is<JsonParser::JsonArray>());
|
|
const auto& arr = mixed_arr.as<JsonParser::JsonArray>();
|
|
assert(arr.size() == 5);
|
|
assert(arr[0].is<JsonParser::JsonNumber>() && arr[0].as<JsonParser::JsonNumber>() == 1.0);
|
|
assert(arr[1].is<JsonParser::JsonString>() && arr[1].as<JsonParser::JsonString>() == "hello");
|
|
assert(arr[2].is<JsonParser::JsonBool>() && arr[2].as<JsonParser::JsonBool>() == true);
|
|
assert(arr[3].is<JsonParser::JsonNull>());
|
|
assert(arr[4].is<JsonParser::JsonArray>());
|
|
|
|
std::cout << "✓ Arrays test passed\n";
|
|
}
|
|
|
|
void test_objects() {
|
|
JsonParser parser;
|
|
|
|
// Empty object
|
|
auto empty_obj = parser.parse("{}");
|
|
assert(empty_obj.is<JsonParser::JsonObject>());
|
|
assert(empty_obj.as<JsonParser::JsonObject>().empty());
|
|
|
|
// Complex object
|
|
auto complex_obj = parser.parse(R"({
|
|
"name": "John Doe",
|
|
"age": 30,
|
|
"is_active": true,
|
|
"scores": [85, 90, 78],
|
|
"address": {
|
|
"street": "123 Main St",
|
|
"city": "Anytown"
|
|
},
|
|
"spouse": null
|
|
})");
|
|
|
|
assert(complex_obj.is<JsonParser::JsonObject>());
|
|
const auto& obj = complex_obj.as<JsonParser::JsonObject>();
|
|
|
|
assert(obj.at("name").as<JsonParser::JsonString>() == "John Doe");
|
|
assert(obj.at("age").as<JsonParser::JsonNumber>() == 30.0);
|
|
assert(obj.at("is_active").as<JsonParser::JsonBool>() == true);
|
|
assert(obj.at("spouse").is<JsonParser::JsonNull>());
|
|
|
|
const auto& scores = obj.at("scores").as<JsonParser::JsonArray>();
|
|
assert(scores.size() == 3);
|
|
assert(scores[0].as<JsonParser::JsonNumber>() == 85.0);
|
|
|
|
const auto& address = obj.at("address").as<JsonParser::JsonObject>();
|
|
assert(address.at("street").as<JsonParser::JsonString>() == "123 Main St");
|
|
|
|
std::cout << "✓ Objects test passed\n";
|
|
}
|
|
|
|
void test_file_parsing() {
|
|
JsonParser parser;
|
|
|
|
try {
|
|
auto file_json = parser.parse_file("test.json");
|
|
assert(file_json.is<JsonParser::JsonObject>());
|
|
const auto& obj = file_json.as<JsonParser::JsonObject>();
|
|
|
|
// Verify some expected content
|
|
assert(obj.at("library").as<JsonParser::JsonString>() == "fast-json-parser");
|
|
assert(obj.at("version").as<JsonParser::JsonString>() == "1.0.0");
|
|
|
|
const auto& features = obj.at("features").as<JsonParser::JsonArray>();
|
|
assert(features.size() > 0);
|
|
|
|
std::cout << "✓ File parsing test passed\n";
|
|
} catch (const std::exception& e) {
|
|
std::cerr << "File parsing test failed: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void test_error_cases() {
|
|
JsonParser parser;
|
|
|
|
// Test various malformed JSON
|
|
std::vector<std::string> invalid_json = {
|
|
"",
|
|
"{",
|
|
"}",
|
|
"[1,]",
|
|
"{\"key\":}",
|
|
"\"unterminated string",
|
|
"123.45.67",
|
|
"truee",
|
|
"nul",
|
|
"{\"key\" \"value\"}", // missing colon
|
|
"[1 2 3]" // missing commas
|
|
};
|
|
|
|
size_t error_count = 0;
|
|
for (const auto& json : invalid_json) {
|
|
try {
|
|
parser.parse(json);
|
|
std::cerr << "Expected error for: " << json << "\n";
|
|
} catch (const std::exception&) {
|
|
error_count++;
|
|
}
|
|
}
|
|
|
|
assert(error_count == invalid_json.size());
|
|
std::cout << "✓ Error handling test passed (" << error_count << " errors caught)\n";
|
|
}
|
|
|
|
int main() {
|
|
std::cout << "Running JSON parser tests...\n\n";
|
|
|
|
test_basic_types();
|
|
test_string_escapes();
|
|
test_arrays();
|
|
test_objects();
|
|
test_file_parsing();
|
|
test_error_cases();
|
|
|
|
std::cout << "\n";
|
|
return 0;
|
|
} |