package svcrole import ( "reflect" "strings" "testing" ) func TestParse(t *testing.T) { for _, want := range All() { got, ok := Parse(string(want)) if !ok || got != want { t.Errorf("Parse(%q) = %q,%v; want %q,true", want, got, ok, want) } } // A role name that is not in the catalogue must not parse. "" is the // value a person's row carries, and it must never resolve to a role. for _, bad := range []string{"", "owner", "member", "Publish", "admin ", "root"} { if got, ok := Parse(bad); ok { t.Errorf("Parse(%q) = %q,true; want false", bad, got) } } } func TestAdminPermitsEveryNonEmptySet(t *testing.T) { // Admin is defined as the union, so it reaches every door that names any // role at all — including doors that name only Admin. for _, s := range []Set{ Allow(Publish), Allow(Instance), Allow(Operate), Allow(Admin), Allow(Publish, Operate), } { if !s.Permits(Admin) { t.Errorf("Allow(%v).Permits(Admin) = false; want true", s.Roles()) } } // Admin is the union of every role EXCEPT Run, so an Allow set never // carries Run on Admin's account either. if Allow(Publish).Permits(Run) { t.Error("Allow(Publish).Permits(Run) = true; want false") } } func TestExactlySetsAdmitOnlyTheirRoles(t *testing.T) { // An Exactly set admits only its listed roles, Admin included. for _, s := range []Set{Exactly(Run), Exactly(Run, Publish), Exactly(Publish), Exactly(Admin)} { for _, r := range All() { listed := false for _, l := range s.Roles() { listed = listed || l == r } if s.Permits(r) != listed { t.Errorf("Exactly set %v: Permits(%q) = %v; want %v", s.Roles(), r, s.Permits(r), listed) } } } } func TestExactlyWithNoRolesIsEmptyAndClosed(t *testing.T) { s := Exactly() if !s.Empty() { t.Error("Exactly().Empty() = false; want true") } for _, r := range append(All(), Role("")) { if s.Permits(r) { t.Errorf("Exactly().Permits(%q) = true; want false", r) } } } func TestAllowRefusesRun(t *testing.T) { // Every Allow set carries Admin, so Allow(Run) would hand Admin a run // door. Both the bare and the mixed form must panic, and name Exactly. for _, roles := range [][]Role{{Run}, {Publish, Run}, {Run, Operate}} { func() { defer func() { got := recover() if got == nil { t.Errorf("Allow(%v) did not panic", roles) return } if msg, _ := got.(string); !strings.Contains(msg, "Exactly(Run)") { t.Errorf("Allow(%v) panic = %v; want it to say to use Exactly(Run)", roles, got) } }() Allow(roles...) }() } } func TestRunIsInTheCatalogue(t *testing.T) { got, ok := Parse("run") if !ok || got != Run { t.Fatalf(`Parse("run") = %q, %v; want %q, true`, got, ok, Run) } found := false for _, r := range All() { found = found || r == Run } if !found { t.Errorf("All() = %v; want it to contain run", All()) } } func TestExactlyDoesNotAddAdmin(t *testing.T) { s := Exactly(Run) if !s.Permits(Run) { t.Error("Exactly(Run).Permits(Run) = false; want true") } for _, r := range All() { if r != Run && s.Permits(r) { t.Errorf("Exactly(Run).Permits(%q) = true; want false", r) } } if s.Permits(Admin) { t.Error("Exactly(Run).Permits(Admin) = true; want false") } if got := s.Roles(); !reflect.DeepEqual(got, []Role{Run}) { t.Errorf("Exactly(Run).Roles() = %v; want [run]", got) } } func TestExactlyPanicsOnAnUnknownRole(t *testing.T) { for _, bad := range []Role{"", "rnu", "Run"} { func() { defer func() { if recover() == nil { t.Errorf("Exactly(%q) did not panic", bad) } }() Exactly(bad) }() } defer func() { if recover() == nil { t.Error("Exactly(Run, invalid) did not panic") } }() Exactly(Run, Role("rnu")) } func TestAllowIsExactForNonAdmin(t *testing.T) { s := Allow(Publish) if !s.Permits(Publish) { t.Error("Allow(Publish).Permits(Publish) = false; want true") } for _, r := range []Role{Instance, Operate} { if s.Permits(r) { t.Errorf("Allow(Publish).Permits(%q) = true; want false", r) } } } func TestEmptySetPermitsNothingIncludingAdmin(t *testing.T) { // The zero Set is what a door gets if someone constructs one by mistake. // It must be closed, not open, and Admin must not be an escape hatch // through it — otherwise "forgot to name a role" reads as "admin-only" // rather than as the refusal it is. var s Set if !s.Empty() { t.Fatal("zero Set.Empty() = false; want true") } for _, r := range append(All(), Role("")) { if s.Permits(r) { t.Errorf("zero Set.Permits(%q) = true; want false", r) } } } func TestUnknownRoleNeverPermitted(t *testing.T) { s := Allow(Publish, Instance, Operate, Admin) for _, r := range []Role{"", "owner", "wildcard", "*"} { if s.Permits(r) { t.Errorf("Permits(%q) = true; want false", r) } } } func TestRolesIsSortedAndDeduplicated(t *testing.T) { // Admin is always present: Allow adds it from the union definition, so a // door naming Publish twice is the set {admin, publish}, sorted. got := Allow(Operate, Publish, Publish).Roles() want := []Role{Admin, Operate, Publish} if !reflect.DeepEqual(got, want) { t.Errorf("Roles() = %v; want %v", got, want) } } func TestAllowPanicsOnAnUnknownRole(t *testing.T) { // A dropped role would be a door silently narrowed — see Allow's comment. // Registration runs once at server start, so this is the cheapest place // for a typo to surface. for _, bad := range []Role{"", "oprate", "Publish", "root"} { func() { defer func() { if recover() == nil { t.Errorf("Allow(%q) did not panic", bad) } }() Allow(bad) }() } // A typo MIXED WITH valid roles is the dangerous case: it would otherwise // produce a plausible Set with the mistyped door quietly missing. defer func() { if recover() == nil { t.Error("Allow(Publish, invalid) did not panic") } }() Allow(Publish, Role("oprate")) } func TestEmptyDistinguishesTheTwoForms(t *testing.T) { if s := Allow(); !s.Empty() { t.Error("Allow() should be the empty Set — the deliberate closed-door form") } if s := Allow(Publish); s.Empty() { t.Error("Allow(Publish).Empty() = true; Empty must not be unconditionally true") } } func TestDeployIsMintableAndNarrow(t *testing.T) { got, ok := Parse("deploy") if !ok || got != Deploy { t.Fatalf("Parse(\"deploy\") = %q, %v", got, ok) } all := All() if len(all) < 2 || all[0] != Publish || all[1] != Deploy { t.Fatalf("All() = %v; want deploy right after publish", all) } // Existing doors do not admit it: adding a role must not widen anything. for _, door := range []Set{Allow(Publish), Allow(Instance), Allow(Operate), Allow(Service)} { if door.Permits(Deploy) { t.Fatalf("%v admits deploy", door.Roles()) } } if !Allow(Deploy).Permits(Admin) { t.Fatal("Allow adds Admin to every set; that changed") } }