Skip to content

Commit bbd1c4c

Browse files
committed
test: Roles, sets, permissions, iterators
1 parent a419a65 commit bbd1c4c

File tree

6 files changed

+164
-12
lines changed

6 files changed

+164
-12
lines changed

coderd/authz/authztest/iterator_test.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,41 @@ import (
1111
)
1212

1313
func TestUnion(t *testing.T) {
14-
for i := 0; i < 10; i++ {
14+
for i := 0; i < 100; i++ {
1515
allPerms := make(authztest.Set, 0)
1616
// 2 - 4 sets
17-
sets := make([]authztest.Set, 2+must(crand.Intn(2)))
17+
sets := make([]authztest.Set, 1+must(crand.Intn(2)))
1818
for j := range sets {
19-
sets[j] = make(authztest.Set, 1+must(crand.Intn(4)))
19+
sets[j] = RandomSet(1 + must(crand.Intn(4)))
2020
allPerms = append(allPerms, sets[j]...)
2121
}
2222

23-
u := authztest.Union(sets...)
24-
require.Equal(t, len(allPerms), u.Size(), "union set total")
25-
require.Equal(t, 1, u.ReturnSize(), "union ret size is 1")
23+
ui := authztest.Union(sets...).Iterator()
24+
require.Equal(t, len(allPerms), ui.Size(), "union set total")
25+
require.Equal(t, 1, ui.ReturnSize(), "union ret size is 1")
2626
for c := 0; ; c++ {
27-
require.Equal(t, allPerms[c], u.Permission(), "permission order")
28-
require.Equal(t, 1, len(u.Permissions()), "permissions size")
29-
require.Equal(t, allPerms[c], u.Permissions()[0], "permission order")
30-
if !u.Next() {
27+
require.Equal(t, 1, len(ui.Permissions()), "permissions size")
28+
require.Equal(t, allPerms[c], ui.Permissions()[0], "permission order")
29+
if !ui.Next() {
3130
break
3231
}
3332
}
3433

35-
u.Reset()
36-
require.True(t, u.Next(), "reset should make next true again")
34+
ui.Reset()
35+
// If the size is 1, next will always return false
36+
if ui.Size() > 1 {
37+
require.True(t, ui.Next(), "reset should make next true again")
38+
}
39+
}
40+
}
41+
42+
func RandomSet(size int) authztest.Set {
43+
set := make(authztest.Set, 0, size)
44+
for i := 0; i < size; i++ {
45+
p := RandomPermission()
46+
set = append(set, &p)
3747
}
48+
return set
3849
}
3950

4051
func RandomPermission() authz.Permission {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package authztest_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/coderd/authz/authztest"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func Test_AllPermissions(t *testing.T) {
11+
// If this changes, then we might have to fix some other tests. This constant
12+
// is the basis for understanding the permutation counts.
13+
const totalUniquePermissions int = 270
14+
require.Equal(t, len(authztest.AllPermissions()), totalUniquePermissions, "expected set size")
15+
}

coderd/authz/authztest/role.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ func (r *Role) Each(ea func(set Set)) {
6565
}
6666

6767
// Next will grab the next cross-product permutation of all permissions of r.
68+
// When Next() returns false, the role would be Reset()
6869
func (r *Role) Next() bool {
6970
for i := range r.PermissionSets {
7071
if r.PermissionSets[i].Next() {

coderd/authz/authztest/role_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package authztest_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/coderd/authz/authztest"
7+
crand "github.com/coder/coder/cryptorand"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func Test_NewRole(t *testing.T) {
12+
for i := 0; i < 50; i++ {
13+
sets := make([]authztest.Iterable, 1+(i%4))
14+
var total int = 1
15+
for j := range sets {
16+
size := 1 + must(crand.Intn(3))
17+
if i < 5 {
18+
// Enforce 1 size sets for some cases
19+
size = 1
20+
}
21+
sets[j] = RandomSet(size)
22+
total *= size
23+
}
24+
25+
crossProduct := authztest.NewRole(sets...)
26+
t.Run("CrossProduct", func(t *testing.T) {
27+
require.Equal(t, total, crossProduct.Size(), "correct N")
28+
require.Equal(t, len(sets), crossProduct.ReturnSize(), "return size")
29+
var c int
30+
crossProduct.Each(func(set authztest.Set) {
31+
require.Equal(t, crossProduct.ReturnSize(), len(set), "each set is correct size")
32+
c++
33+
})
34+
require.Equal(t, total, c, "each run N times")
35+
36+
if crossProduct.Size() > 1 {
37+
crossProduct.Reset()
38+
require.Truef(t, crossProduct.Next(), "reset should always make this true")
39+
}
40+
})
41+
42+
t.Run("NestedRoles", func(t *testing.T) {
43+
merged := authztest.NewRole(sets[0])
44+
for i := 1; i < len(sets); i++ {
45+
merged = authztest.NewRole(sets[i], merged)
46+
}
47+
48+
crossProduct.Reset()
49+
for {
50+
require.Equal(t, crossProduct.Permissions(), merged.Permissions(), "same next")
51+
mn, cn := merged.Next(), crossProduct.Next()
52+
require.Equal(t, cn, mn, "next should be same")
53+
if !cn {
54+
break
55+
}
56+
}
57+
})
58+
}
59+
}

coderd/authz/authztest/set.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ type Set []*authz.Permission
1010

1111
var _ Iterable = (Set)(nil)
1212

13+
// Permissions is a helper function to get the Permissions as non-pointers.
14+
// <nil> permissions are omitted
1315
func (s Set) Permissions() []authz.Permission {
1416
perms := make([]authz.Permission, 0, len(s))
1517
for i := range s {

coderd/authz/authztest/set_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package authztest_test
2+
3+
import (
4+
"github.com/coder/coder/coderd/authz"
5+
"github.com/coder/coder/coderd/authz/authztest"
6+
"testing"
7+
8+
crand "github.com/coder/coder/cryptorand"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func Test_Set(t *testing.T) {
13+
t.Run("Simple", func(t *testing.T) {
14+
for i := 0; i < 10; i++ {
15+
set := RandomSet(i)
16+
require.Equal(t, i, len(set), "set size")
17+
require.Equal(t, i, len(set.Permissions()), "set size")
18+
perms := set.Permissions()
19+
for i, p := range set {
20+
require.Equal(t, *p, perms[i])
21+
}
22+
}
23+
})
24+
25+
t.Run("NilPerms", func(t *testing.T) {
26+
for i := 0; i < 100; i++ {
27+
set := RandomSet(i)
28+
// Set some nils
29+
nilCount := 0
30+
for i := 0; i < len(set); i++ {
31+
if must(crand.Bool()) {
32+
set[i] = nil
33+
nilCount++
34+
}
35+
}
36+
require.Equal(t, i-nilCount, len(set.Permissions()))
37+
}
38+
})
39+
40+
t.Run("String", func(t *testing.T) {
41+
set := authztest.Set{
42+
&authz.Permission{
43+
Sign: true,
44+
Level: authz.LevelOrg,
45+
LevelID: "1234",
46+
ResourceType: authz.ResourceWorkspace,
47+
ResourceID: "1234",
48+
Action: authz.ActionRead,
49+
},
50+
&authz.Permission{
51+
Sign: false,
52+
Level: authz.LevelSite,
53+
LevelID: "",
54+
ResourceType: authz.ResourceWorkspace,
55+
ResourceID: "*",
56+
Action: authz.ActionRead,
57+
},
58+
}
59+
60+
require.Equal(t,
61+
"+org:1234.workspace.1234.read, -site.workspace.*.read",
62+
set.String(), "exp string")
63+
})
64+
}

0 commit comments

Comments
 (0)