forked from jokeez/hackme
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfuzz_settle_pull_test.go
More file actions
125 lines (119 loc) · 3.72 KB
/
Copy pathfuzz_settle_pull_test.go
File metadata and controls
125 lines (119 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"context"
"database/sql"
"path/filepath"
"testing"
"hackme/internal/chain"
"hackme/internal/poolsync"
"hackme/internal/store"
)
func TestFuzzSettleOutboxAction(t *testing.T) {
cases := []struct {
status string
kind string
wantApply bool
wantDrain bool
}{
{"open", "run", true, false},
{"open", "finding", true, false},
{"open", "crash_bonus", true, false},
{"closed", "run", false, false}, // must not ACK unpaid runs after premature finalize
{"closed", "finalize", false, true},
{"bounty_paid", "run", true, false},
{"bounty_paid", "finding", false, true},
{"bounty_paid", "finalize", true, false},
{"unknown", "run", false, false},
}
for _, tc := range cases {
apply, drain := fuzzSettleOutboxAction(tc.status, tc.kind)
if apply != tc.wantApply || drain != tc.wantDrain {
t.Errorf("fuzzSettleOutboxAction(%q,%q) = (%v,%v) want (%v,%v)",
tc.status, tc.kind, apply, drain, tc.wantApply, tc.wantDrain)
}
}
}
func TestFuzzSettleOutboxDrainOnErr(t *testing.T) {
if fuzzSettleOutboxDrainOnErr(chain.ErrFuzzEscrowClosed) {
t.Fatal("closed must not drain/ACK unpaid settles")
}
if !fuzzSettleOutboxDrainOnErr(chain.ErrFuzzEscrowDepleted) {
t.Fatal("depleted should drain")
}
if !fuzzSettleOutboxDrainOnErr(chain.ErrFuzzEscrowAlreadyPaid) {
t.Fatal("already paid should drain")
}
}
func TestApplyLocalFuzzSettleOnceNoDoublePay(t *testing.T) {
ctx := context.Background()
db, err := store.Open(filepath.Join(t.TempDir(), "pull.db"))
if err != nil {
t.Fatal(err)
}
defer db.Close()
svc := chain.New(db)
payer := "HMC-1111111111111111"
miner := "HMC-2222222222222222"
if _, _, err := svc.InitGenesis(ctx, payer); err != nil {
t.Fatal(err)
}
preFundMainEscrow(t, ctx, db, payer, 50)
if _, err := svc.OpenFuzzEscrow(ctx, "pull-camp", 10.0, 100); err != nil {
t.Fatal(err)
}
if _, err := db.ExecContext(ctx, `INSERT OR IGNORE INTO accounts(address, balance_units, next_nonce, updated_at) VALUES(?,0,0,0)`, miner); err != nil {
t.Fatal(err)
}
a := &app{chain: svc}
it := poolsync.SettleOutboxItem{
ID: 7, CampaignID: "pull-camp", Kind: "run", MinerAddress: miner,
}
if err := a.applyLocalFuzzSettleOnce(ctx, it); err != nil {
t.Fatal(err)
}
row, err := svc.GetFuzzEscrow(ctx, "pull-camp")
if err != nil {
t.Fatal(err)
}
paidOnce := row.RunsDone
if paidOnce != 1 {
t.Fatalf("first apply runs_done=%d want 1", paidOnce)
}
// Simulate lost ACK / re-pull of the same outbox event.
if err := a.applyLocalFuzzSettleOnce(ctx, it); err != nil {
t.Fatal(err)
}
row, err = svc.GetFuzzEscrow(ctx, "pull-camp")
if err != nil {
t.Fatal(err)
}
if row.RunsDone != 1 {
t.Fatalf("re-pull must not double-pay: runs_done=%d", row.RunsDone)
}
ok, err := svc.HasFuzzSettleApplied(ctx, chain.FuzzSettleEventID("pull-camp", 7))
if err != nil || !ok {
t.Fatalf("applied event missing: ok=%v err=%v", ok, err)
}
wantID := "outbox:pull-camp:7"
if got := chain.FuzzSettleEventID("pull-camp", 7); got != wantID {
t.Fatalf("event_id format=%q want %q", got, wantID)
}
}
func preFundMainEscrow(t *testing.T, ctx context.Context, db *sql.DB, addr string, hmc float64) {
t.Helper()
units := chain.HMCToUnits(hmc)
if _, err := db.ExecContext(ctx, `UPDATE wallet SET balance_hmc = ?, balance_units = ? WHERE id = 1`, hmc, units); err != nil {
t.Fatal(err)
}
if _, err := db.ExecContext(ctx, `UPDATE accounts SET balance_units = ? WHERE address = ?`, units, addr); err != nil {
t.Fatal(err)
}
if _, err := db.ExecContext(ctx,
`INSERT INTO meta(key, value) VALUES(?, ?)
ON CONFLICT(key) DO UPDATE SET value = CASE
WHEN CAST(value AS REAL) < CAST(excluded.value AS REAL) THEN excluded.value
ELSE value END`,
"econ_total_minted_hmc", hmc); err != nil {
t.Fatal(err)
}
}