Files
GL/infrastructure/postgres/settlement_repository_test.go
T
nfel d33ec51201
CI/CD Stage / stage (push) Failing after 37s
feat: dismiss reviewed settlement failures
2026-10-07 00:32:20 +03:30

85 lines
3.2 KiB
Go

package postgres
import (
"context"
"testing"
"time"
"gl/domain/ledger"
)
func TestIgnoreByOperatorRejectsActiveLockedAndTerminalSettlements(t *testing.T) {
for _, state := range []struct{ status, lock string }{
{"PENDING", ""}, {"SUBMITTED", ""}, {"CONFIRMED", ""}, {"IGNORED", ""}, {"RETRYABLE", "worker"},
} {
tx := &fakeTx{rows: []Row{fakeRow{values: []any{state.status, state.lock}}}}
repository := NewSettlementRepository(&fakeDatabase{tx: tx})
if _, err := repository.IgnoreByOperator(context.Background(), "id", "actor", "reviewed"); err == nil {
t.Fatalf("dismissed ineligible state: %+v", state)
}
if tx.execCount != 0 || tx.committed || !tx.rolledBack {
t.Fatalf("ineligible dismissal changed state: %+v", tx)
}
}
}
func TestIgnoreByOperatorAuditsAndResolvesAtomically(t *testing.T) {
tx := &fakeTx{rows: []Row{fakeRow{values: []any{"MANUAL_REVIEW", ""}}}}
repository := NewSettlementRepository(&fakeDatabase{tx: tx, directRow: fakeRow{values: []any{
"id", "wallet", "110", "wallet:110:kuknos", ledger.SettlementIgnored, "kuknos", "", 1, time.Now(), "tx_bad_seq", "signed-xdr",
}}})
got, err := repository.IgnoreByOperator(context.Background(), "id", "actor", "reviewed")
if err != nil || got.Status != ledger.SettlementIgnored || got.LastError != "tx_bad_seq" || !tx.committed || tx.execCount != 3 {
t.Fatalf("unexpected dismissal: %+v tx=%+v err=%v", got, tx, err)
}
for _, failedStep := range []int{2, 3} {
tx := &fakeTx{rows: []Row{fakeRow{values: []any{"RETRYABLE", ""}}}, execErrAt: failedStep}
repository := NewSettlementRepository(&fakeDatabase{tx: tx})
if _, err := repository.IgnoreByOperator(context.Background(), "id", "actor", "reviewed"); err == nil || tx.committed || !tx.rolledBack {
t.Fatalf("audit or issue failure did not roll back: %+v err=%v", tx, err)
}
}
}
func TestIgnoredSettlementCannotBeRetried(t *testing.T) {
tx := &fakeTx{rows: []Row{fakeRow{values: []any{ledger.SettlementIgnored}}}}
repository := NewSettlementRepository(&fakeDatabase{tx: tx})
if _, err := repository.RetryByOperator(context.Background(), "id", "actor", "retry", time.Now()); err == nil || tx.execCount != 0 {
t.Fatal("ignored settlement was queued again")
}
}
func TestReconcileConfirmationEvidenceCommitsDurableIssueStats(t *testing.T) {
tx := &fakeTx{rows: []Row{
fakeRow{values: []any{int64(1)}},
fakeRow{values: []any{int64(2)}},
}}
repository := NewSettlementRepository(&fakeDatabase{tx: tx})
stats, err := repository.ReconcileConfirmationEvidence(context.Background(), 10*time.Minute)
if err != nil {
t.Fatal(err)
}
if stats.Detected != 1 || stats.Resolved != 1 || stats.Open != 2 {
t.Fatalf("unexpected reconciliation stats: %+v", stats)
}
if !tx.committed || tx.execCount != 1 {
t.Fatalf("unexpected transaction state: %+v", tx)
}
}
func TestReconcileConfirmationEvidenceRollsBackResolutionFailure(t *testing.T) {
tx := &fakeTx{
rows: []Row{fakeRow{values: []any{int64(1)}}},
execErrAt: 1,
}
repository := NewSettlementRepository(&fakeDatabase{tx: tx})
if _, err := repository.ReconcileConfirmationEvidence(context.Background(), time.Minute); err == nil {
t.Fatal("expected resolution error")
}
if !tx.rolledBack || tx.committed {
t.Fatalf("failed reconciliation was not rolled back: %+v", tx)
}
}