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  }