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

     1  package archiver
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"io"
     8  	"math/rand"
     9  	"testing"
    10  
    11  	"github.com/restic/restic/internal/checker"
    12  	"github.com/restic/restic/internal/repository"
    13  	"github.com/restic/restic/internal/restic"
    14  )
    15  
    16  func loadBlob(t *testing.T, repo restic.Repository, id restic.ID, buf []byte) int {
    17  	n, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf)
    18  	if err != nil {
    19  		t.Fatalf("LoadBlob(%v) returned error %v", id, err)
    20  	}
    21  
    22  	return n
    23  }
    24  
    25  func checkSavedFile(t *testing.T, repo restic.Repository, treeID restic.ID, name string, rd io.Reader) {
    26  	tree, err := repo.LoadTree(context.TODO(), treeID)
    27  	if err != nil {
    28  		t.Fatalf("LoadTree() returned error %v", err)
    29  	}
    30  
    31  	if len(tree.Nodes) != 1 {
    32  		t.Fatalf("wrong number of nodes for tree, want %v, got %v", 1, len(tree.Nodes))
    33  	}
    34  
    35  	node := tree.Nodes[0]
    36  	if node.Name != "fakefile" {
    37  		t.Fatalf("wrong filename, want %v, got %v", "fakefile", node.Name)
    38  	}
    39  
    40  	if len(node.Content) == 0 {
    41  		t.Fatalf("node.Content has length 0")
    42  	}
    43  
    44  	// check blobs
    45  	for i, id := range node.Content {
    46  		size, found := repo.LookupBlobSize(id, restic.DataBlob)
    47  		if !found {
    48  			t.Fatal("Failed to find blob", id.Str())
    49  		}
    50  
    51  		buf := restic.NewBlobBuffer(int(size))
    52  		n := loadBlob(t, repo, id, buf)
    53  		if n != len(buf) {
    54  			t.Errorf("wrong number of bytes read, want %d, got %d", len(buf), n)
    55  		}
    56  
    57  		buf2 := make([]byte, int(size))
    58  		_, err := io.ReadFull(rd, buf2)
    59  		if err != nil {
    60  			t.Fatal(err)
    61  		}
    62  
    63  		if !bytes.Equal(buf, buf2) {
    64  			t.Fatalf("blob %d (%v) is wrong", i, id.Str())
    65  		}
    66  	}
    67  }
    68  
    69  // fakeFile returns a reader which yields deterministic pseudo-random data.
    70  func fakeFile(t testing.TB, seed, size int64) io.Reader {
    71  	return io.LimitReader(restic.NewRandReader(rand.New(rand.NewSource(seed))), size)
    72  }
    73  
    74  func TestArchiveReader(t *testing.T) {
    75  	repo, cleanup := repository.TestRepository(t)
    76  	defer cleanup()
    77  
    78  	seed := rand.Int63()
    79  	size := int64(rand.Intn(50*1024*1024) + 50*1024*1024)
    80  	t.Logf("seed is 0x%016x, size is %v", seed, size)
    81  
    82  	f := fakeFile(t, seed, size)
    83  
    84  	r := &Reader{
    85  		Repository: repo,
    86  		Hostname:   "localhost",
    87  		Tags:       []string{"test"},
    88  	}
    89  
    90  	sn, id, err := r.Archive(context.TODO(), "fakefile", f, nil)
    91  	if err != nil {
    92  		t.Fatalf("ArchiveReader() returned error %v", err)
    93  	}
    94  
    95  	if id.IsNull() {
    96  		t.Fatalf("ArchiveReader() returned null ID")
    97  	}
    98  
    99  	t.Logf("snapshot saved as %v, tree is %v", id.Str(), sn.Tree.Str())
   100  
   101  	checkSavedFile(t, repo, *sn.Tree, "fakefile", fakeFile(t, seed, size))
   102  
   103  	checker.TestCheckRepo(t, repo)
   104  }
   105  
   106  func TestArchiveReaderNull(t *testing.T) {
   107  	repo, cleanup := repository.TestRepository(t)
   108  	defer cleanup()
   109  
   110  	r := &Reader{
   111  		Repository: repo,
   112  		Hostname:   "localhost",
   113  		Tags:       []string{"test"},
   114  	}
   115  
   116  	sn, id, err := r.Archive(context.TODO(), "fakefile", bytes.NewReader(nil), nil)
   117  	if err != nil {
   118  		t.Fatalf("ArchiveReader() returned error %v", err)
   119  	}
   120  
   121  	if id.IsNull() {
   122  		t.Fatalf("ArchiveReader() returned null ID")
   123  	}
   124  
   125  	t.Logf("snapshot saved as %v, tree is %v", id.Str(), sn.Tree.Str())
   126  
   127  	checker.TestCheckRepo(t, repo)
   128  }
   129  
   130  type errReader string
   131  
   132  func (e errReader) Read([]byte) (int, error) {
   133  	return 0, errors.New(string(e))
   134  }
   135  
   136  func countSnapshots(t testing.TB, repo restic.Repository) int {
   137  	snapshots := 0
   138  	err := repo.List(context.TODO(), restic.SnapshotFile, func(id restic.ID, size int64) error {
   139  		snapshots++
   140  		return nil
   141  	})
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	return snapshots
   146  }
   147  
   148  func TestArchiveReaderError(t *testing.T) {
   149  	repo, cleanup := repository.TestRepository(t)
   150  	defer cleanup()
   151  
   152  	r := &Reader{
   153  		Repository: repo,
   154  		Hostname:   "localhost",
   155  		Tags:       []string{"test"},
   156  	}
   157  
   158  	sn, id, err := r.Archive(context.TODO(), "fakefile", errReader("error returned by reading stdin"), nil)
   159  	if err == nil {
   160  		t.Errorf("expected error not returned")
   161  	}
   162  
   163  	if sn != nil {
   164  		t.Errorf("Snapshot should be nil, but isn't")
   165  	}
   166  
   167  	if !id.IsNull() {
   168  		t.Errorf("id should be null, but %v returned", id.Str())
   169  	}
   170  
   171  	n := countSnapshots(t, repo)
   172  	if n > 0 {
   173  		t.Errorf("expected zero snapshots, but got %d", n)
   174  	}
   175  
   176  	checker.TestCheckRepo(t, repo)
   177  }
   178  
   179  func BenchmarkArchiveReader(t *testing.B) {
   180  	repo, cleanup := repository.TestRepository(t)
   181  	defer cleanup()
   182  
   183  	const size = 50 * 1024 * 1024
   184  
   185  	buf := make([]byte, size)
   186  	_, err := io.ReadFull(fakeFile(t, 23, size), buf)
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  
   191  	r := &Reader{
   192  		Repository: repo,
   193  		Hostname:   "localhost",
   194  		Tags:       []string{"test"},
   195  	}
   196  
   197  	t.SetBytes(size)
   198  	t.ResetTimer()
   199  
   200  	for i := 0; i < t.N; i++ {
   201  		_, _, err := r.Archive(context.TODO(), "fakefile", bytes.NewReader(buf), nil)
   202  		if err != nil {
   203  			t.Fatal(err)
   204  		}
   205  	}
   206  }