Search Apps Documentation Source Content File Folder Download Copy Actions Download

telescope_test.gno

5.37 Kb · 154 lines
  1package telescope
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/testutils/v0"
  7	"gno.land/p/nt/uassert/v0"
  8)
  9
 10// ownerAddr must match the owner configured in telescope.gno's init().
 11var ownerAddr = address("g13kytw9mpyutwmyg5eq7arqxqcszfl6uq4p89zg")
 12
 13func TestSubmitCommandValid(cur realm, t *testing.T) {
 14	telescope.CommandQueue = nil
 15
 16	testing.SetRealm(testing.NewUserRealm(ownerAddr))
 17	SubmitCommand(cross(cur), "capture", "5.5", "22.5", "60")
 18
 19	uassert.Equal(t, 1, GetCommandCount())
 20	uassert.Equal(t, "busy", GetStatus())
 21}
 22
 23func TestSubmitCommandRejectsMalformedNumber(cur realm, t *testing.T) {
 24	testing.SetRealm(testing.NewUserRealm(ownerAddr))
 25
 26	// A non-numeric RA must be rejected, not silently coerced to 0.
 27	uassert.AbortsContains(t, cur, "invalid RA", func() {
 28		SubmitCommand(cross(cur), "capture", "notanumber", "22.5", "60")
 29	})
 30}
 31
 32func TestSubmitCommandAccessDenied(cur realm, t *testing.T) {
 33	// A stranger with no grant cannot submit.
 34	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("stranger")))
 35	uassert.AbortsContains(t, cur, "access denied", func() {
 36		SubmitCommand(cross(cur), "capture", "5.5", "22.5", "60")
 37	})
 38}
 39
 40func TestGrantThenSubmit(cur realm, t *testing.T) {
 41	telescope.CommandQueue = nil
 42	friend := testutils.TestAddress("friend")
 43
 44	// Owner grants access to the friend.
 45	testing.SetRealm(testing.NewUserRealm(ownerAddr))
 46	GrantAccess(cross(cur), friend.String(), 0)
 47	uassert.Equal(t, 1, GetAccessRuleCount())
 48
 49	// Friend can now submit a stop command.
 50	testing.SetRealm(testing.NewUserRealm(friend))
 51	SubmitCommand(cross(cur), "stop", "", "", "")
 52	uassert.Equal(t, 1, GetCommandCount())
 53
 54	// Owner revokes; friend is denied again.
 55	testing.SetRealm(testing.NewUserRealm(ownerAddr))
 56	RevokeAccess(cross(cur), friend.String())
 57	uassert.Equal(t, 0, GetAccessRuleCount())
 58
 59	testing.SetRealm(testing.NewUserRealm(friend))
 60	uassert.AbortsContains(t, cur, "access denied", func() {
 61		SubmitCommand(cross(cur), "stop", "", "", "")
 62	})
 63}
 64
 65// --- Adversarial ("steal a telescope") tests -------------------------------
 66// An attacker tries to take over or misuse a telescope they do not own. Every
 67// privileged path must reject them, and ownership must be unchanged afterwards.
 68
 69// TestStrangerCannotControlTelescope: an EOA with no relationship to the
 70// telescope cannot use or control it through any entrypoint.
 71func TestStrangerCannotControlTelescope(cur realm, t *testing.T) {
 72	intruder := testutils.TestAddress("intruder")
 73	testing.SetRealm(testing.NewUserRealm(intruder))
 74
 75	// Use is denied (no access grant).
 76	uassert.AbortsContains(t, cur, "access denied", func() {
 77		SubmitCommand(cross(cur), "capture", "5", "5", "30")
 78	})
 79
 80	// Every owner-only entrypoint is denied.
 81	uassert.AbortsContains(t, cur, "owner only", func() {
 82		GrantAccess(cross(cur), intruder.String(), 0) // grant self
 83	})
 84	uassert.AbortsContains(t, cur, "owner only", func() {
 85		RevokeAccess(cross(cur), ownerAddr.String()) // revoke the real owner
 86	})
 87	uassert.AbortsContains(t, cur, "owner only", func() {
 88		GetNextCommand(cross(cur)) // drain the queue
 89	})
 90	uassert.AbortsContains(t, cur, "owner only", func() {
 91		ClearCommandQueue(cross(cur))
 92	})
 93	uassert.AbortsContains(t, cur, "owner only", func() {
 94		UpdateStatus(cross(cur), "offline")
 95	})
 96	uassert.AbortsContains(t, cur, "owner only", func() {
 97		RecordCapture(cross(cur), "https://evil/forged.png", 1, 1, 10, intruder.String())
 98	})
 99
100	// The telescope still belongs to its owner.
101	uassert.Equal(t, ownerAddr.String(), GetOwner())
102}
103
104// TestAccessIsNotOwnership: a user who has been granted *access* can use the
105// telescope, but cannot escalate to control it. This is the core "steal"
106// scenario — proving a granted friend can't quietly take over.
107func TestAccessIsNotOwnership(cur realm, t *testing.T) {
108	friend := testutils.TestAddress("friend")
109	accomplice := testutils.TestAddress("accomplice")
110
111	// Owner grants the friend use-access.
112	testing.SetRealm(testing.NewUserRealm(ownerAddr))
113	GrantAccess(cross(cur), friend.String(), 0)
114
115	// The friend can submit commands (legitimate use)...
116	telescope.CommandQueue = nil
117	testing.SetRealm(testing.NewUserRealm(friend))
118	SubmitCommand(cross(cur), "stop", "", "", "")
119	uassert.Equal(t, 1, GetCommandCount())
120
121	// ...but cannot perform any owner-only action to take control.
122	uassert.AbortsContains(t, cur, "owner only", func() {
123		GrantAccess(cross(cur), accomplice.String(), 0) // invite an accomplice
124	})
125	uassert.AbortsContains(t, cur, "owner only", func() {
126		RevokeAccess(cross(cur), ownerAddr.String()) // lock out the owner
127	})
128	uassert.AbortsContains(t, cur, "owner only", func() {
129		GetNextCommand(cross(cur)) // read/consume the queue
130	})
131	uassert.AbortsContains(t, cur, "owner only", func() {
132		ClearCommandQueue(cross(cur))
133	})
134	uassert.AbortsContains(t, cur, "owner only", func() {
135		UpdateStatus(cross(cur), "error")
136	})
137	uassert.AbortsContains(t, cur, "owner only", func() {
138		RecordCapture(cross(cur), "https://evil/forged.png", 1, 1, 10, friend.String())
139	})
140
141	// The accomplice was never granted access, so they remain locked out.
142	testing.SetRealm(testing.NewUserRealm(accomplice))
143	uassert.AbortsContains(t, cur, "access denied", func() {
144		SubmitCommand(cross(cur), "stop", "", "", "")
145	})
146
147	// Cleanup: owner revokes the grant and clears the queue.
148	testing.SetRealm(testing.NewUserRealm(ownerAddr))
149	RevokeAccess(cross(cur), friend.String())
150	telescope.CommandQueue = nil
151
152	// Ownership unchanged throughout.
153	uassert.Equal(t, ownerAddr.String(), GetOwner())
154}