Files
whetstone_DSL/editor/tests/step489_test.cpp

165 lines
7.1 KiB
C++

// Step 489: Secure-by-Default Code Generation Tests (12 tests)
#include "SecureByDefaultGenerator.h"
#include <iostream>
#include <string>
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 SecureGenerationOutput run(const std::string& lang, SecureSnippetKind kind,
const std::string& op = "") {
SecureGenerationRequest r;
r.language = lang;
r.kind = kind;
r.operationName = op;
r.securityRequirement = "default";
return SecureByDefaultGenerator::generate(r);
}
void test_sql_generation_uses_parameterized_queries_not_concat() {
TEST(sql_generation_uses_parameterized_queries_not_concat);
auto out = run("python", SecureSnippetKind::SqlQuery, "getUser");
CHECK(out.code.find("%s") != std::string::npos, "expected parameter placeholder");
CHECK(out.code.find("+") == std::string::npos, "should not use string concatenation");
PASS();
}
void test_input_handling_marks_raw_until_sanitized() {
TEST(input_handling_marks_raw_until_sanitized);
auto out = run("typescript", SecureSnippetKind::InputHandling, "processInput");
bool foundRaw = false;
for (const auto& a : out.annotations) {
if (a == "@InputValidation(raw)") foundRaw = true;
}
CHECK(foundRaw, "expected @InputValidation(raw)");
CHECK(out.code.find("raw until sanitized") != std::string::npos, "missing raw comment");
PASS();
}
void test_file_operations_include_path_traversal_guard() {
TEST(file_operations_include_path_traversal_guard);
auto out = run("python", SecureSnippetKind::FileOperation, "readSafe");
CHECK(out.code.find("realpath") != std::string::npos, "missing canonicalization");
CHECK(out.code.find("path traversal blocked") != std::string::npos, "missing traversal check");
PASS();
}
void test_network_calls_include_timeout_and_tls_verification() {
TEST(network_calls_include_timeout_and_tls_verification);
auto out = run("python", SecureSnippetKind::NetworkCall, "fetchSecure");
CHECK(out.code.find("timeout=5") != std::string::npos, "missing timeout");
CHECK(out.code.find("verify=True") != std::string::npos, "missing TLS verify");
PASS();
}
void test_crypto_generation_avoids_md5_and_sha1_defaults() {
TEST(crypto_generation_avoids_md5_and_sha1_defaults);
auto out = run("python", SecureSnippetKind::CryptoOperation, "encrypt");
CHECK(out.code.find("MD5") == std::string::npos, "must not include md5");
CHECK(out.code.find("SHA1") == std::string::npos, "must not include sha1");
CHECK(out.code.find("AESGCM") != std::string::npos, "expected modern crypto");
PASS();
}
void test_crypto_generation_is_marked_human_review_only() {
TEST(crypto_generation_is_marked_human_review_only);
auto out = run("rust", SecureSnippetKind::CryptoOperation, "encryptBlob");
CHECK(out.requiresHumanReview, "crypto should require human review");
bool hasAutom = false;
for (const auto& a : out.annotations) if (a == "@Automatability(human)") hasAutom = true;
CHECK(hasAutom, "missing @Automatability(human)");
PASS();
}
void test_all_generated_snippets_include_security_risk_and_review_annotations() {
TEST(all_generated_snippets_include_security_risk_and_review_annotations);
auto a = run("python", SecureSnippetKind::SqlQuery);
auto b = run("python", SecureSnippetKind::InputHandling);
auto c = run("python", SecureSnippetKind::FileOperation);
auto d = run("python", SecureSnippetKind::NetworkCall);
auto e = run("python", SecureSnippetKind::CryptoOperation);
auto hasBase = [](const SecureGenerationOutput& o) {
bool risk = false, review = false;
for (const auto& ann : o.annotations) {
if (ann == "@Risk(security)") risk = true;
if (ann == "@Review(required, human)") review = true;
}
return risk && review;
};
CHECK(hasBase(a) && hasBase(b) && hasBase(c) && hasBase(d) && hasBase(e),
"missing base security annotations");
PASS();
}
void test_sql_generation_for_rust_uses_bind_pattern() {
TEST(sql_generation_for_rust_uses_bind_pattern);
auto out = run("rust", SecureSnippetKind::SqlQuery, "fetchOne");
CHECK(out.code.find(".bind(") != std::string::npos, "expected bind usage");
PASS();
}
void test_network_generation_for_rust_uses_timeout_and_rustls() {
TEST(network_generation_for_rust_uses_timeout_and_rustls);
auto out = run("rust", SecureSnippetKind::NetworkCall, "fetch");
CHECK(out.code.find("use_rustls_tls") != std::string::npos, "missing rustls");
CHECK(out.code.find("from_secs(5)") != std::string::npos, "missing timeout");
PASS();
}
void test_file_operation_for_unknown_lang_falls_back_to_secure_stub() {
TEST(file_operation_for_unknown_lang_falls_back_to_secure_stub);
auto out = run("lua", SecureSnippetKind::FileOperation, "readSafe");
CHECK(out.code.find("canonical path prefix check") != std::string::npos,
"missing secure fallback guidance");
PASS();
}
void test_operation_name_is_respected_in_generated_code() {
TEST(operation_name_is_respected_in_generated_code);
auto out = run("typescript", SecureSnippetKind::InputHandling, "sanitizeLater");
CHECK(out.code.find("sanitizeLater") != std::string::npos, "operation name missing");
PASS();
}
void test_security_requirement_annotation_is_emitted() {
TEST(security_requirement_annotation_is_emitted);
SecureGenerationRequest r;
r.language = "python";
r.kind = SecureSnippetKind::SqlQuery;
r.operationName = "query";
r.securityRequirement = "pci-dss";
auto out = SecureByDefaultGenerator::generate(r);
bool found = false;
for (const auto& a : out.annotations) {
if (a == "@SecurityRequirement(pci-dss)") found = true;
}
CHECK(found, "missing security requirement annotation");
PASS();
}
int main() {
std::cout << "Step 489: Secure-by-Default Code Generation Tests\n";
test_sql_generation_uses_parameterized_queries_not_concat(); // 1
test_input_handling_marks_raw_until_sanitized(); // 2
test_file_operations_include_path_traversal_guard(); // 3
test_network_calls_include_timeout_and_tls_verification(); // 4
test_crypto_generation_avoids_md5_and_sha1_defaults(); // 5
test_crypto_generation_is_marked_human_review_only(); // 6
test_all_generated_snippets_include_security_risk_and_review_annotations(); // 7
test_sql_generation_for_rust_uses_bind_pattern(); // 8
test_network_generation_for_rust_uses_timeout_and_rustls(); // 9
test_file_operation_for_unknown_lang_falls_back_to_secure_stub(); // 10
test_operation_name_is_respected_in_generated_code(); // 11
test_security_requirement_annotation_is_emitted(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}