valopers_test.gno

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