#!/usr/bin/env bash # S1 — 정합성(기능성 축): 평상시 부하 후 전 계층 대사·총액 보존·이중지급 0 검증. # 복원력방안 부록A S1 재현(로컬 1센터). 실행: bash sim/s1_consistency.sh [건수] cd "$(dirname "$0")"; source ./lib.sh N=${1:-30} FAILED=0 BANKS=(1001 1002 1003 1004 1005 1006 1007 1010) hr; echo "S1 정합성 검증 — 이체 ${N}건 투입"; hr TOTAL_BEFORE=$(q "SELECT sum(balance) FROM account") ACCC_BEFORE=$(q "SELECT count(*) FROM transfer WHERE status='ACCC'") echo " 이체 전 총액 = $TOTAL_BEFORE" for ((i=1;i<=N;i++)); do fi=${BANKS[$((RANDOM % ${#BANKS[@]}))]} ti=${BANKS[$((RANDOM % ${#BANKS[@]}))]} while [ "$ti" = "$fi" ]; do ti=${BANKS[$((RANDOM % ${#BANKS[@]}))]}; done amt=$(( (RANDOM % 500) + 1 )) submit "$fi" "$ti" "$amt" "$(mkbmi "$fi" "$i")" done echo " 투입 완료. 정산 드레인 대기..." wait_drain 60 && echo " 드레인 완료" || echo " (경고) 드레인 타임아웃" TOTAL_AFTER=$(q "SELECT sum(balance) FROM account") ACCC_AFTER=$(q "SELECT count(*) FROM transfer WHERE status='ACCC'") STUCK=$(q "SELECT count(*) FROM transfer WHERE status IN ('PDNG','ACSP')") NEG=$(q "SELECT count(*) FROM account WHERE balance < 0") LEDGER=$(q "SELECT count(*) FROM transfer WHERE status='ACCC'") VIEW=$(q "SELECT count(*) FROM settlement_view WHERE final_status='ACCC'") hr; echo "결과"; hr [ "$TOTAL_AFTER" = "$TOTAL_BEFORE" ] && pass "총액 보존: $TOTAL_AFTER (변화 없음)" || fail "총액 불일치: $TOTAL_BEFORE -> $TOTAL_AFTER" [ "$STUCK" = "0" ] && pass "미완결 잔류 0" || fail "미완결(PDNG/ACSP) $STUCK 건 잔류" [ "$NEG" = "0" ] && pass "잔액 음수 계좌 0 (이중지급 없음)" || fail "음수 계좌 $NEG 건" [ "$LEDGER" = "$VIEW" ] && pass "원장=조회사본 대사 일치 (ACCC $LEDGER)" || fail "원장 $LEDGER vs 사본 $VIEW 불일치" echo " (참고) 이번 배치 ACCC 증가분 = $((ACCC_AFTER - ACCC_BEFORE))" hr [ "$FAILED" = "0" ] && echo "S1 PASS ✅" || echo "S1 FAIL ❌" exit $FAILED