github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/renter/streamcache_test.go (about)

     1  package renter
     2  
     3  import (
     4  	"container/heap"
     5  	"reflect"
     6  	"strconv"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  // TestHeapImplementation tests that the streamCache heap functions properly
    12  func TestHeapImplementation(t *testing.T) {
    13  	// Initializing minimum variables
    14  	streamHeap := make(streamHeap, 0, DefaultStreamCacheSize)
    15  	heap.Init(&streamHeap)
    16  
    17  	// Testing Push to Heap
    18  	length := len(streamHeap)
    19  	cd := &chunkData{
    20  		id:         "Push",
    21  		data:       []byte{},
    22  		lastAccess: time.Now(),
    23  	}
    24  	heap.Push(&streamHeap, cd)
    25  
    26  	// Confirming the length of the heap increased by 1
    27  	if len(streamHeap) != length+1 {
    28  		t.Error("Length of heap did not change, chunkData was not pushed onto Heap. Length of heap is still ", len(streamHeap))
    29  	}
    30  	// Confirming the chunk added was the one expected
    31  	if !reflect.DeepEqual(cd, streamHeap[0]) {
    32  		t.Error("Chunk on top of heap is not the chunk that was just pushed on, chunkData.id =", streamHeap[0].id)
    33  	}
    34  
    35  	// Add more chunks to heap
    36  	for i := 0; i < 3; i++ {
    37  		heap.Push(&streamHeap, &chunkData{
    38  			id:         strconv.Itoa(i),
    39  			data:       []byte{},
    40  			lastAccess: time.Now().Add(-1 * time.Minute),
    41  		})
    42  	}
    43  
    44  	// Testing Heap update
    45  	// Confirming recently accessed elements gets removed from the top of Heap
    46  	cd = streamHeap[0]
    47  	streamHeap.update(cd, cd.id, cd.data, time.Now())
    48  	if reflect.DeepEqual(cd, streamHeap[0]) {
    49  		t.Error("Heap order was not updated. Recently accessed element at top of heap")
    50  	}
    51  	// Confirming least recently accessed element is moved to the top of Heap
    52  	cd = streamHeap[len(streamHeap)-1]
    53  	streamHeap.update(cd, cd.id, cd.data, time.Now().Add(-1*time.Hour))
    54  	if !reflect.DeepEqual(cd, streamHeap[0]) {
    55  		t.Error("Heap order was not updated. Least recently accessed element is not at top of heap")
    56  	}
    57  
    58  	// Testing Pop of Heap
    59  	// Confirming element at the top of heap is removed
    60  	cd = streamHeap[0]
    61  	length = len(streamHeap)
    62  	if pop := heap.Pop(&streamHeap).(*chunkData); !reflect.DeepEqual(cd, pop) {
    63  		t.Error("Element at the top of the Heap was not popped off")
    64  	}
    65  	if len(streamHeap) != length-1 {
    66  		t.Error("Heap length was not reduced by 1")
    67  	}
    68  }
    69  
    70  // TestPruneCache tests to make sure that pruneCache always prunes the cache
    71  // to the given size
    72  func TestPruneCache(t *testing.T) {
    73  	if testing.Short() {
    74  		t.SkipNow()
    75  	}
    76  	// Initializing minimum required variables
    77  	sc := newStreamCache(10)
    78  
    79  	// Fill Cache
    80  	// Purposefully trying to fill to a value larger than cacheSize to confirm
    81  	// cacheSize won't be exceeded
    82  	for i := 0; i < int(sc.cacheSize)+5; i++ {
    83  		sc.Add(strconv.Itoa(i), []byte{})
    84  	}
    85  	// Confirm that the streamHeap didn't exceed the cacheSize
    86  	if len(sc.streamHeap) != int(sc.cacheSize) || len(sc.streamMap) != len(sc.streamHeap) {
    87  		t.Error("Cache is not equal to the cacheSize")
    88  	}
    89  
    90  	// Prune the cache down to 2
    91  	sc.pruneCache(2)
    92  
    93  	// Confirm that the length of streamHeap was reduced to 2
    94  	if len(sc.streamHeap) != 2 || len(sc.streamMap) != 2 {
    95  		t.Error("Cache was not pruned")
    96  	}
    97  
    98  	// Confirm calling pruneCache on a value larger than
    99  	// the cache size doesn't change the cache
   100  	sc.pruneCache(20)
   101  	if len(sc.streamHeap) != 2 || len(sc.streamMap) != 2 {
   102  		t.Error("Cache size was changed by pruning to larger value")
   103  	}
   104  
   105  	// Confirm the same chunk won't be added if already added
   106  	sc.pruneCache(0)
   107  	id := "test"
   108  	for i := 0; i < 5; i++ {
   109  		sc.Add(id, []byte{})
   110  	}
   111  	if len(sc.streamHeap) != 1 || len(sc.streamMap) != 1 {
   112  		t.Fatalf("Chunk added more the once.\nHeap length: %v\nMap length: %v\n", len(sc.streamHeap), len(sc.streamMap))
   113  	}
   114  }
   115  
   116  // TestStreamCache tests that when Add() is called, chunks are added and removed
   117  // from both the Heap and the Map
   118  // Retrieve() is tested through the Streaming tests in the siatest packages
   119  // SetStreamingCacheSize() is tested through the API endpoint tests in the
   120  // siatest packages
   121  func TestStreamCache(t *testing.T) {
   122  	if testing.Short() {
   123  		t.SkipNow()
   124  	}
   125  	// Initializing minimum required variables
   126  	sc := newStreamCache(10)
   127  
   128  	// Fill Cache
   129  	// Purposefully trying to fill to a value larger than cacheSize to confirm Add()
   130  	// keeps pruning cache
   131  	for i := 0; i < int(sc.cacheSize)+5; i++ {
   132  		sc.Add(strconv.Itoa(i), []byte{})
   133  	}
   134  	// Confirm that the streamHeap didn't exceed the cacheSize
   135  	if len(sc.streamHeap) != int(sc.cacheSize) || len(sc.streamMap) != len(sc.streamHeap) {
   136  		t.Error("Cache is not equal to the cacheSize")
   137  	}
   138  
   139  	// Reduce cacheSize and call Add() to confirm cache is pruned
   140  	sc.cacheSize = 2
   141  	sc.Add("", []byte{})
   142  	if len(sc.streamHeap) != int(sc.cacheSize) || len(sc.streamMap) != len(sc.streamHeap) {
   143  		t.Error("Cache is not equal to the cacheSize")
   144  	}
   145  
   146  	// Add new chunk with known staticCacheID
   147  	sc.Add("chunk1", []byte{}) // "chunk1" should be at the bottom of the Heap
   148  
   149  	// Confirm chunk is in the Map and at the bottom of the Heap
   150  	cd, ok := sc.streamMap["chunk1"]
   151  	if !ok {
   152  		t.Error("The chunk1 was not added to the Map")
   153  	}
   154  	if !reflect.DeepEqual(cd, sc.streamHeap[len(sc.streamHeap)-1]) {
   155  		t.Error("The chunk1 is not at the bottom of the Heap")
   156  	}
   157  
   158  	// Make chunk1 least recently accessed element, so it is at the top
   159  	sc.streamHeap.update(cd, cd.id, cd.data, time.Now().Add(-1*time.Hour))
   160  
   161  	// Confirm chunk1 is at the top of the heap
   162  	if !reflect.DeepEqual(cd, sc.streamHeap[0]) {
   163  		t.Error("Chunk1 is not at the top of the heap")
   164  	}
   165  
   166  	// Add additional chunk to force deletion of a chunk
   167  	sc.Add("chunk2", []byte{})
   168  
   169  	// check if chunk1 was removed from Map and Heap
   170  	if _, ok := sc.streamMap["chunk1"]; ok {
   171  		t.Error("chunk1 wasn't removed from the map")
   172  	}
   173  	if reflect.DeepEqual(cd, sc.streamHeap[0]) {
   174  		t.Error("chunk1 wasn't removed from the heap")
   175  	}
   176  }