go.chromium.org/luci@v0.0.0-20250314024836-d9a61d0730e6/tokenserver/appengine/impl/utils/identityset/identityset_test.go (about) 1 // Copyright 2016 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package identityset 16 17 import ( 18 "context" 19 "testing" 20 21 "go.chromium.org/luci/auth/identity" 22 "go.chromium.org/luci/common/testing/ftt" 23 "go.chromium.org/luci/common/testing/truth/assert" 24 "go.chromium.org/luci/common/testing/truth/should" 25 "go.chromium.org/luci/server/auth" 26 "go.chromium.org/luci/server/auth/authtest" 27 ) 28 29 func TestFromStrings(t *testing.T) { 30 ftt.Run("Empty", t, func(t *ftt.Test) { 31 s, err := FromStrings(nil, nil) 32 assert.Loosely(t, err, should.BeNil) 33 assert.Loosely(t, s, should.Match(&Set{})) 34 assert.Loosely(t, s.IsEmpty(), should.BeTrue) 35 assert.Loosely(t, s.ToStrings(), should.BeEmpty) 36 }) 37 38 ftt.Run("Universal", t, func(t *ftt.Test) { 39 s, err := FromStrings([]string{"*", "user:abc@example.com"}, nil) 40 assert.Loosely(t, err, should.BeNil) 41 assert.Loosely(t, s, should.Match(&Set{All: true})) 42 assert.Loosely(t, s.IsEmpty(), should.BeFalse) 43 assert.Loosely(t, s.ToStrings(), should.Match([]string{"*"})) 44 }) 45 46 ftt.Run("Normal", t, func(t *ftt.Test) { 47 s, err := FromStrings([]string{ 48 "user:abc@example.com", 49 "user:def@example.com", 50 "user:abc@example.com", 51 "skipped", 52 "group:abc", 53 "group:def", 54 "group:abc", 55 }, func(s string) bool { return s == "skipped" }) 56 assert.Loosely(t, err, should.BeNil) 57 assert.Loosely(t, s, should.Match(&Set{ 58 IDs: identSet{ 59 "user:abc@example.com": struct{}{}, 60 "user:def@example.com": struct{}{}, 61 }, 62 Groups: groupSet{ 63 "abc": struct{}{}, 64 "def": struct{}{}, 65 }, 66 })) 67 assert.Loosely(t, s.IsEmpty(), should.BeFalse) 68 assert.Loosely(t, s.ToStrings(), should.Match([]string{ 69 "group:abc", 70 "group:def", 71 "user:abc@example.com", 72 "user:def@example.com", 73 })) 74 }) 75 76 ftt.Run("Bad group entry", t, func(t *ftt.Test) { 77 s, err := FromStrings([]string{"group:"}, nil) 78 assert.Loosely(t, err, should.ErrLike("invalid entry")) 79 assert.Loosely(t, s, should.BeNil) 80 }) 81 82 ftt.Run("Bad ID entry", t, func(t *ftt.Test) { 83 s, err := FromStrings([]string{"shrug"}, nil) 84 assert.Loosely(t, err, should.ErrLike("bad identity string")) 85 assert.Loosely(t, s, should.BeNil) 86 }) 87 } 88 89 func TestIsMember(t *testing.T) { 90 c := context.Background() 91 c = auth.WithState(c, &authtest.FakeState{ 92 Identity: "user:abc@example.com", 93 IdentityGroups: []string{"abc"}, 94 }) 95 96 ftt.Run("nil", t, func(t *ftt.Test) { 97 var s *Set 98 ok, err := s.IsMember(c, identity.AnonymousIdentity) 99 assert.Loosely(t, err, should.BeNil) 100 assert.Loosely(t, ok, should.BeFalse) 101 }) 102 103 ftt.Run("All", t, func(t *ftt.Test) { 104 s := Set{All: true} 105 ok, err := s.IsMember(c, identity.AnonymousIdentity) 106 assert.Loosely(t, err, should.BeNil) 107 assert.Loosely(t, ok, should.BeTrue) 108 }) 109 110 ftt.Run("Direct hit", t, func(t *ftt.Test) { 111 s, _ := FromStrings([]string{"user:abc@example.com"}, nil) 112 113 ok, err := s.IsMember(c, identity.Identity("user:abc@example.com")) 114 assert.Loosely(t, err, should.BeNil) 115 assert.Loosely(t, ok, should.BeTrue) 116 117 ok, err = s.IsMember(c, identity.AnonymousIdentity) 118 assert.Loosely(t, err, should.BeNil) 119 assert.Loosely(t, ok, should.BeFalse) 120 }) 121 122 ftt.Run("Groups hit", t, func(t *ftt.Test) { 123 s, _ := FromStrings([]string{"group:abc"}, nil) 124 125 ok, err := s.IsMember(c, identity.Identity("user:abc@example.com")) 126 assert.Loosely(t, err, should.BeNil) 127 assert.Loosely(t, ok, should.BeTrue) 128 129 ok, err = s.IsMember(c, identity.AnonymousIdentity) 130 assert.Loosely(t, err, should.BeNil) 131 assert.Loosely(t, ok, should.BeFalse) 132 }) 133 } 134 135 func TestIsSubset(t *testing.T) { 136 empty := &Set{} 137 all := &Set{All: true} 138 some, _ := FromStrings([]string{ 139 "user:abc@example.com", 140 "user:def@example.com", 141 "group:abc", 142 "group:def", 143 }, nil) 144 some1, _ := FromStrings([]string{ 145 "user:abc@example.com", 146 "user:def@example.com", 147 }, nil) 148 some2, _ := FromStrings([]string{ 149 "group:abc", 150 "group:def", 151 }, nil) 152 some3, _ := FromStrings([]string{ 153 "user:abc@example.com", 154 "group:abc", 155 }, nil) 156 some4, _ := FromStrings([]string{ 157 "user:xxx@example.com", 158 "user:yyy@example.com", 159 "group:xxx", 160 "group:yyy", 161 }, nil) 162 163 ftt.Run("empty", t, func(t *ftt.Test) { 164 assert.Loosely(t, empty.IsSubset(empty), should.BeTrue) 165 assert.Loosely(t, empty.IsSubset(all), should.BeTrue) 166 assert.Loosely(t, empty.IsSubset(some), should.BeTrue) 167 168 assert.Loosely(t, empty.IsSuperset(empty), should.BeTrue) // for code coverage 169 }) 170 171 ftt.Run("all", t, func(t *ftt.Test) { 172 assert.Loosely(t, all.IsSubset(empty), should.BeFalse) 173 assert.Loosely(t, all.IsSubset(all), should.BeTrue) 174 assert.Loosely(t, all.IsSubset(some), should.BeFalse) 175 }) 176 177 ftt.Run("some", t, func(t *ftt.Test) { 178 assert.Loosely(t, some.IsSubset(empty), should.BeFalse) 179 assert.Loosely(t, some.IsSubset(all), should.BeTrue) 180 assert.Loosely(t, some.IsSubset(some), should.BeTrue) 181 182 assert.Loosely(t, some1.IsSubset(some), should.BeTrue) 183 assert.Loosely(t, some2.IsSubset(some), should.BeTrue) 184 assert.Loosely(t, some3.IsSubset(some), should.BeTrue) 185 186 assert.Loosely(t, some1.IsSubset(some2), should.BeFalse) 187 assert.Loosely(t, some1.IsSubset(some3), should.BeFalse) 188 assert.Loosely(t, some2.IsSubset(some1), should.BeFalse) 189 assert.Loosely(t, some3.IsSubset(some1), should.BeFalse) 190 191 assert.Loosely(t, some1.IsSubset(some3), should.BeFalse) 192 assert.Loosely(t, some1.IsSubset(some4), should.BeFalse) 193 194 assert.Loosely(t, some2.IsSubset(some3), should.BeFalse) 195 assert.Loosely(t, some2.IsSubset(some4), should.BeFalse) 196 }) 197 } 198 199 func TestUnion(t *testing.T) { 200 empty := &Set{} 201 all := &Set{All: true} 202 some, _ := FromStrings([]string{ 203 "user:abc@example.com", 204 "user:def@example.com", 205 "group:abc", 206 "group:def", 207 }, nil) 208 some1, _ := FromStrings([]string{ 209 "user:abc@example.com", 210 "user:def@example.com", 211 }, nil) 212 some2, _ := FromStrings([]string{ 213 "group:abc", 214 "group:def", 215 }, nil) 216 some3, _ := FromStrings([]string{ 217 "user:abc@example.com", 218 "group:abc", 219 }, nil) 220 221 ftt.Run("empty", t, func(t *ftt.Test) { 222 assert.Loosely(t, Union(), should.Match(empty)) 223 assert.Loosely(t, Union(empty, nil), should.Match(empty)) 224 }) 225 226 ftt.Run("one", t, func(t *ftt.Test) { 227 assert.Loosely(t, Union(some), should.Match(some)) 228 assert.Loosely(t, Union(some, empty), should.Match(some)) 229 }) 230 231 ftt.Run("many", t, func(t *ftt.Test) { 232 assert.Loosely(t, Union(some1, some2, some3, empty), should.Match(some)) 233 }) 234 235 ftt.Run("all", t, func(t *ftt.Test) { 236 assert.Loosely(t, Union(all), should.Match(all)) 237 assert.Loosely(t, Union(all, empty), should.Match(all)) 238 assert.Loosely(t, Union(all, some1), should.Match(all)) 239 }) 240 } 241 242 func TestExtend(t *testing.T) { 243 ftt.Run("Empty", t, func(t *ftt.Test) { 244 assert.Loosely(t, Extend(nil, "user:abc@example.com"), should.Match(&Set{ 245 IDs: identSet{"user:abc@example.com": struct{}{}}, 246 })) 247 }) 248 249 ftt.Run("All", t, func(t *ftt.Test) { 250 all := &Set{All: true} 251 assert.Loosely(t, Extend(all, "user:abc@example.com"), should.Match(all)) 252 }) 253 254 ftt.Run("Already there", t, func(t *ftt.Test) { 255 set, _ := FromStrings([]string{ 256 "user:abc@example.com", 257 "group:abc", 258 }, nil) 259 assert.Loosely(t, Extend(set, "user:abc@example.com"), should.Match(set)) 260 }) 261 262 ftt.Run("Extends", t, func(t *ftt.Test) { 263 set, _ := FromStrings([]string{ 264 "user:def@example.com", 265 "group:abc", 266 }, nil) 267 assert.Loosely(t, Extend(set, "user:abc@example.com"), should.Match(&Set{ 268 IDs: identSet{ 269 "user:abc@example.com": struct{}{}, 270 "user:def@example.com": struct{}{}, 271 }, 272 Groups: groupSet{"abc": struct{}{}}, 273 })) 274 }) 275 }