Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}