permissions_test.gno
19.86 Kb · 714 lines
1package permissions
2
3import (
4 "testing"
5
6 "gno.land/p/gnoland/boards/v0"
7 "gno.land/p/nt/uassert/v0"
8 "gno.land/p/nt/urequire/v0"
9)
10
11// Test permission constants
12const (
13 testPermA boards.Permission = iota
14 testPermB
15 testPermC
16)
17
18var _ boards.Permissions = (*Permissions)(nil)
19
20func TestBasicPermissionsWithPermission(cur realm, t *testing.T) {
21 cases := []struct {
22 name string
23 user address
24 permission boards.Permission
25 args boards.Args
26 setup func() *Permissions
27 err string
28 called bool
29 }{
30 {
31 name: "ok",
32 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
33 permission: testPermA,
34 setup: func() *Permissions {
35 perms := New()
36 perms.AddRole("foo", testPermA)
37 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
38 return perms
39 },
40 called: true,
41 },
42 {
43 name: "ok with arguments",
44 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
45 permission: testPermA,
46 args: boards.Args{"a", "b"},
47 setup: func() *Permissions {
48 perms := New()
49 perms.AddRole("foo", testPermA)
50 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
51 return perms
52 },
53 called: true,
54 },
55 {
56 name: "no permission",
57 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
58 permission: testPermA,
59 setup: func() *Permissions {
60 perms := New()
61 perms.AddRole("foo", testPermA)
62 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
63 return perms
64 },
65 err: "unauthorized, user g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 doesn't have the required permission",
66 },
67 {
68 name: "is not a member",
69 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
70 permission: testPermA,
71 setup: func() *Permissions {
72 return New()
73 },
74 err: "unauthorized, user g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 doesn't have the required permission",
75 },
76 }
77
78 for _, tc := range cases {
79 t.Run(tc.name, func(t *testing.T) {
80 var called bool
81
82 perms := tc.setup()
83 testCaseFn := func() {
84 perms.WithPermission(tc.user, tc.permission, tc.args, func() {
85 called = true
86 })
87 }
88
89 if tc.err != "" {
90 urequire.PanicsWithMessage(t, cur, tc.err, testCaseFn, "expect panic with message")
91 return
92 } else {
93 urequire.NotPanics(t, cur, testCaseFn, "expect no panic")
94 }
95
96 urequire.Equal(t, tc.called, called, "expect callback to be called")
97 })
98 }
99}
100
101func TestBasicPermissionsSetPublicPermissions(t *testing.T) {
102 user := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
103 perms := New()
104
105 // Add a new role with permissions
106 perms.AddRole("adminRole", testPermA, testPermB, testPermC)
107 urequire.False(t, perms.HasPermission(user, testPermA))
108 urequire.False(t, perms.HasPermission(user, testPermB))
109 urequire.False(t, perms.HasPermission(user, testPermC))
110
111 // Assign a couple of public permissions
112 perms.SetPublicPermissions(testPermA, testPermC)
113 urequire.True(t, perms.HasPermission(user, testPermA))
114 urequire.False(t, perms.HasPermission(user, testPermB))
115 urequire.True(t, perms.HasPermission(user, testPermC))
116
117 // Clear all public permissions
118 perms.SetPublicPermissions()
119 urequire.False(t, perms.HasPermission(user, testPermA))
120 urequire.False(t, perms.HasPermission(user, testPermB))
121 urequire.False(t, perms.HasPermission(user, testPermC))
122}
123
124func TestBasicPermissionsGetUserRoles(t *testing.T) {
125 cases := []struct {
126 name string
127 user address
128 roles []string
129 setup func() *Permissions
130 }{
131 {
132 name: "single role",
133 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
134 roles: []string{"admin"},
135 setup: func() *Permissions {
136 perms := New()
137 perms.AddRole("admin", testPermA)
138 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "admin")
139 return perms
140 },
141 },
142 {
143 name: "multiple roles",
144 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
145 roles: []string{"admin", "bar", "foo"},
146 setup: func() *Permissions {
147 perms := New()
148 perms.AddRole("admin", testPermA)
149 perms.AddRole("foo", testPermA)
150 perms.AddRole("bar", testPermA)
151 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "admin", "foo", "bar")
152 return perms
153 },
154 },
155 {
156 name: "without roles",
157 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
158 setup: func() *Permissions {
159 perms := New()
160 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
161 return perms
162 },
163 },
164 {
165 name: "not a user",
166 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
167 setup: func() *Permissions {
168 return New()
169 },
170 },
171 {
172 name: "multiple users",
173 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
174 roles: []string{"admin"},
175 setup: func() *Permissions {
176 perms := New()
177 perms.AddRole("admin", testPermA)
178 perms.AddRole("bar", testPermA)
179 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "admin")
180 perms.SetUserRoles("g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn", "admin")
181 perms.SetUserRoles("g1w4ek2u3jta047h6lta047h6lta047h6l9huexc", "admin", "bar")
182 return perms
183 },
184 },
185 }
186
187 for _, tc := range cases {
188 t.Run(tc.name, func(t *testing.T) {
189 perms := tc.setup()
190 roles := perms.GetUserRoles(tc.user)
191
192 urequire.Equal(t, len(tc.roles), len(roles), "user role count")
193 for i, r := range roles {
194 uassert.Equal(t, tc.roles[i], string(r))
195 }
196 })
197 }
198}
199
200func TestBasicPermissionsHasRole(t *testing.T) {
201 cases := []struct {
202 name string
203 user address
204 role boards.Role
205 setup func() *Permissions
206 want bool
207 }{
208 {
209 name: "ok",
210 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
211 role: "admin",
212 setup: func() *Permissions {
213 perms := New()
214 perms.AddRole("admin", testPermA)
215 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "admin")
216 return perms
217 },
218 want: true,
219 },
220 {
221 name: "ok with multiple roles",
222 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
223 role: "foo",
224 setup: func() *Permissions {
225 perms := New()
226 perms.AddRole("admin", testPermA)
227 perms.AddRole("foo", testPermA)
228 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "admin", "foo")
229 return perms
230 },
231 want: true,
232 },
233 {
234 name: "user without roles",
235 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
236 setup: func() *Permissions {
237 perms := New()
238 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
239 return perms
240 },
241 },
242 {
243 name: "has no role",
244 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
245 role: "bar",
246 setup: func() *Permissions {
247 perms := New()
248 perms.AddRole("foo", testPermA)
249 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
250 return perms
251 },
252 },
253 }
254
255 for _, tc := range cases {
256 t.Run(tc.name, func(t *testing.T) {
257 perms := tc.setup()
258 got := perms.HasRole(tc.user, tc.role)
259 uassert.Equal(t, tc.want, got)
260 })
261 }
262}
263
264func TestBasicPermissionsHasPermission(t *testing.T) {
265 cases := []struct {
266 name string
267 user address
268 permission boards.Permission
269 setup func() *Permissions
270 want bool
271 }{
272 {
273 name: "ok",
274 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
275 permission: testPermA,
276 setup: func() *Permissions {
277 perms := New()
278 perms.AddRole("foo", testPermA)
279 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
280 return perms
281 },
282 want: true,
283 },
284 {
285 name: "ok with multiple users",
286 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
287 permission: testPermA,
288 setup: func() *Permissions {
289 perms := New()
290 perms.AddRole("foo", testPermA)
291 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
292 perms.SetUserRoles("g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn", "foo")
293 return perms
294 },
295 want: true,
296 },
297 {
298 name: "ok with multiple roles",
299 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
300 permission: testPermB,
301 setup: func() *Permissions {
302 perms := New()
303 perms.AddRole("foo", testPermA)
304 perms.AddRole("baz", testPermB)
305 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo", "baz")
306 return perms
307 },
308 want: true,
309 },
310 {
311 name: "no permission",
312 user: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
313 permission: testPermB,
314 setup: func() *Permissions {
315 perms := New()
316 perms.AddRole("foo", testPermA)
317 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "foo")
318 return perms
319 },
320 },
321 }
322
323 for _, tc := range cases {
324 t.Run(tc.name, func(t *testing.T) {
325 perms := tc.setup()
326 got := perms.HasPermission(tc.user, tc.permission)
327 uassert.Equal(t, tc.want, got)
328 })
329 }
330}
331
332func TestBasicPermissionsSetUserRoles(cur realm, t *testing.T) {
333 cases := []struct {
334 name string
335 user address
336 expectedRoles []boards.Role
337 setup func() *Permissions
338 err string
339 }{
340 {
341 name: "add user",
342 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
343 expectedRoles: []boards.Role{"a"},
344 setup: func() *Permissions {
345 perms := New()
346 perms.AddRole("a", testPermA)
347 return perms
348 },
349 },
350 {
351 name: "add user with multiple roles",
352 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
353 expectedRoles: []boards.Role{"a", "b"},
354 setup: func() *Permissions {
355 perms := New()
356 perms.AddRole("a", testPermA)
357 perms.AddRole("b", testPermB)
358 return perms
359 },
360 },
361 {
362 name: "add when other users exists",
363 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
364 expectedRoles: []boards.Role{"a"},
365 setup: func() *Permissions {
366 perms := New()
367 perms.AddRole("a", testPermA)
368 perms.SetUserRoles("g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn", "a")
369 perms.SetUserRoles("g1w4ek2u3jta047h6lta047h6lta047h6l9huexc")
370 return perms
371 },
372 },
373 {
374 name: "add user using single role",
375 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
376 expectedRoles: []boards.Role{"a"},
377 setup: func() *Permissions {
378 perms := New(UseSingleUserRole())
379 perms.AddRole("a", testPermA)
380 return perms
381 },
382 },
383 {
384 name: "update user roles",
385 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
386 expectedRoles: []boards.Role{"a", "b"},
387 setup: func() *Permissions {
388 perms := New()
389 perms.AddRole("a", testPermA)
390 perms.AddRole("b", testPermB)
391 perms.AddRole("c", testPermB)
392 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "c")
393 return perms
394 },
395 },
396 {
397 name: "update user roles using single role",
398 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
399 expectedRoles: []boards.Role{"b"},
400 setup: func() *Permissions {
401 perms := New(UseSingleUserRole())
402 perms.AddRole("a", testPermA)
403 perms.AddRole("b", testPermB)
404 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "a")
405 return perms
406 },
407 },
408 {
409 name: "clear user roles",
410 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
411 expectedRoles: []boards.Role{},
412 setup: func() *Permissions {
413 perms := New()
414 perms.AddRole("a", testPermA)
415 perms.AddRole("b", testPermB)
416 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "a", "b")
417 return perms
418 },
419 },
420 {
421 name: "set invalid role",
422 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
423 expectedRoles: []boards.Role{"a", "foo"},
424 setup: func() *Permissions {
425 perms := New()
426 perms.AddRole("a", testPermA)
427 return perms
428 },
429 err: "invalid role: foo",
430 },
431 {
432 name: "use single role error",
433 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
434 expectedRoles: []boards.Role{"a", "b"},
435 setup: func() *Permissions {
436 perms := New(UseSingleUserRole())
437 perms.AddRole("a", testPermA)
438 perms.AddRole("b", testPermB)
439 return perms
440 },
441 err: "user can only have one role",
442 },
443 }
444
445 for _, tc := range cases {
446 t.Run(tc.name, func(t *testing.T) {
447 perms := tc.setup()
448
449 setUserRoles := func() {
450 perms.SetUserRoles(tc.user, tc.expectedRoles...)
451 }
452
453 if tc.err != "" {
454 urequire.PanicsWithMessage(t, cur, tc.err, setUserRoles, "expected an error")
455 return
456 } else {
457 urequire.NotPanics(t, cur, setUserRoles, "expected no error")
458 }
459
460 roles := perms.GetUserRoles(tc.user)
461 uassert.Equal(t, len(tc.expectedRoles), len(roles))
462 for i, r := range roles {
463 urequire.Equal(t, string(tc.expectedRoles[i]), string(r))
464 }
465 })
466 }
467}
468
469func TestBasicPermissionsAddRoleOverwrite(t *testing.T) {
470 user := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
471
472 perms := New()
473 perms.AddRole("foo", testPermA)
474 perms.SetUserRoles(user, "foo")
475
476 // Re-adding an existing role replaces its permissions and keeps members
477 perms.AddRole("foo", testPermB)
478 uassert.True(t, perms.HasRole(user, "foo"), "expect role members to be kept")
479 uassert.False(t, perms.HasPermission(user, testPermA), "expect old permissions to be revoked")
480 uassert.True(t, perms.HasPermission(user, testPermB), "expect new permissions to be granted")
481}
482
483func TestBasicPermissionsAddRoleEmptyName(cur realm, t *testing.T) {
484 urequire.PanicsWithMessage(t, cur, "role name is required", func() {
485 New().AddRole(" ", testPermA)
486 }, "expect whitespace only role names to be rejected")
487
488 urequire.PanicsWithMessage(t, cur, "permissions super role name is required", func() {
489 New(WithSuperRole(" "))
490 }, "expect whitespace only super role names to be rejected")
491
492 // The empty string is rejected before the superRole sentinel check, so
493 // the outcome doesn't depend on whether a super role is configured.
494 urequire.PanicsWithMessage(t, cur, "role name is required", func() {
495 New().AddRole("", testPermA)
496 }, "expect empty role name to be rejected without a super role")
497 urequire.PanicsWithMessage(t, cur, "role name is required", func() {
498 New(WithSuperRole("owner")).AddRole("", testPermA)
499 }, "expect empty role name to be rejected with a super role")
500}
501
502func TestBasicPermissionsSuperRole(t *testing.T) {
503 user := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
504 super := boards.Role("owner")
505
506 perms := New(WithSuperRole(super))
507 urequire.True(t, perms.RoleExists(super), "expect super role to exist")
508 urequire.False(t, perms.RoleExists("unknown"))
509
510 // Super role members get every permission without explicit mapping
511 perms.SetUserRoles(user, super)
512 urequire.True(t, perms.HasRole(user, super))
513 uassert.True(t, perms.HasUser(user))
514 uassert.True(t, perms.HasPermission(user, testPermA))
515 uassert.True(t, perms.HasPermission(user, testPermC))
516
517 // AddRole on the super role is a no-op: the super role branch grants
518 // every permission regardless of any meta a mapping would set
519 perms.AddRole(super, testPermB)
520 uassert.True(t, perms.HasPermission(user, testPermA), "expect super role to keep all permissions")
521}
522
523func TestBasicPermissionsHasUserUsersCount(t *testing.T) {
524 member := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
525 guest := address("g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn")
526
527 perms := New()
528 perms.AddRole("foo", testPermA)
529 urequire.Equal(t, 0, perms.UsersCount())
530 urequire.False(t, perms.HasUser(member))
531
532 // A user added only through a role counts as a user
533 perms.SetUserRoles(member, "foo")
534 urequire.True(t, perms.HasUser(member), "expect role holder to be a user")
535 urequire.Equal(t, 1, perms.UsersCount())
536
537 // A guest without roles counts as a user
538 perms.SetUserRoles(guest)
539 urequire.True(t, perms.HasUser(guest))
540 urequire.Equal(t, 2, perms.UsersCount())
541
542 // Clearing roles keeps the user and doesn't change the count
543 perms.SetUserRoles(member)
544 urequire.True(t, perms.HasUser(member), "expect user to remain after roles are cleared")
545 urequire.Equal(t, 2, perms.UsersCount())
546
547 // Re-assigning roles must not double count
548 perms.SetUserRoles(member, "foo")
549 urequire.Equal(t, 2, perms.UsersCount())
550}
551
552func TestBasicPermissionsSetUserRolesPanicKeepsState(cur realm, t *testing.T) {
553 user := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
554
555 perms := New()
556 perms.AddRole("a", testPermA)
557 perms.SetUserRoles(user, "a")
558
559 urequire.PanicsWithMessage(t, cur, "invalid role: nope", func() {
560 perms.SetUserRoles(user, "nope")
561 }, "expect invalid role to panic")
562
563 // The failed call must not have mutated state
564 uassert.True(t, perms.HasUser(user))
565 uassert.True(t, perms.HasRole(user, "a"))
566 uassert.Equal(t, 1, perms.UsersCount())
567}
568
569func TestBasicPermissionsRemoveUser(t *testing.T) {
570 cases := []struct {
571 name string
572 user address
573 setup func() *Permissions
574 want bool
575 }{
576 {
577 name: "ok",
578 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
579 setup: func() *Permissions {
580 perms := New()
581 perms.SetUserRoles("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
582 return perms
583 },
584 want: true,
585 },
586 {
587 name: "user not found",
588 user: address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
589 setup: func() *Permissions {
590 return New()
591 },
592 },
593 }
594
595 for _, tc := range cases {
596 t.Run(tc.name, func(t *testing.T) {
597 perms := tc.setup()
598 got := perms.RemoveUser(tc.user)
599 uassert.Equal(t, tc.want, got)
600 })
601 }
602}
603
604func TestBasicPermissionsRemoveUserWithRoles(t *testing.T) {
605 user := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
606
607 perms := New()
608 perms.AddRole("foo", testPermA)
609 perms.AddRole("bar", testPermB)
610 perms.SetUserRoles(user, "foo", "bar")
611
612 urequire.True(t, perms.RemoveUser(user), "expect role holder to be removed")
613
614 uassert.False(t, perms.HasUser(user), "expect removed user to not exist")
615 uassert.False(t, perms.HasRole(user, "foo"), "expect removed user to keep no roles")
616 uassert.False(t, perms.HasPermission(user, testPermA), "expect removed user to keep no permissions")
617 uassert.Equal(t, 0, len(perms.GetUserRoles(user)))
618 uassert.Equal(t, 0, perms.UsersCount())
619 uassert.False(t, perms.RemoveUser(user), "expect second removal to report user not found")
620}
621
622func TestBasicPermissionsIterateUsers(t *testing.T) {
623 // Users are listed sorted by address, including a roleless guest.
624 users := []boards.User{
625 {
626 Address: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5",
627 Roles: []boards.Role{"foo"},
628 },
629 {
630 Address: "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj",
631 Roles: []boards.Role{"bar", "foo"},
632 },
633 {
634 Address: "g1vh7krmmzfua5xjmkatvmx09z37w34lsvd2mxa5",
635 Roles: []boards.Role{"bar"},
636 },
637 {
638 Address: "g1w4ek2u33ta047h6lta047h6lta047h6ldvdwpn",
639 },
640 }
641
642 perms := New()
643 perms.AddRole("foo", testPermA)
644 perms.AddRole("bar", testPermB)
645 // Add users in reverse order to pin that iteration is address-sorted,
646 // not insertion-ordered.
647 for i := len(users) - 1; i >= 0; i-- {
648 perms.SetUserRoles(users[i].Address, users[i].Roles...)
649 }
650
651 cases := []struct {
652 name string
653 start, count, want int
654 }{
655 {
656 name: "exceed users count",
657 count: 50,
658 want: 4,
659 },
660 {
661 name: "exact users count",
662 count: 4,
663 want: 4,
664 },
665 {
666 name: "two users",
667 start: 1,
668 count: 2,
669 want: 2,
670 },
671 {
672 name: "one user",
673 start: 1,
674 count: 1,
675 want: 1,
676 },
677 {
678 name: "no iteration",
679 start: 50,
680 count: 1,
681 },
682 }
683
684 for _, tc := range cases {
685 t.Run(tc.name, func(t *testing.T) {
686 var visited int
687 stopped := perms.IterateUsers(tc.start, tc.count, func(u boards.User) bool {
688 i := tc.start + visited
689 urequire.True(t, i < len(users), "expect iterator to respect number of users")
690 uassert.Equal(t, users[i].Address, u.Address)
691
692 urequire.Equal(t, len(users[i].Roles), len(u.Roles), "expect number of roles to match")
693 for j := range u.Roles {
694 uassert.Equal(t, string(users[i].Roles[j]), string(u.Roles[j]))
695 }
696
697 visited++
698 return false
699 })
700
701 uassert.False(t, stopped, "expect full iteration not to report an early stop")
702 uassert.Equal(t, tc.want, visited, "expect iterator to visit the windowed users")
703 })
704 }
705
706 // Early stop is reported, and iteration actually halts.
707 var visited int
708 stopped := perms.IterateUsers(0, 10, func(boards.User) bool {
709 visited++
710 return true
711 })
712 uassert.True(t, stopped, "expect early stop to be reported")
713 uassert.Equal(t, 1, visited, "expect iteration to halt on early stop")
714}