blob: 5108d65df15761659a9841289e58f2c7dbd27ddc [file] [log] [blame]
package fscache // import "github.com/docker/docker/builder/fscache"
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
"github.com/moby/buildkit/session/filesync"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
)
func TestFSCache(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "fscache")
assert.Check(t, err)
defer os.RemoveAll(tmpDir)
backend := NewNaiveCacheBackend(filepath.Join(tmpDir, "backend"))
opt := Opt{
Root: tmpDir,
Backend: backend,
GCPolicy: GCPolicy{MaxSize: 15, MaxKeepDuration: time.Hour},
}
fscache, err := NewFSCache(opt)
assert.Check(t, err)
defer fscache.Close()
err = fscache.RegisterTransport("test", &testTransport{})
assert.Check(t, err)
src1, err := fscache.SyncFrom(context.TODO(), &testIdentifier{"foo", "data", "bar"})
assert.Check(t, err)
dt, err := ioutil.ReadFile(filepath.Join(src1.Root().Path(), "foo"))
assert.Check(t, err)
assert.Check(t, is.Equal(string(dt), "data"))
// same id doesn't recalculate anything
src2, err := fscache.SyncFrom(context.TODO(), &testIdentifier{"foo", "data2", "bar"})
assert.Check(t, err)
assert.Check(t, is.Equal(src1.Root().Path(), src2.Root().Path()))
dt, err = ioutil.ReadFile(filepath.Join(src1.Root().Path(), "foo"))
assert.Check(t, err)
assert.Check(t, is.Equal(string(dt), "data"))
assert.Check(t, src2.Close())
src3, err := fscache.SyncFrom(context.TODO(), &testIdentifier{"foo2", "data2", "bar"})
assert.Check(t, err)
assert.Check(t, src1.Root().Path() != src3.Root().Path())
dt, err = ioutil.ReadFile(filepath.Join(src3.Root().Path(), "foo2"))
assert.Check(t, err)
assert.Check(t, is.Equal(string(dt), "data2"))
s, err := fscache.DiskUsage(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(s, int64(0)))
assert.Check(t, src3.Close())
s, err = fscache.DiskUsage(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(s, int64(5)))
// new upload with the same shared key shoutl overwrite
src4, err := fscache.SyncFrom(context.TODO(), &testIdentifier{"foo3", "data3", "bar"})
assert.Check(t, err)
assert.Check(t, src1.Root().Path() != src3.Root().Path())
dt, err = ioutil.ReadFile(filepath.Join(src3.Root().Path(), "foo3"))
assert.Check(t, err)
assert.Check(t, is.Equal(string(dt), "data3"))
assert.Check(t, is.Equal(src4.Root().Path(), src3.Root().Path()))
assert.Check(t, src4.Close())
s, err = fscache.DiskUsage(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(s, int64(10)))
// this one goes over the GC limit
src5, err := fscache.SyncFrom(context.TODO(), &testIdentifier{"foo4", "datadata", "baz"})
assert.Check(t, err)
assert.Check(t, src5.Close())
// GC happens async
time.Sleep(100 * time.Millisecond)
// only last insertion after GC
s, err = fscache.DiskUsage(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(s, int64(8)))
// prune deletes everything
released, err := fscache.Prune(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(released, uint64(8)))
s, err = fscache.DiskUsage(context.TODO())
assert.Check(t, err)
assert.Check(t, is.Equal(s, int64(0)))
}
type testTransport struct {
}
func (t *testTransport) Copy(ctx context.Context, id RemoteIdentifier, dest string, cs filesync.CacheUpdater) error {
testid := id.(*testIdentifier)
return ioutil.WriteFile(filepath.Join(dest, testid.filename), []byte(testid.data), 0600)
}
type testIdentifier struct {
filename string
data string
sharedKey string
}
func (t *testIdentifier) Key() string {
return t.filename
}
func (t *testIdentifier) SharedKey() string {
return t.sharedKey
}
func (t *testIdentifier) Transport() string {
return "test"
}