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  }