github.com/mckael/restic@v0.8.3/internal/restic/find_test.go (about)

     1  package restic_test
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"encoding/json"
     7  	"flag"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"sort"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/restic/restic/internal/repository"
    16  	"github.com/restic/restic/internal/restic"
    17  )
    18  
    19  func loadIDSet(t testing.TB, filename string) restic.BlobSet {
    20  	f, err := os.Open(filename)
    21  	if err != nil {
    22  		t.Logf("unable to open golden file %v: %v", filename, err)
    23  		return restic.NewBlobSet()
    24  	}
    25  
    26  	sc := bufio.NewScanner(f)
    27  
    28  	blobs := restic.NewBlobSet()
    29  	for sc.Scan() {
    30  		var h restic.BlobHandle
    31  		err := json.Unmarshal([]byte(sc.Text()), &h)
    32  		if err != nil {
    33  			t.Errorf("file %v contained invalid blob: %#v", filename, err)
    34  			continue
    35  		}
    36  
    37  		blobs.Insert(h)
    38  	}
    39  
    40  	if err = f.Close(); err != nil {
    41  		t.Errorf("closing file %v failed with error %v", filename, err)
    42  	}
    43  
    44  	return blobs
    45  }
    46  
    47  func saveIDSet(t testing.TB, filename string, s restic.BlobSet) {
    48  	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
    49  	if err != nil {
    50  		t.Fatalf("unable to update golden file %v: %v", filename, err)
    51  		return
    52  	}
    53  
    54  	var hs restic.BlobHandles
    55  	for h := range s {
    56  		hs = append(hs, h)
    57  	}
    58  
    59  	sort.Sort(hs)
    60  
    61  	enc := json.NewEncoder(f)
    62  	for _, h := range hs {
    63  		err = enc.Encode(h)
    64  		if err != nil {
    65  			t.Fatalf("Encode() returned error: %v", err)
    66  		}
    67  	}
    68  
    69  	if err = f.Close(); err != nil {
    70  		t.Fatalf("close file %v returned error: %v", filename, err)
    71  	}
    72  }
    73  
    74  var updateGoldenFiles = flag.Bool("update", false, "update golden files in testdata/")
    75  
    76  const (
    77  	findTestSnapshots = 3
    78  	findTestDepth     = 2
    79  )
    80  
    81  var findTestTime = time.Unix(1469960361, 23)
    82  
    83  func TestFindUsedBlobs(t *testing.T) {
    84  	repo, cleanup := repository.TestRepository(t)
    85  	defer cleanup()
    86  
    87  	var snapshots []*restic.Snapshot
    88  	for i := 0; i < findTestSnapshots; i++ {
    89  		sn := restic.TestCreateSnapshot(t, repo, findTestTime.Add(time.Duration(i)*time.Second), findTestDepth, 0)
    90  		t.Logf("snapshot %v saved, tree %v", sn.ID().Str(), sn.Tree.Str())
    91  		snapshots = append(snapshots, sn)
    92  	}
    93  
    94  	for i, sn := range snapshots {
    95  		usedBlobs := restic.NewBlobSet()
    96  		err := restic.FindUsedBlobs(context.TODO(), repo, *sn.Tree, usedBlobs, restic.NewBlobSet())
    97  		if err != nil {
    98  			t.Errorf("FindUsedBlobs returned error: %v", err)
    99  			continue
   100  		}
   101  
   102  		if len(usedBlobs) == 0 {
   103  			t.Errorf("FindUsedBlobs returned an empty set")
   104  			continue
   105  		}
   106  
   107  		goldenFilename := filepath.Join("testdata", fmt.Sprintf("used_blobs_snapshot%d", i))
   108  		want := loadIDSet(t, goldenFilename)
   109  
   110  		if !want.Equals(usedBlobs) {
   111  			t.Errorf("snapshot %d: wrong list of blobs returned:\n  missing blobs: %v\n  extra blobs: %v",
   112  				i, want.Sub(usedBlobs), usedBlobs.Sub(want))
   113  		}
   114  
   115  		if *updateGoldenFiles {
   116  			saveIDSet(t, goldenFilename, usedBlobs)
   117  		}
   118  	}
   119  }
   120  
   121  func BenchmarkFindUsedBlobs(b *testing.B) {
   122  	repo, cleanup := repository.TestRepository(b)
   123  	defer cleanup()
   124  
   125  	sn := restic.TestCreateSnapshot(b, repo, findTestTime, findTestDepth, 0)
   126  
   127  	b.ResetTimer()
   128  
   129  	for i := 0; i < b.N; i++ {
   130  		seen := restic.NewBlobSet()
   131  		blobs := restic.NewBlobSet()
   132  		err := restic.FindUsedBlobs(context.TODO(), repo, *sn.Tree, blobs, seen)
   133  		if err != nil {
   134  			b.Error(err)
   135  		}
   136  
   137  		b.Logf("found %v blobs", len(blobs))
   138  	}
   139  }