github.com/mckael/restic@v0.8.3/internal/pack/pack_test.go (about) 1 package pack_test 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "crypto/sha256" 8 "encoding/binary" 9 "encoding/json" 10 "io" 11 "testing" 12 13 "github.com/restic/restic/internal/backend/mem" 14 "github.com/restic/restic/internal/crypto" 15 "github.com/restic/restic/internal/pack" 16 "github.com/restic/restic/internal/restic" 17 rtest "github.com/restic/restic/internal/test" 18 ) 19 20 var testLens = []int{23, 31650, 25860, 10928, 13769, 19862, 5211, 127, 13690, 30231} 21 22 type Buf struct { 23 data []byte 24 id restic.ID 25 } 26 27 func newPack(t testing.TB, k *crypto.Key, lengths []int) ([]Buf, []byte, uint) { 28 bufs := []Buf{} 29 30 for _, l := range lengths { 31 b := make([]byte, l) 32 _, err := io.ReadFull(rand.Reader, b) 33 rtest.OK(t, err) 34 h := sha256.Sum256(b) 35 bufs = append(bufs, Buf{data: b, id: h}) 36 } 37 38 // pack blobs 39 p := pack.NewPacker(k, nil) 40 for _, b := range bufs { 41 p.Add(restic.TreeBlob, b.id, b.data) 42 } 43 44 _, err := p.Finalize() 45 rtest.OK(t, err) 46 47 packData := p.Writer().(*bytes.Buffer).Bytes() 48 return bufs, packData, p.Size() 49 } 50 51 func verifyBlobs(t testing.TB, bufs []Buf, k *crypto.Key, rd io.ReaderAt, packSize uint) { 52 written := 0 53 for _, buf := range bufs { 54 written += len(buf.data) 55 } 56 // header length 57 written += binary.Size(uint32(0)) 58 // header + header crypto 59 headerSize := len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{})) 60 written += restic.CiphertextLength(headerSize) 61 62 // check length 63 rtest.Equals(t, uint(written), packSize) 64 65 // read and parse it again 66 entries, err := pack.List(k, rd, int64(packSize)) 67 rtest.OK(t, err) 68 rtest.Equals(t, len(entries), len(bufs)) 69 70 var buf []byte 71 for i, b := range bufs { 72 e := entries[i] 73 rtest.Equals(t, b.id, e.ID) 74 75 if len(buf) < int(e.Length) { 76 buf = make([]byte, int(e.Length)) 77 } 78 buf = buf[:int(e.Length)] 79 n, err := rd.ReadAt(buf, int64(e.Offset)) 80 rtest.OK(t, err) 81 buf = buf[:n] 82 83 rtest.Assert(t, bytes.Equal(b.data, buf), 84 "data for blob %v doesn't match", i) 85 } 86 } 87 88 func TestCreatePack(t *testing.T) { 89 // create random keys 90 k := crypto.NewRandomKey() 91 92 bufs, packData, packSize := newPack(t, k, testLens) 93 rtest.Equals(t, uint(len(packData)), packSize) 94 verifyBlobs(t, bufs, k, bytes.NewReader(packData), packSize) 95 } 96 97 var blobTypeJSON = []struct { 98 t restic.BlobType 99 res string 100 }{ 101 {restic.DataBlob, `"data"`}, 102 {restic.TreeBlob, `"tree"`}, 103 } 104 105 func TestBlobTypeJSON(t *testing.T) { 106 for _, test := range blobTypeJSON { 107 // test serialize 108 buf, err := json.Marshal(test.t) 109 rtest.OK(t, err) 110 rtest.Equals(t, test.res, string(buf)) 111 112 // test unserialize 113 var v restic.BlobType 114 err = json.Unmarshal([]byte(test.res), &v) 115 rtest.OK(t, err) 116 rtest.Equals(t, test.t, v) 117 } 118 } 119 120 func TestUnpackReadSeeker(t *testing.T) { 121 // create random keys 122 k := crypto.NewRandomKey() 123 124 bufs, packData, packSize := newPack(t, k, testLens) 125 126 b := mem.New() 127 id := restic.Hash(packData) 128 129 handle := restic.Handle{Type: restic.DataFile, Name: id.String()} 130 rtest.OK(t, b.Save(context.TODO(), handle, bytes.NewReader(packData))) 131 verifyBlobs(t, bufs, k, restic.ReaderAt(b, handle), packSize) 132 } 133 134 func TestShortPack(t *testing.T) { 135 k := crypto.NewRandomKey() 136 137 bufs, packData, packSize := newPack(t, k, []int{23}) 138 139 b := mem.New() 140 id := restic.Hash(packData) 141 142 handle := restic.Handle{Type: restic.DataFile, Name: id.String()} 143 rtest.OK(t, b.Save(context.TODO(), handle, bytes.NewReader(packData))) 144 verifyBlobs(t, bufs, k, restic.ReaderAt(b, handle), packSize) 145 }