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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

nightsky_test.gno

6.90 Kb · 205 lines
  1package nightsky
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/avl/v0"
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9	"gno.land/p/nt/urequire/v0"
 10	nightsky "gno.land/p/nym-vikbez000/nightsky/v1"
 11)
 12
 13const scopeA = "gno.land/r/test/scopea"
 14
 15func reset() {
 16	telescopes = avl.NewTree()
 17	recentCaptures = nightsky.NewCaptureFeed(maxRecentCaptures)
 18}
 19
 20func cfg(name, owner string) nightsky.TelescopeConfig {
 21	return nightsky.NewTelescopeConfig(name, "Seestar S50", 1, 2, owner, "")
 22}
 23
 24// registerAs simulates a telescope code realm at pkgPath crossing into the
 25// registry to register itself.
 26func registerAs(cur realm, pkgPath string, c nightsky.TelescopeConfig) {
 27	testing.SetRealm(testing.NewCodeRealm(pkgPath))
 28	Register(cross(cur), c)
 29}
 30
 31func TestRegisterAndDedup(cur realm, t *testing.T) {
 32	reset()
 33
 34	registerAs(cur, scopeA, cfg("Scope A", "g1owner"))
 35	urequire.Equal(t, 1, GetTelescopeCount())
 36
 37	// RealmPath is stamped from the caller's pkgPath, not the (empty) input.
 38	urequire.True(t, telescopes.Has(scopeA))
 39	stored := telescopes.Get(scopeA)
 40	uassert.Equal(t, scopeA, stored.(nightsky.TelescopeConfig).RealmPath)
 41
 42	// Duplicate registration from the same realm is ignored.
 43	registerAs(cur, scopeA, cfg("Scope A", "g1owner"))
 44	uassert.Equal(t, 1, GetTelescopeCount())
 45
 46	// A second telescope from a different realm is added.
 47	registerAs(cur, "gno.land/r/test/scopeb", cfg("Scope B", "g1owner2"))
 48	uassert.Equal(t, 2, GetTelescopeCount())
 49}
 50
 51func TestRegisterRejectsUserCall(cur realm, t *testing.T) {
 52	reset()
 53
 54	// A direct user transaction (no intermediary realm) must be rejected.
 55	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("eoa")))
 56	uassert.AbortsContains(t, cur, "realm code", func() {
 57		Register(cross(cur), cfg("Bad", "g1owner"))
 58	})
 59	uassert.Equal(t, 0, GetTelescopeCount())
 60}
 61
 62func TestOnlineCountAndStatus(cur realm, t *testing.T) {
 63	reset()
 64
 65	c := cfg("Scope A", "g1owner")
 66	c.UpdateStatus("online")
 67	registerAs(cur, scopeA, c)
 68	uassert.Equal(t, 1, GetOnlineTelescopeCount())
 69
 70	// The telescope realm updates its status to offline.
 71	testing.SetRealm(testing.NewCodeRealm(scopeA))
 72	UpdateTelescopeStatus(cross(cur), "offline")
 73	uassert.Equal(t, 0, GetOnlineTelescopeCount())
 74	uassert.Equal(t, 1, GetTelescopeCount())
 75}
 76
 77func TestSubmitCaptureFeed(cur realm, t *testing.T) {
 78	reset()
 79	registerAs(cur, scopeA, cfg("Scope A", "g1owner"))
 80
 81	testing.SetRealm(testing.NewCodeRealm(scopeA))
 82	SubmitCapture(cross(cur), "https://img/1.png", 5, 10, 30, "g1owner")
 83	SubmitCapture(cross(cur), "https://img/2.png", 6, 11, 40, "g1owner")
 84
 85	latest, ok := recentCaptures.Latest()
 86	urequire.True(t, ok)
 87	uassert.Equal(t, "https://img/2.png", latest.ImageURL)
 88	uassert.Equal(t, 2, recentCaptures.Len())
 89}
 90
 91func TestAdminRemoveAndAuth(cur realm, t *testing.T) {
 92	reset()
 93	registerAs(cur, scopeA, cfg("Scope A", "g1owner"))
 94	urequire.Equal(t, 1, GetTelescopeCount())
 95
 96	// Non-admin cannot remove.
 97	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("intruder")))
 98	uassert.AbortsContains(t, cur, "not owner", func() {
 99		RemoveTelescope(cross(cur), scopeA)
100	})
101	uassert.Equal(t, 1, GetTelescopeCount())
102
103	// Admin can remove.
104	testing.SetRealm(testing.NewUserRealm(OwnableMain.Owner()))
105	RemoveTelescope(cross(cur), scopeA)
106	uassert.Equal(t, 0, GetTelescopeCount())
107
108	// Removing a missing telescope aborts.
109	uassert.AbortsContains(t, cur, "not found", func() {
110		RemoveTelescope(cross(cur), scopeA)
111	})
112}
113
114// --- Adversarial ("steal a telescope") tests -------------------------------
115// An attacker realm or EOA tries to hijack, impersonate, or wipe telescopes
116// that are not theirs.
117
118const (
119	victimPath   = "gno.land/r/victim/scope"
120	attackerPath = "gno.land/r/attacker/evil"
121)
122
123// TestAttackerRealmCannotTouchVictim: registry mutations are keyed by the
124// caller's own pkgPath (cur.Previous().PkgPath()). An unregistered attacker
125// realm therefore cannot update, capture-to, or unregister a victim's entry —
126// it only ever addresses its own (nonexistent) registration.
127func TestAttackerRealmCannotTouchVictim(cur realm, t *testing.T) {
128	reset()
129	registerAs(cur, victimPath, cfg("Victim Scope", "g1victim"))
130	urequire.Equal(t, 1, GetTelescopeCount())
131
132	testing.SetRealm(testing.NewCodeRealm(attackerPath))
133	uassert.AbortsContains(t, cur, "not registered", func() {
134		UpdateTelescopeStatus(cross(cur), "error")
135	})
136	uassert.AbortsContains(t, cur, "not registered", func() {
137		SubmitCapture(cross(cur), "https://evil/forged.png", 1, 1, 10, "g1victim")
138	})
139	uassert.AbortsContains(t, cur, "not registered", func() {
140		UnregisterTelescope(cross(cur))
141	})
142
143	// Victim's entry is untouched.
144	urequire.True(t, telescopes.Has(victimPath))
145	stored := telescopes.Get(victimPath)
146	uassert.Equal(t, "Victim Scope", stored.(nightsky.TelescopeConfig).Name)
147	uassert.Equal(t, 1, GetTelescopeCount())
148}
149
150// TestAttackerCannotUnregisterVictim: even when the attacker is itself
151// registered, UnregisterTelescope removes only the caller's own entry — it
152// cannot take down a neighbour.
153func TestAttackerCannotUnregisterVictim(cur realm, t *testing.T) {
154	reset()
155	registerAs(cur, victimPath, cfg("Victim Scope", "g1victim"))
156	registerAs(cur, attackerPath, cfg("Evil Scope", "g1attacker"))
157	urequire.Equal(t, 2, GetTelescopeCount())
158
159	testing.SetRealm(testing.NewCodeRealm(attackerPath))
160	UnregisterTelescope(cross(cur)) // removes the attacker, nothing else
161
162	uassert.False(t, telescopes.Has(attackerPath))
163	uassert.True(t, telescopes.Has(victimPath)) // victim survives
164	uassert.Equal(t, 1, GetTelescopeCount())
165}
166
167// TestAttackerCaptureCannotImpersonateVictim: the network feed stamps each
168// capture's TelescopeID from the caller's own registration, so an attacker
169// cannot make a forged image appear to come from the victim's telescope —
170// regardless of the capturedBy value they pass.
171func TestAttackerCaptureCannotImpersonateVictim(cur realm, t *testing.T) {
172	reset()
173	registerAs(cur, victimPath, cfg("Victim Scope", "g1victim"))
174	registerAs(cur, attackerPath, cfg("Evil Scope", "g1attacker"))
175
176	testing.SetRealm(testing.NewCodeRealm(attackerPath))
177	SubmitCapture(cross(cur), "https://evil/forged.png", 1, 1, 10, "g1victim")
178
179	latest, ok := recentCaptures.Latest()
180	urequire.True(t, ok)
181	uassert.Equal(t, "Evil Scope", latest.TelescopeID) // not "Victim Scope"
182}
183
184// TestNonAdminCannotUseAdminPowers: the network-admin functions reject anyone
185// who is not the ownable owner, so an intruder cannot wipe the registry or the
186// capture feed.
187func TestNonAdminCannotUseAdminPowers(cur realm, t *testing.T) {
188	reset()
189	registerAs(cur, victimPath, cfg("Victim Scope", "g1victim"))
190	urequire.Equal(t, 1, GetTelescopeCount())
191
192	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("intruder")))
193	uassert.AbortsContains(t, cur, "not owner", func() {
194		RemoveTelescope(cross(cur), victimPath)
195	})
196	uassert.AbortsContains(t, cur, "not owner", func() {
197		ClearAllTelescopes(cross(cur))
198	})
199	uassert.AbortsContains(t, cur, "not owner", func() {
200		RemoveCapture(cross(cur), 0)
201	})
202
203	// Nothing was removed.
204	uassert.Equal(t, 1, GetTelescopeCount())
205}