2015-04-26 13:36:49 +00:00
|
|
|
package pack_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2017-06-04 09:16:55 +00:00
|
|
|
"context"
|
2015-04-26 13:36:49 +00:00
|
|
|
"crypto/rand"
|
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"testing"
|
|
|
|
|
2017-07-23 12:21:03 +00:00
|
|
|
"github.com/restic/restic/internal/backend/mem"
|
|
|
|
"github.com/restic/restic/internal/crypto"
|
|
|
|
"github.com/restic/restic/internal/pack"
|
2017-07-24 15:42:25 +00:00
|
|
|
"github.com/restic/restic/internal/restic"
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest "github.com/restic/restic/internal/test"
|
2015-04-26 13:36:49 +00:00
|
|
|
)
|
|
|
|
|
2016-08-07 14:24:02 +00:00
|
|
|
var testLens = []int{23, 31650, 25860, 10928, 13769, 19862, 5211, 127, 13690, 30231}
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2016-02-20 23:21:06 +00:00
|
|
|
type Buf struct {
|
|
|
|
data []byte
|
2016-08-31 21:07:50 +00:00
|
|
|
id restic.ID
|
2016-02-20 23:21:06 +00:00
|
|
|
}
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2016-08-07 14:24:02 +00:00
|
|
|
func newPack(t testing.TB, k *crypto.Key, lengths []int) ([]Buf, []byte, uint) {
|
2015-04-26 13:36:49 +00:00
|
|
|
bufs := []Buf{}
|
|
|
|
|
|
|
|
for _, l := range lengths {
|
|
|
|
b := make([]byte, l)
|
|
|
|
_, err := io.ReadFull(rand.Reader, b)
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
2015-04-26 13:36:49 +00:00
|
|
|
h := sha256.Sum256(b)
|
2015-07-25 15:05:45 +00:00
|
|
|
bufs = append(bufs, Buf{data: b, id: h})
|
2015-04-26 13:36:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// pack blobs
|
2020-03-09 13:25:55 +00:00
|
|
|
p := pack.NewPacker(k, new(bytes.Buffer))
|
2015-04-26 13:36:49 +00:00
|
|
|
for _, b := range bufs {
|
2016-08-31 21:07:50 +00:00
|
|
|
p.Add(restic.TreeBlob, b.id, b.data)
|
2015-04-26 13:36:49 +00:00
|
|
|
}
|
|
|
|
|
2016-03-06 11:34:23 +00:00
|
|
|
_, err := p.Finalize()
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2016-03-06 11:34:23 +00:00
|
|
|
packData := p.Writer().(*bytes.Buffer).Bytes()
|
2016-02-20 23:21:06 +00:00
|
|
|
return bufs, packData, p.Size()
|
|
|
|
}
|
|
|
|
|
2016-08-25 19:51:07 +00:00
|
|
|
func verifyBlobs(t testing.TB, bufs []Buf, k *crypto.Key, rd io.ReaderAt, packSize uint) {
|
2015-04-26 13:36:49 +00:00
|
|
|
written := 0
|
2016-08-07 14:24:02 +00:00
|
|
|
for _, buf := range bufs {
|
|
|
|
written += len(buf.data)
|
2015-04-26 13:36:49 +00:00
|
|
|
}
|
|
|
|
// header length
|
|
|
|
written += binary.Size(uint32(0))
|
2017-01-13 11:57:05 +00:00
|
|
|
// header + header crypto
|
|
|
|
headerSize := len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{}))
|
|
|
|
written += restic.CiphertextLength(headerSize)
|
2015-04-26 13:36:49 +00:00
|
|
|
|
|
|
|
// check length
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.Equals(t, uint(written), packSize)
|
2015-04-26 13:36:49 +00:00
|
|
|
|
|
|
|
// read and parse it again
|
2016-08-25 19:51:07 +00:00
|
|
|
entries, err := pack.List(k, rd, int64(packSize))
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
|
|
|
rtest.Equals(t, len(entries), len(bufs))
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2016-08-07 12:50:24 +00:00
|
|
|
var buf []byte
|
2015-04-26 13:36:49 +00:00
|
|
|
for i, b := range bufs {
|
2016-08-25 19:08:16 +00:00
|
|
|
e := entries[i]
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.Equals(t, b.id, e.ID)
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2016-08-07 12:50:24 +00:00
|
|
|
if len(buf) < int(e.Length) {
|
|
|
|
buf = make([]byte, int(e.Length))
|
|
|
|
}
|
|
|
|
buf = buf[:int(e.Length)]
|
2016-08-25 19:51:07 +00:00
|
|
|
n, err := rd.ReadAt(buf, int64(e.Offset))
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
2016-08-07 12:50:24 +00:00
|
|
|
buf = buf[:n]
|
2015-04-26 13:36:49 +00:00
|
|
|
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.Assert(t, bytes.Equal(b.data, buf),
|
2015-04-26 13:36:49 +00:00
|
|
|
"data for blob %v doesn't match", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-20 23:21:06 +00:00
|
|
|
func TestCreatePack(t *testing.T) {
|
|
|
|
// create random keys
|
|
|
|
k := crypto.NewRandomKey()
|
|
|
|
|
2016-08-07 14:24:02 +00:00
|
|
|
bufs, packData, packSize := newPack(t, k, testLens)
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.Equals(t, uint(len(packData)), packSize)
|
2016-08-25 19:51:07 +00:00
|
|
|
verifyBlobs(t, bufs, k, bytes.NewReader(packData), packSize)
|
2016-02-20 23:21:06 +00:00
|
|
|
}
|
|
|
|
|
2015-10-25 17:21:48 +00:00
|
|
|
var blobTypeJSON = []struct {
|
2016-08-31 21:07:50 +00:00
|
|
|
t restic.BlobType
|
2015-04-26 13:36:49 +00:00
|
|
|
res string
|
|
|
|
}{
|
2016-08-31 21:07:50 +00:00
|
|
|
{restic.DataBlob, `"data"`},
|
|
|
|
{restic.TreeBlob, `"tree"`},
|
2015-04-26 13:36:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlobTypeJSON(t *testing.T) {
|
2015-10-25 17:21:48 +00:00
|
|
|
for _, test := range blobTypeJSON {
|
2015-04-26 13:36:49 +00:00
|
|
|
// test serialize
|
|
|
|
buf, err := json.Marshal(test.t)
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
|
|
|
rtest.Equals(t, test.res, string(buf))
|
2015-04-26 13:36:49 +00:00
|
|
|
|
|
|
|
// test unserialize
|
2016-08-31 21:07:50 +00:00
|
|
|
var v restic.BlobType
|
2015-04-26 13:36:49 +00:00
|
|
|
err = json.Unmarshal([]byte(test.res), &v)
|
2017-10-02 13:06:39 +00:00
|
|
|
rtest.OK(t, err)
|
|
|
|
rtest.Equals(t, test.t, v)
|
2015-04-26 13:36:49 +00:00
|
|
|
}
|
|
|
|
}
|
2016-02-20 23:21:06 +00:00
|
|
|
|
|
|
|
func TestUnpackReadSeeker(t *testing.T) {
|
|
|
|
// create random keys
|
|
|
|
k := crypto.NewRandomKey()
|
|
|
|
|
2016-08-07 14:24:02 +00:00
|
|
|
bufs, packData, packSize := newPack(t, k, testLens)
|
|
|
|
|
|
|
|
b := mem.New()
|
2016-08-31 21:07:50 +00:00
|
|
|
id := restic.Hash(packData)
|
2016-08-07 14:24:02 +00:00
|
|
|
|
2020-08-16 09:16:38 +00:00
|
|
|
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
2018-03-03 13:20:54 +00:00
|
|
|
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
2020-10-06 13:59:00 +00:00
|
|
|
verifyBlobs(t, bufs, k, restic.ReaderAt(context.TODO(), b, handle), packSize)
|
2016-08-07 14:24:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestShortPack(t *testing.T) {
|
|
|
|
k := crypto.NewRandomKey()
|
|
|
|
|
|
|
|
bufs, packData, packSize := newPack(t, k, []int{23})
|
2016-02-20 23:21:06 +00:00
|
|
|
|
|
|
|
b := mem.New()
|
2016-08-31 21:07:50 +00:00
|
|
|
id := restic.Hash(packData)
|
2016-02-20 23:21:06 +00:00
|
|
|
|
2020-08-16 09:16:38 +00:00
|
|
|
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
2018-03-03 13:20:54 +00:00
|
|
|
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
2020-10-06 13:59:00 +00:00
|
|
|
verifyBlobs(t, bufs, k, restic.ReaderAt(context.TODO(), b, handle), packSize)
|
2016-02-20 23:21:06 +00:00
|
|
|
}
|