github.com/qiniu/go-sdk/v7@v7.27.0/internal/cache/cache_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package cache
     5  
     6  import (
     7  	"errors"
     8  	"os"
     9  	"reflect"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  type integerCacheValue struct {
    15  	Value        int       `json:"value"`
    16  	RefreshAfter time.Time `json:"refresh_after"`
    17  	ExpiredAt    time.Time `json:"expired_at"`
    18  }
    19  
    20  func (v integerCacheValue) ShouldRefresh() bool {
    21  	return time.Now().After(v.RefreshAfter)
    22  }
    23  
    24  func (v integerCacheValue) IsValid() bool {
    25  	return time.Now().Before(v.ExpiredAt)
    26  }
    27  
    28  func (left integerCacheValue) IsEqual(rightV CacheValue) bool {
    29  	right, ok := rightV.(integerCacheValue)
    30  	if !ok {
    31  		return false
    32  	}
    33  	return left.Value == right.Value
    34  }
    35  
    36  func TestCache(t *testing.T) {
    37  	cache := NewCache(200 * time.Millisecond)
    38  	if value, result := cache.Get("key_1", func() (CacheValue, error) {
    39  		return integerCacheValue{
    40  			Value:        1,
    41  			RefreshAfter: time.Now().Add(50 * time.Millisecond),
    42  			ExpiredAt:    time.Now().Add(100 * time.Millisecond),
    43  		}, nil
    44  	}); result != GetResultFromFallback {
    45  		t.Fatalf("unexpected result: %v", result)
    46  	} else if v := value.(integerCacheValue).Value; v != 1 {
    47  		t.Fatalf("unexpected cache value: %v", v)
    48  	}
    49  
    50  	if value, result := cache.Get("key_1", func() (CacheValue, error) {
    51  		t.Fatal("should not call this fallback")
    52  		return nil, nil
    53  	}); result != GetResultFromCache {
    54  		t.Fatalf("unexpected result: %v", result)
    55  	} else if v := value.(integerCacheValue).Value; v != 1 {
    56  		t.Fatalf("unexpected cache value: %v", v)
    57  	}
    58  
    59  	time.Sleep(50 * time.Millisecond)
    60  	if value, result := cache.Get("key_1", func() (CacheValue, error) {
    61  		return integerCacheValue{
    62  			Value:        2,
    63  			RefreshAfter: time.Now().Add(50 * time.Millisecond),
    64  			ExpiredAt:    time.Now().Add(100 * time.Millisecond),
    65  		}, nil
    66  	}); result != GetResultFromCacheAndRefreshAsync {
    67  		t.Fatalf("unexpected result: %v", result)
    68  	} else if v := value.(integerCacheValue).Value; v != 1 {
    69  		t.Fatalf("unexpected cache value: %v", v)
    70  	}
    71  
    72  	time.Sleep(250 * time.Millisecond)
    73  	if value, result := cache.Get("key_1", func() (CacheValue, error) {
    74  		return nil, errors.New("test error")
    75  	}); result != GetResultFromInvalidCache {
    76  		t.Fatalf("unexpected result: %v", result)
    77  	} else if v := value.(integerCacheValue).Value; v != 2 {
    78  		t.Fatalf("unexpected cache value: %v", v)
    79  	}
    80  	time.Sleep(150 * time.Millisecond)
    81  	cache.flush()
    82  	if _, result := cache.Get("key_1", func() (CacheValue, error) {
    83  		return nil, errors.New("test error")
    84  	}); result != NoResultGot {
    85  		t.Fatalf("unexpected result: %v", result)
    86  	}
    87  
    88  	if value, result := cache.Get("key_2", func() (CacheValue, error) {
    89  		return integerCacheValue{Value: 3, ExpiredAt: time.Now().Add(-100 * time.Millisecond)}, nil
    90  	}); result != GetResultFromFallback {
    91  		t.Fatalf("unexpected result: %v", result)
    92  	} else if v := value.(integerCacheValue).Value; v != 3 {
    93  		t.Fatalf("unexpected cache value: %v", v)
    94  	}
    95  
    96  	if value, result := cache.Get("key_3", func() (CacheValue, error) {
    97  		return integerCacheValue{Value: 4, ExpiredAt: time.Now().Add(100 * time.Millisecond)}, nil
    98  	}); result != GetResultFromFallback {
    99  		t.Fatal("unexpected ok")
   100  	} else if v := value.(integerCacheValue).Value; v != 4 {
   101  		t.Fatalf("unexpected cache value: %v", v)
   102  	}
   103  }
   104  
   105  func TestCachePersist(t *testing.T) {
   106  	cacheFile, err := os.CreateTemp("", "")
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	defer cacheFile.Close()
   111  	defer os.Remove(cacheFile.Name())
   112  
   113  	valueType := reflect.TypeOf(integerCacheValue{})
   114  	cache, err := NewPersistentCache(
   115  		valueType,
   116  		cacheFile.Name(),
   117  		100*time.Millisecond,
   118  		100*time.Millisecond,
   119  		func(err error) {
   120  			t.Fatalf("no error are expected: %s", err)
   121  		})
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	if value, result := cache.Get("key_1", func() (CacheValue, error) {
   126  		return integerCacheValue{
   127  			Value:        1,
   128  			RefreshAfter: time.Now().Add(100 * time.Millisecond),
   129  			ExpiredAt:    time.Now().Add(200 * time.Millisecond),
   130  		}, nil
   131  	}); result != GetResultFromFallback {
   132  		t.Fatal("unexpected ok")
   133  	} else if v := value.(integerCacheValue).Value; v != 1 {
   134  		t.Fatalf("unexpected cache value: %v", v)
   135  	}
   136  
   137  	time.Sleep(100 * time.Millisecond)
   138  	cache.flush()
   139  
   140  	cacheMap, err := loadCacheMapFrom(valueType, cacheFile)
   141  	if err != nil {
   142  		t.Fatal(err)
   143  	}
   144  	if value, ok := cacheMap["key_1"]; !ok {
   145  		t.Fatalf("key_1 should be existed")
   146  	} else if v := value.Value.(integerCacheValue).Value; v != 1 {
   147  		t.Fatalf("unexpected cache value: %v", v)
   148  	}
   149  
   150  	time.Sleep(100 * time.Millisecond)
   151  	cache.flush()
   152  
   153  	cacheMap, err = loadCacheMapFrom(valueType, cacheFile)
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  	if len(cacheMap) != 0 {
   158  		t.Fatalf("key_1 should be deleted")
   159  	}
   160  }