157 lines
6.2 KiB
C++
157 lines
6.2 KiB
C++
|
|
// Step 472: Module Decomposition Engine Tests (12 tests)
|
||
|
|
|
||
|
|
#include "ArchitectModuleDecomposer.h"
|
||
|
|
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
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 StructuredRequirements reqFromText(const std::string& s) {
|
||
|
|
return ArchitectProblemParser::parse(s);
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_decomposes_auth_api_data_modules() {
|
||
|
|
TEST(decomposes_auth_api_data_modules);
|
||
|
|
auto req = reqFromText("Build a REST API with auth and PostgreSQL.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("auth"), "missing auth module");
|
||
|
|
CHECK(g.hasModule("api"), "missing api module");
|
||
|
|
CHECK(g.hasModule("data"), "missing data module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_decomposes_ui_module_from_web_mobile_constraints() {
|
||
|
|
TEST(decomposes_ui_module_from_web_mobile_constraints);
|
||
|
|
auto req = reqFromText("Create a web and mobile dashboard.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("ui"), "missing ui module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_decomposes_search_reporting_modules() {
|
||
|
|
TEST(decomposes_search_reporting_modules);
|
||
|
|
auto req = reqFromText("App requires search and reporting features.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("search"), "missing search module");
|
||
|
|
CHECK(g.hasModule("reporting"), "missing reporting module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_adds_integration_module_for_external_systems() {
|
||
|
|
TEST(adds_integration_module_for_external_systems);
|
||
|
|
auto req = reqFromText("Integrate Stripe and Salesforce APIs.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("integrations"), "missing integrations module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_cross_cutting_modules_are_present() {
|
||
|
|
TEST(cross_cutting_modules_are_present);
|
||
|
|
auto req = reqFromText("Build a REST API.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("logging"), "missing logging");
|
||
|
|
CHECK(g.hasModule("config"), "missing config");
|
||
|
|
CHECK(g.hasModule("error_handling"), "missing error_handling");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_security_nonfunctional_adds_security_module() {
|
||
|
|
TEST(security_nonfunctional_adds_security_module);
|
||
|
|
auto req = reqFromText("System must be secure and reliable.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.hasModule("security"), "missing security module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_layered_strategy_generates_expected_dependencies() {
|
||
|
|
TEST(layered_strategy_generates_expected_dependencies);
|
||
|
|
auto req = reqFromText("Web REST API with auth and PostgreSQL.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req, DecompositionStrategy::Layered);
|
||
|
|
bool sawUiApi = false;
|
||
|
|
bool sawApiData = false;
|
||
|
|
for (const auto& e : g.edges) {
|
||
|
|
if (e.from == "ui" && e.to == "api") sawUiApi = true;
|
||
|
|
if (e.from == "api" && e.to == "data") sawApiData = true;
|
||
|
|
}
|
||
|
|
CHECK(sawUiApi, "missing ui->api edge");
|
||
|
|
CHECK(sawApiData, "missing api->data edge");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_microservice_strategy_changes_edge_shape() {
|
||
|
|
TEST(microservice_strategy_changes_edge_shape);
|
||
|
|
auto req = reqFromText("REST API with auth and stripe integration.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req, DecompositionStrategy::Microservice);
|
||
|
|
bool sawApiIntegrations = false;
|
||
|
|
for (const auto& e : g.edges) {
|
||
|
|
if (e.from == "api" && e.to == "integrations") sawApiIntegrations = true;
|
||
|
|
}
|
||
|
|
CHECK(sawApiIntegrations, "missing api->integrations edge in microservice strategy");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_monolith_strategy_uses_core_hub() {
|
||
|
|
TEST(monolith_strategy_uses_core_hub);
|
||
|
|
auto req = reqFromText("simple app with auth and web ui");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req, DecompositionStrategy::Monolith);
|
||
|
|
bool sawCoreDep = false;
|
||
|
|
for (const auto& e : g.edges) {
|
||
|
|
if (e.from == "core") sawCoreDep = true;
|
||
|
|
}
|
||
|
|
CHECK(g.hasModule("core"), "missing core module");
|
||
|
|
CHECK(sawCoreDep, "expected core dependencies in monolith strategy");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_complexity_scores_are_clamped() {
|
||
|
|
TEST(complexity_scores_are_clamped);
|
||
|
|
auto req = reqFromText("web mobile api auth search reporting notification postgres stripe secure scalable");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
for (const auto& n : g.nodes) {
|
||
|
|
CHECK(n.complexity >= 1 && n.complexity <= 10, "complexity out of range");
|
||
|
|
}
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_dependency_count_helper_reports_nonzero() {
|
||
|
|
TEST(dependency_count_helper_reports_nonzero);
|
||
|
|
auto req = reqFromText("REST API with auth and PostgreSQL.");
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req);
|
||
|
|
CHECK(g.dependencyCountFor("api") > 0, "expected api dependencies");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_fallback_core_module_when_sparse_requirements() {
|
||
|
|
TEST(fallback_core_module_when_sparse_requirements);
|
||
|
|
StructuredRequirements req;
|
||
|
|
req.functionalRequirements = {{"core application behavior", 0.55f}};
|
||
|
|
auto g = ArchitectModuleDecomposer::decompose(req, DecompositionStrategy::Monolith);
|
||
|
|
CHECK(g.hasModule("core"), "missing fallback core module");
|
||
|
|
PASS();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
std::cout << "Step 472: Module Decomposition Engine Tests\n";
|
||
|
|
|
||
|
|
test_decomposes_auth_api_data_modules(); // 1
|
||
|
|
test_decomposes_ui_module_from_web_mobile_constraints(); // 2
|
||
|
|
test_decomposes_search_reporting_modules(); // 3
|
||
|
|
test_adds_integration_module_for_external_systems(); // 4
|
||
|
|
test_cross_cutting_modules_are_present(); // 5
|
||
|
|
test_security_nonfunctional_adds_security_module(); // 6
|
||
|
|
test_layered_strategy_generates_expected_dependencies(); // 7
|
||
|
|
test_microservice_strategy_changes_edge_shape(); // 8
|
||
|
|
test_monolith_strategy_uses_core_hub(); // 9
|
||
|
|
test_complexity_scores_are_clamped(); // 10
|
||
|
|
test_dependency_count_helper_reports_nonzero(); // 11
|
||
|
|
test_fallback_core_module_when_sparse_requirements(); // 12
|
||
|
|
|
||
|
|
std::cout << "\nResults: " << passed << "/" << (passed + failed)
|
||
|
|
<< " passed\n";
|
||
|
|
return failed == 0 ? 0 : 1;
|
||
|
|
}
|