Phase 11b — Validation & Conflict Completion: - Step 297: Subject 2-4 validation rules E0600-E0805 (12/12) - Step 298: Subject 5-8 validation rules E0900-E1202 (12/12) - Step 299: Cross-type conflict detection, 6 conflict pairs (12/12) - Step 300: TransformEngineExtended — float folding, dead var, annotation-aware (12/12) - Step 301: Phase 11b integration tests (8/8) Phase 11c — Parser Deepening (start): - Step 302: New AST nodes — ClassDeclaration, InterfaceDeclaration, MethodDeclaration, GenericType, TypeParameter with JSON roundtrip (12/12) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
254 lines
8.8 KiB
C++
254 lines
8.8 KiB
C++
// Step 297: Subject 2-4 Validation Tests (12 tests)
|
|
// Tests AnnotationValidatorExtended for type system (E0600-E0608),
|
|
// concurrency (E0700-E0708), and scope (E0800-E0805) rules.
|
|
|
|
#include "AnnotationValidatorExtended.h"
|
|
#include "ast/Module.h"
|
|
#include "ast/Function.h"
|
|
#include "ast/Annotation.h"
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
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 {}
|
|
|
|
static bool hasCode(const std::vector<AnnotationValidator::Diagnostic>& diags,
|
|
const std::string& code) {
|
|
for (const auto& d : diags)
|
|
if (d.message.find("[" + code + "]") != std::string::npos) return true;
|
|
return false;
|
|
}
|
|
|
|
// 1. BitWidth non-power-of-2 -> E0600
|
|
void test_bitwidth_invalid() {
|
|
TEST(bitwidth_invalid_E0600);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto bw = new BitWidthAnnotation(); bw->width = 3;
|
|
fn->addChild("annotations", bw);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0600"), "expected E0600 for width=3");
|
|
PASS();
|
|
}
|
|
|
|
// 2. BitWidth valid (32) -> no diagnostic
|
|
void test_bitwidth_valid() {
|
|
TEST(bitwidth_valid_no_diag);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto bw = new BitWidthAnnotation(); bw->width = 32;
|
|
fn->addChild("annotations", bw);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(!hasCode(diags, "E0600"), "should not trigger E0600 for width=32");
|
|
PASS();
|
|
}
|
|
|
|
// 3. Endian invalid -> E0601
|
|
void test_endian_invalid() {
|
|
TEST(endian_invalid_E0601);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto e = new EndianAnnotation(); e->order = "middle";
|
|
fn->addChild("annotations", e);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0601"), "expected E0601 for order=middle");
|
|
PASS();
|
|
}
|
|
|
|
// 4. Layout invalid mode -> E0602, invalid alignment -> E0603
|
|
void test_layout_invalid() {
|
|
TEST(layout_invalid_E0602_E0603);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto lay = new LayoutAnnotation(); lay->mode = "scattered"; lay->alignment = 3;
|
|
fn->addChild("annotations", lay);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0602"), "expected E0602 for mode=scattered");
|
|
CHECK(hasCode(diags, "E0603"), "expected E0603 for alignment=3");
|
|
PASS();
|
|
}
|
|
|
|
// 5. Nullability invalid -> E0604
|
|
void test_nullability_invalid() {
|
|
TEST(nullability_invalid_E0604);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto n = new NullabilityAnnotation(); n->strategy = "maybe";
|
|
fn->addChild("annotations", n);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0604"), "expected E0604 for strategy=maybe");
|
|
PASS();
|
|
}
|
|
|
|
// 6. Variance invalid -> E0605
|
|
void test_variance_invalid() {
|
|
TEST(variance_invalid_E0605);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto va = new VarianceAnnotation(); va->variance = "bivariant";
|
|
fn->addChild("annotations", va);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0605"), "expected E0605 for variance=bivariant");
|
|
PASS();
|
|
}
|
|
|
|
// 7. Atomic invalid -> E0700
|
|
void test_atomic_invalid() {
|
|
TEST(atomic_invalid_E0700);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto a = new AtomicAnnotation(); a->consistency = "strong";
|
|
fn->addChild("annotations", a);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0700"), "expected E0700 for consistency=strong");
|
|
PASS();
|
|
}
|
|
|
|
// 8. Exec async without ThreadModel -> E0704
|
|
void test_exec_async_no_threadmodel() {
|
|
TEST(exec_async_no_threadmodel_E0704);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto exec = new ExecAnnotation(); exec->mode = "async";
|
|
fn->addChild("annotations", exec);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0704"), "expected E0704 for async without ThreadModel");
|
|
PASS();
|
|
}
|
|
|
|
// 9. Exec async WITH ThreadModel -> no E0704
|
|
void test_exec_async_with_threadmodel() {
|
|
TEST(exec_async_with_threadmodel_no_E0704);
|
|
auto mod = std::make_unique<Module>();
|
|
// Add ThreadModel to parent module
|
|
auto tm = new ThreadModelAnnotation(); tm->model = "os";
|
|
mod->addChild("annotations", tm);
|
|
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto exec = new ExecAnnotation(); exec->mode = "async";
|
|
fn->addChild("annotations", exec);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(!hasCode(diags, "E0704"), "should not trigger E0704 when ThreadModel is on ancestor");
|
|
PASS();
|
|
}
|
|
|
|
// 10. Capture invalid -> E0802
|
|
void test_capture_invalid() {
|
|
TEST(capture_invalid_E0802);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto c = new CaptureAnnotation(); c->strategy = "borrow";
|
|
fn->addChild("annotations", c);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0802"), "expected E0802 for strategy=borrow");
|
|
PASS();
|
|
}
|
|
|
|
// 11. Visibility invalid -> E0803
|
|
void test_visibility_invalid() {
|
|
TEST(visibility_invalid_E0803);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
auto vis = new VisibilityAnnotation(); vis->level = "protected";
|
|
fn->addChild("annotations", vis);
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(hasCode(diags, "E0803"), "expected E0803 for level=protected");
|
|
PASS();
|
|
}
|
|
|
|
// 12. All valid Subject 2-4 annotations -> 0 diagnostics
|
|
void test_all_valid_subject_2_4() {
|
|
TEST(all_valid_subject_2_4_no_diags);
|
|
auto mod = std::make_unique<Module>();
|
|
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
|
|
|
|
// Valid Subject 2
|
|
auto bw = new BitWidthAnnotation(); bw->width = 64;
|
|
fn->addChild("annotations", bw);
|
|
auto en = new EndianAnnotation(); en->order = "big";
|
|
fn->addChild("annotations", en);
|
|
auto lay = new LayoutAnnotation(); lay->mode = "packed"; lay->alignment = 0;
|
|
fn->addChild("annotations", lay);
|
|
auto nu = new NullabilityAnnotation(); nu->strategy = "strict";
|
|
fn->addChild("annotations", nu);
|
|
auto va = new VarianceAnnotation(); va->variance = "covariant";
|
|
fn->addChild("annotations", va);
|
|
|
|
// Valid Subject 3
|
|
auto at = new AtomicAnnotation(); at->consistency = "seq_cst";
|
|
fn->addChild("annotations", at);
|
|
auto sy = new SyncAnnotation(); sy->primitive = "monitor";
|
|
fn->addChild("annotations", sy);
|
|
|
|
// Valid Subject 4
|
|
auto bi = new BindingAnnotation(); bi->time = "static";
|
|
fn->addChild("annotations", bi);
|
|
auto ca = new CaptureAnnotation(); ca->strategy = "value";
|
|
fn->addChild("annotations", ca);
|
|
auto vis = new VisibilityAnnotation(); vis->level = "public";
|
|
fn->addChild("annotations", vis);
|
|
|
|
mod->addChild("functions", fn);
|
|
|
|
AnnotationValidatorExtended v;
|
|
auto diags = v.validate(mod.get());
|
|
CHECK(diags.empty(), "expected 0 diagnostics for all valid annotations, got " + std::to_string(diags.size()));
|
|
PASS();
|
|
}
|
|
|
|
int main() {
|
|
std::cout << "=== Step 297: Subject 2-4 Validation Tests ===\n";
|
|
test_bitwidth_invalid();
|
|
test_bitwidth_valid();
|
|
test_endian_invalid();
|
|
test_layout_invalid();
|
|
test_nullability_invalid();
|
|
test_variance_invalid();
|
|
test_atomic_invalid();
|
|
test_exec_async_no_threadmodel();
|
|
test_exec_async_with_threadmodel();
|
|
test_capture_invalid();
|
|
test_visibility_invalid();
|
|
test_all_valid_subject_2_4();
|
|
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
|
|
return failed > 0 ? 1 : 0;
|
|
}
|