| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2017-07-23 14:21:03 +02:00
										 |  |  | 	"github.com/restic/restic/internal/archiver" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 		// save | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +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) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 		// save | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +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) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											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++ { | 
					
						
							| 
									
										
										
										
											2020-06-28 17:15:26 +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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-03 13:34:04 +02:00
										 |  |  | func TestLoadTree(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-06-26 22:12:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	if rtest.BenchArchiveDirectory == "" { | 
					
						
							| 
									
										
										
										
											2015-05-09 13:32:52 +02:00
										 |  |  | 		t.Skip("benchdir not set, skipping") | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// archive a few files | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	sn := archiver.TestSnapshot(t, repo, rtest.BenchArchiveDirectory, nil) | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 	rtest.OK(t, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2015-03-28 15:07:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	_, err := repo.LoadTree(context.TODO(), *sn.Tree) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-03 13:34:04 +02:00
										 |  |  | func BenchmarkLoadTree(t *testing.B) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-10-26 20:47:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	if rtest.BenchArchiveDirectory == "" { | 
					
						
							| 
									
										
										
										
											2015-10-26 20:47:48 +01:00
										 |  |  | 		t.Skip("benchdir not set, skipping") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// archive a few files | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	sn := archiver.TestSnapshot(t, repo, rtest.BenchArchiveDirectory, nil) | 
					
						
							| 
									
										
										
										
											2017-11-22 06:27:29 -05:00
										 |  |  | 	rtest.OK(t, repo.Flush(context.Background())) | 
					
						
							| 
									
										
										
										
											2015-10-26 20:47:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t.ResetTimer() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < t.N; i++ { | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 		_, err := repo.LoadTree(context.TODO(), *sn.Tree) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-10-26 20:47:48 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:25:33 +01:00
										 |  |  | func TestLoadBlob(t *testing.T) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							|  |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							|  |  |  | 	buf := restic.NewBlobBuffer(length) | 
					
						
							|  |  |  | 	_, 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +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
										 |  |  | 
 | 
					
						
							|  |  |  | 	base := restic.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) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepository(b) | 
					
						
							|  |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							| 
									
										
										
										
											2017-01-13 12:57:05 +01:00
										 |  |  | 	buf := restic.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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +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) { | 
					
						
							| 
									
										
										
										
											2017-01-13 20:56:50 +01:00
										 |  |  | 	repo, cleanup := repository.TestRepository(b) | 
					
						
							|  |  |  | 	defer cleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := 1000000 | 
					
						
							|  |  |  | 	buf := restic.NewBlobBuffer(length) | 
					
						
							|  |  |  | 	_, 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-02-13 00:01:27 +01:00
										 |  |  | 		data, err := repo.LoadUnpacked(context.TODO(), nil, restic.PackFile, storageID) | 
					
						
							| 
									
										
										
										
											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-05-04 20:40:17 +02:00
										 |  |  | func TestLoadJSONUnpacked(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-09-04 13:24:51 +02:00
										 |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											2016-09-04 12:52:43 +02:00
										 |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-06-26 22:12:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	if rtest.BenchArchiveDirectory == "" { | 
					
						
							| 
									
										
										
										
											2015-05-09 13:32:52 +02:00
										 |  |  | 		t.Skip("benchdir not set, skipping") | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 	// archive a snapshot | 
					
						
							|  |  |  | 	sn := restic.Snapshot{} | 
					
						
							|  |  |  | 	sn.Hostname = "foobar" | 
					
						
							|  |  |  | 	sn.Username = "test!" | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	id, err := repo.SaveJSONUnpacked(context.TODO(), restic.SnapshotFile, &sn) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-26 17:44:38 +02:00
										 |  |  | 	var sn2 restic.Snapshot | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// restore | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	err = repo.LoadJSONUnpacked(context.TODO(), restic.SnapshotFile, id, &sn2) | 
					
						
							| 
									
										
										
										
											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, sn.Hostname, sn2.Hostname) | 
					
						
							|  |  |  | 	rtest.Equals(t, sn.Username, sn2.Username) | 
					
						
							| 
									
										
										
										
											2019-12-05 14:29:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var cf restic.Config | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// load and check Config | 
					
						
							|  |  |  | 	err = repo.LoadJSONUnpacked(context.TODO(), restic.ConfigFile, id, &cf) | 
					
						
							|  |  |  | 	rtest.OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rtest.Equals(t, cf.ChunkerPolynomial, repository.TestChunkerPol) | 
					
						
							| 
									
										
										
										
											2015-02-18 22:46:09 +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-02-13 00:01:27 +01:00
										 |  |  | 	buf, err := repo.LoadUnpacked(ctx, nil, restic.IndexFile, id) | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:39:40 +01:00
										 |  |  | 	repository.TestUseLowSecurityKDFParameters(b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepository(b) | 
					
						
							| 
									
										
										
										
											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++ { | 
					
						
							|  |  |  | 		idx.Store(restic.PackedBlob{ | 
					
						
							|  |  |  | 			Blob: 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
										 |  |  | 			}, | 
					
						
							|  |  |  | 			PackID: restic.NewRandomID(), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	b.Logf("index saved as %v (%v entries)", id.Str(), idx.Count(restic.DataBlob)) | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +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) { | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +02:00
										 |  |  | 	r, cleanup := repository.TestRepository(t) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	// add 15 packs | 
					
						
							|  |  |  | 	for j := 0; j < 5; j++ { | 
					
						
							|  |  |  | 		// add 3 packs, write intermediate index | 
					
						
							|  |  |  | 		for i := 0; i < 3; i++ { | 
					
						
							|  |  |  | 			saveRandomDataBlobs(t, repo, 5, 1<<15) | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +02:00
										 |  |  | 			rtest.OK(t, repo.FlushPacks(context.Background())) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, repo.SaveFullIndex(context.TODO())) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// add another 5 packs | 
					
						
							|  |  |  | 	for i := 0; i < 5; i++ { | 
					
						
							|  |  |  | 		saveRandomDataBlobs(t, repo, 5, 1<<15) | 
					
						
							| 
									
										
										
										
											2020-06-06 22:20:44 +02:00
										 |  |  | 		rtest.OK(t, repo.FlushPacks(context.Background())) | 
					
						
							| 
									
										
										
										
											2015-10-25 15:35:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// save final index | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, repo.SaveIndex(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. | 
					
						
							|  |  |  | func buildPackfileWithoutHeader(t testing.TB, blobSizes []int, key *crypto.Key) (blobs []restic.Blob, packfile []byte) { | 
					
						
							|  |  |  | 	var offset uint | 
					
						
							|  |  |  | 	for i, size := range blobSizes { | 
					
						
							|  |  |  | 		plaintext := test.Random(800+i, size) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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{ | 
					
						
							|  |  |  | 				ID:   restic.Hash(plaintext), | 
					
						
							|  |  |  | 				Type: restic.DataBlob, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Length: uint(ciphertextLength), | 
					
						
							|  |  |  | 			Offset: offset, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		offset = uint(len(packfile)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return blobs, packfile | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestStreamPack(t *testing.T) { | 
					
						
							|  |  |  | 	// 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{ | 
					
						
							|  |  |  | 		10, | 
					
						
							|  |  |  | 		5231, | 
					
						
							|  |  |  | 		18812, | 
					
						
							|  |  |  | 		123123, | 
					
						
							|  |  |  | 		12301, | 
					
						
							|  |  |  | 		892242, | 
					
						
							|  |  |  | 		28616, | 
					
						
							|  |  |  | 		13351, | 
					
						
							|  |  |  | 		252287, | 
					
						
							|  |  |  | 		188883, | 
					
						
							|  |  |  | 		2522811, | 
					
						
							|  |  |  | 		18883, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packfileBlobs, packfile := buildPackfileWithoutHeader(t, blobSizes, &key) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return fn(bytes.NewReader(data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// first, test regular usage | 
					
						
							|  |  |  | 	t.Run("regular", func(t *testing.T) { | 
					
						
							|  |  |  | 		tests := []struct { | 
					
						
							|  |  |  | 			blobs []restic.Blob | 
					
						
							|  |  |  | 		}{ | 
					
						
							|  |  |  | 			{packfileBlobs[1:2]}, | 
					
						
							|  |  |  | 			{packfileBlobs[2:5]}, | 
					
						
							|  |  |  | 			{packfileBlobs[2:8]}, | 
					
						
							|  |  |  | 			{[]restic.Blob{ | 
					
						
							|  |  |  | 				packfileBlobs[0], | 
					
						
							|  |  |  | 				packfileBlobs[8], | 
					
						
							|  |  |  | 				packfileBlobs[4], | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 			{[]restic.Blob{ | 
					
						
							|  |  |  | 				packfileBlobs[0], | 
					
						
							|  |  |  | 				packfileBlobs[len(packfileBlobs)-1], | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				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)) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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
										 |  |  | } |