Search Apps Documentation Source Content File Folder Download Copy Actions Download

valopers_test.gno

17.03 Kb ยท 663 lines
  1package valopers
  2
  3import (
  4	"chain"
  5	"strings"
  6	"testing"
  7
  8	"gno.land/p/nt/avl"
  9	"gno.land/p/nt/ownable/exts/authorizable"
 10	"gno.land/p/nt/testutils"
 11	"gno.land/p/nt/uassert"
 12	"gno.land/p/nt/ufmt"
 13)
 14
 15func validValidatorInfo(t *testing.T) struct {
 16	Moniker     string
 17	Description string
 18	ServerType  string
 19	Address     address
 20	PubKey      string
 21} {
 22	t.Helper()
 23
 24	return struct {
 25		Moniker     string
 26		Description string
 27		ServerType  string
 28		Address     address
 29		PubKey      string
 30	}{
 31		Moniker:     "test-1",
 32		Description: "test-1's description",
 33		ServerType:  ServerTypeOnPrem,
 34		Address:     address("g1sp8v98h2gadm5jggtzz9w5ksexqn68ympsd68h"),
 35		PubKey:      "gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zqwpdwpd0f9fvqla089ndw5g9hcsufad77fml2vlu73fk8q8sh8v72cza5p",
 36	}
 37}
 38
 39func TestValopers_Register(t *testing.T) {
 40	test1 := testutils.TestAddress("test1")
 41	testing.SetRealm(testing.NewUserRealm(test1))
 42
 43	t.Run("already a valoper", func(t *testing.T) {
 44		// Clear the set for the test
 45		valopers = avl.NewTree()
 46
 47		info := validValidatorInfo(t)
 48
 49		v := Valoper{
 50			Moniker:     info.Moniker,
 51			Description: info.Description,
 52			ServerType:  info.ServerType,
 53			Address:     info.Address,
 54			PubKey:      info.PubKey,
 55			KeepRunning: true,
 56		}
 57
 58		// Add the valoper
 59		valopers.Set(v.Address.String(), v)
 60
 61		// Send coins
 62		testing.SetOriginSend(chain.Coins{minFee})
 63
 64		uassert.AbortsWithMessage(t, ErrValoperExists.Error(), func() {
 65			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
 66		})
 67	})
 68
 69	t.Run("no coins deposited", func(t *testing.T) {
 70		// Clear the set for the test
 71		valopers = avl.NewTree()
 72
 73		info := validValidatorInfo(t)
 74
 75		// Send no coins
 76		testing.SetOriginSend(chain.Coins{chain.NewCoin("ugnot", 0)})
 77
 78		uassert.AbortsWithMessage(t, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
 79			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
 80		})
 81	})
 82
 83	t.Run("insufficient coins amount deposited", func(t *testing.T) {
 84		// Clear the set for the test
 85		valopers = avl.NewTree()
 86
 87		info := validValidatorInfo(t)
 88
 89		// Send invalid coins
 90		testing.SetOriginSend(chain.Coins{chain.NewCoin("ugnot", minFee.Amount-1)})
 91
 92		uassert.AbortsWithMessage(t, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
 93			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
 94		})
 95	})
 96
 97	t.Run("coin amount deposited is not ugnot", func(t *testing.T) {
 98		// Clear the set for the test
 99		valopers = avl.NewTree()
100
101		info := validValidatorInfo(t)
102
103		// Send invalid coins
104		testing.SetOriginSend(chain.Coins{chain.NewCoin("gnogno", minFee.Amount)})
105
106		uassert.AbortsWithMessage(t, "incompatible coin denominations: gnogno, ugnot", func() {
107			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
108		})
109	})
110
111	t.Run("successful registration", func(t *testing.T) {
112		// Clear the set for the test
113		valopers = avl.NewTree()
114
115		info := validValidatorInfo(t)
116
117		// Send coins
118		testing.SetOriginSend(chain.Coins{minFee})
119
120		uassert.NotAborts(t, func() {
121			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
122		})
123
124		uassert.NotPanics(t, func() {
125			valoper := GetByAddr(info.Address)
126
127			uassert.Equal(t, info.Moniker, valoper.Moniker)
128			uassert.Equal(t, info.Description, valoper.Description)
129			uassert.Equal(t, info.ServerType, valoper.ServerType)
130			uassert.Equal(t, info.Address, valoper.Address)
131			uassert.Equal(t, info.PubKey, valoper.PubKey)
132			uassert.Equal(t, true, valoper.KeepRunning)
133		})
134	})
135}
136
137func TestValopers_UpdateAuthMembers(t *testing.T) {
138	test1Address := testutils.TestAddress("test1")
139	test2Address := testutils.TestAddress("test2")
140
141	t.Run("unauthorized member adds member", func(t *testing.T) {
142		// Clear the set for the test
143		valopers = avl.NewTree()
144
145		info := validValidatorInfo(t)
146
147		// Send coins
148		testing.SetOriginSend(chain.Coins{minFee})
149
150		testing.SetRealm(testing.NewUserRealm(test1Address))
151
152		// Add the valoper
153		uassert.NotPanics(t, func() {
154			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
155		})
156
157		testing.SetRealm(testing.NewUserRealm(info.Address))
158
159		// try to add member without being authorized
160		uassert.AbortsWithMessage(t, authorizable.ErrNotSuperuser.Error(), func() {
161			AddToAuthList(cross, info.Address, test2Address)
162		})
163	})
164
165	t.Run("unauthorized member deletes member", func(t *testing.T) {
166		// Clear the set for the test
167		valopers = avl.NewTree()
168
169		info := validValidatorInfo(t)
170
171		// Send coins
172		testing.SetOriginSend(chain.Coins{minFee})
173
174		testing.SetRealm(testing.NewUserRealm(test1Address))
175
176		// Add the valoper
177		uassert.NotPanics(t, func() {
178			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
179		})
180
181		uassert.NotPanics(t, func() {
182			// XXX this panics.
183			AddToAuthList(cross, info.Address, test2Address)
184		})
185
186		testing.SetRealm(testing.NewUserRealm(info.Address))
187
188		// try to add member without being authorized
189		uassert.AbortsWithMessage(t, authorizable.ErrNotSuperuser.Error(), func() {
190			DeleteFromAuthList(cross, info.Address, test2Address)
191		})
192	})
193
194	t.Run("authorized member adds member", func(t *testing.T) {
195		// Clear the set for the test
196		valopers = avl.NewTree()
197
198		info := validValidatorInfo(t)
199
200		// Send coins
201		testing.SetOriginSend(chain.Coins{minFee})
202
203		testing.SetRealm(testing.NewUserRealm(test1Address))
204
205		// Add the valoper
206		uassert.NotPanics(t, func() {
207			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
208		})
209
210		uassert.NotPanics(t, func() {
211			AddToAuthList(cross, info.Address, test2Address)
212		})
213
214		testing.SetRealm(testing.NewUserRealm(test2Address))
215
216		newMoniker := "new moniker"
217		// Update the valoper
218		uassert.NotPanics(t, func() {
219			UpdateMoniker(cross, info.Address, newMoniker)
220		})
221
222		uassert.NotPanics(t, func() {
223			valoper := GetByAddr(info.Address)
224			uassert.Equal(t, newMoniker, valoper.Moniker)
225		})
226	})
227}
228
229func TestValopers_UpdateMoniker(t *testing.T) {
230	test1Address := testutils.TestAddress("test1")
231	test2Address := testutils.TestAddress("test2")
232
233	t.Run("non-existing valoper", func(t *testing.T) {
234		// Clear the set for the test
235		valopers = avl.NewTree()
236
237		info := validValidatorInfo(t)
238
239		// Update the valoper
240		uassert.AbortsWithMessage(t, ErrValoperMissing.Error(), func() {
241			UpdateMoniker(cross, info.Address, "new moniker")
242		})
243	})
244
245	t.Run("invalid caller", func(t *testing.T) {
246		// Set the origin caller
247		testing.SetOriginCaller(test1Address)
248
249		// Clear the set for the test
250		valopers = avl.NewTree()
251
252		info := validValidatorInfo(t)
253
254		// Send coins
255		testing.SetOriginSend(chain.Coins{minFee})
256
257		// Add the valoper
258		uassert.NotPanics(t, func() {
259			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
260		})
261
262		// Change the origin caller
263		testing.SetOriginCaller(test2Address)
264
265		// Update the valoper
266		uassert.AbortsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
267			UpdateMoniker(cross, info.Address, "new moniker")
268		})
269	})
270
271	t.Run("invalid moniker", func(t *testing.T) {
272		invalidMonikers := []string{
273			"",     // Empty
274			"    ", // Whitespace
275			"a",    // Too short
276			"a very long moniker that is longer than 32 characters", // Too long
277			"!@#$%^&*()+{}|:<>?/.,;'",                               // Invalid characters
278			" space in front",
279			"space in back ",
280		}
281
282		// Clear the set for the test
283		valopers = avl.NewTree()
284
285		info := validValidatorInfo(t)
286
287		// Set the origin caller
288		testing.SetOriginCaller(test1Address)
289
290		// Send coins
291		testing.SetOriginSend(chain.Coins{minFee})
292
293		// Add the valoper
294		uassert.NotPanics(t, func() {
295			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
296		})
297
298		for _, invalidMoniker := range invalidMonikers {
299			// Update the valoper
300			uassert.AbortsWithMessage(t, ErrInvalidMoniker.Error(), func() {
301				UpdateMoniker(cross, info.Address, invalidMoniker)
302			})
303		}
304	})
305
306	t.Run("too long moniker", func(t *testing.T) {
307		// Clear the set for the test
308		valopers = avl.NewTree()
309
310		info := validValidatorInfo(t)
311
312		// Set the origin caller
313		testing.SetOriginCaller(test1Address)
314
315		// Send coins
316		testing.SetOriginSend(chain.Coins{minFee})
317
318		// Add the valoper
319		uassert.NotPanics(t, func() {
320			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
321		})
322
323		// Update the valoper
324		uassert.AbortsWithMessage(t, ErrInvalidMoniker.Error(), func() {
325			UpdateMoniker(cross, info.Address, strings.Repeat("a", MonikerMaxLength+1))
326		})
327	})
328
329	t.Run("successful update", func(t *testing.T) {
330		// Clear the set for the test
331		valopers = avl.NewTree()
332
333		info := validValidatorInfo(t)
334
335		// Set the origin caller
336		testing.SetOriginCaller(test1Address)
337
338		// Send coins
339		testing.SetOriginSend(chain.Coins{minFee})
340
341		// Add the valoper
342		uassert.NotPanics(t, func() {
343			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
344		})
345
346		newMoniker := "new moniker"
347		// Update the valoper
348		uassert.NotPanics(t, func() {
349			UpdateMoniker(cross, info.Address, newMoniker)
350		})
351
352		// Make sure the valoper is updated
353		uassert.NotPanics(t, func() {
354			valoper := GetByAddr(info.Address)
355
356			uassert.Equal(t, newMoniker, valoper.Moniker)
357		})
358	})
359}
360
361func TestValopers_UpdateDescription(t *testing.T) {
362	test1Address := testutils.TestAddress("test1")
363	test2Address := testutils.TestAddress("test2")
364
365	t.Run("non-existing valoper", func(t *testing.T) {
366		// Clear the set for the test
367		valopers = avl.NewTree()
368
369		// Update the valoper
370		uassert.AbortsWithMessage(t, ErrValoperMissing.Error(), func() {
371			UpdateDescription(cross, validValidatorInfo(t).Address, "new description")
372		})
373	})
374
375	t.Run("invalid caller", func(t *testing.T) {
376		// Set the origin caller
377		testing.SetOriginCaller(test1Address)
378
379		info := validValidatorInfo(t)
380
381		// Clear the set for the test
382		valopers = avl.NewTree()
383
384		// Send coins
385		testing.SetOriginSend(chain.Coins{minFee})
386
387		// Add the valoper
388		uassert.NotPanics(t, func() {
389			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
390		})
391
392		// Change the origin caller
393		testing.SetOriginCaller(test2Address)
394
395		// Update the valoper
396		uassert.AbortsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
397			UpdateDescription(cross, info.Address, "new description")
398		})
399	})
400
401	t.Run("empty description", func(t *testing.T) {
402		// Clear the set for the test
403		valopers = avl.NewTree()
404
405		info := validValidatorInfo(t)
406
407		// Set the origin caller
408		testing.SetOriginCaller(test1Address)
409
410		// Send coins
411		testing.SetOriginSend(chain.Coins{minFee})
412
413		// Add the valoper
414		uassert.NotPanics(t, func() {
415			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
416		})
417
418		emptyDescription := ""
419		// Update the valoper
420		uassert.AbortsWithMessage(t, ErrInvalidDescription.Error(), func() {
421			UpdateDescription(cross, info.Address, emptyDescription)
422		})
423	})
424
425	t.Run("too long description", func(t *testing.T) {
426		// Clear the set for the test
427		valopers = avl.NewTree()
428
429		info := validValidatorInfo(t)
430
431		// Set the origin caller
432		testing.SetOriginCaller(test1Address)
433
434		// Send coins
435		testing.SetOriginSend(chain.Coins{minFee})
436
437		// Add the valoper
438		uassert.NotPanics(t, func() {
439			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
440		})
441
442		// Update the valoper
443		uassert.AbortsWithMessage(t, ErrInvalidDescription.Error(), func() {
444			UpdateDescription(cross, info.Address, strings.Repeat("a", DescriptionMaxLength+1))
445		})
446	})
447
448	t.Run("successful update", func(t *testing.T) {
449		// Clear the set for the test
450		valopers = avl.NewTree()
451
452		info := validValidatorInfo(t)
453
454		// Set the origin caller
455		testing.SetOriginCaller(test1Address)
456
457		// Send coins
458		testing.SetOriginSend(chain.Coins{minFee})
459
460		// Add the valoper
461		uassert.NotPanics(t, func() {
462			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
463		})
464
465		newDescription := "new description"
466		// Update the valoper
467		uassert.NotPanics(t, func() {
468			UpdateDescription(cross, info.Address, newDescription)
469		})
470
471		// Make sure the valoper is updated
472		uassert.NotPanics(t, func() {
473			valoper := GetByAddr(info.Address)
474
475			uassert.Equal(t, newDescription, valoper.Description)
476		})
477	})
478}
479
480func TestValopers_UpdateKeepRunning(t *testing.T) {
481	test1Address := testutils.TestAddress("test1")
482	test2Address := testutils.TestAddress("test2")
483
484	t.Run("non-existing valoper", func(t *testing.T) {
485		// Clear the set for the test
486		valopers = avl.NewTree()
487
488		// Update the valoper
489		uassert.AbortsWithMessage(t, ErrValoperMissing.Error(), func() {
490			UpdateKeepRunning(cross, validValidatorInfo(t).Address, false)
491		})
492	})
493
494	t.Run("invalid caller", func(t *testing.T) {
495		// Set the origin caller
496		testing.SetOriginCaller(test1Address)
497
498		// Clear the set for the test
499		valopers = avl.NewTree()
500
501		info := validValidatorInfo(t)
502
503		// Send coins
504		testing.SetOriginSend(chain.Coins{minFee})
505
506		// Add the valoper
507		uassert.NotPanics(t, func() {
508			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
509		})
510
511		// Change the origin caller
512		testing.SetOriginCaller(test2Address)
513
514		// Update the valoper
515		uassert.AbortsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
516			UpdateKeepRunning(cross, info.Address, false)
517		})
518	})
519
520	t.Run("successful update", func(t *testing.T) {
521		// Clear the set for the test
522		valopers = avl.NewTree()
523
524		info := validValidatorInfo(t)
525
526		// Set the origin caller
527		testing.SetOriginCaller(test1Address)
528
529		// Send coins
530		testing.SetOriginSend(chain.Coins{minFee})
531
532		// Add the valoper
533		uassert.NotPanics(t, func() {
534			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
535		})
536
537		// Update the valoper
538		uassert.NotPanics(t, func() {
539			UpdateKeepRunning(cross, info.Address, false)
540		})
541
542		// Make sure the valoper is updated
543		uassert.NotPanics(t, func() {
544			valoper := GetByAddr(info.Address)
545
546			uassert.Equal(t, false, valoper.KeepRunning)
547		})
548	})
549}
550
551func TestValopers_UpdateServerType(t *testing.T) {
552	test1Address := testutils.TestAddress("test1")
553	test2Address := testutils.TestAddress("test2")
554
555	t.Run("non-existing valoper", func(t *testing.T) {
556		// Clear the set for the test
557		valopers = avl.NewTree()
558
559		// Update the valoper
560		uassert.AbortsWithMessage(t, ErrValoperMissing.Error(), func() {
561			UpdateServerType(cross, validValidatorInfo(t).Address, ServerTypeCloud)
562		})
563	})
564
565	t.Run("invalid caller", func(t *testing.T) {
566		// Set the origin caller
567		testing.SetOriginCaller(test1Address)
568
569		// Clear the set for the test
570		valopers = avl.NewTree()
571
572		info := validValidatorInfo(t)
573
574		// Send coins
575		testing.SetOriginSend(chain.Coins{minFee})
576
577		// Add the valoper
578		uassert.NotPanics(t, func() {
579			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
580		})
581
582		// Change the origin caller
583		testing.SetOriginCaller(test2Address)
584
585		// Update the valoper
586		uassert.AbortsWithMessage(t, authorizable.ErrNotInAuthList.Error(), func() {
587			UpdateServerType(cross, info.Address, ServerTypeCloud)
588		})
589	})
590
591	t.Run("invalid server type", func(t *testing.T) {
592		// Clear the set for the test
593		valopers = avl.NewTree()
594
595		info := validValidatorInfo(t)
596
597		// Set the origin caller
598		testing.SetOriginCaller(test1Address)
599
600		// Send coins
601		testing.SetOriginSend(chain.Coins{minFee})
602
603		// Add the valoper
604		uassert.NotPanics(t, func() {
605			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
606		})
607
608		invalidServerTypes := []string{
609			"",
610			"invalid",
611			"Cloud",      // case sensitive
612			"ON-PREM",    // case sensitive
613			"datacenter", // wrong format
614		}
615
616		for _, invalidType := range invalidServerTypes {
617			// Update the valoper with invalid server type
618			uassert.AbortsWithMessage(t, ErrInvalidServerType.Error(), func() {
619				UpdateServerType(cross, info.Address, invalidType)
620			})
621		}
622	})
623
624	t.Run("successful update", func(t *testing.T) {
625		// Clear the set for the test
626		valopers = avl.NewTree()
627
628		info := validValidatorInfo(t)
629
630		// Set the origin caller
631		testing.SetOriginCaller(test1Address)
632
633		// Send coins
634		testing.SetOriginSend(chain.Coins{minFee})
635
636		// Add the valoper with on-prem server type
637		uassert.NotPanics(t, func() {
638			Register(cross, info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
639		})
640
641		// Update the valoper to cloud
642		uassert.NotPanics(t, func() {
643			UpdateServerType(cross, info.Address, ServerTypeCloud)
644		})
645
646		// Make sure the valoper is updated
647		uassert.NotPanics(t, func() {
648			valoper := GetByAddr(info.Address)
649			uassert.Equal(t, ServerTypeCloud, valoper.ServerType)
650		})
651
652		// Update the valoper to data-center
653		uassert.NotPanics(t, func() {
654			UpdateServerType(cross, info.Address, ServerTypeDataCenter)
655		})
656
657		// Make sure the valoper is updated
658		uassert.NotPanics(t, func() {
659			valoper := GetByAddr(info.Address)
660			uassert.Equal(t, ServerTypeDataCenter, valoper.ServerType)
661		})
662	})
663}