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  }