github.com/opcr-io/oras-go/v2@v2.0.0-20231122155130-eb4260d8a0ae/registry/remote/auth/scope_test.go (about) 1 /* 2 Copyright The ORAS Authors. 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 16 package auth 17 18 import ( 19 "context" 20 "reflect" 21 "testing" 22 ) 23 24 func TestScopeRepository(t *testing.T) { 25 tests := []struct { 26 name string 27 repository string 28 actions []string 29 want string 30 }{ 31 { 32 name: "empty repository", 33 actions: []string{ 34 "pull", 35 }, 36 }, 37 { 38 name: "nil actions", 39 repository: "foo", 40 }, 41 { 42 name: "empty actions", 43 repository: "foo", 44 actions: []string{}, 45 }, 46 { 47 name: "empty actions list", 48 repository: "foo", 49 actions: []string{}, 50 }, 51 { 52 name: "empty actions", 53 repository: "foo", 54 actions: []string{ 55 "", 56 }, 57 }, 58 { 59 name: "single action", 60 repository: "foo", 61 actions: []string{ 62 "pull", 63 }, 64 want: "repository:foo:pull", 65 }, 66 { 67 name: "multiple actions", 68 repository: "foo", 69 actions: []string{ 70 "pull", 71 "push", 72 }, 73 want: "repository:foo:pull,push", 74 }, 75 { 76 name: "unordered actions", 77 repository: "foo", 78 actions: []string{ 79 "push", 80 "pull", 81 }, 82 want: "repository:foo:pull,push", 83 }, 84 { 85 name: "duplicated actions", 86 repository: "foo", 87 actions: []string{ 88 "push", 89 "pull", 90 "pull", 91 "delete", 92 "push", 93 }, 94 want: "repository:foo:delete,pull,push", 95 }, 96 } 97 for _, tt := range tests { 98 t.Run(tt.name, func(t *testing.T) { 99 if got := ScopeRepository(tt.repository, tt.actions...); got != tt.want { 100 t.Errorf("ScopeRepository() = %v, want %v", got, tt.want) 101 } 102 }) 103 } 104 } 105 106 func TestWithScopes(t *testing.T) { 107 ctx := context.Background() 108 109 // with single scope 110 want := []string{ 111 "repository:foo:pull", 112 } 113 ctx = WithScopes(ctx, want...) 114 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 115 t.Errorf("GetScopes(WithScopes()) = %v, want %v", got, want) 116 } 117 118 // overwrite scopes 119 want = []string{ 120 "repository:bar:push", 121 } 122 ctx = WithScopes(ctx, want...) 123 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 124 t.Errorf("GetScopes(WithScopes()) = %v, want %v", got, want) 125 } 126 127 // overwrite scopes with de-duplication 128 scopes := []string{ 129 "repository:hello-world:push", 130 "repository:alpine:delete", 131 "repository:hello-world:pull", 132 "repository:alpine:delete", 133 } 134 want = []string{ 135 "repository:alpine:delete", 136 "repository:hello-world:pull,push", 137 } 138 ctx = WithScopes(ctx, scopes...) 139 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 140 t.Errorf("GetScopes(WithScopes()) = %v, want %v", got, want) 141 } 142 143 // clean scopes 144 want = nil 145 ctx = WithScopes(ctx, want...) 146 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 147 t.Errorf("GetScopes(WithScopes()) = %v, want %v", got, want) 148 } 149 } 150 151 func TestAppendScopes(t *testing.T) { 152 ctx := context.Background() 153 154 // append single scope 155 want := []string{ 156 "repository:foo:pull", 157 } 158 ctx = AppendScopes(ctx, want...) 159 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 160 t.Errorf("GetScopes(AppendScopes()) = %v, want %v", got, want) 161 } 162 163 // append scopes with de-duplication 164 scopes := []string{ 165 "repository:hello-world:push", 166 "repository:alpine:delete", 167 "repository:hello-world:pull", 168 "repository:alpine:delete", 169 } 170 want = []string{ 171 "repository:alpine:delete", 172 "repository:foo:pull", 173 "repository:hello-world:pull,push", 174 } 175 ctx = AppendScopes(ctx, scopes...) 176 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 177 t.Errorf("GetScopes(AppendScopes()) = %v, want %v", got, want) 178 } 179 180 // append empty scopes 181 ctx = AppendScopes(ctx) 182 if got := GetScopes(ctx); !reflect.DeepEqual(got, want) { 183 t.Errorf("GetScopes(AppendScopes()) = %v, want %v", got, want) 184 } 185 } 186 187 func TestCleanScopes(t *testing.T) { 188 tests := []struct { 189 name string 190 scopes []string 191 want []string 192 }{ 193 { 194 name: "nil scope", 195 }, 196 { 197 name: "empty scope", 198 scopes: []string{}, 199 }, 200 { 201 name: "single scope", 202 scopes: []string{ 203 "repository:foo:pull", 204 }, 205 want: []string{ 206 "repository:foo:pull", 207 }, 208 }, 209 { 210 name: "single scope with unordered actions", 211 scopes: []string{ 212 "repository:foo:push,pull,delete", 213 }, 214 want: []string{ 215 "repository:foo:delete,pull,push", 216 }, 217 }, 218 { 219 name: "single scope with duplicated actions", 220 scopes: []string{ 221 "repository:foo:push,pull,push,pull,push,push,pull", 222 }, 223 want: []string{ 224 "repository:foo:pull,push", 225 }, 226 }, 227 { 228 name: "single scope with wild cards", 229 scopes: []string{ 230 "repository:foo:pull,*,push", 231 }, 232 want: []string{ 233 "repository:foo:*", 234 }, 235 }, 236 { 237 name: "single scope with no actions", 238 scopes: []string{ 239 "repository:foo:,", 240 }, 241 want: nil, 242 }, 243 { 244 name: "multiple scopes", 245 scopes: []string{ 246 "repository:bar:push", 247 "repository:foo:pull", 248 }, 249 want: []string{ 250 "repository:bar:push", 251 "repository:foo:pull", 252 }, 253 }, 254 { 255 name: "multiple unordered scopes", 256 scopes: []string{ 257 "repository:foo:pull", 258 "repository:bar:push", 259 }, 260 want: []string{ 261 "repository:bar:push", 262 "repository:foo:pull", 263 }, 264 }, 265 { 266 name: "multiple scopes with duplicates", 267 scopes: []string{ 268 "repository:foo:pull", 269 "repository:bar:push", 270 "repository:foo:push", 271 "repository:bar:push,delete,pull", 272 "repository:bar:delete,pull", 273 "repository:foo:pull", 274 "registry:catalog:*", 275 "registry:catalog:pull", 276 }, 277 want: []string{ 278 "registry:catalog:*", 279 "repository:bar:delete,pull,push", 280 "repository:foo:pull,push", 281 }, 282 }, 283 { 284 name: "multiple scopes with no actions", 285 scopes: []string{ 286 "repository:foo:,", 287 "repository:bar:,", 288 }, 289 want: nil, 290 }, 291 { 292 name: "single unknown or invalid scope", 293 scopes: []string{ 294 "unknown", 295 }, 296 want: []string{ 297 "unknown", 298 }, 299 }, 300 { 301 name: "multiple unknown or invalid scopes", 302 scopes: []string{ 303 "repository:foo:pull", 304 "unknown", 305 "invalid:scope", 306 "no:actions:", 307 "repository:foo:push", 308 }, 309 want: []string{ 310 "invalid:scope", 311 "repository:foo:pull,push", 312 "unknown", 313 }, 314 }, 315 } 316 for _, tt := range tests { 317 t.Run(tt.name, func(t *testing.T) { 318 if got := CleanScopes(tt.scopes); !reflect.DeepEqual(got, tt.want) { 319 t.Errorf("CleanScopes() = %v, want %v", got, tt.want) 320 } 321 }) 322 } 323 } 324 325 func Test_cleanActions(t *testing.T) { 326 tests := []struct { 327 name string 328 actions []string 329 want []string 330 }{ 331 { 332 name: "nil action", 333 }, 334 { 335 name: "empty action", 336 actions: []string{}, 337 }, 338 { 339 name: "single action", 340 actions: []string{ 341 "pull", 342 }, 343 want: []string{ 344 "pull", 345 }, 346 }, 347 { 348 name: "single empty action", 349 actions: []string{ 350 "", 351 }, 352 }, 353 { 354 name: "multiple actions", 355 actions: []string{ 356 "pull", 357 "push", 358 }, 359 want: []string{ 360 "pull", 361 "push", 362 }, 363 }, 364 { 365 name: "multiple actions with empty action", 366 actions: []string{ 367 "pull", 368 "", 369 "push", 370 }, 371 want: []string{ 372 "pull", 373 "push", 374 }, 375 }, 376 { 377 name: "multiple actions with all empty action", 378 actions: []string{ 379 "", 380 "", 381 "", 382 }, 383 want: nil, 384 }, 385 { 386 name: "unordered actions", 387 actions: []string{ 388 "push", 389 "pull", 390 "delete", 391 }, 392 want: []string{ 393 "delete", 394 "pull", 395 "push", 396 }, 397 }, 398 { 399 name: "wildcard", 400 actions: []string{ 401 "*", 402 }, 403 want: []string{ 404 "*", 405 }, 406 }, 407 { 408 name: "wildcard at the begining", 409 actions: []string{ 410 "*", 411 "push", 412 "pull", 413 "delete", 414 }, 415 want: []string{ 416 "*", 417 }, 418 }, 419 { 420 name: "wildcard in the middle", 421 actions: []string{ 422 "push", 423 "pull", 424 "*", 425 "delete", 426 }, 427 want: []string{ 428 "*", 429 }, 430 }, 431 { 432 name: "wildcard at the end", 433 actions: []string{ 434 "push", 435 "pull", 436 "delete", 437 "*", 438 }, 439 want: []string{ 440 "*", 441 }, 442 }, 443 } 444 for _, tt := range tests { 445 t.Run(tt.name, func(t *testing.T) { 446 if got := cleanActions(tt.actions); !reflect.DeepEqual(got, tt.want) { 447 t.Errorf("cleanActions() = %v, want %v", got, tt.want) 448 } 449 }) 450 } 451 }