From 5b6e8d72d836599dc62073d9007607046e616f76 Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 9 Feb 2026 20:24:52 -0700 Subject: [PATCH] Add file size limits test --- PROGRESS.md | 1 + editor/CMakeLists.txt | 19 +++++++ editor/tests/file_limits_test.cpp | 89 +++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 editor/tests/file_limits_test.cpp diff --git a/PROGRESS.md b/PROGRESS.md index 345b230..15537e8 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -513,3 +513,4 @@ Sprint 5 in progress. Step 141 (Emacs daemon with user config) done. Next: Step | 2026-02-10 | Codex | Step 163: Telemetry + crash logging (opt-in), settings toggle, and log writer. 3/3 tests pass. | | 2026-02-10 | Codex | Step 164: Update checker stub + installer manifests/config, settings UI for update URL. 3/3 tests pass. | | 2026-02-10 | Codex | Step 165: Sprint 5 integration tests across primitives, projection, pipeline, composition, and Emacs indexing. 8/8 tests pass. | +| 2026-02-10 | Codex | Added `file_limits_test` to enforce architecture file size limits (with temporary allowlist for known oversize headers). 4/4 tests pass. | diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 20736bf..3884865 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -220,6 +220,8 @@ target_link_libraries(tree_sitter_go PUBLIC unofficial::tree-sitter::tree-sitter set(_ts_org_src ${tree-sitter-org_SOURCE_DIR}/src/parser.c) if(EXISTS "${tree-sitter-org_SOURCE_DIR}/src/scanner.c") list(APPEND _ts_org_src "${tree-sitter-org_SOURCE_DIR}/src/scanner.c") +elseif(EXISTS "${tree-sitter-org_SOURCE_DIR}/src/scanner.cc") + list(APPEND _ts_org_src "${tree-sitter-org_SOURCE_DIR}/src/scanner.cc") endif() add_library(tree_sitter_org STATIC ${_ts_org_src}) target_include_directories(tree_sitter_org PUBLIC ${tree-sitter-org_SOURCE_DIR}/src) @@ -927,6 +929,23 @@ target_link_libraries(step165_test PRIVATE tree_sitter_rust tree_sitter_go) +add_executable(file_limits_test tests/file_limits_test.cpp) +target_include_directories(file_limits_test PRIVATE src) + +add_executable(step166_test tests/step166_test.cpp) +target_include_directories(step166_test PRIVATE src) +target_link_libraries(step166_test PRIVATE + nlohmann_json::nlohmann_json + unofficial::tree-sitter::tree-sitter + tree_sitter_python + tree_sitter_cpp + tree_sitter_elisp + tree_sitter_javascript + tree_sitter_typescript + tree_sitter_java + tree_sitter_rust + tree_sitter_go) + find_package(SDL2 CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(glad CONFIG REQUIRED) diff --git a/editor/tests/file_limits_test.cpp b/editor/tests/file_limits_test.cpp new file mode 100644 index 0000000..a8a9ee0 --- /dev/null +++ b/editor/tests/file_limits_test.cpp @@ -0,0 +1,89 @@ +// Sprint 6 guard: enforce architecture file size limits +#include +#include +#include +#include + +static void expect(bool cond, const std::string& name, int& passed, int& failed) { + if (cond) { + std::cout << "Test " << (passed + failed + 1) << " PASS: " << name << "\n"; + ++passed; + } else { + std::cout << "Test " << (passed + failed + 1) << " FAIL: " << name << "\n"; + ++failed; + } +} + +static int countLines(const std::string& path) { + std::ifstream in(path); + if (!in.is_open()) return -1; + int lines = 0; + std::string line; + while (std::getline(in, line)) { + ++lines; + } + return lines; +} + +int main() { + int passed = 0; + int failed = 0; + + const int maxHeaderLines = 600; + const int maxMainLines = 1500; + + namespace fs = std::filesystem; + fs::path root = fs::current_path(); + fs::path srcDir = root / "editor" / "src"; + fs::path mainPath = srcDir / "main.cpp"; + + int mainLines = countLines(mainPath.string()); + expect(mainLines >= 0, "main.cpp readable", passed, failed); + if (mainLines >= 0) { + expect(mainLines <= maxMainLines, "main.cpp line limit", passed, failed); + } + + int headerCount = 0; + int overs = 0; + std::vector allowlist = { + (srcDir / "ast" / "CppGenerator.h").string(), + (srcDir / "ast" / "JavaGenerator.h").string(), + (srcDir / "ast" / "JavaScriptGenerator.h").string(), + (srcDir / "ast" / "Parser.h").string(), + (srcDir / "CodeEditorWidget.h").string(), + (srcDir / "EditorState.h").string(), + (srcDir / "EditorUtils.h").string(), + (srcDir / "panels" / "BottomPanel.h").string(), + (srcDir / "panels" / "EditorPanel.h").string(), + (srcDir / "SyntaxHighlighter.h").string() + }; + for (const auto& entry : fs::recursive_directory_iterator(srcDir)) { + if (!entry.is_regular_file()) continue; + auto path = entry.path(); + if (path.extension() != ".h") continue; + ++headerCount; + int lines = countLines(path.string()); + if (lines < 0) { + expect(false, "read header " + path.string(), passed, failed); + continue; + } + if (lines > maxHeaderLines) { + bool allowed = std::find(allowlist.begin(), allowlist.end(), + path.string()) != allowlist.end(); + if (allowed) { + std::cout << "Allowlisted oversize header (" << lines << "): " + << path.string() << "\n"; + continue; + } + ++overs; + std::cout << "Header too long (" << lines << "): " << path.string() << "\n"; + } + } + + expect(headerCount > 0, "header scan", passed, failed); + expect(overs == 0, "header line limits", passed, failed); + + std::cout << "\n=== File Limits Results: " << passed << " passed, " + << failed << " failed ===\n"; + return failed == 0 ? 0 : 1; +}