valopers_test.gno

13.28 Kb ยท 525 lines
  1package valopers
  2
  3import (
  4	"std"
  5	"strings"
  6	"testing"
  7
  8	"gno.land/p/demo/avl"
  9	"gno.land/p/demo/ownable/exts/authorizable"
 10	"gno.land/p/demo/testutils"
 11	"gno.land/p/demo/uassert"
 12	"gno.land/p/demo/ufmt"
 13)
 14
 15func validValidatorInfo(t *testing.T) struct {
 16	Moniker     string
 17	Description string
 18	Address     std.Address
 19	PubKey      string
 20} {
 21	t.Helper()
 22
 23	return struct {
 24		Moniker     string
 25		Description string
 26		Address     std.Address
 27		PubKey      string
 28	}{
 29		Moniker:     "test-1",
 30		Description: "test-1's description",
 31		Address:     std.Address("g1sp8v98h2gadm5jggtzz9w5ksexqn68ympsd68h"),
 32		PubKey:      "gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zqwpdwpd0f9fvqla089ndw5g9hcsufad77fml2vlu73fk8q8sh8v72cza5p",
 33	}
 34}
 35
 36func TestValopers_Register(t *testing.T) {
 37	t.Run("already a valoper", func(t *testing.T) {
 38		// Clear the set for the test
 39		valopers = avl.NewTree()
 40
 41		info := validValidatorInfo(t)
 42
 43		v := Valoper{
 44			Moniker:     info.Moniker,
 45			Description: info.Description,
 46			Address:     info.Address,
 47			PubKey:      info.PubKey,
 48			KeepRunning: true,
 49		}
 50
 51		// Add the valoper
 52		valopers.Set(v.Address.String(), v)
 53
 54		// Send coins
 55		testing.SetOriginSend(std.Coins{minFee})
 56
 57		uassert.PanicsWithMessage(t, ErrValoperExists.Error(), func() {
 58			Register(info.Moniker, info.Description, info.Address, info.PubKey)
 59		})
 60	})
 61
 62	t.Run("no coins deposited", func(t *testing.T) {
 63		// Clear the set for the test
 64		valopers = avl.NewTree()
 65
 66		info := validValidatorInfo(t)
 67
 68		// Send no coins
 69		testing.SetOriginSend(std.Coins{std.NewCoin("ugnot", 0)})
 70
 71		uassert.PanicsWithMessage(t, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
 72			Register(info.Moniker, info.Description, info.Address, info.PubKey)
 73		})
 74	})
 75
 76	t.Run("insufficient coins amount deposited", func(t *testing.T) {
 77		// Clear the set for the test
 78		valopers = avl.NewTree()
 79
 80		info := validValidatorInfo(t)
 81
 82		// Send invalid coins
 83		testing.SetOriginSend(std.Coins{std.NewCoin("ugnot", minFee.Amount-1)})
 84
 85		uassert.PanicsWithMessage(t, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
 86			Register(info.Moniker, info.Description, info.Address, info.PubKey)
 87		})
 88	})
 89
 90	t.Run("coin amount deposited is not ugnot", func(t *testing.T) {
 91		// Clear the set for the test
 92		valopers = avl.NewTree()
 93
 94		info := validValidatorInfo(t)
 95
 96		// Send invalid coins
 97		testing.SetOriginSend(std.Coins{std.NewCoin("gnogno", minFee.Amount)})
 98
 99		uassert.PanicsWithMessage(t, "incompatible coin denominations: gnogno, ugnot", func() {
100			Register(info.Moniker, info.Description, info.Address, info.PubKey)
101		})
102	})
103
104	t.Run("successful registration", func(t *testing.T) {
105		// Clear the set for the test
106		valopers = avl.NewTree()
107
108		info := validValidatorInfo(t)
109
110		// Send coins
111		testing.SetOriginSend(std.Coins{minFee})
112
113		uassert.NotPanics(t, func() {
114			Register(info.Moniker, info.Description, info.Address, info.PubKey)
115		})
116
117		uassert.NotPanics(t, func() {
118			valoper := GetByAddr(info.Address)
119
120			uassert.Equal(t, info.Moniker, valoper.Moniker)
121			uassert.Equal(t, info.Description, valoper.Description)
122			uassert.Equal(t, info.Address, valoper.Address)
123			uassert.Equal(t, info.PubKey, valoper.PubKey)
124			uassert.Equal(t, true, valoper.KeepRunning)
125		})
126	})
127}
128
129func TestValopers_UpdateAuthMembers(t *testing.T) {
130	test1Address := testutils.TestAddress("test1")
131	test2Address := testutils.TestAddress("test2")
132
133	t.Run("unauthorized member adds member", func(t *testing.T) {
134		// Clear the set for the test
135		valopers = avl.NewTree()
136
137		info := validValidatorInfo(t)
138
139		// Send coins
140		testing.SetOriginSend(std.Coins{minFee})
141
142		testing.SetRealm(std.NewUserRealm(test1Address))
143		testing.SetOriginCaller(test1Address) // TODO(bug, issue #2371): should not be needed
144
145		// Add the valoper
146		uassert.NotPanics(t, func() {
147			Register(info.Moniker, info.Description, info.Address, info.PubKey)
148		})
149
150		testing.SetRealm(std.NewUserRealm(info.Address))
151		testing.SetOriginCaller(info.Address) // TODO(bug, issue #2371): should not be needed
152
153		// try to add member without being authorized
154		uassert.PanicsWithMessage(t, authorizable.ErrNotSuperuser.Error(), func() {
155			AddToAuthList(info.Address, test2Address)
156		})
157	})
158
159	t.Run("unauthorized member deletes member", func(t *testing.T) {
160		// Clear the set for the test
161		valopers = avl.NewTree()
162
163		info := validValidatorInfo(t)
164
165		// Send coins
166		testing.SetOriginSend(std.Coins{minFee})
167
168		testing.SetRealm(std.NewUserRealm(test1Address))
169		testing.SetOriginCaller(test1Address) // TODO(bug, issue #2371): should not be needed
170
171		// Add the valoper
172		uassert.NotPanics(t, func() {
173			Register(info.Moniker, info.Description, info.Address, info.PubKey)
174		})
175
176		uassert.NotPanics(t, func() {
177			AddToAuthList(info.Address, test2Address)
178		})
179
180		testing.SetRealm(std.NewUserRealm(info.Address))
181		testing.SetOriginCaller(info.Address) // TODO(bug, issue #2371): should not be needed
182
183		// try to add member without being authorized
184		uassert.PanicsWithMessage(t, authorizable.ErrNotSuperuser.Error(), func() {
185			DeleteFromAuthList(info.Address, test2Address)
186		})
187	})
188
189	t.Run("authorized member adds member", func(t *testing.T) {
190		// Clear the set for the test
191		valopers = avl.NewTree()
192
193		info := validValidatorInfo(t)
194
195		// Send coins
196		testing.SetOriginSend(std.Coins{minFee})
197
198		testing.SetRealm(std.NewUserRealm(test1Address))
199		testing.SetOriginCaller(test1Address) // TODO(bug, issue #2371): should not be needed
200
201		// Add the valoper
202		uassert.NotPanics(t, func() {
203			Register(info.Moniker, info.Description, info.Address, info.PubKey)
204		})
205
206		uassert.NotPanics(t, func() {
207			AddToAuthList(info.Address, test2Address)
208		})
209
210		testing.SetRealm(std.NewUserRealm(test2Address))
211		testing.SetOriginCaller(test2Address) // TODO(bug, issue #2371): should not be needed
212
213		newMoniker := "new moniker"
214		// Update the valoper
215		uassert.NotPanics(t, func() {
216			UpdateMoniker(info.Address, newMoniker)
217		})
218
219		uassert.NotPanics(t, func() {
220			valoper := GetByAddr(info.Address)
221			uassert.Equal(t, newMoniker, valoper.Moniker)
222		})
223	})
224}
225
226func TestValopers_UpdateMoniker(t *testing.T) {
227	test1Address := testutils.TestAddress("test1")
228	test2Address := testutils.TestAddress("test2")
229
230	t.Run("non-existing valoper", func(t *testing.T) {
231		// Clear the set for the test
232		valopers = avl.NewTree()
233
234		info := validValidatorInfo(t)
235
236		// Update the valoper
237		uassert.PanicsWithMessage(t, ErrValoperMissing.Error(), func() {
238			UpdateMoniker(info.Address, "new moniker")
239		})
240	})
241
242	t.Run("invalid caller", func(t *testing.T) {
243		// Set the origin caller
244		testing.SetOriginCaller(test1Address)
245
246		// Clear the set for the test
247		valopers = avl.NewTree()
248
249		info := validValidatorInfo(t)
250
251		// Send coins
252		testing.SetOriginSend(std.Coins{minFee})
253
254		// Add the valoper
255		uassert.NotPanics(t, func() {
256			Register(info.Moniker, info.Description, info.Address, info.PubKey)
257		})
258
259		// Change the origin caller
260		testing.SetOriginCaller(test2Address)
261
262		// Update the valoper
263		uassert.PanicsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
264			UpdateMoniker(info.Address, "new moniker")
265		})
266	})
267
268	t.Run("invalid moniker", func(t *testing.T) {
269		invalidMonikers := []string{
270			"",     // Empty
271			"    ", // Whitespace
272			"a",    // Too short
273			"a very long moniker that is longer than 32 characters", // Too long
274			"!@#$%^&*()+{}|:<>?/.,;'",                               // Invalid characters
275			" space in front",
276			"space in back ",
277		}
278
279		// Clear the set for the test
280		valopers = avl.NewTree()
281
282		info := validValidatorInfo(t)
283
284		// Send coins
285		testing.SetOriginSend(std.Coins{minFee})
286
287		// Add the valoper
288		uassert.NotPanics(t, func() {
289			Register(info.Moniker, info.Description, info.Address, info.PubKey)
290		})
291
292		for _, invalidMoniker := range invalidMonikers {
293			// Update the valoper
294			uassert.PanicsWithMessage(t, ErrInvalidMoniker.Error(), func() {
295				UpdateMoniker(info.Address, invalidMoniker)
296			})
297		}
298	})
299
300	t.Run("too long moniker", func(t *testing.T) {
301		// Clear the set for the test
302		valopers = avl.NewTree()
303
304		info := validValidatorInfo(t)
305
306		// Send coins
307		testing.SetOriginSend(std.Coins{minFee})
308
309		// Add the valoper
310		uassert.NotPanics(t, func() {
311			Register(info.Moniker, info.Description, info.Address, info.PubKey)
312		})
313
314		// Update the valoper
315		uassert.PanicsWithMessage(t, ErrInvalidMoniker.Error(), func() {
316			UpdateMoniker(info.Address, strings.Repeat("a", MonikerMaxLength+1))
317		})
318	})
319
320	t.Run("successful update", func(t *testing.T) {
321		// Clear the set for the test
322		valopers = avl.NewTree()
323
324		info := validValidatorInfo(t)
325
326		// Send coins
327		testing.SetOriginSend(std.Coins{minFee})
328
329		// Add the valoper
330		uassert.NotPanics(t, func() {
331			Register(info.Moniker, info.Description, info.Address, info.PubKey)
332		})
333
334		newMoniker := "new moniker"
335		// Update the valoper
336		uassert.NotPanics(t, func() {
337			UpdateMoniker(info.Address, newMoniker)
338		})
339
340		// Make sure the valoper is updated
341		uassert.NotPanics(t, func() {
342			valoper := GetByAddr(info.Address)
343
344			uassert.Equal(t, newMoniker, valoper.Moniker)
345		})
346	})
347}
348
349func TestValopers_UpdateDescription(t *testing.T) {
350	test1Address := testutils.TestAddress("test1")
351	test2Address := testutils.TestAddress("test2")
352
353	t.Run("non-existing valoper", func(t *testing.T) {
354		// Clear the set for the test
355		valopers = avl.NewTree()
356
357		// Update the valoper
358		uassert.PanicsWithMessage(t, ErrValoperMissing.Error(), func() {
359			UpdateDescription(validValidatorInfo(t).Address, "new description")
360		})
361	})
362
363	t.Run("invalid caller", func(t *testing.T) {
364		// Set the origin caller
365		testing.SetOriginCaller(test1Address)
366
367		info := validValidatorInfo(t)
368
369		// Clear the set for the test
370		valopers = avl.NewTree()
371
372		// Send coins
373		testing.SetOriginSend(std.Coins{minFee})
374
375		// Add the valoper
376		uassert.NotPanics(t, func() {
377			Register(info.Moniker, info.Description, info.Address, info.PubKey)
378		})
379
380		// Change the origin caller
381		testing.SetOriginCaller(test2Address)
382
383		// Update the valoper
384		uassert.PanicsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
385			UpdateDescription(info.Address, "new description")
386		})
387	})
388
389	t.Run("empty description", func(t *testing.T) {
390		// Clear the set for the test
391		valopers = avl.NewTree()
392
393		info := validValidatorInfo(t)
394
395		// Send coins
396		testing.SetOriginSend(std.Coins{minFee})
397
398		// Add the valoper
399		uassert.NotPanics(t, func() {
400			Register(info.Moniker, info.Description, info.Address, info.PubKey)
401		})
402
403		emptyDescription := ""
404		// Update the valoper
405		uassert.PanicsWithMessage(t, ErrInvalidDescription.Error(), func() {
406			UpdateDescription(info.Address, emptyDescription)
407		})
408	})
409
410	t.Run("too long description", func(t *testing.T) {
411		// Clear the set for the test
412		valopers = avl.NewTree()
413
414		info := validValidatorInfo(t)
415
416		// Send coins
417		testing.SetOriginSend(std.Coins{minFee})
418
419		// Add the valoper
420		uassert.NotPanics(t, func() {
421			Register(info.Moniker, info.Description, info.Address, info.PubKey)
422		})
423
424		// Update the valoper
425		uassert.PanicsWithMessage(t, ErrInvalidDescription.Error(), func() {
426			UpdateDescription(info.Address, strings.Repeat("a", DescriptionMaxLength+1))
427		})
428	})
429
430	t.Run("successful update", func(t *testing.T) {
431		// Clear the set for the test
432		valopers = avl.NewTree()
433
434		info := validValidatorInfo(t)
435
436		// Send coins
437		testing.SetOriginSend(std.Coins{minFee})
438
439		// Add the valoper
440		uassert.NotPanics(t, func() {
441			Register(info.Moniker, info.Description, info.Address, info.PubKey)
442		})
443
444		newDescription := "new description"
445		// Update the valoper
446		uassert.NotPanics(t, func() {
447			UpdateDescription(info.Address, newDescription)
448		})
449
450		// Make sure the valoper is updated
451		uassert.NotPanics(t, func() {
452			valoper := GetByAddr(info.Address)
453
454			uassert.Equal(t, newDescription, valoper.Description)
455		})
456	})
457}
458
459func TestValopers_UpdateKeepRunning(t *testing.T) {
460	test1Address := testutils.TestAddress("test1")
461	test2Address := testutils.TestAddress("test2")
462
463	t.Run("non-existing valoper", func(t *testing.T) {
464		// Clear the set for the test
465		valopers = avl.NewTree()
466
467		// Update the valoper
468		uassert.PanicsWithMessage(t, ErrValoperMissing.Error(), func() {
469			UpdateKeepRunning(validValidatorInfo(t).Address, false)
470		})
471	})
472
473	t.Run("invalid caller", func(t *testing.T) {
474		// Set the origin caller
475		testing.SetOriginCaller(test1Address)
476
477		// Clear the set for the test
478		valopers = avl.NewTree()
479
480		info := validValidatorInfo(t)
481
482		// Send coins
483		testing.SetOriginSend(std.Coins{minFee})
484
485		// Add the valoper
486		uassert.NotPanics(t, func() {
487			Register(info.Moniker, info.Description, info.Address, info.PubKey)
488		})
489
490		// Change the origin caller
491		testing.SetOriginCaller(test2Address)
492
493		// Update the valoper
494		uassert.PanicsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
495			UpdateKeepRunning(info.Address, false)
496		})
497	})
498
499	t.Run("successful update", func(t *testing.T) {
500		// Clear the set for the test
501		valopers = avl.NewTree()
502
503		info := validValidatorInfo(t)
504
505		// Send coins
506		testing.SetOriginSend(std.Coins{minFee})
507
508		// Add the valoper
509		uassert.NotPanics(t, func() {
510			Register(info.Moniker, info.Description, info.Address, info.PubKey)
511		})
512
513		// Update the valoper
514		uassert.NotPanics(t, func() {
515			UpdateKeepRunning(info.Address, false)
516		})
517
518		// Make sure the valoper is updated
519		uassert.NotPanics(t, func() {
520			valoper := GetByAddr(info.Address)
521
522			uassert.Equal(t, false, valoper.KeepRunning)
523		})
524	})
525}