registration_test.gno
4.16 Kb · 146 lines
1package gns
2
3import (
4 "chain"
5 "testing"
6)
7
8func TestCommitRevealFlow(cur realm, t *testing.T) {
9 reset()
10
11 secret := "hunter2"
12 dur := int64(1000)
13 commit, err := MakeCommitment("alice", alice, dur, secret, "", config.PolicyRevision)
14 noErr(t, err, "make commitment")
15
16 testing.SetRealm(testing.NewUserRealm(alice))
17 Commit(cross(cur), commit)
18
19 // commitment visible, not yet ready
20 cs := CommitmentStatus(commit)
21 isTrue(t, cs.Exists, "commitment exists")
22 eqStr(t, alice.String(), cs.Committer, "committer")
23
24 testing.SkipHeights(3) // pass MinCommitAge
25
26 testing.SetRealm(testing.NewUserRealm(alice))
27 res := Register(cross(cur), RegisterRequest{
28 Name: "alice",
29 Owner: alice,
30 Duration: dur,
31 Secret: secret,
32 PolicyRevision: config.PolicyRevision,
33 })
34 eqStr(t, "alice", res.Canonical, "result canonical")
35 eqInt(t, 1, int64(res.Generation), "generation")
36
37 // commitment consumed exactly once (invariant 7)
38 isFalse(t, CommitmentStatus(commit).Exists, "commitment consumed")
39 // second reveal with same commitment can't find it
40 _, ok := getCommitment(commit)
41 isFalse(t, ok, "commitment removed")
42}
43
44func TestPricingDeterministic(t *testing.T) {
45 reset()
46 config.BasePricePerSecond = 10
47
48 // 5+ char label -> multiplier 1
49 p, err := priceFor("alice", 100)
50 noErr(t, err, "price alice")
51 eqInt(t, 1000, p, "price 5-char")
52
53 // 1 char -> multiplier 100
54 p, err = priceFor("a", 100)
55 noErr(t, err, "price a")
56 eqInt(t, 100000, p, "price 1-char")
57
58 // 3 char -> multiplier 5
59 p, err = priceFor("abc", 100)
60 noErr(t, err, "price abc")
61 eqInt(t, 5000, p, "price 3-char")
62
63 // invariant 10: overflow-safe
64 _, err = priceFor("a", 1<<62)
65 isErr(t, err, "overflow rejected")
66
67 // zero/negative duration
68 _, err = priceFor("alice", 0)
69 errIs(t, err, errDurationTooShort, "zero duration")
70}
71
72func TestGenerationRecycle(cur realm, t *testing.T) {
73 reset()
74 doRegister(cur, "alice", alice, 1000)
75
76 // put a record, then let it expire
77 testing.SetRealm(testing.NewUserRealm(alice))
78 SetText(cross(cur), "alice", "url", "https://old.example")
79
80 testing.SkipHeights(500) // beyond grace
81
82 // re-register by a different owner
83 doRegister(cur, "alice", bob, 1000)
84
85 view, ok := GetName("alice")
86 isTrue(t, ok, "exists after recycle")
87 eqInt(t, 2, int64(view.Generation), "generation incremented (invariant 20)")
88 eqStr(t, bob.String(), view.Owner, "new owner")
89
90 // invariant 19: old records do not leak
91 _, ok = Text("alice", "url")
92 isFalse(t, ok, "old record cleared on recycle")
93}
94
95func TestReservedNames(cur realm, t *testing.T) {
96 reset()
97
98 testing.SetRealm(testing.NewUserRealm(admin))
99 ReserveName(cross(cur), "gno", true)
100
101 // invariant 17: reserved names cannot be publicly registered
102 isFalse(t, available("gno"), "reserved not available")
103 eqStr(t, string(StatusReserved), string(Status("gno")), "status reserved")
104
105 // unreserve
106 testing.SetRealm(testing.NewUserRealm(admin))
107 ReserveName(cross(cur), "gno", false)
108 isTrue(t, available("gno"), "available after unreserve")
109}
110
111func TestRegisterWithPayment(cur realm, t *testing.T) {
112 reset()
113 config.BasePricePerSecond = 1
114 config.Treasury = cur.Address() // realm keeps funds; no banker forward needed
115
116 dur := int64(1000) // price = 1000 * 1 * 1 (5+ chars)
117 secret := "s"
118 commit, _ := MakeCommitment("alice", alice, dur, secret, "", config.PolicyRevision)
119
120 testing.SetRealm(testing.NewUserRealm(alice))
121 Commit(cross(cur), commit)
122 testing.SkipHeights(3)
123
124 testing.IssueCoins(cur.Address(), chain.Coins{{Denom: "ugnot", Amount: 1000}})
125 testing.SetOriginSend(chain.Coins{{Denom: "ugnot", Amount: 1000}})
126 testing.SetRealm(testing.NewUserRealm(alice))
127 res := Register(cross(cur), RegisterRequest{
128 Name: "alice",
129 Owner: alice,
130 Duration: dur,
131 Secret: secret,
132 PolicyRevision: config.PolicyRevision,
133 })
134 eqInt(t, 1000, res.Paid, "paid exact price")
135 eqInt(t, 0, res.Refunded, "no refund")
136}
137
138func TestPriceQuote(t *testing.T) {
139 reset()
140 config.BasePricePerSecond = 2
141 q, err := Price("bob", 500) // 3-char -> mult 5; 500*2*5 = 5000
142 noErr(t, err, "quote")
143 eqInt(t, 5000, q.Amount, "quote amount")
144 eqStr(t, "ugnot", q.Denom, "quote denom")
145 eqInt(t, int64(config.PolicyRevision), int64(q.Revision), "quote revision")
146}