Files
whetstone_DSL/editor/tests/step445_test.cpp
Bill ad6c1eb1f4 Complete Sprint 20: Legacy Code Ingestion (steps 439-448, 124/124 tests)
Phase 20a delivers legacy analysis, safety audit with CWE mapping,
modernization suggestions with effort routing, and RPC/MCP tools.
Phase 20b adds multi-file migration planning, API boundary preservation,
target-language test generation, and progressive migration execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 19:22:15 -07:00

183 lines
6.7 KiB
C++

// Step 445: API Boundary Preservation Tests (12 tests)
#include "APIBoundaryPreserver.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 MigrationUnit makeUnit(const std::string& path, const std::string& mod,
const std::vector<std::string>& exports,
const std::string& target = "rust") {
MigrationUnit u;
u.id = "unit-0";
u.filePath = path;
u.moduleName = mod;
u.sourceLanguage = "c";
u.targetLanguage = target;
u.exports = exports;
return u;
}
static const std::string UTILS_SRC =
"int clamp(int x, int lo, int hi){ return x<lo?lo:x>hi?hi:x; }\n"
"int max(int a, int b){ return a>b?a:b; }\n";
static const std::string PARSER_SRC =
"typedef struct { int type; char* text; } Token;\n"
"Token* parse(const char* input){ return 0; }\n"
"void free_tokens(Token* t){ }\n";
void test_public_api_extracted() {
TEST(public_api_extracted);
auto unit = makeUnit("utils.c", "utils", {"clamp", "max"});
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.hasFunction("clamp"), "expected clamp in public API");
CHECK(report.hasFunction("max"), "expected max in public API");
CHECK(report.publicAPI.size() == 2, "expected 2 public functions");
PASS();
}
void test_function_signatures_captured() {
TEST(function_signatures_captured);
auto unit = makeUnit("utils.c", "utils", {"clamp"});
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(!report.publicAPI.empty(), "expected public API");
auto& sig = report.publicAPI[0];
CHECK(sig.name == "clamp", "expected clamp");
CHECK(!sig.returnType.empty(), "expected return type");
CHECK(!sig.paramTypes.empty(), "expected param types");
PASS();
}
void test_type_mappings_c_to_rust() {
TEST(type_mappings_c_to_rust);
auto unit = makeUnit("utils.c", "utils", {"clamp"}, "rust");
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.hasTypeMapping("int"), "expected int type mapping");
PASS();
}
void test_type_mappings_c_to_java() {
TEST(type_mappings_c_to_java);
auto unit = makeUnit("utils.c", "utils", {"clamp"}, "java");
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.hasTypeMapping("int"), "expected int type mapping for java");
PASS();
}
void test_pointer_type_mapping() {
TEST(pointer_type_mapping);
auto unit = makeUnit("parser.c", "parser", {"parse"}, "rust");
auto report = APIBoundaryPreserver::analyze(PARSER_SRC, unit);
CHECK(report.hasTypeMapping("char*"), "expected char* type mapping");
PASS();
}
void test_contract_for_pointer_params() {
TEST(contract_for_pointer_params);
auto unit = makeUnit("parser.c", "parser", {"free_tokens"}, "rust");
auto report = APIBoundaryPreserver::analyze(PARSER_SRC, unit);
CHECK(report.hasContract("free_tokens"), "expected contract for free_tokens");
// Should have non-null precondition for pointer param
for (const auto& c : report.contracts) {
if (c.functionName == "free_tokens") {
CHECK(c.precondition.find("NULL") != std::string::npos,
"expected NULL check precondition");
}
}
PASS();
}
void test_contract_for_pointer_return() {
TEST(contract_for_pointer_return);
auto unit = makeUnit("parser.c", "parser", {"parse"}, "rust");
auto report = APIBoundaryPreserver::analyze(PARSER_SRC, unit);
CHECK(report.hasContract("parse"), "expected contract for parse");
for (const auto& c : report.contracts) {
if (c.functionName == "parse") {
CHECK(!c.postcondition.empty(), "expected postcondition for pointer return");
}
}
PASS();
}
void test_ffi_boundary_rust() {
TEST(ffi_boundary_rust);
auto unit = makeUnit("utils.c", "utils", {"clamp", "max"}, "rust");
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.hasFFI("clamp"), "expected FFI for clamp");
CHECK(report.hasFFI("max"), "expected FFI for max");
for (const auto& f : report.ffiBoundaries) {
CHECK(f.annotation.find("no_mangle") != std::string::npos,
"Rust FFI should have #[no_mangle]");
}
PASS();
}
void test_ffi_boundary_java() {
TEST(ffi_boundary_java);
auto unit = makeUnit("utils.c", "utils", {"clamp"}, "java");
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.hasFFI("clamp"), "expected FFI for clamp");
for (const auto& f : report.ffiBoundaries) {
CHECK(f.annotation.find("JNI") != std::string::npos,
"Java FFI should mention JNI");
}
PASS();
}
void test_api_preserved_flag() {
TEST(api_preserved_flag);
auto unit = makeUnit("utils.c", "utils", {"clamp", "max"});
auto report = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
CHECK(report.apiPreserved, "API should be preserved");
PASS();
}
void test_verify_preservation_pass() {
TEST(verify_preservation_pass);
auto unit = makeUnit("utils.c", "utils", {"clamp", "max"});
auto original = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
auto migrated = original; // same API = preserved
CHECK(APIBoundaryPreserver::verifyPreservation(original, migrated),
"same API should verify as preserved");
PASS();
}
void test_verify_preservation_fail() {
TEST(verify_preservation_fail);
auto unit = makeUnit("utils.c", "utils", {"clamp", "max"});
auto original = APIBoundaryPreserver::analyze(UTILS_SRC, unit);
auto migrated = original;
migrated.publicAPI.pop_back(); // remove one function
CHECK(!APIBoundaryPreserver::verifyPreservation(original, migrated),
"missing function should fail verification");
PASS();
}
int main() {
std::cout << "Step 445: API Boundary Preservation Tests\n";
test_public_api_extracted(); // 1
test_function_signatures_captured(); // 2
test_type_mappings_c_to_rust(); // 3
test_type_mappings_c_to_java(); // 4
test_pointer_type_mapping(); // 5
test_contract_for_pointer_params(); // 6
test_contract_for_pointer_return(); // 7
test_ffi_boundary_rust(); // 8
test_ffi_boundary_java(); // 9
test_api_preserved_flag(); // 10
test_verify_preservation_pass(); // 11
test_verify_preservation_fail(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}