github.com/weaviate/weaviate@v1.24.6/usecases/backup/zip_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package backup 13 14 import ( 15 "bytes" 16 "compress/gzip" 17 "context" 18 "fmt" 19 "io" 20 "os" 21 "path/filepath" 22 "strings" 23 "testing" 24 25 "github.com/weaviate/weaviate/entities/backup" 26 ) 27 28 func TestZip(t *testing.T) { 29 var ( 30 pathNode = "test_data/node1" 31 pathDest = "./test_data/node-unzipped" 32 ctx = context.Background() 33 ) 34 35 defer os.RemoveAll(pathDest) 36 // setup 37 sd, err := getShard(pathNode, "cT9eTErXgmTX") 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 // compression writer 43 compressBuf := bytes.NewBuffer(make([]byte, 0, 1000_000)) 44 z, rc := NewZip(pathNode, 0) 45 var zInputLen int64 46 go func() { 47 zInputLen, err = z.WriteShard(ctx, &sd) 48 if err != nil { 49 t.Errorf("compress: %v", err) 50 } 51 z.Close() 52 }() 53 54 // compression reader 55 zOutputLen, err := io.Copy(compressBuf, rc) 56 if err != nil { 57 t.Fatal("copy to buffer", err) 58 } 59 60 if err := rc.Close(); err != nil { 61 t.Errorf("compress:close %v", err) 62 } 63 64 f := float32(zInputLen) / float32(zOutputLen) 65 fmt.Printf("compression input_size=%d output_size=%d factor=%v\n", zInputLen, zOutputLen, f) 66 os.RemoveAll(pathDest) 67 // decompression 68 uz, wc := NewUnzip(pathDest) 69 70 // decompression reader 71 var uzInputLen int64 72 go func() { 73 uzInputLen, err = io.Copy(wc, compressBuf) 74 if err != nil { 75 t.Errorf("writer: %v", err) 76 } 77 if err := wc.Close(); err != nil { 78 t.Errorf("close writer: %v", err) 79 } 80 }() 81 82 // decompression writer 83 uzOutputLen, err := uz.ReadChunk() 84 if err != nil { 85 t.Fatalf("unzip: %v", err) 86 } 87 if err := uz.Close(); err != nil { 88 t.Errorf("close reader: %v", err) 89 } 90 91 fmt.Printf("unzip input_size=%d output_size=%d\n", uzInputLen, uzOutputLen) 92 93 _, err = os.Stat(pathDest) 94 if err != nil { 95 t.Fatalf("cannot find decompressed folder: %v", err) 96 } 97 98 if zInputLen != uzOutputLen { 99 t.Errorf("zip input size %d != unzip output size %d", uzOutputLen, zInputLen) 100 } 101 if zOutputLen != uzInputLen { 102 t.Errorf("zip output size %d != unzip input size %d", zOutputLen, uzInputLen) 103 } 104 } 105 106 func TestZipLevel(t *testing.T) { 107 tests := []struct { 108 in int 109 out int 110 }{ 111 {-1, gzip.DefaultCompression}, 112 {4, gzip.DefaultCompression}, 113 {0, gzip.DefaultCompression}, 114 {int(BestCompression), gzip.BestCompression}, 115 {int(BestSpeed), gzip.BestSpeed}, 116 } 117 118 for _, test := range tests { 119 if got := zipLevel(test.in); got != test.out { 120 t.Errorf("compression level got=%d want=%d", got, test.out) 121 } 122 } 123 } 124 125 func TestZipConfig(t *testing.T) { 126 tests := []struct { 127 chunkSize int 128 percentage int 129 130 expectedChunkSize int 131 minPoolSize int 132 maxPoolSize int 133 }{ 134 {0, 0, DefaultChunkSize, 1, _NUMCPU / 2}, 135 {2 - 1, 50, minChunkSize, _NUMCPU / 2, _NUMCPU}, 136 {512 + 1, 50, maxChunkSize, _NUMCPU / 2, _NUMCPU}, 137 {2, 0, minChunkSize, 1, _NUMCPU / 2}, 138 {1, 100, minChunkSize, 1, _NUMCPU}, 139 {100, 0, 100 * 1024 * 1024, 1, _NUMCPU / 2}, // 100 MB 140 {513, 0, maxChunkSize, 1, _NUMCPU / 2}, 141 } 142 143 for i, test := range tests { 144 got := newZipConfig(Compression{ 145 Level: BestSpeed, 146 CPUPercentage: test.percentage, 147 ChunkSize: test.chunkSize, 148 }) 149 if got.ChunkSize != test.expectedChunkSize { 150 t.Errorf("%d. chunk size got=%v want=%v", i, got.ChunkSize, test.expectedChunkSize) 151 } 152 if n := test.minPoolSize; got.GoPoolSize < n { 153 t.Errorf("%d. min pool size got=%d want>=%d", i, got.GoPoolSize, n) 154 } 155 if n := test.maxPoolSize; got.GoPoolSize > n { 156 t.Errorf("%d. max pool size got=%d want<%d", i, got.GoPoolSize, n) 157 } 158 } 159 } 160 161 func getShard(src, shardName string) (sd backup.ShardDescriptor, err error) { 162 sd.Name = shardName 163 err = filepath.Walk(src, func(fPath string, fi os.FileInfo, err error) error { 164 // return on any error 165 if err != nil { 166 return err 167 } 168 if !fi.Mode().IsRegular() || !strings.Contains(fPath, shardName) { 169 return nil 170 } 171 relPath := strings.TrimPrefix(strings.Replace(fPath, src, "", -1), string(filepath.Separator)) 172 name := fi.Name() 173 174 if strings.Contains(name, "indexcount") { 175 sd.DocIDCounterPath = relPath 176 sd.DocIDCounter, err = os.ReadFile(fPath) 177 } else if strings.Contains(name, "proplengths") { 178 sd.PropLengthTrackerPath = relPath 179 sd.PropLengthTracker, err = os.ReadFile(fPath) 180 181 } else if strings.Contains(name, "version") { 182 sd.ShardVersionPath = relPath 183 sd.Version, err = os.ReadFile(fPath) 184 } else { 185 sd.Files = append(sd.Files, relPath) 186 } 187 188 return err 189 }) 190 191 return sd, err 192 }