Files
whetstone_DSL/editor/tests/step1880_test.cpp
Bill de5bdd358f Close all 26 generator readiness gaps (sprints 267-270)
Sprint 268: GR-002/003/006/007/008/016/017/019/021/024 — self-containment,
  graduation thresholds, asm/ir/jvm/elixir lang coverage, semanno format.
Sprint 269: GR-005/011/013/015 — prose capture in RequirementsParser,
  GateEnforcer, ParitySkewAnalyzer, CrossArtifactConsistencyEngine.
Sprint 270: GR-009/010/012/014/018/020 — CrossFileTransactionGate,
  SemanticCompletionGate, ConstrainedProjectionGate, TokenBudgetGate,
  CppConstraintRefactorPolicy, NativeDecompositionDepthGuard.
All 50 new tests passing (steps 1873-1882, 5/5 per step).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 22:28:41 -07:00

92 lines
3.3 KiB
C++

// Step 1880 TDD: GR-009 — CrossFileTransactionGate enforces multi-file atomic promotion
//
// DeploymentPromotionGate tracked single environments (files) independently.
// Long-range edits that span multiple files had no atomic gate: one file could
// be blocked while others promoted. CrossFileTransactionGate fixes this.
//
// t1: all files fully checked + approved → transaction promotable
// t2: one file has blocking issues → transaction not promotable, that file in blockedFiles
// t3: empty transaction → promotable (vacuously)
// t4: one file not fully checked → not promotable
// t5: mixed: 2 ready + 1 blocked → promotable=false, blockedFiles has exactly 1
#include "CrossFileTransactionGate.h"
#include <iostream>
#include <string>
static int p=0,f=0;
#define T(n) { std::cout<<" "<<#n<<"... "; }
#define P() { std::cout<<"PASS\n"; ++p; }
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
#define C(c,m) if(!(c)){F(m);return;}
static FileEditState ready(const std::string& id) {
return {id, 3, 3, 1, 0}; // 3/3 checks, 1 approval, 0 blocking issues
}
static FileEditState blocked(const std::string& id) {
return {id, 3, 2, 0, 1}; // 2/3 checks, no approval, 1 blocking issue
}
void t1(){
T(all_files_ready_transaction_promotable);
auto result = CrossFileTransactionGate::evaluate({
ready("src/auth.cpp"),
ready("src/session.cpp"),
ready("include/auth.h")
});
C(result.promotable, "all files ready → transaction should be promotable");
C(result.blockedFiles.empty(), "no files should be blocked");
C(result.readyFiles == 3, "expected 3 ready files");
P();
}
void t2(){
T(one_blocked_file_blocks_transaction);
auto result = CrossFileTransactionGate::evaluate({
ready("src/auth.cpp"),
blocked("src/session.cpp")
});
C(!result.promotable, "one blocked file should block the transaction");
C(result.blockedFiles.size() == 1u, "expected 1 blocked file");
C(result.blockedFiles[0] == "src/session.cpp", "expected session.cpp as blocked");
P();
}
void t3(){
T(empty_transaction_promotable);
auto result = CrossFileTransactionGate::evaluate({});
C(result.promotable, "empty transaction should be vacuously promotable");
C(result.totalFiles == 0, "expected 0 total files");
P();
}
void t4(){
T(partially_checked_file_not_promotable);
FileEditState partial{"src/db.cpp", 4, 2, 1, 0}; // 2/4 checks — not complete
auto result = CrossFileTransactionGate::evaluate({partial});
C(!result.promotable, "partially checked file should not be promotable");
C(result.blockedFiles.size() == 1u, "expected 1 blocked file");
P();
}
void t5(){
T(two_ready_one_blocked);
auto result = CrossFileTransactionGate::evaluate({
ready("a.cpp"),
ready("b.cpp"),
blocked("c.cpp")
});
C(!result.promotable, "transaction should not promote with 1 blocked file");
C(result.readyFiles == 2, "expected 2 ready files, got " + std::to_string(result.readyFiles));
C(result.blockedFiles.size() == 1u, "expected exactly 1 blocked file");
P();
}
int main(){
std::cout<<"Step 1880: GR-009 CrossFileTransactionGate multi-file atomic promotion\n";
t1();t2();t3();t4();t5();
std::cout<<"\nResults: "<<p<<"/"<<(p+f)<<" passed\n";
return f?1:0;
}