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

across_test.gno

5.39 Kb · 139 lines
  1package across
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9
 10	"gno.land/r/moul/x/daily/erc20/v0"
 11	"gno.land/r/moul/x/daily/streak/v0"
 12	"gno.land/r/moul/x/pairs/aaa/v0"
 13	"gno.land/r/moul/x/pairs/bbb/v0"
 14)
 15
 16// seeded is the address the mutation tests build state for. Everything after
 17// TestReportReadsCrossRealmState sees whatever they left in the imported
 18// realms, which is the whole point of the demo but also makes test order load
 19// bearing: nothing below may assume a clean source realm for this address.
 20var seeded = testutils.TestAddress("across-seeded")
 21
 22// fresh is never written to by anything here, so every source answers it with
 23// its zero value. ExampleRender pins that page.
 24var fresh = testutils.TestAddress("across-fresh")
 25
 26func TestSourceCount(t *testing.T) {
 27	// The package doc and the rendered prose both say fifteen. If this fails,
 28	// one of them is now a lie.
 29	uassert.Equal(t, 15, Sources())
 30}
 31
 32// Report must never name a realm that sourceRealms does not list, or the index
 33// table silently stops covering what the report reads.
 34func TestSourcesCoverReport(t *testing.T) {
 35	known := map[string]bool{}
 36	for _, s := range sourceRealms {
 37		known[s] = true
 38	}
 39	for _, f := range Report(fresh) {
 40		uassert.True(t, known[f.source], "report names an unlisted source: "+f.source)
 41	}
 42}
 43
 44// Every source answers, and no source panics. The count is asserted rather
 45// than the values, so this stays true as the sources gain state.
 46func TestReportAnswersFromEverySource(t *testing.T) {
 47	facts := Report(fresh)
 48	uassert.Equal(t, 18, len(facts))
 49
 50	seen := map[string]bool{}
 51	for _, f := range facts {
 52		seen[f.source] = true
 53	}
 54	// amm is the one listed source that contributes to the index only.
 55	uassert.Equal(t, 14, len(seen))
 56	uassert.False(t, seen["r/moul/x/amm/v0"], "amm must not be read per address")
 57}
 58
 59// The load-bearing test: write to four realms that know nothing about this one,
 60// then read all four back through Report. Break any of the four reads and this
 61// goes red.
 62func TestReportReadsCrossRealmState(cur realm, t *testing.T) {
 63	// SetRealm governs only the crossing calls made from this frame, so the
 64	// switch has to stay inline with the calls it is meant to cover.
 65	testing.SetRealm(testing.NewUserRealm(seeded))
 66	erc20.Mint(cross(cur), seeded, 4_200)
 67	aaa.Faucet(cross(cur))
 68	bbb.Faucet(cross(cur))
 69	days := streak.CheckIn(cross(cur))
 70	uassert.Equal(t, 1, days, "first check-in is day 1")
 71
 72	got := map[string]string{}
 73	for _, f := range Report(seeded) {
 74		if f.zero {
 75			continue
 76		}
 77		got[f.source+" "+f.what] = f.value
 78	}
 79
 80	uassert.Equal(t, "4200 "+erc20.Symbol(), got["r/moul/x/daily/erc20/v0 balance"])
 81	uassert.Equal(t, "1 day(s)", got["r/moul/x/daily/streak/v0 current streak"])
 82	uassert.Equal(t, "1 day(s)", got["r/moul/x/daily/streak/v0 best streak"])
 83	uassert.True(t, got["r/moul/x/pairs/aaa/v0 balance"] != "", "aaa faucet must show up")
 84	uassert.True(t, got["r/moul/x/pairs/bbb/v0 balance"] != "", "bbb faucet must show up")
 85}
 86
 87// The rendered page for the seeded address must carry the same four facts, and
 88// must hide the reads that came back empty rather than printing a wall of zeros.
 89func TestRenderAddressShowsOnlyLiveFacts(t *testing.T) {
 90	out := Render(seeded.String())
 91
 92	uassert.True(t, strings.Contains(out, "4200 "+erc20.Symbol()), "erc20 balance on the page")
 93	uassert.True(t, strings.Contains(out, "current streak"), "streak on the page")
 94	uassert.True(t, strings.Contains(out, "r/moul/x/pairs/aaa/v0"), "aaa on the page")
 95	uassert.True(t, strings.Contains(out, "reads came back empty and are hidden"), "quiet rows hidden")
 96	uassert.False(t, strings.Contains(out, "vesting grant"), "an empty grant must not render")
 97}
 98
 99// An address-shaped path that is not an address must not reach a source realm.
100func TestRenderRejectsNonAddress(t *testing.T) {
101	out := Render("not-an-address")
102	uassert.True(t, strings.Contains(out, "is not a valid address"), "explicit refusal")
103	uassert.False(t, strings.Contains(out, "## Answers"), "no report for a bad path")
104}
105
106// The index reads a global from every source. Pinned by Contains rather than by
107// an example, because most of those globals move with chain state.
108func TestRenderIndexReadsEverySource(t *testing.T) {
109	out := Render("")
110	for _, s := range sourceRealms {
111		uassert.True(t, strings.Contains(out, s), "index must list "+s)
112	}
113	uassert.True(t, strings.Contains(out, "pool(s), index only"), "amm is flagged index-only")
114	uassert.True(t, strings.Contains(out, "roll(s) all time"), "dice global is read")
115	uassert.True(t, strings.Contains(out, "page(s) reacted to"), "reactions global is read")
116}
117
118// ExampleRender pins the report for an address no test writes to. Every value
119// in it comes from a source realm's zero state, except the rate limiter, which
120// answers a full bucket for an address it has never seen: absence and a fresh
121// allowance are the same thing there, and the report says so rather than
122// pretending the read was empty.
123func ExampleRender() {
124	print(Render(fresh.String()))
125	// Output:
126	// # across: `g1v93hymmnwvkkvun9wd597h6lta047h6l220muq`
127	//
128	// What 15 independently deployed realms say about this address. None of them was changed to answer.
129	//
130	// ## Answers
131	//
132	// | source | fact | value |
133	// | --- | --- | --- |
134	// | [`r/moul/x/daily/ratelimitdemo/v0`](/r/moul/x/daily/ratelimitdemo/v0) | rate-limit tokens left | 5 |
135	//
136	// 17 of 18 reads came back empty and are hidden.
137	//
138	// [back to the index](/r/moul/x/across/v0)
139}