| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | package backend_test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2017-06-03 17:39:57 +02:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2018-01-16 23:59:16 -05:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | 	"math/rand" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-23 14:21:03 +02:00
										 |  |  | 	"github.com/restic/restic/internal/backend" | 
					
						
							|  |  |  | 	"github.com/restic/restic/internal/backend/mem" | 
					
						
							| 
									
										
										
										
											2018-01-16 23:59:16 -05:00
										 |  |  | 	"github.com/restic/restic/internal/errors" | 
					
						
							| 
									
										
										
										
											2017-07-24 17:42:25 +02:00
										 |  |  | 	"github.com/restic/restic/internal/restic" | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest "github.com/restic/restic/internal/test" | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const KiB = 1 << 10 | 
					
						
							|  |  |  | const MiB = 1 << 20 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestLoadAll(t *testing.T) { | 
					
						
							|  |  |  | 	b := mem.New() | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | 	var buf []byte | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 20; i++ { | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		data := rtest.Random(23+i, rand.Intn(MiB)+500*KiB) | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-31 22:51:35 +02:00
										 |  |  | 		id := restic.Hash(data) | 
					
						
							| 
									
										
										
										
											2020-08-16 11:16:38 +02:00
										 |  |  | 		h := restic.Handle{Name: id.String(), Type: restic.PackFile} | 
					
						
							| 
									
										
										
										
											2020-12-19 12:39:48 +01:00
										 |  |  | 		err := b.Save(context.TODO(), h, restic.NewByteReader(data, b.Hasher())) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 11:16:38 +02:00
										 |  |  | 		buf, err := backend.LoadAll(context.TODO(), buf, b, restic.Handle{Type: restic.PackFile, Name: id.String()}) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2016-01-23 23:41:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if len(buf) != len(data) { | 
					
						
							|  |  |  | 			t.Errorf("length of returned buffer does not match, want %d, got %d", len(data), len(buf)) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !bytes.Equal(buf, data) { | 
					
						
							|  |  |  | 			t.Errorf("wrong data returned") | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | func save(t testing.TB, be restic.Backend, buf []byte) restic.Handle { | 
					
						
							|  |  |  | 	id := restic.Hash(buf) | 
					
						
							| 
									
										
										
										
											2020-08-16 11:16:38 +02:00
										 |  |  | 	h := restic.Handle{Name: id.String(), Type: restic.PackFile} | 
					
						
							| 
									
										
										
										
											2020-12-19 12:39:48 +01:00
										 |  |  | 	err := be.Save(context.TODO(), h, restic.NewByteReader(buf, be.Hasher())) | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | 	return h | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | func TestLoadAllAppend(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | 	b := mem.New() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | 	h1 := save(t, b, []byte("foobar test string")) | 
					
						
							|  |  |  | 	randomData := rtest.Random(23, rand.Intn(MiB)+500*KiB) | 
					
						
							|  |  |  | 	h2 := save(t, b, randomData) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var tests = []struct { | 
					
						
							|  |  |  | 		handle restic.Handle | 
					
						
							|  |  |  | 		buf    []byte | 
					
						
							|  |  |  | 		want   []byte | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			handle: h1, | 
					
						
							|  |  |  | 			buf:    nil, | 
					
						
							|  |  |  | 			want:   []byte("foobar test string"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			handle: h1, | 
					
						
							|  |  |  | 			buf:    []byte("xxx"), | 
					
						
							|  |  |  | 			want:   []byte("foobar test string"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			handle: h2, | 
					
						
							|  |  |  | 			buf:    nil, | 
					
						
							|  |  |  | 			want:   randomData, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			handle: h2, | 
					
						
							|  |  |  | 			buf:    make([]byte, 0, 200), | 
					
						
							|  |  |  | 			want:   randomData, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			handle: h2, | 
					
						
							|  |  |  | 			buf:    []byte("foobarbaz"), | 
					
						
							|  |  |  | 			want:   randomData, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 21:59:14 +01:00
										 |  |  | 	for _, test := range tests { | 
					
						
							|  |  |  | 		t.Run("", func(t *testing.T) { | 
					
						
							|  |  |  | 			buf, err := backend.LoadAll(context.TODO(), test.buf, b, test.handle) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if !bytes.Equal(buf, test.want) { | 
					
						
							|  |  |  | 				t.Errorf("wrong data returned, want %q, got %q", test.want, buf) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-02-07 23:48:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-16 23:59:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | type mockReader struct { | 
					
						
							|  |  |  | 	closed bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (rd *mockReader) Read(p []byte) (n int, err error) { | 
					
						
							|  |  |  | 	return 0, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func (rd *mockReader) Close() error { | 
					
						
							|  |  |  | 	rd.closed = true | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDefaultLoad(t *testing.T) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 11:16:38 +02:00
										 |  |  | 	h := restic.Handle{Name: "id", Type: restic.PackFile} | 
					
						
							| 
									
										
										
										
											2018-01-16 23:59:16 -05:00
										 |  |  | 	rd := &mockReader{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// happy case, assert correct parameters are passed around and content stream is closed | 
					
						
							|  |  |  | 	err := backend.DefaultLoad(context.TODO(), h, 10, 11, func(ctx context.Context, ih restic.Handle, length int, offset int64) (io.ReadCloser, error) { | 
					
						
							|  |  |  | 		rtest.Equals(t, h, ih) | 
					
						
							|  |  |  | 		rtest.Equals(t, int(10), length) | 
					
						
							|  |  |  | 		rtest.Equals(t, int64(11), offset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return rd, nil | 
					
						
							|  |  |  | 	}, func(ird io.Reader) error { | 
					
						
							|  |  |  | 		rtest.Equals(t, rd, ird) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	rtest.OK(t, err) | 
					
						
							|  |  |  | 	rtest.Equals(t, true, rd.closed) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// unhappy case, assert producer errors are handled correctly | 
					
						
							|  |  |  | 	err = backend.DefaultLoad(context.TODO(), h, 10, 11, func(ctx context.Context, ih restic.Handle, length int, offset int64) (io.ReadCloser, error) { | 
					
						
							|  |  |  | 		return nil, errors.Errorf("producer error") | 
					
						
							|  |  |  | 	}, func(ird io.Reader) error { | 
					
						
							|  |  |  | 		t.Fatalf("unexpected consumer invocation") | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	rtest.Equals(t, "producer error", err.Error()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// unhappy case, assert consumer errors are handled correctly | 
					
						
							|  |  |  | 	rd = &mockReader{} | 
					
						
							|  |  |  | 	err = backend.DefaultLoad(context.TODO(), h, 10, 11, func(ctx context.Context, ih restic.Handle, length int, offset int64) (io.ReadCloser, error) { | 
					
						
							|  |  |  | 		return rd, nil | 
					
						
							|  |  |  | 	}, func(ird io.Reader) error { | 
					
						
							|  |  |  | 		return errors.Errorf("consumer error") | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	rtest.Equals(t, true, rd.closed) | 
					
						
							|  |  |  | 	rtest.Equals(t, "consumer error", err.Error()) | 
					
						
							|  |  |  | } |