github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/stores/indexshipper/uploads/index_set_test.go (about) 1 package uploads 2 3 import ( 4 "context" 5 "io/ioutil" 6 "path/filepath" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/grafana/loki/pkg/storage/stores/indexshipper/index" 13 "github.com/grafana/loki/pkg/storage/stores/indexshipper/storage" 14 "github.com/grafana/loki/pkg/storage/stores/shipper/testutil" 15 util_log "github.com/grafana/loki/pkg/util/log" 16 ) 17 18 const userID = "user-id" 19 20 func TestIndexSet_Add(t *testing.T) { 21 tempDir := t.TempDir() 22 testStorageClient := buildTestStorageClient(t, tempDir) 23 24 for _, userID := range []string{userID, ""} { 25 t.Run(userID, func(t *testing.T) { 26 indexSet, err := NewIndexSet(testTableName, userID, storage.NewIndexSet(testStorageClient, userID != ""), util_log.Logger) 27 require.NoError(t, err) 28 29 defer indexSet.Close() 30 31 testIndexes := buildTestIndexes(t, t.TempDir(), 10) 32 for _, testIndex := range testIndexes { 33 indexSet.Add(testIndex) 34 } 35 36 // see if we can find all the added indexes in the table. 37 indexesFound := map[string]*mockIndex{} 38 err = indexSet.ForEach(func(_ bool, index index.Index) error { 39 indexesFound[index.Path()] = index.(*mockIndex) 40 return nil 41 }) 42 require.NoError(t, err) 43 44 require.Equal(t, testIndexes, indexesFound) 45 }) 46 } 47 } 48 49 func TestIndexSet_Upload(t *testing.T) { 50 tempDir := t.TempDir() 51 testStorageClient := buildTestStorageClient(t, tempDir) 52 53 for _, userID := range []string{userID, ""} { 54 t.Run(userID, func(t *testing.T) { 55 idxSet, err := NewIndexSet(testTableName, userID, storage.NewIndexSet(testStorageClient, userID != ""), util_log.Logger) 56 require.NoError(t, err) 57 58 defer idxSet.Close() 59 60 testIndexes := buildTestIndexes(t, t.TempDir(), 5) 61 for _, testIndex := range testIndexes { 62 idxSet.Add(testIndex) 63 } 64 65 err = idxSet.Upload(context.Background()) 66 require.NoError(t, err) 67 68 for _, testIndex := range testIndexes { 69 indexPathInStorage := filepath.Join(tempDir, objectsStorageDirName, testTableName, userID, idxSet.(*indexSet).buildFileName(testIndex.Name())) 70 require.FileExists(t, indexPathInStorage) 71 72 // compare the contents of created test index and uploaded index in storage 73 _, err = testIndex.Seek(0, 0) 74 require.NoError(t, err) 75 expectedIndexContent, err := ioutil.ReadAll(testIndex.File) 76 require.NoError(t, err) 77 require.Equal(t, expectedIndexContent, readCompressedFile(t, indexPathInStorage)) 78 } 79 }) 80 } 81 } 82 83 func TestIndexSet_Cleanup(t *testing.T) { 84 dbRetainPeriod := 5 * time.Minute 85 tempDir := t.TempDir() 86 testStorageClient := buildTestStorageClient(t, tempDir) 87 88 for _, userID := range []string{userID, ""} { 89 t.Run(userID, func(t *testing.T) { 90 idxSet, err := NewIndexSet(testTableName, userID, storage.NewIndexSet(testStorageClient, userID != ""), util_log.Logger) 91 require.NoError(t, err) 92 defer idxSet.Close() 93 94 testIndexes := buildTestIndexes(t, t.TempDir(), 5) 95 for _, testIndex := range testIndexes { 96 idxSet.Add(testIndex) 97 } 98 99 // upload the indexes 100 err = idxSet.Upload(context.Background()) 101 require.NoError(t, err) 102 103 // cleanup the indexes outside the retention period 104 err = idxSet.Cleanup(dbRetainPeriod) 105 require.NoError(t, err) 106 107 // all the indexes should be retained since they were just uploaded 108 indexesFound := map[string]*mockIndex{} 109 err = idxSet.ForEach(func(_ bool, index index.Index) error { 110 indexesFound[index.Path()] = index.(*mockIndex) 111 return nil 112 }) 113 require.NoError(t, err) 114 115 require.Equal(t, testIndexes, indexesFound) 116 117 // change the upload time of some of the indexes to now-(retention period+minute) so that they get dropped during cleanup 118 indexToCleanup := map[string]struct{}{} 119 for _, testIndex := range testIndexes { 120 indexToCleanup[testIndex.Path()] = struct{}{} 121 idxSet.(*indexSet).indexUploadTime[testIndex.Name()] = time.Now().Add(-(dbRetainPeriod + time.Minute)) 122 if len(indexToCleanup) == 2 { 123 break 124 } 125 } 126 127 // cleanup the indexes outside the retention period 128 err = idxSet.Cleanup(dbRetainPeriod) 129 require.NoError(t, err) 130 131 // get all the indexes that are retained 132 indexesFound = map[string]*mockIndex{} 133 err = idxSet.ForEach(func(_ bool, index index.Index) error { 134 indexesFound[index.Path()] = index.(*mockIndex) 135 return nil 136 }) 137 require.NoError(t, err) 138 139 // we should have only the indexes whose upload time was not changed above 140 require.Len(t, indexesFound, len(testIndexes)-(len(indexToCleanup))) 141 for _, testIndex := range testIndexes { 142 if _, ok := indexToCleanup[testIndex.Path()]; ok { 143 // make sure that file backing the index is dropped from local disk 144 require.NoFileExists(t, testIndex.Path()) 145 continue 146 } 147 require.Contains(t, indexesFound, testIndex.Path()) 148 } 149 }) 150 } 151 } 152 153 // readCompressedFile reads the contents of a compressed file at given path. 154 func readCompressedFile(t *testing.T, path string) []byte { 155 tempDir := t.TempDir() 156 decompressedFilePath := filepath.Join(tempDir, "decompressed") 157 testutil.DecompressFile(t, path, decompressedFilePath) 158 159 fileContent, err := ioutil.ReadFile(decompressedFilePath) 160 require.NoError(t, err) 161 162 return fileContent 163 }