| 1 | package idear |
| 2 | |
| 3 | import "testing" |
| 4 | |
| 5 | // The six spellings every AtLeast case below is drawn from: the three |
| 6 | // valid roles, plus three shapes an app might plausibly hand in — empty, |
| 7 | // upper-cased, and a made-up name — none of which is a role. |
| 8 | const ( |
| 9 | rOwner = RoleOwner |
| 10 | rAdmin = RoleAdmin |
| 11 | rMember = RoleMember |
| 12 | rEmpty = Role("") |
| 13 | rUpper = Role("OWNER") |
| 14 | rBogus = Role("root") |
| 15 | ) |
| 16 | |
| 17 | // TestRole_AtLeast enumerates every ordered pair of the six spellings |
| 18 | // above by hand. Each want is written down, not computed from rank() — |
| 19 | // a table that recomputes the implementation's own formula would only |
| 20 | // prove the formula equals itself. |
| 21 | func TestRole_AtLeast(t *testing.T) { |
| 22 | cases := []struct { |
| 23 | r, min Role |
| 24 | want bool |
| 25 | }{ |
| 26 | // r = owner |
| 27 | {rOwner, rOwner, true}, |
| 28 | {rOwner, rAdmin, true}, |
| 29 | {rOwner, rMember, true}, |
| 30 | {rOwner, rEmpty, false}, |
| 31 | {rOwner, rUpper, false}, |
| 32 | {rOwner, rBogus, false}, |
| 33 | |
| 34 | // r = admin |
| 35 | {rAdmin, rOwner, false}, |
| 36 | {rAdmin, rAdmin, true}, |
| 37 | {rAdmin, rMember, true}, |
| 38 | {rAdmin, rEmpty, false}, |
| 39 | {rAdmin, rUpper, false}, |
| 40 | {rAdmin, rBogus, false}, |
| 41 | |
| 42 | // r = member |
| 43 | {rMember, rOwner, false}, |
| 44 | {rMember, rAdmin, false}, |
| 45 | {rMember, rMember, true}, |
| 46 | {rMember, rEmpty, false}, |
| 47 | {rMember, rUpper, false}, |
| 48 | {rMember, rBogus, false}, |
| 49 | |
| 50 | // r = "" (invalid) — false against every minimum, valid or not |
| 51 | {rEmpty, rOwner, false}, |
| 52 | {rEmpty, rAdmin, false}, |
| 53 | {rEmpty, rMember, false}, |
| 54 | {rEmpty, rEmpty, false}, |
| 55 | {rEmpty, rUpper, false}, |
| 56 | {rEmpty, rBogus, false}, |
| 57 | |
| 58 | // r = "OWNER" (invalid) — false against every minimum, valid or not |
| 59 | {rUpper, rOwner, false}, |
| 60 | {rUpper, rAdmin, false}, |
| 61 | {rUpper, rMember, false}, |
| 62 | {rUpper, rEmpty, false}, |
| 63 | {rUpper, rUpper, false}, |
| 64 | {rUpper, rBogus, false}, |
| 65 | |
| 66 | // r = "root" (invalid) — false against every minimum, valid or not |
| 67 | {rBogus, rOwner, false}, |
| 68 | {rBogus, rAdmin, false}, |
| 69 | {rBogus, rMember, false}, |
| 70 | {rBogus, rEmpty, false}, |
| 71 | {rBogus, rUpper, false}, |
| 72 | {rBogus, rBogus, false}, |
| 73 | } |
| 74 | |
| 75 | if len(cases) != 36 { |
| 76 | t.Fatalf("expected all 36 ordered pairs of 6 spellings, got %d", len(cases)) |
| 77 | } |
| 78 | |
| 79 | for _, c := range cases { |
| 80 | got := c.r.AtLeast(c.min) |
| 81 | if got != c.want { |
| 82 | t.Errorf("Role(%q).AtLeast(%q) = %v, want %v", c.r, c.min, got, c.want) |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | func TestRole_Valid(t *testing.T) { |
| 88 | cases := []struct { |
| 89 | r Role |
| 90 | want bool |
| 91 | }{ |
| 92 | {rOwner, true}, |
| 93 | {rAdmin, true}, |
| 94 | {rMember, true}, |
| 95 | {rEmpty, false}, |
| 96 | {rUpper, false}, |
| 97 | {rBogus, false}, |
| 98 | } |
| 99 | for _, c := range cases { |
| 100 | if got := c.r.Valid(); got != c.want { |
| 101 | t.Errorf("Role(%q).Valid() = %v, want %v", c.r, got, c.want) |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | func TestRole_Title(t *testing.T) { |
| 107 | cases := []struct { |
| 108 | r Role |
| 109 | want string |
| 110 | }{ |
| 111 | {rOwner, "Owner"}, |
| 112 | {rAdmin, "Admin"}, |
| 113 | {rMember, "Member"}, |
| 114 | {rEmpty, ""}, |
| 115 | {rUpper, ""}, |
| 116 | {rBogus, ""}, |
| 117 | } |
| 118 | for _, c := range cases { |
| 119 | if got := c.r.Title(); got != c.want { |
| 120 | t.Errorf("Role(%q).Title() = %q, want %q", c.r, got, c.want) |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | func TestParseRole(t *testing.T) { |
| 126 | accept := []struct { |
| 127 | s string |
| 128 | want Role |
| 129 | }{ |
| 130 | {"owner", RoleOwner}, |
| 131 | {"admin", RoleAdmin}, |
| 132 | {"member", RoleMember}, |
| 133 | } |
| 134 | for _, c := range accept { |
| 135 | got, ok := ParseRole(c.s) |
| 136 | if !ok || got != c.want { |
| 137 | t.Errorf("ParseRole(%q) = (%q, %v), want (%q, true)", c.s, got, ok, c.want) |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | reject := []string{"", "OWNER", "root", "Owner"} |
| 142 | for _, s := range reject { |
| 143 | if got, ok := ParseRole(s); ok { |
| 144 | t.Errorf("ParseRole(%q) = (%q, true), want ok=false", s, got) |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | |