Files
whetstone_DSL/editor/tests/step341_test.cpp

370 lines
13 KiB
C++
Raw Normal View History

// Step 341: Phase 12d Integration + Sprint 12 Summary (8 tests)
// Full C++ depth validation: parse → AST → generate roundtrips, cross-language,
// combined workflow + C++ constructs, sprint 12 totals verification
#include <cassert>
#include <iostream>
#include <string>
#include <set>
#include "ast/PreprocessorNodes.h"
#include "ast/EnumNamespaceNodes.h"
#include "ast/ClassDeclaration.h"
#include "ast/GenericType.h"
#include "ast/AsyncNodes.h"
#include "ast/Serialization.h"
#include "ast/Parser.h"
#include "ast/PythonGenerator.h"
#include "ast/CppGenerator.h"
#include "ast/JavaGenerator.h"
#include "ast/RustGenerator.h"
#include "ast/GoGenerator.h"
#include "ast/JavaScriptGenerator.h"
#include "ast/ElispGenerator.h"
#include "ast/KotlinGenerator.h"
#include "ast/CSharpGenerator.h"
#include "CompactAST.h"
int main() {
int passed = 0;
// Test 1: Parse realistic C++ header: includes + pragma + namespace + enum + class + function
{
std::string src = R"(
#pragma once
#include <string>
#include "ast/ASTNode.h"
namespace whetstone {
enum class NodeKind : int {
Function = 0,
Variable = 1,
Class = 2
};
class ASTVisitor {
public:
virtual void visit() {}
};
void helper(int x) { return; }
}
)";
auto mod = TreeSitterParser::parseCpp(src);
auto stmts = mod->getChildren("statements");
// Collect all concept types present
std::set<std::string> types;
for (auto* s : stmts) types.insert(s->conceptType);
assert(types.count("PragmaDirective") || types.count("IncludeDirective"));
assert(types.count("NamespaceDeclaration"));
// Namespace should contain enum, class, function
bool foundNs = false;
for (auto* s : stmts) {
if (s->conceptType == "NamespaceDeclaration") {
foundNs = true;
auto body = s->getChildren("body");
std::set<std::string> bodyTypes;
for (auto* b : body) bodyTypes.insert(b->conceptType);
assert(bodyTypes.count("EnumDeclaration"));
assert(bodyTypes.count("ClassDeclaration"));
assert(bodyTypes.count("Function"));
}
}
assert(foundNs);
std::cout << "Test 1 PASSED: Parse realistic C++ header with all constructs\n";
passed++;
}
// Test 2: Round-trip: C++ header → AST → JSON → fromJson → generate → verify structure
{
std::string src = R"(
enum class Color : int {
Red = 0,
Green = 1
};
)";
auto mod = TreeSitterParser::parseCpp(src);
auto stmts = mod->getChildren("statements");
bool foundEnum = false;
for (auto* s : stmts) {
if (s->conceptType == "EnumDeclaration") {
foundEnum = true;
// JSON roundtrip
nlohmann::json j = propertiesToJson(s);
auto* restored = createNode(s->conceptType);
setPropertiesFromJson(restored, j);
// Verify properties survived
auto* orig = static_cast<EnumDeclaration*>(s);
auto* rest = static_cast<EnumDeclaration*>(restored);
assert(rest->name == orig->name);
assert(rest->isScoped == orig->isScoped);
delete restored;
}
}
assert(foundEnum);
std::cout << "Test 2 PASSED: Enum parse → JSON roundtrip → verify\n";
passed++;
}
// Test 3: Enum inside namespace: parse → verify scoping in AST
{
std::string src = R"(
namespace outer {
enum class Status { Active, Inactive };
}
)";
auto mod = TreeSitterParser::parseCpp(src);
auto stmts = mod->getChildren("statements");
bool found = false;
for (auto* s : stmts) {
if (s->conceptType == "NamespaceDeclaration") {
auto* ns = static_cast<NamespaceDeclaration*>(s);
assert(ns->name == "outer");
auto body = ns->getChildren("body");
bool hasEnum = false;
for (auto* b : body) {
if (b->conceptType == "EnumDeclaration") {
hasEnum = true;
auto* e = static_cast<EnumDeclaration*>(b);
assert(e->name == "Status");
assert(e->isScoped);
}
}
assert(hasEnum);
found = true;
}
}
assert(found);
std::cout << "Test 3 PASSED: Enum inside namespace scoping\n";
passed++;
}
// Test 4: Cross-language: C++ enum → Java enum + Python class(Enum) + Rust enum
{
EnumDeclaration e; e.name = "Color"; e.isScoped = true;
e.addChild("members", new EnumMember("m1", "Red", "0"));
e.addChild("members", new EnumMember("m2", "Green", "1"));
e.addChild("members", new EnumMember("m3", "Blue", "2"));
CppGenerator cppGen;
std::string cppOut = cppGen.generate(&e);
assert(cppOut.find("enum class Color") != std::string::npos);
JavaGenerator javaGen;
std::string javaOut = javaGen.generate(&e);
assert(javaOut.find("enum Color") != std::string::npos);
assert(javaOut.find("Red") != std::string::npos);
PythonGenerator pyGen;
std::string pyOut = pyGen.generate(&e);
assert(pyOut.find("class Color(Enum)") != std::string::npos);
RustGenerator rustGen;
std::string rustOut = rustGen.generate(&e);
assert(rustOut.find("enum Color") != std::string::npos);
KotlinGenerator ktGen;
std::string ktOut = ktGen.generate(&e);
assert(ktOut.find("enum class Color") != std::string::npos);
CSharpGenerator csGen;
std::string csOut = csGen.generate(&e);
assert(csOut.find("enum Color") != std::string::npos);
std::cout << "Test 4 PASSED: C++ enum → 6 language outputs\n";
passed++;
}
// Test 5: Combined namespace + class + enum + function → full pipeline
{
NamespaceDeclaration ns; ns.name = "ast";
auto* cls = new ClassDeclaration(); cls->name = "Node"; cls->isAbstract = true;
auto* meth = new Function(); meth->name = "accept";
cls->addChild("methods", meth);
ns.addChild("body", cls);
auto* e = new EnumDeclaration(); e->name = "Kind"; e->isScoped = true;
e->addChild("members", new EnumMember("m1", "Expr"));
e->addChild("members", new EnumMember("m2", "Stmt"));
ns.addChild("body", e);
auto* func = new Function(); func->name = "createNode";
ns.addChild("body", func);
CppGenerator gen;
std::string out = gen.generate(&ns);
assert(out.find("namespace ast") != std::string::npos);
assert(out.find("Node") != std::string::npos);
assert(out.find("accept") != std::string::npos);
assert(out.find("enum class Kind") != std::string::npos);
assert(out.find("Expr") != std::string::npos);
assert(out.find("createNode") != std::string::npos);
std::cout << "Test 5 PASSED: Combined namespace + class + enum + function pipeline\n";
passed++;
}
// Test 6: All new AST nodes serialize/deserialize correctly (batch verification)
{
// IncludeDirective
IncludeDirective inc; inc.path = "vector"; inc.isSystem = true;
nlohmann::json j1 = propertiesToJson(&inc);
auto* r1 = createNode("IncludeDirective");
setPropertiesFromJson(r1, j1);
assert(static_cast<IncludeDirective*>(r1)->path == "vector");
assert(static_cast<IncludeDirective*>(r1)->isSystem);
// PragmaDirective
PragmaDirective prag; prag.directive = "once";
nlohmann::json j2 = propertiesToJson(&prag);
auto* r2 = createNode("PragmaDirective");
setPropertiesFromJson(r2, j2);
assert(static_cast<PragmaDirective*>(r2)->directive == "once");
// MacroDefinition
MacroDefinition mac; mac.name = "MAX"; mac.isFunctionLike = true;
mac.parameters = {"a", "b"}; mac.body = "((a)>(b)?(a):(b))";
nlohmann::json j3 = propertiesToJson(&mac);
auto* r3 = createNode("MacroDefinition");
setPropertiesFromJson(r3, j3);
auto* rm = static_cast<MacroDefinition*>(r3);
assert(rm->name == "MAX");
assert(rm->isFunctionLike);
assert(rm->parameters.size() == 2);
// EnumDeclaration
EnumDeclaration ed; ed.name = "Color"; ed.isScoped = true; ed.underlyingType = "int";
nlohmann::json j4 = propertiesToJson(&ed);
auto* r4 = createNode("EnumDeclaration");
setPropertiesFromJson(r4, j4);
auto* re = static_cast<EnumDeclaration*>(r4);
assert(re->name == "Color");
assert(re->isScoped);
assert(re->underlyingType == "int");
// NamespaceDeclaration
NamespaceDeclaration nsd; nsd.name = "whetstone";
nlohmann::json j5 = propertiesToJson(&nsd);
auto* r5 = createNode("NamespaceDeclaration");
setPropertiesFromJson(r5, j5);
assert(static_cast<NamespaceDeclaration*>(r5)->name == "whetstone");
// TypeAlias
TypeAlias ta; ta.aliasName = "Ptr"; ta.targetType = "int*"; ta.isUsing = true;
nlohmann::json j6 = propertiesToJson(&ta);
auto* r6 = createNode("TypeAlias");
setPropertiesFromJson(r6, j6);
auto* rt = static_cast<TypeAlias*>(r6);
assert(rt->aliasName == "Ptr");
assert(rt->targetType == "int*");
assert(rt->isUsing);
delete r1; delete r2; delete r3; delete r4; delete r5; delete r6;
std::cout << "Test 6 PASSED: All 6 new AST nodes serialize/deserialize correctly\n";
passed++;
}
// Test 7: CompactAST names for all new node types
{
IncludeDirective inc; inc.path = "vector"; inc.isSystem = true;
PragmaDirective prag; prag.directive = "once";
MacroDefinition mac; mac.name = "MAX";
EnumDeclaration ed; ed.name = "Color";
EnumMember em("m1", "Red", "0");
NamespaceDeclaration nsd; nsd.name = "whetstone";
TypeAlias ta; ta.aliasName = "Ptr";
assert(getNodeName(&inc) == "vector");
assert(getNodeName(&prag) == "once");
assert(getNodeName(&mac) == "MAX");
assert(getNodeName(&ed) == "Color");
assert(getNodeName(&em) == "Red");
assert(getNodeName(&nsd) == "whetstone");
assert(getNodeName(&ta) == "Ptr");
std::cout << "Test 7 PASSED: CompactAST names for all new node types\n";
passed++;
}
// Test 8: C++ self-hosting progress — parse simplified Whetstone header fragment
{
std::string src = R"(
#pragma once
#include <string>
#include <vector>
#include "ASTNode.h"
namespace whetstone {
enum class NodeKind {
Module,
Function,
Variable
};
class ProjectionGenerator {
public:
virtual std::string generate() {}
};
class CppGenerator : public ProjectionGenerator {
public:
std::string generate() {}
};
}
)";
auto mod = TreeSitterParser::parseCpp(src);
auto stmts = mod->getChildren("statements");
// Count constructs found
int includes = 0, pragmas = 0, namespaces = 0;
for (auto* s : stmts) {
if (s->conceptType == "IncludeDirective") includes++;
if (s->conceptType == "PragmaDirective") pragmas++;
if (s->conceptType == "NamespaceDeclaration") namespaces++;
}
assert(includes >= 2); // <string>, <vector>, "ASTNode.h"
assert(pragmas >= 1);
assert(namespaces >= 1);
// Inside namespace: enum + 2 classes
for (auto* s : stmts) {
if (s->conceptType == "NamespaceDeclaration") {
auto body = s->getChildren("body");
int enums = 0, classes = 0;
for (auto* b : body) {
if (b->conceptType == "EnumDeclaration") enums++;
if (b->conceptType == "ClassDeclaration") classes++;
}
assert(enums >= 1);
assert(classes >= 2);
// CppGenerator should inherit from ProjectionGenerator
for (auto* b : body) {
if (b->conceptType == "ClassDeclaration") {
auto* cls = static_cast<ClassDeclaration*>(b);
if (cls->name == "CppGenerator") {
auto bases = cls->getBases();
assert(!bases.empty());
assert(bases[0].name == "ProjectionGenerator");
}
}
}
}
}
std::cout << "Test 8 PASSED: Self-hosting progress — Whetstone header fragment parsed\n";
passed++;
}
std::cout << "\nResults: " << passed << "/8\n";
assert(passed == 8);
return 0;
}