istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/jwks_resolver_test.go (about) 1 // Copyright Istio 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 model 16 17 import ( 18 "fmt" 19 "sync/atomic" 20 "testing" 21 "time" 22 23 "istio.io/istio/pilot/pkg/model/test" 24 "istio.io/istio/pkg/monitoring/monitortest" 25 "istio.io/istio/pkg/test/util/retry" 26 ) 27 28 const ( 29 testRetryInterval = time.Millisecond * 10 30 testRequestTimeout = time.Second * 5 31 ) 32 33 func TestResolveJwksURIUsingOpenID(t *testing.T) { 34 r := NewJwksResolver(JwtPubKeyEvictionDuration, JwtPubKeyRefreshInterval, JwtPubKeyRefreshIntervalOnFailure, testRetryInterval) 35 defer r.Close() 36 37 ms, err := test.StartNewServer() 38 defer ms.Stop() 39 if err != nil { 40 t.Fatal("failed to start a mock server") 41 } 42 43 mockCertURL := ms.URL + "/oauth2/v3/certs" 44 cases := []struct { 45 in string 46 expectedJwksURI string 47 expectedError bool 48 }{ 49 { 50 in: ms.URL, 51 expectedJwksURI: mockCertURL, 52 }, 53 { 54 in: ms.URL, 55 expectedJwksURI: mockCertURL, 56 }, 57 { 58 // if the URL has a trailing slash, it should be handled. 59 in: ms.URL + "/", 60 expectedJwksURI: mockCertURL, 61 }, 62 { 63 in: "http://xyz", 64 expectedError: true, 65 }, 66 } 67 for _, c := range cases { 68 jwksURI, err := r.resolveJwksURIUsingOpenID(c.in, testRequestTimeout) 69 if err != nil && !c.expectedError { 70 t.Errorf("resolveJwksURIUsingOpenID(%+v): got error (%v)", c.in, err) 71 } else if err == nil && c.expectedError { 72 t.Errorf("resolveJwksURIUsingOpenID(%+v): expected error, got no error", c.in) 73 } else if c.expectedJwksURI != jwksURI { 74 t.Errorf("resolveJwksURIUsingOpenID(%+v): expected (%s), got (%s)", 75 c.in, c.expectedJwksURI, jwksURI) 76 } 77 } 78 79 // Verify mock openID discovery http://localhost:9999/.well-known/openid-configuration was called three times. 80 if got, want := ms.OpenIDHitNum, uint64(3); got != want { 81 t.Errorf("Mock OpenID discovery Hit number => expected %d but got %d", want, got) 82 } 83 } 84 85 func TestGetPublicKey(t *testing.T) { 86 r := NewJwksResolver(JwtPubKeyEvictionDuration, JwtPubKeyRefreshInterval, JwtPubKeyRefreshIntervalOnFailure, testRetryInterval) 87 defer r.Close() 88 89 ms, err := test.StartNewServer() 90 defer ms.Stop() 91 if err != nil { 92 t.Fatal("failed to start a mock server") 93 } 94 95 mockCertURL := ms.URL + "/oauth2/v3/certs" 96 97 cases := []struct { 98 in []string 99 expectedJwtPubkey string 100 }{ 101 { 102 in: []string{"testIssuer", mockCertURL}, 103 expectedJwtPubkey: test.JwtPubKey1, 104 }, 105 { 106 in: []string{"testIssuer", mockCertURL}, // Send two same request, mock server is expected to hit only once because of the cache. 107 expectedJwtPubkey: test.JwtPubKey1, 108 }, 109 } 110 for _, c := range cases { 111 pk, err := r.GetPublicKey(c.in[0], c.in[1], testRequestTimeout) 112 if err != nil { 113 t.Errorf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", c.in, err) 114 } 115 if c.expectedJwtPubkey != pk { 116 t.Errorf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", c.in, c.expectedJwtPubkey, pk) 117 } 118 } 119 120 // Verify mock server http://localhost:9999/oauth2/v3/certs was only called once because of the cache. 121 if got, want := ms.PubKeyHitNum, uint64(1); got != want { 122 t.Errorf("Mock server Hit number => expected %d but got %d", want, got) 123 } 124 } 125 126 func TestGetPublicKeyWithTimeout(t *testing.T) { 127 r := NewJwksResolver(JwtPubKeyEvictionDuration, JwtPubKeyRefreshInterval, JwtPubKeyRefreshIntervalOnFailure, testRetryInterval) 128 defer r.Close() 129 serverDelay := 100 * time.Millisecond 130 ms, err := test.StartNewServerWithHandlerDelay(serverDelay) 131 defer ms.Stop() 132 if err != nil { 133 t.Fatal("failed to start a mock server") 134 } 135 136 mockCertURL := ms.URL + "/oauth2/v3/certs" 137 138 cases := []struct { 139 in []string 140 timeout time.Duration 141 expectedFailure bool 142 }{ 143 { 144 in: []string{"testIssuer", mockCertURL}, 145 timeout: 5 * time.Second, 146 expectedFailure: false, 147 }, 148 { 149 in: []string{"testIssuer2", mockCertURL}, // Send two same request, mock server is expected to hit only once because of the cache. 150 timeout: 20 * time.Millisecond, 151 expectedFailure: true, 152 }, 153 } 154 for _, c := range cases { 155 _, err := r.GetPublicKey(c.in[0], c.in[1], c.timeout) 156 if c.timeout < serverDelay && err == nil { 157 t.Errorf("GetPublicKey(\"\", %+v) fails: did not timed out as expected", c) 158 } else if c.timeout >= serverDelay && err != nil { 159 t.Errorf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", c, err) 160 } 161 } 162 } 163 164 func TestGetPublicKeyReorderedKey(t *testing.T) { 165 r := NewJwksResolver(JwtPubKeyEvictionDuration, testRetryInterval*20, testRetryInterval*10, testRetryInterval) 166 defer r.Close() 167 168 ms, err := test.StartNewServer() 169 defer ms.Stop() 170 if err != nil { 171 t.Fatal("failed to start a mock server") 172 } 173 ms.ReturnReorderedKeyAfterFirstNumHits = 1 174 175 mockCertURL := ms.URL + "/oauth2/v3/certs" 176 177 cases := []struct { 178 in []string 179 expectedJwtPubkey string 180 }{ 181 { 182 in: []string{"", mockCertURL}, 183 expectedJwtPubkey: test.JwtPubKey1, 184 }, 185 { 186 in: []string{"", mockCertURL}, // Send two same request, mock server is expected to hit only once because of the cache. 187 expectedJwtPubkey: test.JwtPubKey1Reordered, 188 }, 189 } 190 for _, c := range cases { 191 pk, err := r.GetPublicKey(c.in[0], c.in[1], testRequestTimeout) 192 if err != nil { 193 t.Errorf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", c.in, err) 194 } 195 if c.expectedJwtPubkey != pk { 196 t.Errorf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", c.in, c.expectedJwtPubkey, pk) 197 } 198 r.refresh() 199 } 200 201 // Verify refresh job key changed count is zero. 202 if got, want := r.refreshJobKeyChangedCount, uint64(0); got != want { 203 t.Errorf("JWKs Resolver Refreshed Key Count => expected %d but got %d", want, got) 204 } 205 } 206 207 func TestGetPublicKeyUsingTLS(t *testing.T) { 208 r := newJwksResolverWithCABundlePaths( 209 JwtPubKeyEvictionDuration, 210 JwtPubKeyRefreshInterval, 211 JwtPubKeyRefreshIntervalOnFailure, 212 testRetryInterval, 213 []string{"./test/testcert/cert.pem"}, 214 ) 215 defer r.Close() 216 217 ms, err := test.StartNewTLSServer("./test/testcert/cert.pem", "./test/testcert/key.pem") 218 defer ms.Stop() 219 if err != nil { 220 t.Fatal("failed to start a mock server") 221 } 222 223 mockCertURL := ms.URL + "/oauth2/v3/certs" 224 pk, err := r.GetPublicKey("", mockCertURL, testRequestTimeout) 225 if err != nil { 226 t.Errorf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", mockCertURL, err) 227 } 228 if test.JwtPubKey1 != pk { 229 t.Errorf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", mockCertURL, test.JwtPubKey1, pk) 230 } 231 } 232 233 func TestGetPublicKeyUsingTLSBadCert(t *testing.T) { 234 r := newJwksResolverWithCABundlePaths( 235 JwtPubKeyEvictionDuration, 236 JwtPubKeyRefreshInterval, 237 testRetryInterval, 238 testRetryInterval, 239 []string{"./test/testcert/cert2.pem"}, 240 ) 241 defer r.Close() 242 243 ms, err := test.StartNewTLSServer("./test/testcert/cert.pem", "./test/testcert/key.pem") 244 defer ms.Stop() 245 if err != nil { 246 t.Fatal("failed to start a mock server") 247 } 248 249 mockCertURL := ms.URL + "/oauth2/v3/certs" 250 _, err = r.GetPublicKey("", mockCertURL, testRequestTimeout) 251 if err == nil { 252 t.Errorf("GetPublicKey(\"\", %+v) did not fail: expected bad certificate error, got no error", mockCertURL) 253 } 254 } 255 256 func TestGetPublicKeyUsingTLSWithoutCABundles(t *testing.T) { 257 r := newJwksResolverWithCABundlePaths( 258 JwtPubKeyEvictionDuration, 259 JwtPubKeyRefreshInterval, 260 testRetryInterval, 261 testRetryInterval, 262 []string{}, 263 ) 264 defer r.Close() 265 266 ms, err := test.StartNewTLSServer("./test/testcert/cert.pem", "./test/testcert/key.pem") 267 defer ms.Stop() 268 if err != nil { 269 t.Fatal("failed to start a mock server") 270 } 271 272 mockCertURL := ms.URL + "/oauth2/v3/certs" 273 _, err = r.GetPublicKey("", mockCertURL, testRequestTimeout) 274 if err == nil { 275 t.Errorf("GetPublicKey(\"\", %+v) did not fail: expected https unsupported error, got no error", mockCertURL) 276 } 277 } 278 279 func TestJwtPubKeyEvictionForNotUsed(t *testing.T) { 280 r := NewJwksResolver( 281 100*time.Millisecond, /*EvictionDuration*/ 282 2*time.Millisecond, /*RefreshInterval*/ 283 2*time.Millisecond, /*RefreshIntervalOnFailure*/ 284 testRetryInterval, 285 ) 286 defer r.Close() 287 288 ms := startMockServer(t) 289 defer ms.Stop() 290 291 // Mock server returns JwtPubKey2 for later calls. 292 // Verify the refresher has run and got new key from mock server. 293 verifyKeyRefresh(t, r, ms, test.JwtPubKey2) 294 295 // Wait until unused keys are evicted. 296 key := jwtKey{jwksURI: ms.URL + "/oauth2/v3/certs", issuer: "istio-test"} 297 298 retry.UntilSuccessOrFail(t, func() error { 299 // Verify the public key is evicted. 300 if _, found := r.keyEntries.Load(key); found { 301 return fmt.Errorf("public key is not evicted") 302 } 303 return nil 304 }) 305 } 306 307 func TestJwtPubKeyEvictionForNotRefreshed(t *testing.T) { 308 r := NewJwksResolver( 309 100*time.Millisecond, /*EvictionDuration*/ 310 10*time.Millisecond, /*RefreshInterval*/ 311 10*time.Millisecond, /*RefreshIntervalOnFailure*/ 312 testRetryInterval, /*RetryInterval*/ 313 ) 314 defer r.Close() 315 316 ms := startMockServer(t) 317 defer ms.Stop() 318 319 // Configures the mock server to return error after the first request. 320 ms.ReturnErrorAfterFirstNumHits = 1 321 322 mockCertURL := ms.URL + "/oauth2/v3/certs" 323 324 pk, err := r.GetPublicKey("", mockCertURL, testRequestTimeout) 325 if err != nil { 326 t.Fatalf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", mockCertURL, err) 327 } 328 // Mock server returns JwtPubKey1 for first call. 329 if test.JwtPubKey1 != pk { 330 t.Fatalf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", mockCertURL, test.JwtPubKey1, pk) 331 } 332 333 // Keep getting the public key to change the lastUsedTime of the public key. 334 done := make(chan struct{}) 335 go func() { 336 c := time.NewTicker(10 * time.Millisecond) 337 for { 338 select { 339 case <-done: 340 c.Stop() 341 return 342 case <-c.C: 343 _, _ = r.GetPublicKey(mockCertURL, "", testRequestTimeout) 344 } 345 } 346 }() 347 defer func() { 348 done <- struct{}{} 349 }() 350 351 // Verify the cached public key is removed after failed to refresh longer than the eviction duration. 352 retry.UntilSuccessOrFail(t, func() error { 353 _, err = r.GetPublicKey(mockCertURL, "", testRequestTimeout) 354 if err == nil { 355 return fmt.Errorf("getPublicKey(\"\", %+v) fails: expected error, got no error", mockCertURL) 356 } 357 return nil 358 }) 359 } 360 361 func TestJwtPubKeyLastRefreshedTime(t *testing.T) { 362 r := NewJwksResolver( 363 JwtPubKeyEvictionDuration, 364 2*time.Millisecond, /*RefreshInterval*/ 365 2*time.Millisecond, /*RefreshIntervalOnFailure*/ 366 testRetryInterval, /*RetryInterval*/ 367 ) 368 defer r.Close() 369 370 ms := startMockServer(t) 371 defer ms.Stop() 372 373 // Mock server returns JwtPubKey2 for later calls. 374 // Verify the refresher has run and got new key from mock server. 375 verifyKeyRefresh(t, r, ms, test.JwtPubKey2) 376 377 // The lastRefreshedTime should change for each successful refresh. 378 verifyKeyLastRefreshedTime(t, r, ms, true /* wantChanged */) 379 } 380 381 func TestJwtPubKeyRefreshWithNetworkError(t *testing.T) { 382 r := NewJwksResolver( 383 JwtPubKeyEvictionDuration, 384 time.Second, /*RefreshInterval*/ 385 time.Second, /*RefreshIntervalOnFailure*/ 386 testRetryInterval, 387 ) 388 defer r.Close() 389 390 ms := startMockServer(t) 391 defer ms.Stop() 392 393 // Configures the mock server to return error after the first request. 394 ms.ReturnErrorAfterFirstNumHits = 1 395 396 // The refresh job should continue using the previously fetched public key (JwtPubKey1). 397 verifyKeyRefresh(t, r, ms, test.JwtPubKey1) 398 399 // The lastRefreshedTime should not change the refresh failed due to network error. 400 verifyKeyLastRefreshedTime(t, r, ms, false /* wantChanged */) 401 } 402 403 func TestJwtRefreshIntervalRecoverFromInitialFailOnFirstHit(t *testing.T) { 404 defaultRefreshInterval := 50 * time.Millisecond 405 refreshIntervalOnFail := 2 * time.Millisecond 406 r := NewJwksResolver(JwtPubKeyEvictionDuration, defaultRefreshInterval, refreshIntervalOnFail, 1*time.Millisecond) 407 408 ms := startMockServer(t) 409 defer ms.Stop() 410 411 // Configures the mock server to return error for the first 3 requests. 412 ms.ReturnErrorForFirstNumHits = 3 413 414 mockCertURL := ms.URL + "/oauth2/v3/certs" 415 pk, err := r.GetPublicKey("", mockCertURL, testRequestTimeout) 416 if err == nil { 417 t.Fatalf("GetPublicKey(%q, %+v) fails: expected error, got no error: (%v)", pk, mockCertURL, err) 418 } 419 420 retry.UntilOrFail(t, func() bool { 421 pk, _ := r.GetPublicKey("", mockCertURL, testRequestTimeout) 422 return test.JwtPubKey2 == pk 423 }, retry.Delay(time.Millisecond)) 424 r.Close() 425 426 i := 0 427 r.keyEntries.Range(func(_ any, _ any) bool { 428 i++ 429 return true 430 }) 431 432 expectedEntries := 1 433 if i != expectedEntries { 434 t.Errorf("expected entries in cache: %d , got %d", expectedEntries, i) 435 } 436 437 if r.refreshInterval != defaultRefreshInterval { 438 t.Errorf("expected refreshInterval to be refreshDefaultInterval: %v, got %v", defaultRefreshInterval, r.refreshInterval) 439 } 440 } 441 442 func TestJwtRefreshIntervalRecoverFromFail(t *testing.T) { 443 defaultRefreshInterval := 50 * time.Millisecond 444 refreshIntervalOnFail := 2 * time.Millisecond 445 r := NewJwksResolver(JwtPubKeyEvictionDuration, defaultRefreshInterval, refreshIntervalOnFail, 1*time.Millisecond) 446 447 ms := startMockServer(t) 448 defer ms.Stop() 449 450 // Configures the mock server to return error after the first request. 451 ms.ReturnErrorAfterFirstNumHits = 1 452 ms.ReturnSuccessAfterFirstNumHits = 3 453 454 mockCertURL := ms.URL + "/oauth2/v3/certs" 455 _, err := r.GetPublicKey("", mockCertURL, testRequestTimeout) 456 if err != nil { 457 t.Fatalf("GetPublicKey(%q, %+v) fails: expected no error, got (%v)", "", mockCertURL, err) 458 } 459 460 retry.UntilOrFail(t, func() bool { 461 pk, _ := r.GetPublicKey("", mockCertURL, testRequestTimeout) 462 return test.JwtPubKey1 == pk 463 }, retry.Delay(time.Millisecond)) 464 r.Close() 465 466 if r.refreshInterval != defaultRefreshInterval { 467 t.Errorf("expected defaultRefreshInterval: %v , got %v", defaultRefreshInterval, r.refreshInterval) 468 } 469 } 470 471 func TestJwtPubKeyMetric(t *testing.T) { 472 mt := monitortest.New(t) 473 defaultRefreshInterval := 50 * time.Millisecond 474 refreshIntervalOnFail := 2 * time.Millisecond 475 r := NewJwksResolver(JwtPubKeyEvictionDuration, defaultRefreshInterval, refreshIntervalOnFail, 1*time.Millisecond) 476 defer r.Close() 477 478 ms := startMockServer(t) 479 defer ms.Stop() 480 481 ms.ReturnErrorForFirstNumHits = 1 482 483 mockCertURL := ms.URL + "/oauth2/v3/certs" 484 cases := []struct { 485 name string 486 in []string 487 expectedJwtPubkey string 488 metric string 489 }{ 490 { 491 name: "fail", 492 in: []string{"", mockCertURL}, 493 expectedJwtPubkey: "", 494 metric: networkFetchFailCounter.Name(), 495 }, 496 { 497 name: "success", 498 in: []string{"", mockCertURL}, 499 expectedJwtPubkey: test.JwtPubKey2, 500 metric: networkFetchFailCounter.Name(), 501 }, 502 } 503 504 // First attempt should fail, but retries cause subsequent ones to succeed 505 // Mock server only returns an error on the first attempt 506 for _, c := range cases { 507 retry.UntilOrFail(t, func() bool { 508 pk, _ := r.GetPublicKey(c.in[0], c.in[1], testRequestTimeout) 509 return c.expectedJwtPubkey == pk 510 }, retry.Delay(time.Millisecond)) 511 mt.Assert(c.metric, nil, monitortest.AtLeast(1)) 512 } 513 } 514 515 func startMockServer(t *testing.T) *test.MockOpenIDDiscoveryServer { 516 t.Helper() 517 518 ms, err := test.StartNewServer() 519 if err != nil { 520 t.Fatal("failed to start a mock server") 521 } 522 return ms 523 } 524 525 func verifyKeyRefresh(t *testing.T, r *JwksResolver, ms *test.MockOpenIDDiscoveryServer, expectedJwtPubkey string) { 526 t.Helper() 527 mockCertURL := ms.URL + "/oauth2/v3/certs" 528 529 pk, err := r.GetPublicKey("", mockCertURL, testRequestTimeout) 530 if err != nil { 531 t.Fatalf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", mockCertURL, err) 532 } 533 // Mock server returns JwtPubKey1 for first call. 534 if test.JwtPubKey1 != pk { 535 t.Fatalf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", mockCertURL, test.JwtPubKey1, pk) 536 } 537 538 // Wait until refresh job at least finished once. 539 retry.UntilSuccessOrFail(t, func() error { 540 // Make sure refresh job has run and detect change or refresh happened. 541 if atomic.LoadUint64(&r.refreshJobKeyChangedCount) > 0 || atomic.LoadUint64(&r.refreshJobFetchFailedCount) > 0 { 542 return nil 543 } 544 return fmt.Errorf("refresher failed to run") 545 }) 546 pk, err = r.GetPublicKey("", mockCertURL, testRequestTimeout) 547 if err != nil { 548 t.Fatalf("GetPublicKey(\"\", %+v) fails: expected no error, got (%v)", mockCertURL, err) 549 } 550 if expectedJwtPubkey != pk { 551 t.Fatalf("GetPublicKey(\"\", %+v): expected (%s), got (%s)", mockCertURL, expectedJwtPubkey, pk) 552 } 553 } 554 555 func verifyKeyLastRefreshedTime(t *testing.T, r *JwksResolver, ms *test.MockOpenIDDiscoveryServer, wantChanged bool) { 556 t.Helper() 557 mockCertURL := ms.URL + "/oauth2/v3/certs" 558 key := jwtKey{jwksURI: mockCertURL} 559 560 e, found := r.keyEntries.Load(key) 561 if !found { 562 t.Fatalf("No cached public key for %+v", key) 563 } 564 oldRefreshedTime := e.(jwtPubKeyEntry).lastRefreshedTime 565 566 time.Sleep(200 * time.Millisecond) 567 568 e, found = r.keyEntries.Load(key) 569 if !found { 570 t.Fatalf("No cached public key for %+v", key) 571 } 572 newRefreshedTime := e.(jwtPubKeyEntry).lastRefreshedTime 573 574 if actualChanged := oldRefreshedTime != newRefreshedTime; actualChanged != wantChanged { 575 t.Errorf("Want changed: %t but got %t", wantChanged, actualChanged) 576 } 577 } 578 579 func TestCompareJWKSResponse(t *testing.T) { 580 type args struct { 581 oldKeyString string 582 newKeyString string 583 } 584 tests := []struct { 585 name string 586 args args 587 want bool 588 wantErr bool 589 }{ 590 {"testEquivalentStrings", args{test.JwtPubKey1, test.JwtPubKey1}, false, false}, 591 {"testReorderedKeys", args{test.JwtPubKey1, test.JwtPubKey1Reordered}, false, false}, 592 {"testDifferentKeys", args{test.JwtPubKey1, test.JwtPubKey2}, true, false}, 593 {"testOldJsonParseFailure", args{"This is not JSON", test.JwtPubKey1}, true, false}, 594 {"testNewJsonParseFailure", args{test.JwtPubKey1, "This is not JSON"}, false, true}, 595 {"testNewNoKid", args{test.JwtPubKey1, test.JwtPubKeyNoKid}, true, false}, 596 {"testOldNoKid", args{test.JwtPubKeyNoKid, test.JwtPubKey1}, true, false}, 597 {"testBothNoKidSame", args{test.JwtPubKeyNoKid, test.JwtPubKeyNoKid}, false, false}, 598 {"testBothNoKidDifferent", args{test.JwtPubKeyNoKid, test.JwtPubKeyNoKid2}, true, false}, 599 {"testNewNoKeys", args{test.JwtPubKey1, test.JwtPubKeyNoKeys}, true, false}, 600 {"testOldNoKeys", args{test.JwtPubKeyNoKeys, test.JwtPubKey1}, true, false}, 601 {"testBothNoKeysSame", args{test.JwtPubKeyNoKeys, test.JwtPubKeyNoKeys}, false, false}, 602 {"testBothNoKeysDifferent", args{test.JwtPubKeyNoKeys, test.JwtPubKeyNoKeys2}, true, false}, 603 {"testNewExtraElements", args{test.JwtPubKey1, test.JwtPubKeyExtraElements}, true, false}, 604 {"testOldExtraElements", args{test.JwtPubKeyExtraElements, test.JwtPubKey1}, true, false}, 605 {"testBothExtraElements", args{test.JwtPubKeyExtraElements, test.JwtPubKeyExtraElements}, false, false}, 606 } 607 for _, tt := range tests { 608 t.Run(tt.name, func(t *testing.T) { 609 got, err := compareJWKSResponse(tt.args.oldKeyString, tt.args.newKeyString) 610 if (err != nil) != tt.wantErr { 611 t.Errorf("compareJWKSResponse() error = %v, wantErr %v", err, tt.wantErr) 612 return 613 } 614 if got != tt.want { 615 t.Errorf("compareJWKSResponse() got = %v, want %v", got, tt.want) 616 } 617 }) 618 } 619 }