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  }