github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/fetch_decider_test.go (about) 1 // Copyright 2017 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "testing" 9 "time" 10 11 "github.com/keybase/client/go/kbfs/test/clocktest" 12 "github.com/keybase/client/go/libkb" 13 "github.com/keybase/client/go/logger" 14 "github.com/stretchr/testify/require" 15 "golang.org/x/net/context" 16 ) 17 18 func TestFetchDecider(t *testing.T) { 19 errCh := make(chan error, 1) 20 fetcher := func(ctx context.Context) error { 21 return <-errCh 22 } 23 24 log := logger.NewTestLogger(t) 25 clock := clocktest.NewTestClockNow() 26 fd := newFetchDecider( 27 log, libkb.NewVDebugLog(log), fetcher, "", "", &testClockGetter{clock}) 28 ctx, cancel := context.WithTimeout( 29 context.Background(), individualTestTimeout) 30 defer cancel() 31 32 t.Log("Blocking fetch") 33 errCh <- nil 34 err := fd.Do(ctx, 2*time.Second, 4*time.Second, time.Time{}) 35 require.NoError(t, err) 36 37 t.Log("Use cached value (`fetcher` isn't called)") 38 err = fd.Do( 39 ctx, 2*time.Second, 4*time.Second, clock.Now().Add(-1*time.Second)) 40 require.NoError(t, err) 41 42 t.Log("Use cached value, but launch bg fetcher (will return before " + 43 "`fetcher` completes)") 44 err = fd.Do( 45 ctx, 2*time.Second, 4*time.Second, clock.Now().Add(-3*time.Second)) 46 require.NoError(t, err) 47 48 errCh <- nil // Let the background fetcher complete. 49 50 // Once we can put a new value in the sized-1 `errCh`, we know the 51 // bg fetch has finished. 52 errCh <- nil 53 <-errCh 54 55 t.Log("Use cached value, and subsequent blocking call will wait for " + 56 "the background fetcher") 57 err = fd.Do( 58 ctx, 2*time.Second, 4*time.Second, clock.Now().Add(-3*time.Second)) 59 require.NoError(t, err) 60 61 checkBlocking := make(chan struct{}) 62 fd.blockingForTest = checkBlocking 63 blockingCh := make(chan error, 1) 64 go func() { 65 blockingCh <- fd.Do(ctx, 2*time.Second, 4*time.Second, time.Time{}) 66 }() 67 68 // Wait for the previous call to start blocking. 69 select { 70 case <-checkBlocking: 71 case <-ctx.Done(): 72 require.NoError(t, ctx.Err()) 73 } 74 75 errCh <- nil 76 select { 77 case err = <-blockingCh: 78 require.NoError(t, err) 79 case <-ctx.Done(): 80 require.NoError(t, ctx.Err()) 81 } 82 }