Search Apps Documentation Source Content File Folder Download Copy Actions Download

verifier_test.gno

7.72 Kb · 213 lines
  1package names
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/testutils/v0"
  7	"gno.land/p/nt/uassert/v0"
  8	"gno.land/p/nt/urequire/v0"
  9)
 10
 11// cur is a zero-value realm used as a placeholder when forwarding to
 12// uassert/urequire dispatch helpers that gained an `rlm realm` param.
 13// These tests pass `func()` callbacks (no crossing inside the callback),
 14// so rlm is ignored — a nil realm here is safe.
 15var cur realm
 16var (
 17	alice = testutils.TestAddress("alice")
 18	bob   = testutils.TestAddress("bob")
 19)
 20
 21func TestDefaultVerifier(t *testing.T) {
 22	// Disabled: any case is true (regardless of paused or lookup).
 23	uassert.True(t, verifier(false, false, alice, alice.String(), nil))
 24	uassert.True(t, verifier(false, false, "", alice.String(), nil))
 25	uassert.True(t, verifier(false, false, alice, "somerandomusername", nil))
 26
 27	// Pre-Enable bypass takes priority over paused — even when paused=true,
 28	// !isEnabled returns true. This is the documented "stage pause before
 29	// Enable" behavior.
 30	uassert.True(t, verifier(false, true, alice, alice.String(), nil))
 31	uassert.True(t, verifier(false, true, alice, "anything", nil))
 32
 33	// Enabled: PA namespace check.
 34	uassert.True(t, verifier(true, false, alice, alice.String(), nil))
 35
 36	// Enabled: non-PA namespaces denied when no registered-name lookup.
 37	uassert.False(t, verifier(true, false, alice, "notregistered", nil))
 38	uassert.False(t, verifier(true, false, alice, "alice", nil))
 39
 40	// Enabled: empty name/address.
 41	uassert.False(t, verifier(true, false, address(""), "", nil))
 42	uassert.False(t, verifier(true, false, alice, "", nil))
 43	uassert.False(t, verifier(true, false, address(""), "something", nil))
 44}
 45
 46// TestRegisteredNameVerifier exercises the second authorization path —
 47// the registered-name lookup. Uses a fake lookup so this test doesn't
 48// depend on r/sys/users state.
 49func TestRegisteredNameVerifier(t *testing.T) {
 50	// Lookup that says "gnobody" is registered to alice.
 51	aliceOwnsGnobody := func(name string) (address, bool) {
 52		if name == "gnobody" {
 53			return alice, true
 54		}
 55		return "", false
 56	}
 57
 58	// alice can deploy under "gnobody" (her registered name).
 59	uassert.True(t, verifier(true, false, alice, "gnobody", aliceOwnsGnobody))
 60
 61	// bob cannot deploy under "gnobody" (registered to alice, not bob).
 62	uassert.False(t, verifier(true, false, bob, "gnobody", aliceOwnsGnobody))
 63
 64	// Unknown name still rejects (lookup returns ok=false).
 65	uassert.False(t, verifier(true, false, alice, "notregistered", aliceOwnsGnobody))
 66
 67	// PA path still works alongside registered-name lookup. Tried first.
 68	uassert.True(t, verifier(true, false, alice, alice.String(), aliceOwnsGnobody))
 69
 70	// Disabled bypasses both paths entirely (returns true regardless).
 71	uassert.True(t, verifier(false, false, bob, "gnobody", aliceOwnsGnobody))
 72
 73	// Empty namespace + non-nil lookup: still rejects (early-out before lookup).
 74	uassert.False(t, verifier(true, false, alice, "", aliceOwnsGnobody))
 75
 76	// Lookup returns ok=true for current-but-mismatched address.
 77	bobOwnsGnobody := func(name string) (address, bool) {
 78		if name == "gnobody" {
 79			return bob, true
 80		}
 81		return "", false
 82	}
 83	uassert.False(t, verifier(true, false, alice, "gnobody", bobOwnsGnobody))
 84}
 85
 86// TestPausedVerifier covers the emergency-halt semantic. When paused
 87// AND enabled, the verifier rejects EVERY namespace check including PA.
 88func TestPausedVerifier(t *testing.T) {
 89	// Lookup that says "gnobody" is registered to alice. Used to confirm
 90	// the registered-name path is also halted by pause.
 91	aliceOwnsGnobody := func(name string) (address, bool) {
 92		if name == "gnobody" {
 93			return alice, true
 94		}
 95		return "", false
 96	}
 97
 98	t.Run("paused blocks PA namespaces", func(t *testing.T) {
 99		// PA would normally succeed (addr.String() == namespace), but
100		// pause short-circuits before the PA check.
101		uassert.False(t, verifier(true, true, alice, alice.String(), nil))
102		uassert.False(t, verifier(true, true, alice, alice.String(), aliceOwnsGnobody))
103	})
104
105	t.Run("paused blocks registered-name namespaces", func(t *testing.T) {
106		// Registered-name path would normally succeed, but pause
107		// short-circuits before the lookup is consulted.
108		uassert.False(t, verifier(true, true, alice, "gnobody", aliceOwnsGnobody))
109	})
110
111	t.Run("paused blocks any other namespace too", func(t *testing.T) {
112		uassert.False(t, verifier(true, true, alice, "anything", aliceOwnsGnobody))
113		uassert.False(t, verifier(true, true, alice, "", aliceOwnsGnobody))
114		uassert.False(t, verifier(true, true, address(""), "anything", aliceOwnsGnobody))
115	})
116
117	t.Run("pre-Enable bypass takes priority over paused", func(t *testing.T) {
118		// !enabled is checked BEFORE paused in the verifier — the
119		// pre-Enable shortcut returns true regardless of pause state.
120		// This is the "pause is staged, applies on Enable" semantic.
121		uassert.True(t, verifier(false, true, alice, alice.String(), nil))
122		uassert.True(t, verifier(false, true, alice, "gnobody", aliceOwnsGnobody))
123		uassert.True(t, verifier(false, true, alice, "anything", nil))
124	})
125
126	t.Run("paused=false with enabled=true behaves normally", func(t *testing.T) {
127		// Sanity: just confirms the false case doesn't accidentally do
128		// something different from the no-pause baseline.
129		uassert.True(t, verifier(true, false, alice, alice.String(), nil))
130		uassert.True(t, verifier(true, false, alice, "gnobody", aliceOwnsGnobody))
131		uassert.False(t, verifier(true, false, bob, "gnobody", aliceOwnsGnobody))
132	})
133}
134
135// TestProposeSetPaused_idempotency verifies the proposal-creation guard:
136// requesting a pause state that already matches the current state panics
137// at proposal-creation time, so voters never see a no-op proposal.
138//
139// NOTE: this test mutates the package-level `paused` var directly to
140// avoid driving the full DAO flow. Restores the value via defer.
141func TestProposeSetPaused_idempotency(cur realm, t *testing.T) {
142	saved := paused
143	defer func() { paused = saved }()
144
145	t.Run("propose pause when already paused panics", func(t *testing.T) {
146		paused = true
147		urequire.PanicsWithMessage(t, cur,
148			"paused state already matches requested value; no-op proposal rejected",
149			func() { ProposeSetPaused(cur, true) })
150	})
151
152	t.Run("propose unpause when already unpaused panics", func(t *testing.T) {
153		paused = false
154		urequire.PanicsWithMessage(t, cur,
155			"paused state already matches requested value; no-op proposal rejected",
156			func() { ProposeSetPaused(cur, false) })
157	})
158
159	t.Run("propose pause when unpaused succeeds", func(t *testing.T) {
160		paused = false
161		urequire.NotPanics(t, cur, func() { ProposeSetPaused(cur, true) })
162		// The proposal-create call doesn't actually mutate paused —
163		// only its execution would. Confirm.
164		uassert.False(t, paused)
165	})
166
167	t.Run("propose unpause when paused succeeds", func(t *testing.T) {
168		paused = true
169		urequire.NotPanics(t, cur, func() { ProposeSetPaused(cur, false) })
170		// Same: proposal-create does not mutate.
171		uassert.True(t, paused)
172	})
173}
174
175// TestSetPaused_internal verifies the private setPaused actuator
176// directly. Bypasses the proposal flow to confirm the toggle and the
177// event-emission path independently.
178func TestSetPaused_internal(cur realm, t *testing.T) {
179	saved := paused
180	defer func() { paused = saved }()
181
182	paused = false
183	setPaused(0, cur, true)
184	uassert.True(t, paused)
185
186	setPaused(0, cur, false)
187	uassert.False(t, paused)
188}
189
190func TestIsPaused(t *testing.T) {
191	saved := paused
192	defer func() { paused = saved }()
193
194	paused = false
195	uassert.False(t, IsPaused())
196
197	paused = true
198	uassert.True(t, IsPaused())
199}
200
201func TestEnable(cur realm, t *testing.T) {
202	testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("random")))
203	uassert.AbortsWithMessage(t, cur, "caller is not admin", func() {
204		Enable(cross(cur))
205	})
206	uassert.False(t, IsEnabled())
207
208	testing.SetRealm(testing.NewUserRealm(admin))
209	uassert.NotPanics(t, cur, func() {
210		Enable(cross(cur))
211	})
212	uassert.True(t, IsEnabled())
213}