From f438005413d136516dccd63b09cb33cae9b3e0e7 Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 7 Feb 2026 08:24:58 -0700 Subject: [PATCH] Step 57 TDD test: Buffer management Tests BufferManager: open/close/switch buffers, multiple buffers tracked simultaneously, buffer content retrieval, language tracking, and modification flag. Defines BufferManager interface. Co-Authored-By: Claude Opus 4.6 --- editor/CMakeLists.txt | 3 + editor/tests/step57_test.cpp | 175 +++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 editor/tests/step57_test.cpp diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 2ba3599..101ca82 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -166,6 +166,9 @@ target_include_directories(step53_test PRIVATE src) add_executable(step56_test tests/step56_test.cpp) target_include_directories(step56_test PRIVATE src) +add_executable(step57_test tests/step57_test.cpp) +target_include_directories(step57_test PRIVATE src) + add_executable(whetstone_editor src/main.cpp) target_include_directories(whetstone_editor PRIVATE src) # find_package(SDL2 REQUIRED) # Commented out for now to avoid build issues diff --git a/editor/tests/step57_test.cpp b/editor/tests/step57_test.cpp new file mode 100644 index 0000000..44586ce --- /dev/null +++ b/editor/tests/step57_test.cpp @@ -0,0 +1,175 @@ +// Step 57 TDD Test: Buffer management +// +// Tests orchestrator buffer management: +// 1. Open files → tracked in buffer map +// 2. Close buffer → removed from map +// 3. Switch between buffers → correct content +// 4. Multiple buffers tracked simultaneously +// 5. Buffer state includes file path and modification flag +// +// Will fail until buffer management is implemented. + +#include +#include +#include +#include +#include + +static bool contains(const std::string& haystack, const std::string& needle) { + return haystack.find(needle) != std::string::npos; +} + +// Forward declaration — BufferManager class +class BufferManager { +public: + struct BufferInfo { + std::string path; + std::string content; + std::string language; + bool modified; + }; + + // Open a file into a buffer + bool openBuffer(const std::string& path, const std::string& content, const std::string& language); + + // Close a buffer by path + bool closeBuffer(const std::string& path); + + // Get current active buffer path + std::string getActiveBufferPath() const; + + // Switch to a different buffer + bool switchToBuffer(const std::string& path); + + // Get buffer content + std::string getBufferContent(const std::string& path) const; + + // Get list of all open buffer paths + std::vector getOpenBuffers() const; + + // Check if a buffer exists + bool hasBuffer(const std::string& path) const; + + // Get buffer info + BufferInfo getBufferInfo(const std::string& path) const; + + // Mark buffer as modified + void setModified(const std::string& path, bool modified); +}; + +int main() { + int passed = 0; + int failed = 0; + + // --- Test 1: Open a buffer --- + { + BufferManager mgr; + bool ok = mgr.openBuffer("/test/foo.py", "def foo(): pass", "python"); + assert(ok && "Opening a buffer should succeed"); + assert(mgr.hasBuffer("/test/foo.py") && "Buffer should exist after opening"); + + std::cout << "Test 1 PASS: Buffer opened and tracked" << std::endl; + ++passed; + } + + // --- Test 2: Get buffer content --- + { + BufferManager mgr; + mgr.openBuffer("/test/foo.py", "def foo(): pass", "python"); + + std::string content = mgr.getBufferContent("/test/foo.py"); + assert(content == "def foo(): pass" && "Buffer content should match what was opened"); + + std::cout << "Test 2 PASS: Buffer content retrievable" << std::endl; + ++passed; + } + + // --- Test 3: Close buffer removes it --- + { + BufferManager mgr; + mgr.openBuffer("/test/foo.py", "def foo(): pass", "python"); + assert(mgr.hasBuffer("/test/foo.py") && "Buffer should exist"); + + bool closed = mgr.closeBuffer("/test/foo.py"); + assert(closed && "Close should succeed"); + assert(!mgr.hasBuffer("/test/foo.py") && "Buffer should not exist after closing"); + + std::cout << "Test 3 PASS: Close buffer removes it" << std::endl; + ++passed; + } + + // --- Test 4: Multiple buffers tracked --- + { + BufferManager mgr; + mgr.openBuffer("/test/a.py", "# a", "python"); + mgr.openBuffer("/test/b.cpp", "// b", "cpp"); + mgr.openBuffer("/test/c.el", ";; c", "elisp"); + + auto buffers = mgr.getOpenBuffers(); + assert(buffers.size() == 3 && "Should have 3 open buffers"); + + assert(mgr.hasBuffer("/test/a.py") && "Should have a.py"); + assert(mgr.hasBuffer("/test/b.cpp") && "Should have b.cpp"); + assert(mgr.hasBuffer("/test/c.el") && "Should have c.el"); + + std::cout << "Test 4 PASS: Multiple buffers tracked simultaneously" << std::endl; + ++passed; + } + + // --- Test 5: Switch between buffers --- + { + BufferManager mgr; + mgr.openBuffer("/test/a.py", "# a", "python"); + mgr.openBuffer("/test/b.cpp", "// b", "cpp"); + + mgr.switchToBuffer("/test/a.py"); + assert(mgr.getActiveBufferPath() == "/test/a.py" && "Active should be a.py"); + + mgr.switchToBuffer("/test/b.cpp"); + assert(mgr.getActiveBufferPath() == "/test/b.cpp" && "Active should be b.cpp"); + + std::cout << "Test 5 PASS: Switch between buffers works" << std::endl; + ++passed; + } + + // --- Test 6: Close one buffer, others remain --- + { + BufferManager mgr; + mgr.openBuffer("/test/a.py", "# a", "python"); + mgr.openBuffer("/test/b.cpp", "// b", "cpp"); + mgr.openBuffer("/test/c.el", ";; c", "elisp"); + + mgr.closeBuffer("/test/b.cpp"); + + auto buffers = mgr.getOpenBuffers(); + assert(buffers.size() == 2 && "Should have 2 buffers after closing one"); + assert(!mgr.hasBuffer("/test/b.cpp") && "Closed buffer should be gone"); + assert(mgr.hasBuffer("/test/a.py") && "Other buffers should remain"); + assert(mgr.hasBuffer("/test/c.el") && "Other buffers should remain"); + + std::cout << "Test 6 PASS: Close one buffer, others remain" << std::endl; + ++passed; + } + + // --- Test 7: Buffer info includes language and modified flag --- + { + BufferManager mgr; + mgr.openBuffer("/test/foo.py", "def foo(): pass", "python"); + + auto info = mgr.getBufferInfo("/test/foo.py"); + assert(info.path == "/test/foo.py" && "Path should match"); + assert(info.language == "python" && "Language should be python"); + assert(!info.modified && "New buffer should not be modified"); + + mgr.setModified("/test/foo.py", true); + auto info2 = mgr.getBufferInfo("/test/foo.py"); + assert(info2.modified && "Buffer should be marked modified"); + + std::cout << "Test 7 PASS: Buffer info has language and modified flag" << std::endl; + ++passed; + } + + // --- Summary --- + std::cout << "\n=== Step 57 Results: " << passed << " passed, " << failed << " failed ===" << std::endl; + return failed > 0 ? 1 : 0; +}