storage/pkg/chunked/cache_linux_test.go

191 lines
5.0 KiB
Go

package chunked
import (
"bytes"
"fmt"
"io"
"path/filepath"
"reflect"
"strings"
"testing"
graphdriver "github.com/containers/storage/drivers"
)
const jsonTOC = `
{
"version": 1,
"entries": [
{
"type": "symlink",
"name": "bin",
"linkName": "usr/bin",
"mode": 511,
"modtime": "1970-01-01T01:00:00+01:00",
"accesstime": "0001-01-01T00:00:00Z",
"changetime": "0001-01-01T00:00:00Z"
},
{
"type": "dir",
"name": "usr/bin",
"mode": 511,
"modtime": "2022-01-07T12:36:43+01:00",
"accesstime": "0001-01-01T00:00:00Z",
"changetime": "0001-01-01T00:00:00Z"
},
{
"type": "reg",
"name": "usr/bin/foo",
"mode": 511,
"size": 103867,
"modtime": "1970-01-01T01:00:00+01:00",
"accesstime": "0001-01-01T00:00:00Z",
"changetime": "0001-01-01T00:00:00Z",
"digest": "sha256:99fe908c699dc068438b23e28319cadff1f2153c3043bafb8e83a430bba0a2c6",
"offset": 94149,
"endOffset": 120135,
"chunkSize": 17615,
"chunkDigest": "sha256:2ce0d0f8eb2aa93d13007097763e4459c814c8d0e859e5a57465af924169b544"
},
{
"type": "chunk",
"name": "usr/bin/foo",
"offset": 99939,
"chunkSize": 86252,
"chunkOffset": 17615,
"chunkDigest": "sha256:2a9d3f1b6b37abc8bb35eb8fa98b893a2a2447bcb01184c3bafc8c6b40da099d"
}
}
`
func TestPrepareMetadata(t *testing.T) {
toc, err := prepareMetadata([]byte(jsonTOC), graphdriver.DifferOutputFormatDir)
if err != nil {
t.Errorf("got error from prepareMetadata: %v", err)
}
if len(toc) != 2 {
t.Error("prepareMetadata returns the wrong length")
}
}
func TestPrepareMetadataFlat(t *testing.T) {
toc, err := prepareMetadata([]byte(jsonTOC), graphdriver.DifferOutputFormatFlat)
if err != nil {
t.Errorf("got error from prepareMetadata: %v", err)
}
for _, e := range toc {
if len(strings.Split(e.Name, "/")) != 2 {
t.Error("prepareMetadata returns the wrong number of path elements for flat directories")
}
if len(filepath.Dir(e.Name)) != 2 {
t.Error("prepareMetadata returns the wrong path for flat directories")
}
}
}
type bigDataToBuffer struct {
buf *bytes.Buffer
id string
key string
called bool
}
func (b *bigDataToBuffer) SetLayerBigData(id, key string, data io.Reader) error {
b.id = id
b.key = key
if b.called {
return fmt.Errorf("SetLayerBigData already called once")
}
b.called = true
_, err := io.Copy(b.buf, data)
return err
}
func TestWriteCache(t *testing.T) {
toc, err := prepareMetadata([]byte(jsonTOC), graphdriver.DifferOutputFormatDir)
if err != nil {
t.Errorf("got error from prepareMetadata: %v", err)
}
dest := bigDataToBuffer{
buf: bytes.NewBuffer(nil),
}
cache, err := writeCache([]byte(jsonTOC), graphdriver.DifferOutputFormatDir, "foobar", &dest)
if err != nil {
t.Errorf("got error from writeCache: %v", err)
}
if digest, _, _ := findTag("foobar", cache); digest != "" {
t.Error("found invalid tag")
}
for _, r := range toc {
if r.Digest != "" {
// find the element in the cache by the digest checksum
digest, off, len := findTag(r.Digest, cache)
if digest == "" {
t.Error("file tag not found")
}
if digest != r.Digest {
t.Error("wrong file found")
}
expectedLocation := generateFileLocation(r.Name, 0)
location := cache.vdata[off : off+len]
if !bytes.Equal(location, expectedLocation) {
t.Errorf("wrong file found %q instead of %q", location, expectedLocation)
}
fingerprint, err := calculateHardLinkFingerprint(r)
if err != nil {
t.Errorf("got error from writeCache: %v", err)
}
// find the element in the cache by the hardlink fingerprint
digest, off, len = findTag(fingerprint, cache)
if digest == "" {
t.Error("file tag not found")
}
if digest != fingerprint {
t.Error("wrong file found")
}
expectedLocation = generateFileLocation(r.Name, 0)
location = cache.vdata[off : off+len]
if !bytes.Equal(location, expectedLocation) {
t.Errorf("wrong file found %q instead of %q", location, expectedLocation)
}
}
if r.ChunkDigest != "" {
// find the element in the cache by the chunk digest checksum
digest, off, len := findTag(r.ChunkDigest, cache)
if digest == "" {
t.Error("chunk tag not found")
}
if digest != r.ChunkDigest {
t.Error("wrong digest found")
}
expectedLocation := generateFileLocation(r.Name, uint64(r.ChunkOffset))
location := cache.vdata[off : off+len]
if !bytes.Equal(location, expectedLocation) {
t.Errorf("wrong file found %q instead of %q", location, expectedLocation)
}
}
}
}
func TestReadCache(t *testing.T) {
dest := bigDataToBuffer{
buf: bytes.NewBuffer(nil),
}
cache, err := writeCache([]byte(jsonTOC), graphdriver.DifferOutputFormatDir, "foobar", &dest)
if err != nil {
t.Errorf("got error from writeCache: %v", err)
}
cacheRead, err := readMetadataFromCache(dest.buf)
if err != nil {
t.Errorf("got error from readMetadataFromCache: %v", err)
}
if !reflect.DeepEqual(cache, cacheRead) {
t.Errorf("read a different struct than what was written")
}
}