go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/auth/cache_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 auth 16 17 import ( 18 "context" 19 "errors" 20 "testing" 21 "time" 22 23 "go.chromium.org/luci/common/clock" 24 "go.chromium.org/luci/common/clock/testclock" 25 26 "go.chromium.org/luci/server/caching" 27 "go.chromium.org/luci/server/caching/cachingtest" 28 "go.chromium.org/luci/server/caching/layered" 29 30 . "github.com/smartystreets/goconvey/convey" 31 ) 32 33 var testCache = newTokenCache(tokenCacheConfig{ 34 Kind: "testing", 35 ProcessCacheCapacity: 9, 36 }) 37 38 func TestTokenCache(t *testing.T) { 39 t.Parallel() 40 41 Convey("with in-process cache", t, func() { 42 ctx := context.Background() 43 ctx, tc := testclock.UseTime(ctx, testclock.TestRecentTimeUTC) 44 ctx = caching.WithEmptyProcessCache(ctx) 45 ctx = cachingtest.WithGlobalCache(ctx, map[string]caching.BlobCache{ 46 globalCacheNamespace: cachingtest.NewBlobCache(), 47 }) 48 49 makeTestToken := func(ctx context.Context, val string) *cachedToken { 50 return &cachedToken{ 51 Created: clock.Now(ctx), 52 Expiry: clock.Now(ctx).Add(time.Hour), 53 OAuth2Token: val, 54 } 55 } 56 57 call := func(mocked *cachedToken, err error, label string) (*cachedToken, error, string) { 58 return testCache.fetchOrMintToken(ctx, &fetchOrMintTokenOp{ 59 CacheKey: "key", 60 MinTTL: 10 * time.Minute, 61 Mint: func(ctx context.Context) (*cachedToken, error, string) { 62 return mocked, err, label 63 }, 64 }) 65 } 66 67 Convey("Basic usage", func() { 68 // Generate initial token. 69 tok1 := makeTestToken(ctx, "token-1") 70 tok, err, label := call(tok1, nil, "") 71 So(err, ShouldBeNil) 72 So(label, ShouldEqual, "SUCCESS_CACHE_MISS") 73 So(tok, ShouldEqual, tok1) 74 75 // Some time later still cache hit. 76 tc.Add(49 * time.Minute) 77 tok, err, label = call(nil, errors.New("must not be called"), "") 78 So(err, ShouldBeNil) 79 So(label, ShouldEqual, "SUCCESS_CACHE_HIT") 80 So(tok, ShouldEqual, tok1) 81 82 // Lifetime of the existing token is not good enough => refreshed. 83 tc.Add(2 * time.Minute) 84 tok2 := makeTestToken(ctx, "token-1") 85 tok, err, label = call(tok2, nil, "") 86 So(err, ShouldBeNil) 87 So(label, ShouldEqual, "SUCCESS_CACHE_MISS") 88 So(tok, ShouldEqual, tok2) 89 }) 90 91 Convey("Marshalling works", func() { 92 // Generate initial token. 93 tok1 := makeTestToken(ctx, "token-1") 94 tok, err, label := call(tok1, nil, "") 95 So(err, ShouldBeNil) 96 So(label, ShouldEqual, "SUCCESS_CACHE_MISS") 97 So(tok, ShouldEqual, tok1) 98 99 // Kick it out of local cache by wiping it. It still in global cache. 100 ctx = caching.WithEmptyProcessCache(ctx) 101 102 // Cache hit through the global cache. 103 tok, err, label = call(nil, errors.New("must not be called"), "") 104 So(err, ShouldBeNil) 105 So(label, ShouldEqual, "SUCCESS_CACHE_HIT") 106 So(tok.Created.Equal(tok1.Created), ShouldBeTrue) 107 So(tok.Expiry.Equal(tok1.Expiry), ShouldBeTrue) 108 So(tok.OAuth2Token, ShouldEqual, tok1.OAuth2Token) 109 }) 110 111 Convey("Mint error", func() { 112 err := errors.New("some error") 113 tok, err, label := call(nil, err, "SOME_LABEL") 114 So(tok, ShouldBeNil) 115 So(err, ShouldEqual, err) 116 So(label, ShouldEqual, "SOME_LABEL") 117 118 tok, err, label = call(nil, err, "") 119 So(tok, ShouldBeNil) 120 So(err, ShouldEqual, err) 121 So(label, ShouldEqual, "ERROR_UNSPECIFIED") 122 }) 123 124 Convey("Small TTL", func() { 125 tok1 := makeTestToken(ctx, "token") 126 tok1.Expiry = tok1.Created.Add(time.Second) 127 128 tok, err, label := call(tok1, nil, "") 129 So(tok, ShouldBeNil) 130 So(err, ShouldEqual, layered.ErrCantSatisfyMinTTL) 131 So(label, ShouldEqual, "ERROR_INSUFFICIENT_MINTED_TTL") 132 }) 133 }) 134 }