| 
									
										
										
										
											2015-05-09 23:52:03 +02:00
										 |  |  | package repository_test | 
					
						
							| 
									
										
										
										
											2015-02-16 19:32:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2015-02-16 19:32:36 +01:00
										 |  |  | 	"crypto/sha256" | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	"math/rand" | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2015-07-04 16:52:17 +02:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2015-02-16 19:32:36 +01:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2015-02-16 19:32:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	"github.com/google/go-cmp/cmp" | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 	"github.com/klauspost/compress/zstd" | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	"github.com/restic/restic/internal/crypto" | 
					
						
							| 
									
										
										
										
											2017-07-23 14:21:03 +02:00
										 |  |  | 	"github.com/restic/restic/internal/repository" | 
					
						
							| 
									
										
										
										
											2017-07-24 17:42:25 +02:00
										 |  |  | 	"github.com/restic/restic/internal/restic" | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	"github.com/restic/restic/internal/test" | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest "github.com/restic/restic/internal/test" | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 	"golang.org/x/sync/errgroup" | 
					
						
							| 
									
										
										
										
											2015-02-16 19:32:36 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | var testSizes = []int{5, 23, 2<<18 + 23, 1 << 20} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | func TestSave(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.TestAllVersions(t, testSave) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testSave(t *testing.T, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(t, version) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, size := range testSizes { | 
					
						
							|  |  |  | 		data := make([]byte, size) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		_, err := io.ReadFull(rnd, data) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-31 20:29:54 +02:00
										 |  |  | 		id := restic.Hash(data) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 		var wg errgroup.Group | 
					
						
							|  |  |  | 		repo.StartPackUploader(context.TODO(), &wg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 		// save | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 		sid, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, data, restic.ID{}, false) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.Equals(t, id, sid) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 		rtest.OK(t, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		// rtest.OK(t, repo.SaveIndex()) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// read back | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		rtest.Equals(t, size, len(buf)) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.Assert(t, len(buf) == len(data), | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 			"number of bytes read back does not match: expected %d, got %d", | 
					
						
							|  |  |  | 			len(data), len(buf)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.Assert(t, bytes.Equal(buf, data), | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 			"data does not match: expected %02x, got %02x", | 
					
						
							|  |  |  | 			data, buf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | func TestSaveFrom(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.TestAllVersions(t, testSaveFrom) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testSaveFrom(t *testing.T, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(t, version) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, size := range testSizes { | 
					
						
							|  |  |  | 		data := make([]byte, size) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		_, err := io.ReadFull(rnd, data) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-31 20:29:54 +02:00
										 |  |  | 		id := restic.Hash(data) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 		var wg errgroup.Group | 
					
						
							|  |  |  | 		repo.StartPackUploader(context.TODO(), &wg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 		// save | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 		id2, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, data, id, false) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							|  |  |  | 		rtest.Equals(t, id, id2) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 		rtest.OK(t, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 		// read back | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		rtest.Equals(t, size, len(buf)) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.Assert(t, len(buf) == len(data), | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 			"number of bytes read back does not match: expected %d, got %d", | 
					
						
							|  |  |  | 			len(data), len(buf)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.Assert(t, bytes.Equal(buf, data), | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 			"data does not match: expected %02x, got %02x", | 
					
						
							|  |  |  | 			data, buf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-08 13:13:29 +02:00
										 |  |  | func BenchmarkSaveAndEncrypt(t *testing.B) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.BenchmarkAllVersions(t, benchmarkSaveAndEncrypt) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func benchmarkSaveAndEncrypt(t *testing.B, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(t, version) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	size := 4 << 20 // 4MiB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data := make([]byte, size) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	_, err := io.ReadFull(rnd, data) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-31 20:29:54 +02:00
										 |  |  | 	id := restic.ID(sha256.Sum256(data)) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-26 23:26:11 +01:00
										 |  |  | 	t.ReportAllocs() | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 	t.ResetTimer() | 
					
						
							|  |  |  | 	t.SetBytes(int64(size)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < t.N; i++ { | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 		_, _, _, err = repo.SaveBlob(context.TODO(), restic.DataBlob, data, id, true) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-02-16 20:00:23 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-17 23:05:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | func TestLoadBlob(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.TestAllVersions(t, testLoadBlob) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testLoadBlob(t *testing.T, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(t, version) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							| 
									
										
										
										
											2022-06-12 14:48:30 +02:00
										 |  |  | 	buf := crypto.NewBlobBuffer(length) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 	_, err := io.ReadFull(rnd, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 	var wg errgroup.Group | 
					
						
							|  |  |  | 	repo.StartPackUploader(context.TODO(), &wg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 	id, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, buf, restic.ID{}, false) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 	rtest.OK(t, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-12 14:48:30 +02:00
										 |  |  | 	base := crypto.CiphertextLength(length) | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 	for _, testlength := range []int{0, base - 20, base - 1, base, base + 7, base + 15, base + 1000} { | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 		buf = make([]byte, 0, testlength) | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Errorf("LoadBlob() returned an error for buffer size %v: %v", testlength, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		if len(buf) != length { | 
					
						
							|  |  |  | 			t.Errorf("LoadBlob() returned the wrong number of bytes: want %v, got %v", length, len(buf)) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | func BenchmarkLoadBlob(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.BenchmarkAllVersions(b, benchmarkLoadBlob) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func benchmarkLoadBlob(b *testing.B, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(b, version) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							| 
									
										
										
										
											2022-06-12 14:48:30 +02:00
										 |  |  | 	buf := crypto.NewBlobBuffer(length) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	_, err := io.ReadFull(rnd, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 	var wg errgroup.Group | 
					
						
							|  |  |  | 	repo.StartPackUploader(context.TODO(), &wg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 	id, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, buf, restic.ID{}, false) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 	rtest.OK(b, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.SetBytes(int64(length)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		var err error | 
					
						
							|  |  |  | 		buf, err = repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf) | 
					
						
							| 
									
										
										
										
											2020-04-28 07:57:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Checking the SHA-256 with restic.Hash can make up 38% of the time | 
					
						
							|  |  |  | 		// spent in this loop, so pause the timer. | 
					
						
							|  |  |  | 		b.StopTimer() | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		if len(buf) != length { | 
					
						
							|  |  |  | 			b.Errorf("wanted %d bytes, got %d", length, len(buf)) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 16:41:22 +01:00
										 |  |  | 		id2 := restic.Hash(buf) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		if !id.Equal(id2) { | 
					
						
							|  |  |  | 			b.Errorf("wrong data returned, wanted %v, got %v", id.Str(), id2.Str()) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-28 07:57:29 +02:00
										 |  |  | 		b.StartTimer() | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-13 00:01:27 +01:00
										 |  |  | func BenchmarkLoadUnpacked(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.BenchmarkAllVersions(b, benchmarkLoadUnpacked) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func benchmarkLoadUnpacked(b *testing.B, version uint) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(b, version) | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							| 
									
										
										
										
											2022-06-12 14:48:30 +02:00
										 |  |  | 	buf := crypto.NewBlobBuffer(length) | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 	_, err := io.ReadFull(rnd, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dataID := restic.Hash(buf) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 11:16:38 +02:00
										 |  |  | 	storageID, err := repo.SaveUnpacked(context.TODO(), restic.PackFile, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							|  |  |  | 	// rtest.OK(b, repo.Flush()) | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	b.SetBytes(int64(length)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2022-06-12 14:38:19 +02:00
										 |  |  | 		data, err := repo.LoadUnpacked(context.TODO(), restic.PackFile, storageID, nil) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2020-04-28 07:57:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// See comment in BenchmarkLoadBlob. | 
					
						
							|  |  |  | 		b.StopTimer() | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 		if len(data) != length { | 
					
						
							|  |  |  | 			b.Errorf("wanted %d bytes, got %d", length, len(data)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		id2 := restic.Hash(data) | 
					
						
							|  |  |  | 		if !dataID.Equal(id2) { | 
					
						
							|  |  |  | 			b.Errorf("wrong data returned, wanted %v, got %v", storageID.Str(), id2.Str()) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-28 07:57:29 +02:00
										 |  |  | 		b.StartTimer() | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 16:52:17 +02:00
										 |  |  | var repoFixture = filepath.Join("testdata", "test-repo.tar.gz") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-08 12:22:17 +02:00
										 |  |  | func TestRepositoryLoadIndex(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	repodir, cleanup := rtest.Env(t, repoFixture) | 
					
						
							| 
									
										
										
										
											2016-09-04 14:29:04 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	repo := repository.TestOpenLocal(t, repodir) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, repo.LoadIndex(context.TODO())) | 
					
						
							| 
									
										
										
										
											2015-07-04 16:52:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | // loadIndex loads the index id from backend and returns it. | 
					
						
							|  |  |  | func loadIndex(ctx context.Context, repo restic.Repository, id restic.ID) (*repository.Index, error) { | 
					
						
							| 
									
										
										
										
											2022-06-12 14:38:19 +02:00
										 |  |  | 	buf, err := repo.LoadUnpacked(ctx, restic.IndexFile, id, nil) | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	idx, oldFormat, err := repository.DecodeIndex(buf, id) | 
					
						
							|  |  |  | 	if oldFormat { | 
					
						
							|  |  |  | 		fmt.Fprintf(os.Stderr, "index %v has old format\n", id.Str()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return idx, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 16:52:17 +02:00
										 |  |  | func BenchmarkLoadIndex(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.BenchmarkAllVersions(b, benchmarkLoadIndex) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func benchmarkLoadIndex(b *testing.B, version uint) { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 	repository.TestUseLowSecurityKDFParameters(b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepositoryWithVersion(b, version) | 
					
						
							| 
									
										
										
										
											2016-09-04 14:29:04 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 	idx := repository.NewIndex() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 5000; i++ { | 
					
						
							| 
									
										
										
										
											2022-05-26 13:41:06 +02:00
										 |  |  | 		idx.StorePack(restic.NewRandomID(), []restic.Blob{ | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2020-11-05 22:18:00 +01:00
										 |  |  | 				BlobHandle: restic.NewRandomBlobHandle(), | 
					
						
							|  |  |  | 				Length:     1234, | 
					
						
							|  |  |  | 				Offset:     1235, | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	id, err := repository.SaveIndex(context.TODO(), repo, idx) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-26 15:05:29 +02:00
										 |  |  | 	b.Logf("index saved as %v", id.Str()) | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	fi, err := repo.Backend().Stat(context.TODO(), restic.Handle{Type: restic.IndexFile, Name: id.String()}) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 	b.Logf("filesize is %v", fi.Size) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-04 14:29:04 +02:00
										 |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | 		_, err := loadIndex(context.TODO(), repo, id) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(b, err) | 
					
						
							| 
									
										
										
										
											2016-09-04 14:29:04 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-04 16:52:17 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // saveRandomDataBlobs generates random data blobs and saves them to the repository. | 
					
						
							| 
									
										
										
										
											2016-09-03 13:34:04 +02:00
										 |  |  | func saveRandomDataBlobs(t testing.TB, repo restic.Repository, num int, sizeMax int) { | 
					
						
							| 
									
										
										
										
											2021-08-07 22:52:05 +02:00
										 |  |  | 	var wg errgroup.Group | 
					
						
							|  |  |  | 	repo.StartPackUploader(context.TODO(), &wg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	for i := 0; i < num; i++ { | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		size := rand.Int() % sizeMax | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		buf := make([]byte, size) | 
					
						
							| 
									
										
										
										
											2017-01-13 12:20:37 +01:00
										 |  |  | 		_, err := io.ReadFull(rnd, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-01 14:26:57 +02:00
										 |  |  | 		_, _, _, err = repo.SaveBlob(context.TODO(), restic.DataBlob, buf, restic.ID{}, false) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRepositoryIncrementalIndex(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-29 23:16:16 +02:00
										 |  |  | 	repository.TestAllVersions(t, testRepositoryIncrementalIndex) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testRepositoryIncrementalIndex(t *testing.T, version uint) { | 
					
						
							|  |  |  | 	r, cleanup := repository.TestRepositoryWithVersion(t, version) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +02:00
										 |  |  | 	repo := r.(*repository.Repository) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-10 12:20:15 +02:00
										 |  |  | 	repository.IndexFull = func(*repository.Index, bool) bool { return true } | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-26 13:30:52 +02:00
										 |  |  | 	// add a few rounds of packs | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	for j := 0; j < 5; j++ { | 
					
						
							| 
									
										
										
										
											2022-05-26 13:30:52 +02:00
										 |  |  | 		// add some packs, write intermediate index | 
					
						
							|  |  |  | 		saveRandomDataBlobs(t, repo, 20, 1<<15) | 
					
						
							| 
									
										
										
										
											2022-05-26 12:38:18 +02:00
										 |  |  | 		rtest.OK(t, repo.Flush(context.TODO())) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// save final index | 
					
						
							| 
									
										
										
										
											2022-05-26 12:38:18 +02:00
										 |  |  | 	rtest.OK(t, repo.Flush(context.TODO())) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-31 20:29:54 +02:00
										 |  |  | 	packEntries := make(map[restic.ID]map[restic.ID]struct{}) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-21 17:25:36 +01:00
										 |  |  | 	err := repo.List(context.TODO(), restic.IndexFile, func(id restic.ID, size int64) error { | 
					
						
							| 
									
										
										
										
											2020-11-07 18:53:59 +01:00
										 |  |  | 		idx, err := loadIndex(context.TODO(), repo, id) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-18 14:45:02 +02:00
										 |  |  | 		for pb := range idx.Each(context.TODO()) { | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 			if _, ok := packEntries[pb.PackID]; !ok { | 
					
						
							| 
									
										
										
										
											2016-08-31 20:29:54 +02:00
										 |  |  | 				packEntries[pb.PackID] = make(map[restic.ID]struct{}) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			packEntries[pb.PackID][id] = struct{}{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-21 17:25:36 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for packID, ids := range packEntries { | 
					
						
							|  |  |  | 		if len(ids) > 1 { | 
					
						
							|  |  |  | 			t.Errorf("pack %v listed in %d indexes\n", packID, len(ids)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // buildPackfileWithoutHeader returns a manually built pack file without a header. | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | func buildPackfileWithoutHeader(t testing.TB, blobSizes []int, key *crypto.Key, compress bool) (blobs []restic.Blob, packfile []byte) { | 
					
						
							|  |  |  | 	opts := []zstd.EOption{ | 
					
						
							|  |  |  | 		// Set the compression level configured. | 
					
						
							|  |  |  | 		zstd.WithEncoderLevel(zstd.SpeedDefault), | 
					
						
							|  |  |  | 		// Disable CRC, we have enough checks in place, makes the | 
					
						
							|  |  |  | 		// compressed data four bytes shorter. | 
					
						
							|  |  |  | 		zstd.WithEncoderCRC(false), | 
					
						
							|  |  |  | 		// Set a window of 512kbyte, so we have good lookbehind for usual | 
					
						
							|  |  |  | 		// blob sizes. | 
					
						
							|  |  |  | 		zstd.WithWindowSize(512 * 1024), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	enc, err := zstd.NewWriter(nil, opts...) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	var offset uint | 
					
						
							|  |  |  | 	for i, size := range blobSizes { | 
					
						
							|  |  |  | 		plaintext := test.Random(800+i, size) | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 		id := restic.Hash(plaintext) | 
					
						
							|  |  |  | 		uncompressedLength := uint(0) | 
					
						
							|  |  |  | 		if compress { | 
					
						
							|  |  |  | 			uncompressedLength = uint(len(plaintext)) | 
					
						
							|  |  |  | 			plaintext = enc.EncodeAll(plaintext, nil) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// we use a deterministic nonce here so the whole process is | 
					
						
							|  |  |  | 		// deterministic, last byte is the blob index | 
					
						
							|  |  |  | 		var nonce = []byte{ | 
					
						
							|  |  |  | 			0x15, 0x98, 0xc0, 0xf7, 0xb9, 0x65, 0x97, 0x74, | 
					
						
							|  |  |  | 			0x12, 0xdc, 0xd3, 0x62, 0xa9, 0x6e, 0x20, byte(i), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		before := len(packfile) | 
					
						
							|  |  |  | 		packfile = append(packfile, nonce...) | 
					
						
							|  |  |  | 		packfile = key.Seal(packfile, nonce, plaintext, nil) | 
					
						
							|  |  |  | 		after := len(packfile) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ciphertextLength := after - before | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		blobs = append(blobs, restic.Blob{ | 
					
						
							|  |  |  | 			BlobHandle: restic.BlobHandle{ | 
					
						
							|  |  |  | 				Type: restic.DataBlob, | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 				ID:   id, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 			Length:             uint(ciphertextLength), | 
					
						
							|  |  |  | 			UncompressedLength: uncompressedLength, | 
					
						
							|  |  |  | 			Offset:             offset, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		offset = uint(len(packfile)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return blobs, packfile | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestStreamPack(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 	repository.TestAllVersions(t, testStreamPack) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testStreamPack(t *testing.T, version uint) { | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	// always use the same key for deterministic output | 
					
						
							|  |  |  | 	const jsonKey = `{"mac":{"k":"eQenuI8adktfzZMuC8rwdA==","r":"k8cfAly2qQSky48CQK7SBA=="},"encrypt":"MKO9gZnRiQFl8mDUurSDa9NMjiu9MUifUrODTHS05wo="}` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var key crypto.Key | 
					
						
							|  |  |  | 	err := json.Unmarshal([]byte(jsonKey), &key) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blobSizes := []int{ | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 		5522811, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		10, | 
					
						
							|  |  |  | 		5231, | 
					
						
							|  |  |  | 		18812, | 
					
						
							|  |  |  | 		123123, | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 		13522811, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		12301, | 
					
						
							|  |  |  | 		892242, | 
					
						
							|  |  |  | 		28616, | 
					
						
							|  |  |  | 		13351, | 
					
						
							|  |  |  | 		252287, | 
					
						
							|  |  |  | 		188883, | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 		3522811, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		18883, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-30 00:31:55 +02:00
										 |  |  | 	var compress bool | 
					
						
							|  |  |  | 	switch version { | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		compress = false | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		compress = true | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatal("test does not suport repository version", version) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packfileBlobs, packfile := buildPackfileWithoutHeader(t, blobSizes, &key, compress) | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 	loadCalls := 0 | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 	load := func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error { | 
					
						
							|  |  |  | 		data := packfile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if offset > int64(len(data)) { | 
					
						
							|  |  |  | 			offset = 0 | 
					
						
							|  |  |  | 			length = 0 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		data = data[offset:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if length > len(data) { | 
					
						
							|  |  |  | 			length = len(data) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		data = data[:length] | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 		loadCalls++ | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return fn(bytes.NewReader(data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// first, test regular usage | 
					
						
							|  |  |  | 	t.Run("regular", func(t *testing.T) { | 
					
						
							|  |  |  | 		tests := []struct { | 
					
						
							|  |  |  | 			blobs []restic.Blob | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 			calls int | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		}{ | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 			{packfileBlobs[1:2], 1}, | 
					
						
							|  |  |  | 			{packfileBlobs[2:5], 1}, | 
					
						
							|  |  |  | 			{packfileBlobs[2:8], 1}, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 			{[]restic.Blob{ | 
					
						
							|  |  |  | 				packfileBlobs[0], | 
					
						
							|  |  |  | 				packfileBlobs[4], | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 				packfileBlobs[2], | 
					
						
							|  |  |  | 			}, 1}, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 			{[]restic.Blob{ | 
					
						
							|  |  |  | 				packfileBlobs[0], | 
					
						
							|  |  |  | 				packfileBlobs[len(packfileBlobs)-1], | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 			}, 2}, | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, test := range tests { | 
					
						
							|  |  |  | 			t.Run("", func(t *testing.T) { | 
					
						
							|  |  |  | 				ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 				defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				gotBlobs := make(map[restic.ID]int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				handleBlob := func(blob restic.BlobHandle, buf []byte, err error) error { | 
					
						
							|  |  |  | 					gotBlobs[blob.ID]++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					id := restic.Hash(buf) | 
					
						
							|  |  |  | 					if !id.Equal(blob.ID) { | 
					
						
							|  |  |  | 						t.Fatalf("wrong id %v for blob %s returned", id, blob.ID) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				wantBlobs := make(map[restic.ID]int) | 
					
						
							|  |  |  | 				for _, blob := range test.blobs { | 
					
						
							|  |  |  | 					wantBlobs[blob.ID] = 1 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 				loadCalls = 0 | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 				err = repository.StreamPack(ctx, load, &key, restic.ID{}, test.blobs, handleBlob) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					t.Fatal(err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if !cmp.Equal(wantBlobs, gotBlobs) { | 
					
						
							|  |  |  | 					t.Fatal(cmp.Diff(wantBlobs, gotBlobs)) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-07-23 22:40:15 +02:00
										 |  |  | 				rtest.Equals(t, test.calls, loadCalls) | 
					
						
							| 
									
										
										
										
											2022-03-21 20:38:53 +01:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// next, test invalid uses, which should return an error | 
					
						
							|  |  |  | 	t.Run("invalid", func(t *testing.T) { | 
					
						
							|  |  |  | 		tests := []struct { | 
					
						
							|  |  |  | 			blobs []restic.Blob | 
					
						
							|  |  |  | 			err   string | 
					
						
							|  |  |  | 		}{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// pass one blob several times | 
					
						
							|  |  |  | 				blobs: []restic.Blob{ | 
					
						
							|  |  |  | 					packfileBlobs[3], | 
					
						
							|  |  |  | 					packfileBlobs[8], | 
					
						
							|  |  |  | 					packfileBlobs[3], | 
					
						
							|  |  |  | 					packfileBlobs[4], | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				err: "overlapping blobs in pack", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// pass something that's not a valid blob in the current pack file | 
					
						
							|  |  |  | 				blobs: []restic.Blob{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Offset: 123, | 
					
						
							|  |  |  | 						Length: 20000, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				err: "ciphertext verification failed", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// pass a blob that's too small | 
					
						
							|  |  |  | 				blobs: []restic.Blob{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Offset: 123, | 
					
						
							|  |  |  | 						Length: 10, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				err: "invalid blob length", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, test := range tests { | 
					
						
							|  |  |  | 			t.Run("", func(t *testing.T) { | 
					
						
							|  |  |  | 				ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 				defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				handleBlob := func(blob restic.BlobHandle, buf []byte, err error) error { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				err = repository.StreamPack(ctx, load, &key, restic.ID{}, test.blobs, handleBlob) | 
					
						
							|  |  |  | 				if err == nil { | 
					
						
							|  |  |  | 					t.Fatalf("wanted error %v, got nil", test.err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if !strings.Contains(err.Error(), test.err) { | 
					
						
							|  |  |  | 					t.Fatalf("wrong error returned, it should contain %q but was %q", test.err, err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | } |