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}