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

nativereg_test.gno

5.34 Kb · 132 lines
  1package nativereg
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11const (
 12	issuerPath = "gno.land/r/test/coiner"
 13	issuerCoin = "/gno.land/r/test/coiner:testcoin"
 14	otherPath  = "gno.land/r/test/stranger"
 15	otherCoin  = "/gno.land/r/test/stranger:othercoin"
 16)
 17
 18// testing.SetRealm governs only the crossing calls made from the frame that
 19// called it, so each switch below is inline in the test body.
 20
 21func TestOnlyTheIssuerRegisters(cur realm, t *testing.T) {
 22	testing.SetRealm(testing.NewCodeRealm(issuerPath))
 23	Register(cross(cur), issuerCoin, "Test Coin", "TEST", 6, "a coin for a test")
 24
 25	e := MustGet(issuerCoin)
 26	uassert.Equal(t, issuerPath, e.Issuer, "the issuer is read out of the denom, not supplied")
 27	uassert.Equal(t, "TEST", e.Symbol)
 28	uassert.Equal(t, 6, e.Decimals)
 29	uassert.Equal(t, 0, e.Revisions)
 30
 31	// The same realm cannot describe somebody else's coin.
 32	uassert.AbortsContains(t, cur, "is issued by "+otherPath, func() {
 33		Register(cross(cur), otherCoin, "Not Mine", "NOPE", 0, "")
 34	})
 35}
 36
 37func TestAUserAccountCannotRegister(cur realm, t *testing.T) {
 38	alice := testutils.TestAddress("nr-alice")
 39	testing.SetRealm(testing.NewUserRealm(alice))
 40	// Even for a denom she holds every unit of: what is being described is the
 41	// issuance, and a wallet has no package path to prove.
 42	uassert.AbortsContains(t, cur, "no package path to prove", func() {
 43		Register(cross(cur), issuerCoin, "Mine Now", "MINE", 0, "")
 44	})
 45}
 46
 47func TestReregisteringBumpsRevisions(cur realm, t *testing.T) {
 48	testing.SetRealm(testing.NewCodeRealm(issuerPath))
 49	before := Count()
 50	Register(cross(cur), issuerCoin, "Test Coin v2", "TEST2", 4, "renamed")
 51
 52	e := MustGet(issuerCoin)
 53	uassert.Equal(t, "TEST2", e.Symbol, "an issuer can always re-describe its own coin")
 54	uassert.Equal(t, 1, e.Revisions)
 55	uassert.Equal(t, before, Count(), "a rewrite is not a second entry")
 56	uassert.Equal(t, 1, len(ByIssuer(issuerPath)))
 57	uassert.Equal(t, 0, len(ByIssuer(otherPath)))
 58}
 59
 60func TestBounds(cur realm, t *testing.T) {
 61	testing.SetRealm(testing.NewCodeRealm(issuerPath))
 62	uassert.AbortsContains(t, cur, "name is", func() {
 63		Register(cross(cur), issuerCoin, strings.Repeat("x", MaxName+1), "T", 0, "")
 64	})
 65	uassert.AbortsContains(t, cur, "symbol is", func() {
 66		Register(cross(cur), issuerCoin, "n", strings.Repeat("x", MaxSymbol+1), 0, "")
 67	})
 68	uassert.AbortsContains(t, cur, "doc is", func() {
 69		Register(cross(cur), issuerCoin, "n", "T", 0, strings.Repeat("x", MaxDoc+1))
 70	})
 71	uassert.AbortsContains(t, cur, "decimals is 19", func() {
 72		Register(cross(cur), issuerCoin, "n", "T", MaxDecimals+1, "")
 73	})
 74	uassert.AbortsContains(t, cur, "decimals is -1", func() {
 75		Register(cross(cur), issuerCoin, "n", "T", -1, "")
 76	})
 77}
 78
 79func TestIssuerOfReadsTheDenom(cur realm, t *testing.T) {
 80	// The relation is in the string, so this answers for a denom nobody ever
 81	// registered, which is the case that matters: given a balance you did not
 82	// ask for, this is how you find the code that can take it away.
 83	uassert.Equal(t, "gno.land/r/nobody/here/v3", IssuerOf("/gno.land/r/nobody/here/v3:ghost"))
 84	uassert.Equal(t, issuerPath, IssuerOf(issuerCoin))
 85
 86	uassert.PanicsContains(t, cur, "must start with /", func() { IssuerOf("ugnot") })
 87	uassert.PanicsContains(t, cur, "must contain :", func() { IssuerOf("/gno.land/r/a/v0") })
 88	uassert.PanicsContains(t, cur, "malformed", func() { IssuerOf("/gno.land/r/a/v0:") })
 89	uassert.PanicsContains(t, cur, "malformed", func() { IssuerOf("/:x") })
 90}
 91
 92func TestUnregisteredReadsCleanly(cur realm, t *testing.T) {
 93	_, ok := Get("/gno.land/r/nobody/here/v3:ghost")
 94	uassert.False(t, ok)
 95	uassert.False(t, IsRegistered("/gno.land/r/nobody/here/v3:ghost"))
 96	uassert.PanicsContains(t, cur, "no entry for", func() { MustGet("/gno.land/r/x/y/v0:zz") })
 97}
 98
 99func TestRender(cur realm, t *testing.T) {
100	testing.SetRealm(testing.NewCodeRealm(otherPath))
101	Register(cross(cur), otherCoin, "Other Coin", "OTHER", 0, "the second one")
102
103	index := Render("")
104	uassert.True(t, strings.Contains(index, "# nativereg"), index)
105	uassert.True(t, strings.Contains(index, "OTHER"), "the index lists entries:\n"+index)
106
107	one := Render(otherCoin)
108	uassert.True(t, strings.Contains(one, "the second one"), one)
109	uassert.True(t, strings.Contains(one, otherPath), one)
110
111	byIssuer := Render(issuerPath)
112	uassert.True(t, strings.Contains(byIssuer, "TEST2"), byIssuer)
113	uassert.False(t, strings.Contains(byIssuer, "OTHER"), "one issuer's page shows only its own")
114
115	// A Render never aborts on a path a reader typed, registered or not.
116	uassert.True(t, strings.Contains(Render("/gno.land/r/x/y/v0:nope"), "Not registered"))
117	uassert.True(t, strings.Contains(Render("ugnot"), "registered nothing"),
118		"a non-denom path falls through to the issuer view rather than aborting")
119	uassert.True(t, strings.Contains(Render("/garbage"), "not a realm denom"))
120}
121
122func TestRenderEscapesWhatAnIssuerWrote(cur realm, t *testing.T) {
123	// An issuer's own name and doc are still caller-supplied text, and a realm
124	// that can register can write a table-breaking pipe as easily as a name.
125	const nasty = "gno.land/r/test/nasty"
126	testing.SetRealm(testing.NewCodeRealm(nasty))
127	Register(cross(cur), "/gno.land/r/test/nasty:nastycoin", "a|b", "x|y", 0, "")
128
129	index := Render("")
130	uassert.False(t, strings.Contains(index, "| a|b |"), "a raw pipe would open a column:\n"+index)
131	uassert.True(t, strings.Contains(index, "a\\|b"), "it is escaped instead:\n"+index)
132}