github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/avatars/urlcaching_test.go (about) 1 package avatars 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/keybase/client/go/libkb" 8 "github.com/keybase/client/go/protocol/keybase1" 9 "github.com/keybase/clockwork" 10 "github.com/stretchr/testify/require" 11 ) 12 13 type apiHandlerFn func(libkb.MetaContext, libkb.APIArg, libkb.APIResponseWrapper) error 14 type avatarMockAPI struct { 15 libkb.API 16 handler apiHandlerFn 17 } 18 19 func (a *avatarMockAPI) GetDecode(mctx libkb.MetaContext, arg libkb.APIArg, res libkb.APIResponseWrapper) error { 20 return a.handler(mctx, arg, res) 21 } 22 23 func newAvatarMockAPI(f apiHandlerFn) *avatarMockAPI { 24 return &avatarMockAPI{handler: f} 25 } 26 27 func makeHandler(url string, cb chan struct{}) apiHandlerFn { 28 return func(mctx libkb.MetaContext, arg libkb.APIArg, res libkb.APIResponseWrapper) error { 29 m := make(map[keybase1.AvatarFormat]keybase1.AvatarUrl) 30 m["square"] = keybase1.MakeAvatarURL(url) 31 res.(*apiAvatarRes).Pictures = []map[keybase1.AvatarFormat]keybase1.AvatarUrl{m} 32 cb <- struct{}{} 33 return nil 34 } 35 } 36 37 func TestAvatarsURLCaching(t *testing.T) { 38 tc := libkb.SetupTest(t, "TestAvatarsURLCaching", 1) 39 defer tc.Cleanup() 40 41 clock := clockwork.NewFakeClock() 42 tc.G.SetClock(clock) 43 44 cb := make(chan struct{}, 5) 45 46 tc.G.API = newAvatarMockAPI(makeHandler("url", cb)) 47 source := NewURLCachingSource(time.Hour, 10) 48 49 t.Logf("API server fetch") 50 m := libkb.NewMetaContextForTest(tc) 51 res, err := source.LoadUsers(m, []string{"mike"}, []keybase1.AvatarFormat{"square"}) 52 require.NoError(t, err) 53 require.Equal(t, "url", res.Picmap["mike"]["square"].String()) 54 select { 55 case <-cb: 56 case <-time.After(20 * time.Second): 57 require.Fail(t, "no API call") 58 } 59 t.Logf("cache fetch") 60 res, err = source.LoadUsers(m, []string{"mike"}, []keybase1.AvatarFormat{"square"}) 61 require.NoError(t, err) 62 require.Equal(t, "url", res.Picmap["mike"]["square"].String()) 63 select { 64 case <-cb: 65 require.Fail(t, "no API call") 66 default: 67 } 68 69 t.Logf("stale") 70 source.staleFetchCh = make(chan struct{}, 5) 71 clock.Advance(2 * time.Hour) 72 tc.G.API = newAvatarMockAPI(makeHandler("url2", cb)) 73 res, err = source.LoadUsers(m, []string{"mike"}, []keybase1.AvatarFormat{"square"}) 74 require.NoError(t, err) 75 require.Equal(t, "url", res.Picmap["mike"]["square"].String()) 76 select { 77 case <-cb: 78 case <-time.After(20 * time.Second): 79 require.Fail(t, "no API call") 80 } 81 select { 82 case <-source.staleFetchCh: 83 case <-time.After(20 * time.Second): 84 require.Fail(t, "no stale fetch") 85 } 86 res, err = source.LoadUsers(m, []string{"mike"}, []keybase1.AvatarFormat{"square"}) 87 require.NoError(t, err) 88 require.Equal(t, "url2", res.Picmap["mike"]["square"].String()) 89 select { 90 case <-cb: 91 require.Fail(t, "no API call") 92 default: 93 } 94 }