Files
whetstone_DSL/editor/tests/step595_test.cpp
2026-02-17 11:38:29 -07:00

150 lines
6.1 KiB
C++

// Step 595: Approval Escalation Planner (12 tests)
#include "ApprovalEscalationPlanner.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 PolicyGuardrailCatalog catalogWithRules() {
PolicyGuardrailCatalog c;
std::string error;
c.addRule({"allow-push", "git push", GuardrailDecision::Allow, "trusted push path"}, &error);
c.addRule({"review-deploy", "deploy", GuardrailDecision::RequireReview, "deployment review required"}, &error);
c.addRule({"deny-rm", "rm -rf", GuardrailDecision::Deny, "destructive operation denied"}, &error);
return c;
}
void test_allow_rule_produces_no_escalation() {
TEST(allow_rule_produces_no_escalation);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "git push origin main");
CHECK(plan.level == EscalationLevel::None, "level should be none");
CHECK(!plan.requiresJustification, "justification should be false");
CHECK(plan.approverRoles.empty(), "approvers should be empty");
PASS();
}
void test_review_rule_produces_reviewer_escalation() {
TEST(review_rule_produces_reviewer_escalation);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "deploy prod");
CHECK(plan.level == EscalationLevel::Reviewer, "level should be reviewer");
CHECK(plan.requiresJustification, "justification should be true");
CHECK(plan.approverRoles.size() == 1 && plan.approverRoles[0] == "reviewer", "reviewer role expected");
PASS();
}
void test_deny_rule_produces_admin_escalation() {
TEST(deny_rule_produces_admin_escalation);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "rm -rf /tmp/x");
CHECK(plan.level == EscalationLevel::Admin, "level should be admin");
CHECK(plan.approverRoles.size() == 2, "two admin approvers expected");
PASS();
}
void test_default_review_when_no_rule_matches() {
TEST(default_review_when_no_rule_matches);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "unknown op");
CHECK(plan.decision == GuardrailDecision::RequireReview, "default decision should be review");
CHECK(plan.reason == "default_review_required", "default reason mismatch");
PASS();
}
void test_reason_propagates_from_guardrail_decision() {
TEST(reason_propagates_from_guardrail_decision);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "deploy prod");
CHECK(plan.reason == "deployment review required", "reason should propagate");
PASS();
}
void test_operation_field_is_preserved() {
TEST(operation_field_is_preserved);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "git push origin main");
CHECK(plan.operation == "git push origin main", "operation field mismatch");
PASS();
}
void test_is_executable_true_for_allow() {
TEST(is_executable_true_for_allow);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "git push origin main");
CHECK(ApprovalEscalationPlanner::isExecutable(plan), "allow should be executable");
PASS();
}
void test_is_executable_true_for_review() {
TEST(is_executable_true_for_review);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "deploy prod");
CHECK(ApprovalEscalationPlanner::isExecutable(plan), "review should be executable");
PASS();
}
void test_is_executable_false_for_deny() {
TEST(is_executable_false_for_deny);
auto c = catalogWithRules();
auto plan = ApprovalEscalationPlanner::planFor(c, "rm -rf /tmp/x");
CHECK(!ApprovalEscalationPlanner::isExecutable(plan), "deny should not be executable");
PASS();
}
void test_risk_score_increases_by_decision_severity() {
TEST(risk_score_increases_by_decision_severity);
auto c = catalogWithRules();
auto allowPlan = ApprovalEscalationPlanner::planFor(c, "git push origin main");
auto reviewPlan = ApprovalEscalationPlanner::planFor(c, "deploy prod");
auto denyPlan = ApprovalEscalationPlanner::planFor(c, "rm -rf /tmp/x");
CHECK(ApprovalEscalationPlanner::riskScore(allowPlan) < ApprovalEscalationPlanner::riskScore(reviewPlan),
"review risk should exceed allow risk");
CHECK(ApprovalEscalationPlanner::riskScore(reviewPlan) < ApprovalEscalationPlanner::riskScore(denyPlan),
"deny risk should exceed review risk");
PASS();
}
void test_risk_score_capped_at_100() {
TEST(risk_score_capped_at_100);
EscalationPlan p;
p.decision = GuardrailDecision::Deny;
p.level = EscalationLevel::Admin;
p.requiresJustification = true;
CHECK(ApprovalEscalationPlanner::riskScore(p) <= 100, "risk score should be capped");
PASS();
}
void test_admin_plan_requires_justification() {
TEST(admin_plan_requires_justification);
auto c = catalogWithRules();
auto p = ApprovalEscalationPlanner::planFor(c, "rm -rf /tmp/x");
CHECK(p.requiresJustification, "admin plan should require justification");
PASS();
}
int main() {
std::cout << "Step 595: Approval Escalation Planner\n";
test_allow_rule_produces_no_escalation(); // 1
test_review_rule_produces_reviewer_escalation(); // 2
test_deny_rule_produces_admin_escalation(); // 3
test_default_review_when_no_rule_matches(); // 4
test_reason_propagates_from_guardrail_decision(); // 5
test_operation_field_is_preserved(); // 6
test_is_executable_true_for_allow(); // 7
test_is_executable_true_for_review(); // 8
test_is_executable_false_for_deny(); // 9
test_risk_score_increases_by_decision_severity(); // 10
test_risk_score_capped_at_100(); // 11
test_admin_plan_requires_justification(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}