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}