pilotdemo_test.gno
4.55 Kb · 144 lines
1package pilotdemo
2
3import (
4 "chain"
5 "chain/banker"
6 "testing"
7
8 "gno.land/p/nt/testutils/v0"
9 "gno.land/p/nt/uassert/v0"
10
11 account "gno.land/r/moul/pilot/v0"
12)
13
14const modPath = "gno.land/r/moul/x/pilotdemo/v0"
15
16var (
17 // r/moul/pilot pins Claim to this address, so the tests have to use it
18 owner = address("g1manfred47kzduec920z88wfr64ylksmdcedlf5")
19 dest = testutils.TestAddress("dest")
20 claimed bool
21)
22
23// claim is safe to call from every test: realm state carries over between
24// test functions, so the account is claimed exactly once per run.
25func claim(cur realm) {
26 if claimed {
27 return
28 }
29 claimed = true
30 account.Claim(cross(cur))
31}
32
33func balance(addr address) int64 {
34 return banker.NewReadonlyBanker().GetCoin(addr, "ugnot")
35}
36
37func TestPurseGrantIsRevocable(cur realm, t *testing.T) {
38 testing.SetRealm(testing.NewUserRealm(owner))
39 claim(cur)
40
41 treasury := account.Address()
42 testing.IssueCoins(treasury, chain.NewCoins(chain.NewCoin("ugnot", 10_000)))
43
44 testing.SetRealm(testing.NewUserRealm(owner))
45 account.Approve(cross(cur), modPath, "payout", false, 250)
46
47 // the module installs itself; the account reads its path from the runtime
48 Install(cross(cur), dest)
49
50 testing.SetRealm(testing.NewUserRealm(owner))
51 uassert.Equal(t, "paid 100ugnot from the main treasury, 150 left",
52 account.Exec(cross(cur), modPath, ""))
53 uassert.Equal(t, int64(100), balance(dest))
54 uassert.Equal(t, int64(9_900), balance(treasury))
55
56 // the owner revokes. the module still holds the purse object.
57 testing.SetRealm(testing.NewUserRealm(owner))
58 account.Revoke(cross(cur), modPath)
59 uassert.Equal(t, int64(0), self.purse.Left())
60
61 // both doors are shut: through the account...
62 testing.SetRealm(testing.NewUserRealm(owner))
63 uassert.AbortsContains(t, cur, "revoked", func() {
64 account.Exec(cross(cur), modPath, "")
65 })
66 // ...and through the retained purse, which is the one that matters.
67 uassert.AbortsContains(t, cur, "revoked", func() {
68 self.purse.Pay(dest, 10)
69 })
70 uassert.Equal(t, int64(100), balance(dest))
71}
72
73func TestIdentityGrantActsAsTheAccount(cur realm, t *testing.T) {
74 testing.SetRealm(testing.NewUserRealm(owner))
75 claim(cur)
76
77 testing.SetRealm(testing.NewUserRealm(owner))
78 account.Approve(cross(cur), modPath, "payout", true, 250)
79 Install(cross(cur), dest)
80
81 sub := account.SubAddress(modPath)
82 testing.IssueCoins(account.Address(), chain.NewCoins(chain.NewCoin("ugnot", 10_000)))
83
84 testing.SetRealm(testing.NewUserRealm(owner))
85 account.Fund(cross(cur), modPath, 1_000)
86 uassert.Equal(t, int64(1_000), balance(sub))
87
88 testing.SetRealm(testing.NewUserRealm(owner))
89 got := account.Exec(cross(cur), modPath, "")
90
91 // the module acted as the ACCOUNT's sub-identity, not as itself
92 uassert.Equal(t, "acted as gno.land/r/moul/pilot/v0#payout", got)
93 uassert.Equal(t, int64(900), balance(sub))
94 uassert.Equal(t, int64(100), balance(dest))
95}
96
97func TestIdentityGrantOutlivesRevoke(cur realm, t *testing.T) {
98 testing.SetRealm(testing.NewUserRealm(owner))
99 claim(cur)
100
101 testing.SetRealm(testing.NewUserRealm(owner))
102 account.Approve(cross(cur), modPath, "payout", true, 250)
103 Install(cross(cur), dest)
104
105 sub := account.SubAddress(modPath)
106 testing.IssueCoins(account.Address(), chain.NewCoins(chain.NewCoin("ugnot", 10_000)))
107 testing.SetRealm(testing.NewUserRealm(owner))
108 account.Fund(cross(cur), modPath, 1_000)
109
110 testing.SetRealm(testing.NewUserRealm(owner))
111 account.Exec(cross(cur), modPath, "") // mints and keeps a banker on the sub-address
112 uassert.Equal(t, int64(900), balance(sub))
113
114 // revoke shuts the account door
115 testing.SetRealm(testing.NewUserRealm(owner))
116 account.Revoke(cross(cur), modPath)
117 uassert.AbortsContains(t, cur, "revoked", func() {
118 account.Exec(cross(cur), modPath, "")
119 })
120
121 // and the retained banker keeps spending anyway. This is the documented
122 // cost of an identity grant: revoking is not taking it back.
123 testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("anyone")))
124 Payout(cross(cur), dest, 900)
125 uassert.Equal(t, int64(0), balance(sub))
126}
127
128func TestRender(cur realm, t *testing.T) {
129 testing.SetRealm(testing.NewUserRealm(owner))
130 claim(cur)
131
132 // a fresh approval is a fresh allowance, so this reads the same whatever
133 // ran before it
134 testing.SetRealm(testing.NewUserRealm(owner))
135 account.Approve(cross(cur), modPath, "payout", false, 1_000)
136 Install(cross(cur), dest)
137 testing.IssueCoins(account.Address(), chain.NewCoins(chain.NewCoin("ugnot", 10_000)))
138
139 testing.SetRealm(testing.NewUserRealm(owner))
140 account.Exec(cross(cur), modPath, "")
141
142 uassert.Equal(t, "# pilotdemo\n\n| | |\n|---|---|\n| destination | "+
143 dest.String()+" |\n| purse left | 900 ugnot |\n", Render(""))
144}