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

proxy_test.gno

7.20 Kb · 220 lines
  1package config
  2
  3import (
  4	"testing"
  5
  6	"chain"
  7
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11// v2Path is a plausible next version. Nothing is deployed there; the tests
 12// only need the address the path resolves to, which is what an incoming
 13// relayed call is actually compared against.
 14const v2Path = "gno.land/r/moul/config/v2"
 15
 16func v2Addr() address { return chain.PackageAddress(v2Path) }
 17
 18func TestAllowAndRevokeProxy(cur realm, t *testing.T) {
 19	resetSettings()
 20	uassert.Equal(t, 0, len(ListProxies()))
 21	uassert.False(t, IsProxy(v2Addr()))
 22
 23	testing.SetRealm(testing.NewUserRealm(originAddr))
 24	AllowProxy(cross(cur), v2Path)
 25
 26	uassert.True(t, IsProxy(v2Addr()))
 27	uassert.Equal(t, 1, len(ListProxies()))
 28	uassert.Equal(t, v2Path, ListProxies()[0])
 29
 30	testing.SetRealm(testing.NewUserRealm(originAddr))
 31	RevokeProxy(cross(cur), v2Path)
 32	uassert.False(t, IsProxy(v2Addr()))
 33	uassert.Equal(t, 0, len(ListProxies()))
 34}
 35
 36func TestProxyRegistrationIsManagerOnly(cur realm, t *testing.T) {
 37	resetSettings()
 38
 39	testing.SetRealm(testing.NewUserRealm(nonManagerAddr))
 40	uassert.AbortsContains(t, cur, "unauthorized", func() {
 41		AllowProxy(cross(cur), v2Path)
 42	})
 43	uassert.False(t, IsProxy(v2Addr()), "a rejected registration leaves nothing behind")
 44}
 45
 46// TestProxyPathMustBeASiblingVersion keeps a fat-fingered AllowProxy from
 47// becoming a standing write grant to an unrelated realm.
 48func TestProxyPathMustBeASiblingVersion(cur realm, t *testing.T) {
 49	resetSettings()
 50
 51	bad := []string{
 52		"gno.land/r/someone/evil",
 53		"gno.land/r/moul/home",
 54		"gno.land/r/moul/configuration/v2", // prefix-adjacent, not a sibling
 55		"gno.land/r/moul/config/v",         // no number
 56		"gno.land/r/moul/config/vnext",
 57		"gno.land/r/moul/config/v2/sub",
 58		"",
 59	}
 60	for _, path := range bad {
 61		testing.SetRealm(testing.NewUserRealm(originAddr))
 62		uassert.AbortsContains(t, cur, "must be a later version", func() {
 63			AllowProxy(cross(cur), path)
 64		})
 65	}
 66	uassert.Equal(t, 0, len(ListProxies()))
 67}
 68
 69func TestRevokeUnknownProxyAborts(cur realm, t *testing.T) {
 70	resetSettings()
 71	testing.SetRealm(testing.NewUserRealm(originAddr))
 72	uassert.AbortsWithMessage(t, cur, "no such proxy: "+v2Path, func() {
 73		RevokeProxy(cross(cur), v2Path)
 74	})
 75}
 76
 77// TestRelayNeedsRegistration is the first of the relay's two checks: without
 78// it, any realm could claim to be acting for any principal.
 79func TestRelayNeedsRegistration(cur realm, t *testing.T) {
 80	resetSettings()
 81
 82	testing.SetRealm(testing.NewCodeRealm(v2Path))
 83	uassert.AbortsContains(t, cur, "not a registered proxy", func() {
 84		SetAs(cross(cur), originAddr, "some.key", "value")
 85	})
 86	uassert.Equal(t, 0, Size())
 87}
 88
 89// TestRelayStillChecksThePrincipal is the second check, and the reason a proxy
 90// is not simply an unconditional bypass: the member list stays the single
 91// answer to "who may change config", for every version at once.
 92func TestRelayStillChecksThePrincipal(cur realm, t *testing.T) {
 93	resetSettings()
 94	testing.SetRealm(testing.NewUserRealm(originAddr))
 95	AllowProxy(cross(cur), v2Path)
 96
 97	testing.SetRealm(testing.NewCodeRealm(v2Path))
 98	uassert.AbortsContains(t, cur, "unauthorized", func() {
 99		SetAs(cross(cur), nonManagerAddr, "some.key", "value")
100	})
101	uassert.Equal(t, 0, Size())
102
103	// An empty principal is not a wildcard.
104	testing.SetRealm(testing.NewCodeRealm(v2Path))
105	uassert.AbortsContains(t, cur, "no principal", func() {
106		SetAs(cross(cur), "", "some.key", "value")
107	})
108}
109
110// TestRelayWritesTheSameState is the property the whole version chain exists
111// for: a write arriving through a later version lands in exactly the store
112// that a direct write lands in, so v1 and v2 readers never disagree.
113func TestRelayWritesTheSameState(cur realm, t *testing.T) {
114	resetSettings()
115	testing.SetRealm(testing.NewUserRealm(originAddr))
116	AllowProxy(cross(cur), v2Path)
117
118	testing.SetRealm(testing.NewCodeRealm(v2Path))
119	SetAs(cross(cur), originAddr, KeyMygnoscanURL, "https://scan.example.com")
120
121	uassert.Equal(t, "https://scan.example.com", Get(KeyMygnoscanURL))
122	uassert.Equal(t, "https://scan.example.com", MygnoscanURL(),
123		"the typed accessor sees the relayed write too")
124
125	testing.SetRealm(testing.NewCodeRealm(v2Path))
126	UnsetAs(cross(cur), originAddr, KeyMygnoscanURL)
127	uassert.False(t, Has(KeyMygnoscanURL))
128}
129
130// TestRelayValidatesLikeTheDirectPath: a relay is a different door, not a
131// different set of rules. Key shape and value grammar are checked identically.
132func TestRelayValidatesLikeTheDirectPath(cur realm, t *testing.T) {
133	resetSettings()
134	testing.SetRealm(testing.NewUserRealm(originAddr))
135	AllowProxy(cross(cur), v2Path)
136
137	testing.SetRealm(testing.NewCodeRealm(v2Path))
138	uassert.AbortsContains(t, cur, "invalid key", func() {
139		SetAs(cross(cur), originAddr, "Bad Key", "value")
140	})
141
142	testing.SetRealm(testing.NewCodeRealm(v2Path))
143	uassert.AbortsContains(t, cur, "invalid pause value", func() {
144		SetAs(cross(cur), originAddr, KeyPause, "yes")
145	})
146}
147
148// TestRevokedProxyCannotWrite: revocation is the emergency brake on the relay
149// itself, so it has to bite immediately.
150func TestRevokedProxyCannotWrite(cur realm, t *testing.T) {
151	resetSettings()
152	testing.SetRealm(testing.NewUserRealm(originAddr))
153	AllowProxy(cross(cur), v2Path)
154
155	testing.SetRealm(testing.NewCodeRealm(v2Path))
156	SetAs(cross(cur), originAddr, "some.key", "before")
157
158	testing.SetRealm(testing.NewUserRealm(originAddr))
159	RevokeProxy(cross(cur), v2Path)
160
161	testing.SetRealm(testing.NewCodeRealm(v2Path))
162	uassert.AbortsContains(t, cur, "not a registered proxy", func() {
163		SetAs(cross(cur), originAddr, "some.key", "after")
164	})
165	uassert.Equal(t, "before", Get("some.key"))
166}
167
168// TestManagerChangesReachTheRelay is what makes one member list serve every
169// version: adding a manager here works through v2 with no further deploys.
170func TestManagerChangesReachTheRelay(cur realm, t *testing.T) {
171	resetSettings()
172	testing.SetRealm(testing.NewUserRealm(originAddr))
173	AllowProxy(cross(cur), v2Path)
174
175	testing.SetRealm(testing.NewCodeRealm(v2Path))
176	uassert.AbortsContains(t, cur, "unauthorized", func() {
177		SetAs(cross(cur), manager1Addr, "some.key", "value")
178	})
179
180	testing.SetRealm(testing.NewUserRealm(originAddr))
181	uassert.NoError(t, AddManager(cross(cur), manager1Addr))
182
183	testing.SetRealm(testing.NewCodeRealm(v2Path))
184	SetAs(cross(cur), manager1Addr, "some.key", "value")
185	uassert.Equal(t, "value", Get("some.key"))
186}
187
188// ExampleRender_proxies pins the section that only exists once a later version
189// is registered, which is the state this realm spends most of its life NOT in.
190func ExampleRender_proxies() {
191	resetSettings()
192	proxies.Set(v2Path, chain.PackageAddress(v2Path))
193	print(Render(""))
194	// Output:
195	// # gno.land/r/moul/config
196	//
197	// moul's settings, read by his other realms. rev 0 · 0 setting(s)
198	//
199	// ## Settings
200	//
201	// _none set; every reader is on its built-in default_
202	//
203	// ## Pause
204	//
205	// _running; no global pause_
206	//
207	// ## Authority
208	//
209	// `member_authority[g1daexjemfde047h6lta047h6lta047h6ld2pug6]`
210	//
211	// ## Proxies
212	//
213	// Later versions of this realm that may relay a write:
214	//
215	// - `gno.land/r/moul/config/v2`
216	//
217	// ---
218	//
219	// [explorer](https://mygnoscan.moul.p2p.team/realm/r/moul/config/v1) · [source](https://mygnoscan.moul.p2p.team/realm/r/moul/config/v1?tab=source) · [calls](https://mygnoscan.moul.p2p.team/realm/r/moul/config/v1?tab=calls) · [deps](https://mygnoscan.moul.p2p.team/realm/r/moul/config/v1?tab=deps)
220}