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}