tests: add regression test suite; update test fixtures
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I5ccf7cb25394bdcae068b49f66787c3a6a6a6964
This commit is contained in:
parent
f4135a5dca
commit
ddfbc91b58
12 changed files with 186 additions and 2 deletions
184
tests/regression_test.cpp
Normal file
184
tests/regression_test.cpp
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
#include "irc/serializer.h"
|
||||
#include "irc/types.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
using namespace nix_irc;
|
||||
|
||||
int failures = 0;
|
||||
|
||||
#define TEST_CHECK(cond, msg) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
std::cerr << " FAIL: " << msg << std::endl; \
|
||||
failures++; \
|
||||
} else { \
|
||||
std::cout << " PASS: " << msg << std::endl; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_PASS(msg) std::cout << " PASS: " << msg << std::endl
|
||||
#define TEST_FAIL(msg) \
|
||||
do { \
|
||||
std::cerr << " FAIL: " << msg << std::endl; \
|
||||
failures++; \
|
||||
} while (0)
|
||||
|
||||
void test_enum_compatibility() {
|
||||
std::cout << "> Enum compatibility..." << std::endl;
|
||||
|
||||
if (static_cast<uint8_t>(NodeType::WITH) == 0x32) {
|
||||
std::cout << " PASS: WITH has correct value 0x32" << std::endl;
|
||||
} else {
|
||||
std::cerr << " FAIL: WITH should be 0x32, got "
|
||||
<< static_cast<uint8_t>(NodeType::WITH) << std::endl;
|
||||
}
|
||||
|
||||
if (static_cast<uint8_t>(NodeType::HAS_ATTR) == 0x34) {
|
||||
std::cout << " PASS: HAS_ATTR has value 0x34 (new slot after WITH bump)"
|
||||
<< std::endl;
|
||||
} else if (static_cast<uint8_t>(NodeType::HAS_ATTR) == 0x33 &&
|
||||
static_cast<uint8_t>(NodeType::WITH) == 0x32) {
|
||||
std::cout << " PASS: HAS_ATTR has value 0x33 (restored original with WITH "
|
||||
"at 0x32)"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cerr << " FAIL: HAS_ATTR value is "
|
||||
<< static_cast<uint8_t>(NodeType::HAS_ATTR)
|
||||
<< " (expected 0x34 or 0x33 with WITH=0x32)" << std::endl;
|
||||
}
|
||||
|
||||
if (IR_VERSION == 2) {
|
||||
std::cout << " PASS: IR_VERSION bumped to 2 for breaking change"
|
||||
<< std::endl;
|
||||
} else if (static_cast<uint8_t>(NodeType::WITH) == 0x32) {
|
||||
std::cout << " PASS: IR_VERSION unchanged but WITH restored to 0x32"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cerr << " FAIL: Either bump IR_VERSION or fix enum values"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void test_serializer_select_with_default() {
|
||||
std::cout << "> SELECT serialization with default_expr..." << std::endl;
|
||||
|
||||
auto expr = std::make_shared<Node>(ConstIntNode(42));
|
||||
auto attr = std::make_shared<Node>(ConstStringNode("key"));
|
||||
auto default_val = std::make_shared<Node>(ConstIntNode(100));
|
||||
|
||||
SelectNode select_node(expr, attr);
|
||||
select_node.default_expr = default_val;
|
||||
auto select = std::make_shared<Node>(select_node);
|
||||
|
||||
IRModule module;
|
||||
module.entry = select;
|
||||
|
||||
Serializer ser;
|
||||
auto bytes = ser.serialize_to_bytes(module);
|
||||
|
||||
Deserializer deser;
|
||||
auto loaded = deser.deserialize(bytes);
|
||||
|
||||
auto *loaded_select = loaded.entry->get_if<SelectNode>();
|
||||
if (loaded_select && loaded_select->default_expr &&
|
||||
*loaded_select->default_expr) {
|
||||
auto *def_val = (*loaded_select->default_expr)->get_if<ConstIntNode>();
|
||||
if (def_val && def_val->value == 100) {
|
||||
std::cout << " PASS: SELECT with default_expr round-trips correctly"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cerr << " FAIL: default_expr value incorrect" << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cerr << " FAIL: default_expr not deserialized (missing u8 flag read)"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void test_serializer_select_without_default() {
|
||||
std::cout << "> SELECT serialization without default_expr..." << std::endl;
|
||||
|
||||
auto expr = std::make_shared<Node>(ConstIntNode(42));
|
||||
auto attr = std::make_shared<Node>(ConstStringNode("key"));
|
||||
|
||||
SelectNode select_node(expr, attr);
|
||||
auto select = std::make_shared<Node>(select_node);
|
||||
|
||||
IRModule module;
|
||||
module.entry = select;
|
||||
|
||||
Serializer ser;
|
||||
auto bytes = ser.serialize_to_bytes(module);
|
||||
|
||||
Deserializer deser;
|
||||
auto loaded = deser.deserialize(bytes);
|
||||
|
||||
auto *loaded_select = loaded.entry->get_if<SelectNode>();
|
||||
if (loaded_select &&
|
||||
(!loaded_select->default_expr || !*loaded_select->default_expr)) {
|
||||
std::cout << " PASS: SELECT without default_expr round-trips correctly"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cerr << " FAIL: default_expr should be null/absent" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void test_parser_brace_depth_in_strings() {
|
||||
std::cout << "> Parser brace depth handling in strings..." << std::endl;
|
||||
|
||||
std::string test_input = R"(
|
||||
let s = "test}"; in ${s}
|
||||
)";
|
||||
|
||||
std::cout << " Test input contains '}' inside string - should not end "
|
||||
"interpolation"
|
||||
<< std::endl;
|
||||
std::cout << " NOTE: This test requires running through actual parser"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void test_parser_has_ellipsis_usage() {
|
||||
std::cout << "> Parser has_ellipsis usage..." << std::endl;
|
||||
|
||||
std::cout << " NOTE: LambdaNode should have strict_pattern field when "
|
||||
"has_ellipsis is false"
|
||||
<< std::endl;
|
||||
std::cout << " This requires checking the parser output for strict patterns"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void test_parser_expect_in_speculative_parsing() {
|
||||
std::cout << "> Parser expect() in speculative parsing..." << std::endl;
|
||||
|
||||
std::cout << " NOTE: try_parse_lambda should not throw on non-lambda input"
|
||||
<< std::endl;
|
||||
std::cout << " This requires testing parser with invalid lambda patterns"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Regression Tests for Nixir ===" << std::endl << std::endl;
|
||||
|
||||
test_enum_compatibility();
|
||||
std::cout << std::endl;
|
||||
|
||||
test_serializer_select_with_default();
|
||||
std::cout << std::endl;
|
||||
|
||||
test_serializer_select_without_default();
|
||||
std::cout << std::endl;
|
||||
|
||||
test_parser_brace_depth_in_strings();
|
||||
std::cout << std::endl;
|
||||
|
||||
test_parser_has_ellipsis_usage();
|
||||
std::cout << std::endl;
|
||||
|
||||
test_parser_expect_in_speculative_parsing();
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "=== Tests Complete ===" << std::endl;
|
||||
std::cout << "Failures: " << failures << std::endl;
|
||||
return failures > 0 ? 1 : 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue