diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 3d12f21..c921748 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -2623,4 +2623,13 @@ target_link_libraries(step415_test PRIVATE tree_sitter_javascript tree_sitter_typescript tree_sitter_java tree_sitter_rust tree_sitter_go) +add_executable(step416_test tests/step416_test.cpp) +target_include_directories(step416_test PRIVATE src) +target_link_libraries(step416_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) + # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) diff --git a/editor/tests/step416_test.cpp b/editor/tests/step416_test.cpp new file mode 100644 index 0000000..41908b6 --- /dev/null +++ b/editor/tests/step416_test.cpp @@ -0,0 +1,181 @@ +// Step 416: Phase 17b Integration + Sprint Summary (8 tests) + +#include "Pipeline.h" +#include "SqlAnnotationMapper.h" +#include "ast/ClassDeclaration.h" +#include "ast/Variable.h" +#include "ast/SqlNodes.h" +#include "ast/PostgreSQLGenerator.h" + +#include +#include +#include + +static int passed = 0, failed = 0; +#define TEST(name) { std::cout << " " << #name << "... "; } +#define PASS() { std::cout << "PASS\n"; ++passed; } +#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; } +#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {} + +void test_sql_dialect_parse_routes() { + TEST(sql_dialect_parse_routes); + Pipeline p; + std::vector d1, d2, d3, d4, d5; + auto pg = p.parse("SELECT id FROM users;\n", "postgresql", d1); + auto ts = p.parse("SELECT TOP 1 id FROM users;\n", "tsql", d2); + auto ss = p.parse("SELECT TOP 1 id FROM users;\n", "sqlserver", d3); + auto my = p.parse("SELECT id FROM users LIMIT 1;\n", "mysql", d4); + auto ma = p.parse("SELECT id FROM users LIMIT 1;\n", "mariadb", d5); + CHECK(pg && ts && ss && my && ma, "expected parse success for all SQL routes"); + CHECK(pg->targetLanguage == "postgresql", "postgresql target mismatch"); + CHECK(ts->targetLanguage == "tsql", "tsql target mismatch"); + CHECK(my->targetLanguage == "mysql", "mysql target mismatch"); + PASS(); +} + +void test_sql_dialect_generate_routes() { + TEST(sql_dialect_generate_routes); + DeleteStatement del("d1", "audit"); + Pipeline p; + std::string pg = p.generate(&del, "postgresql"); + std::string ts = p.generate(&del, "tsql"); + std::string my = p.generate(&del, "mysql"); + CHECK(pg == "DELETE FROM audit;", "postgres delete format mismatch"); + CHECK(ts == "DELETE FROM audit;", "tsql delete format mismatch"); + CHECK(my == "DELETE FROM `audit`;", "mysql delete format mismatch"); + PASS(); +} + +void test_sql_risk_inference_delete_without_where() { + TEST(sql_risk_inference_delete_without_where); + Pipeline p; + std::vector diags; + auto mod = p.parse("DELETE FROM users;\n", "postgresql", diags); + CHECK(mod != nullptr, "parse failed"); + SqlAnnotationMapper mapper; + auto inf = mapper.inferForModule(mod.get()); + bool found = false; + for (const auto& a : inf) { + if (a.annotationType == "RiskAnnotation" && a.value == "high") { + found = true; + break; + } + } + CHECK(found, "expected high-risk inference"); + PASS(); +} + +void test_sql_complexity_inference_join_depth() { + TEST(sql_complexity_inference_join_depth); + Pipeline p; + std::vector diags; + auto mod = p.parse( + "SELECT u.id FROM users u " + "LEFT JOIN orders o ON u.id = o.user_id " + "LEFT JOIN profiles p ON p.user_id = u.id;\n", + "postgresql", diags); + CHECK(mod != nullptr, "parse failed"); + SqlAnnotationMapper mapper; + auto inf = mapper.inferForModule(mod.get()); + bool found = false; + for (const auto& a : inf) { + if (a.annotationType == "ComplexityAnnotation" && + a.value.find("O(n^2)") != std::string::npos) { + found = true; + break; + } + } + CHECK(found, "expected O(n^2) complexity inference"); + PASS(); +} + +void test_sql_boundscheck_inference_limit_top() { + TEST(sql_boundscheck_inference_limit_top); + SqlAnnotationMapper mapper; + auto tInf = mapper.inferForSqlText("SELECT TOP 5 id FROM users;"); + auto lInf = mapper.inferForSqlText("SELECT id FROM users LIMIT 10;"); + bool topFound = false, limitFound = false; + for (const auto& a : tInf) if (a.annotationType == "BoundsCheckAnnotation") topFound = true; + for (const auto& a : lInf) if (a.annotationType == "BoundsCheckAnnotation") limitFound = true; + CHECK(topFound, "expected TOP bounds check"); + CHECK(limitFound, "expected LIMIT bounds check"); + PASS(); +} + +void test_cross_stack_python_to_csharp_to_sql_table() { + TEST(cross_stack_python_to_csharp_to_sql_table); + Pipeline p; + std::vector pyDiags; + auto py = p.parse("class User:\n def save(self):\n return 1\n", "python", pyDiags); + CHECK(py != nullptr, "python parse failed"); + + ClassDeclaration cls("c1", "User"); + cls.addChild("fields", new Variable("f1", "id")); + cls.addChild("fields", new Variable("f2", "email")); + std::string csharp = p.generate(&cls, "csharp"); + CHECK(csharp.find("class User") != std::string::npos, "expected csharp class"); + + TableDeclaration table("t1", "users"); + table.addChild("columns", new ColumnDefinition("col1", "id", "INT", false)); + table.addChild("columns", new ColumnDefinition("col2", "email", "TEXT", false)); + PostgreSQLGenerator pgGen; + std::string ddl = pgGen.generate(&table); + CHECK(ddl.find("CREATE TABLE users") != std::string::npos, "expected sql table"); + PASS(); +} + +void test_sql_contract_mapping_for_orm_schema() { + TEST(sql_contract_mapping_for_orm_schema); + ClassDeclaration cls("c1", "User"); + cls.addChild("fields", new Variable("f1", "id")); + cls.addChild("fields", new Variable("f2", "email")); + TableDeclaration table("t1", "users"); + table.addChild("columns", new ColumnDefinition("col1", "id", "INT", false)); + table.addChild("columns", new ColumnDefinition("col2", "email", "TEXT", false)); + + SqlAnnotationMapper mapper; + auto inf = mapper.inferCrossStackOrmMapping(&cls, &table); + bool classContract = false, tableContract = false; + for (const auto& a : inf) { + if (a.nodeId == "c1" && a.annotationType == "ContractAnnotation") classContract = true; + if (a.nodeId == "t1" && a.annotationType == "ContractAnnotation") tableContract = true; + } + CHECK(classContract && tableContract, "expected cross-stack contracts"); + PASS(); +} + +void test_sprint17_totals_verification() { + TEST(sprint17_totals_verification); + Pipeline p; + std::vector d1, d2, d3, d4, d5; + auto fs = p.parse("let inc x = x + 1\n", "fsharp", d1); + auto vb = p.parse("Sub Main()\nEnd Sub\n", "vbnet", d2); + auto pg = p.parse("SELECT id FROM users;\n", "postgresql", d3); + auto ts = p.parse("SELECT TOP 1 id FROM users;\n", "tsql", d4); + auto my = p.parse("SELECT id FROM users LIMIT 1;\n", "mysql", d5); + CHECK(fs && vb && pg && ts && my, "expected Sprint 17 language parse support"); + + int sqlDialects = 0; + if (pg) ++sqlDialects; + if (ts) ++sqlDialects; + if (my) ++sqlDialects; + CHECK(sqlDialects == 3, "expected 3 SQL dialects in Sprint 17"); + PASS(); +} + +int main() { + std::cout << "Step 416: Phase 17b Integration + Sprint Summary\n"; + + test_sql_dialect_parse_routes(); // 1 + test_sql_dialect_generate_routes(); // 2 + test_sql_risk_inference_delete_without_where(); // 3 + test_sql_complexity_inference_join_depth(); // 4 + test_sql_boundscheck_inference_limit_top(); // 5 + test_cross_stack_python_to_csharp_to_sql_table(); // 6 + test_sql_contract_mapping_for_orm_schema(); // 7 + test_sprint17_totals_verification(); // 8 + + std::cout << "\nResults: " << passed << "/" << (passed + failed) + << " passed\n"; + return failed == 0 ? 0 : 1; +} diff --git a/progress.md b/progress.md index 66436e6..cb668ab 100644 --- a/progress.md +++ b/progress.md @@ -4176,6 +4176,57 @@ bounds checks, index contracts, and cross-stack ORM<->schema consistency. - `editor/src/MCPServer.h` (`1679` > `600`) - `editor/src/HeadlessAgentRPCHandler.h` (`2629` > `600`) +### Step 416: Phase 17b Integration + Sprint Summary +**Status:** PASS (8/8 tests) + +Added Phase 17b integration validation across the 3 SQL dialect paths, the SQL +annotation mapper, and cross-stack class-to-SQL flow checkpoints. + +**Files created:** +- `editor/tests/step416_test.cpp` — 8 integration tests covering: + 1. SQL dialect parse routes (`postgresql`, `tsql`/`sqlserver`, `mysql`/`mariadb`) + 2. SQL dialect generate route behavior differences + 3. high-risk SQL inference (`DELETE` without `WHERE`) + 4. SQL complexity inference from JOIN depth + 5. bounds-check inference from `LIMIT`/`TOP` + 6. cross-stack flow checkpoint (`Python class` parse + `C# class` generation + SQL table DDL) + 7. ORM-schema contract mapping inference + 8. Sprint 17 totals verification checkpoint (F#, VB.NET, and 3 SQL dialects available) + +**Files modified:** +- `editor/CMakeLists.txt` — `step416_test` target + +**Verification run:** +- `step416_test` — PASS (8/8) new step coverage +- `step415_test` — PASS (12/12) regression coverage +- `step414_test` — PASS (12/12) regression coverage + +**Phase 17b completion snapshot (Steps 410-416):** +- Step 410: SQL AST nodes + serialization +- Step 411: PostgreSQL parser +- Step 412: PostgreSQL generator +- Step 413: T-SQL parser + generator +- Step 414: MySQL parser + generator +- Step 415: SQL annotation mapping +- Step 416: phase integration + summary + +**Sprint 17 completion snapshot (Steps 405-416):** +- Phase 17a complete (Steps 405-409, 56 tests) +- Phase 17b complete (Steps 410-416, 80 tests) +- Sprint 17 total: 12 steps, 136 tests + +**Architecture gate check (end of Sprint 17):** +- `editor/tests/step416_test.cpp` within test-file size guidance (`181` lines) +- `editor/src/SqlAnnotationMapper.h` within header-size limit (`246` <= `600`) +- `editor/src/ast/PostgreSQLGenerator.h` within header-size limit (`412` <= `600`) +- `editor/src/ast/TSQLParser.h` within header-size limit (`377` <= `600`) +- `editor/src/ast/MySQLParser.h` within header-size limit (`331` <= `600`) +- `editor/src/Pipeline.h` within header-size limit (`268` <= `600`) +- Legacy oversized headers persist: + - `editor/src/ast/Serialization.h` (`1427` > `600`) + - `editor/src/MCPServer.h` (`1679` > `600`) + - `editor/src/HeadlessAgentRPCHandler.h` (`2629` > `600`) + # Roadmap Planning — Sprints 12-25+ ## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)