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

coin_test.gno

3.75 Kb · 129 lines
  1package coin
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/seqid/v0"
  8	"gno.land/p/nt/testutils/v0"
  9	"gno.land/p/nt/uassert/v0"
 10	"gno.land/p/nt/urequire/v0"
 11)
 12
 13var fullPolicy = Policy{
 14	Mint:  "1 per distinct replier",
 15	Sink:  "burned to pin a thread",
 16	Buyer: "anyone who wants placement",
 17}
 18
 19// newTestCoin builds a Coin from a test. The same-realm cross promotes the
 20// test's EOA-origin cur into a code realm frame, which is what grc20.NewToken
 21// requires: it is the shape grc20's own tests use (vendor/.../token_test.gno).
 22func newTestCoin(t *testing.T, policy Policy, id seqid.ID, rlm realm) (c *Coin) {
 23	t.Helper()
 24	func(cur realm) {
 25		c = New("Test Points", "TEST", 0, id, policy, 0, cur)
 26	}(cross(rlm))
 27	return
 28}
 29
 30func TestPolicyValid(t *testing.T) {
 31	tests := []struct {
 32		name string
 33		p    Policy
 34		want bool
 35	}{
 36		{"complete", fullPolicy, true},
 37		{"no mint rule", Policy{Sink: "s", Buyer: "b"}, false},
 38		{"no sink", Policy{Mint: "m", Buyer: "b"}, false},
 39		{"no buyer", Policy{Mint: "m", Sink: "s"}, false},
 40		{"empty", Policy{}, false},
 41	}
 42	for _, tt := range tests {
 43		uassert.Equal(t, tt.want, tt.p.Valid(), tt.name)
 44	}
 45}
 46
 47// New's refusal is asserted with AbortsContains and not PanicsContains: the
 48// constructor runs behind a same-realm cross (the frame grc20.NewToken
 49// requires), and a panic raised across a crossing call is an abort that no
 50// recover() in the caller can catch.
 51func TestNewRefusesAnIncompletePolicy(cur realm, t *testing.T) {
 52	uassert.AbortsContains(t, cur, "mint rule, a sink and a buyer", func() {
 53		newTestCoin(t, Policy{Mint: "m", Sink: "s"}, 0, cur)
 54	})
 55}
 56
 57func TestEarnAndSpendMoveSupplyInOppositeDirections(cur realm, t *testing.T) {
 58	c := newTestCoin(t, fullPolicy, 1, cur)
 59	alice := testutils.TestAddress("alice")
 60
 61	c.Earn(alice, 10)
 62	uassert.Equal(t, int64(10), c.BalanceOf(alice))
 63	uassert.Equal(t, int64(10), c.Supply())
 64
 65	c.Spend(alice, 4)
 66	uassert.Equal(t, int64(6), c.BalanceOf(alice))
 67	uassert.Equal(t, int64(6), c.Supply())
 68
 69	// The flows stay visible after the fact, which the supply alone cannot
 70	// show: 6 in supply could be 6 earned and nothing burned.
 71	uassert.Equal(t, int64(10), c.Earned())
 72	uassert.Equal(t, int64(4), c.Spent())
 73}
 74
 75func TestEarnOfNothingIsANoOp(cur realm, t *testing.T) {
 76	c := newTestCoin(t, fullPolicy, 2, cur)
 77	alice := testutils.TestAddress("alice")
 78
 79	c.Earn(alice, 0)
 80	c.Earn(alice, -5)
 81	uassert.Equal(t, int64(0), c.Supply())
 82	uassert.Equal(t, int64(0), c.Earned())
 83	uassert.Equal(t, 0, c.Holders())
 84}
 85
 86func TestSpendNamesBothNumbersWhenShort(cur realm, t *testing.T) {
 87	c := newTestCoin(t, fullPolicy, 3, cur)
 88	alice := testutils.TestAddress("alice")
 89	c.Earn(alice, 2)
 90
 91	uassert.PanicsContains(t, cur, "balance 2 is short of 5", func() {
 92		c.Spend(alice, 5)
 93	})
 94	uassert.PanicsContains(t, cur, "must be positive", func() {
 95		c.Spend(alice, 0)
 96	})
 97	uassert.Equal(t, int64(2), c.BalanceOf(alice))
 98}
 99
100func TestRenderCarriesTheThreeDeclarations(cur realm, t *testing.T) {
101	c := newTestCoin(t, fullPolicy, 4, cur)
102	c.Earn(testutils.TestAddress("alice"), 7)
103	c.Spend(testutils.TestAddress("alice"), 3)
104
105	out := c.Render()
106	for _, want := range []string{
107		"Test Points",
108		"TEST",
109		fullPolicy.Mint,
110		fullPolicy.Sink,
111		fullPolicy.Buyer,
112	} {
113		uassert.True(t, strings.Contains(out, want), "render is missing "+want)
114	}
115	// 4 in supply, 7 earned, 3 burned, 1 holder.
116	uassert.True(t, strings.Contains(out, "| 4 | 7 | 3 | 1 |"), "render is missing the flow row: "+out)
117}
118
119func TestTokenIsAnOrdinaryGRC20(cur realm, t *testing.T) {
120	c := newTestCoin(t, fullPolicy, 5, cur)
121	alice := testutils.TestAddress("alice")
122	c.Earn(alice, 3)
123
124	tok := c.Token()
125	urequire.False(t, tok == nil, "token should not be nil")
126	uassert.Equal(t, "TEST", tok.GetSymbol())
127	uassert.Equal(t, int64(3), tok.TotalSupply())
128	uassert.Equal(t, int64(3), tok.BalanceOf(alice))
129}