text reader passes tests

This commit is contained in:
2026-08-04 14:22:57 -06:00
parent fa511520c6
commit 897e155b0e
6 changed files with 406 additions and 162 deletions
+129 -1
View File
@@ -3,12 +3,140 @@
#include <spider/compiler/common.hpp>
#include <spider/compiler/text/utf8.hpp>
namespace spider {
#include <spider/compiler/text/TextReader.hpp>
using namespace spider;
class TestRunner {
private:
int totalTests = 0;
int passedTests = 0;
public:
void assertCondition(bool condition, const std::string& testName) {
totalTests++;
if (condition) {
std::cout << " [PASS] " << testName << "\n";
passedTests++;
} else {
std::cout << " [FAIL] " << testName << "\n";
}
}
void printSummary() const {
std::cout << "\n========================================\n";
std::cout << "Test Results: " << passedTests << "/" << totalTests << " passed.\n";
std::cout << "========================================\n";
}
};
// ============================================================================
// TEST SUITES FOR StringTextReader
// ============================================================================
void test_basic_reading(TestRunner& runner) {
std::cout << "\n--- Running: Basic Reading Tests ---\n";
std::cout.flush();
StringTextReader reader("hello");
runner.assertCondition(reader.current().has_value() && reader.current().value() == 'h', "Initial current character is 'h'");
runner.assertCondition(reader.peekChar(1).has_value() && reader.peekChar(1).value() == 'e', "Peek +1 char is 'e'");
auto next = reader.nextChar(1);
runner.assertCondition(next.has_value() && next.value() == 'e', "Advance to next char gives 'e'");
runner.assertCondition(reader.current().has_value() && reader.current().value() == 'e', "Current character is now 'e'");
}
void test_eat_operations(TestRunner& runner) {
std::cout << "\n--- Running: Eat Operations Tests ---\n";
std::cout.flush();
StringTextReader reader("constexpr int x = 42;");
runner.assertCondition(reader.eat("constexpr"), "Eat exact string match 'constexpr'");
runner.assertCondition(reader.eat(' '), "Eat single space character");
runner.assertCondition(reader.eat("int"), "Eat second string match 'int'");
runner.assertCondition(!reader.eat("float"), "Eat fails on mismatched string 'float'");
runner.assertCondition(reader.eat(' '), "Eat single space after failure");
runner.assertCondition(reader.eat('x'), "Eat character 'x'");
}
void test_push_pop_rollback(TestRunner& runner) {
std::cout << "\n--- Running: Push/Pop Rollback Tests ---\n";
std::cout.flush();
StringTextReader reader("function_name()");
auto savedPos = reader.push();
runner.assertCondition(reader.eat("function_"), "Incomplete parse attempt");
// Rollback
reader.pop(savedPos);
runner.assertCondition(reader.current().has_value() && reader.current().value() == 'f', "Rollback restores cursor to 'f'");
runner.assertCondition(reader.eat("function_name"), "Subsequent match succeeds after rollback");
}
void test_commit(TestRunner& runner) {
std::cout << "\n--- Running: Buffer Commit Tests ---\n";
std::cout.flush();
StringTextReader reader("line1\nline2");
reader.eat("line1\n");
reader.commit(); // Discard historical rollback buffer
runner.assertCondition(reader.current().has_value() && reader.current().value() == 'l', "Current char after commit is 'l'");
runner.assertCondition(reader.eat("line2"), "Reading continues normally after commit");
}
void test_string_mutations(TestRunner& runner) {
std::cout << "\n--- Running: String Mutation Tests (set/append) ---\n";
std::cout.flush();
StringTextReader reader("foo");
runner.assertCondition(reader.eat("foo"), "Read initial text 'foo'");
reader.set("reset_text");
runner.assertCondition(reader.eat("reset_text"), "Read completely new text after set()");
}
void test_eof_handling(TestRunner& runner) {
std::cout << "\n--- Running: EOF & Error State Tests ---\n";
std::cout.flush();
StringTextReader reader("a");
runner.assertCondition(static_cast<bool>(reader), "Reader is valid initially");
runner.assertCondition(!reader.isEOF(), "isEOF is false initially");
reader.eat('a');
std::cout << "Index: " << reader.push().index << std::endl;
std::cout << "Value: " << reader.current().value_or(0) << std::endl;
runner.assertCondition(!reader.current().has_value(), "current() returns empty optional at EOF");
runner.assertCondition(reader.isEOF(), "isEOF is true after consuming all input");
runner.assertCondition(!reader.hasError(), "hasError remains false on normal EOF");
}
// ============================================================================
// MAIN DRIVER
// ============================================================================
int main() {
std::cout << "========================================\n";
std::cout << " StringTextReader Unit Test Suite \n";
std::cout << "========================================\n";
TestRunner runner;
test_basic_reading(runner);
test_eat_operations(runner);
test_push_pop_rollback(runner);
test_commit(runner);
test_string_mutations(runner);
test_eof_handling(runner);
runner.printSummary();
return 0;
}