2017-11-06 22:38:52 +01:00
|
|
|
package vfs
|
|
|
|
|
|
|
|
import (
|
2018-04-06 20:13:27 +02:00
|
|
|
"context"
|
2017-11-28 15:18:48 +01:00
|
|
|
"fmt"
|
2017-11-06 22:38:52 +01:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-11-28 15:18:48 +01:00
|
|
|
"sort"
|
2017-11-06 22:38:52 +01:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/djherbis/times"
|
|
|
|
"github.com/ncw/rclone/fstest"
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Check CacheMode it satisfies the pflag interface
|
|
|
|
var _ pflag.Value = (*CacheMode)(nil)
|
|
|
|
|
|
|
|
func TestCacheModeString(t *testing.T) {
|
|
|
|
assert.Equal(t, "off", CacheModeOff.String())
|
|
|
|
assert.Equal(t, "full", CacheModeFull.String())
|
|
|
|
assert.Equal(t, "CacheMode(17)", CacheMode(17).String())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCacheModeSet(t *testing.T) {
|
|
|
|
var m CacheMode
|
|
|
|
|
|
|
|
err := m.Set("full")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, CacheModeFull, m)
|
|
|
|
|
|
|
|
err = m.Set("potato")
|
|
|
|
assert.Error(t, err, "Unknown cache mode level")
|
|
|
|
|
|
|
|
err = m.Set("")
|
|
|
|
assert.Error(t, err, "Unknown cache mode level")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCacheModeType(t *testing.T) {
|
|
|
|
var m CacheMode
|
2019-02-07 17:42:26 +01:00
|
|
|
assert.Equal(t, "CacheMode", m.Type())
|
2017-11-06 22:38:52 +01:00
|
|
|
}
|
|
|
|
|
2017-11-28 15:18:48 +01:00
|
|
|
// convert c.item to a string
|
2018-02-26 17:59:14 +01:00
|
|
|
func itemAsString(c *cache) []string {
|
2017-11-28 15:18:48 +01:00
|
|
|
c.itemMu.Lock()
|
|
|
|
defer c.itemMu.Unlock()
|
|
|
|
var out []string
|
|
|
|
for name, item := range c.item {
|
2019-02-02 00:35:03 +01:00
|
|
|
out = append(out, fmt.Sprintf("name=%q isFile=%v opens=%d size=%d", name, item.isFile, item.opens, item.size))
|
2017-11-28 15:18:48 +01:00
|
|
|
}
|
|
|
|
sort.Strings(out)
|
2018-02-26 17:59:14 +01:00
|
|
|
return out
|
2017-11-28 15:18:48 +01:00
|
|
|
}
|
|
|
|
|
2017-11-06 22:38:52 +01:00
|
|
|
func TestCacheNew(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
2018-02-16 15:12:46 +01:00
|
|
|
defer cancel()
|
2017-11-06 22:38:52 +01:00
|
|
|
|
2018-02-16 15:12:46 +01:00
|
|
|
// Disable the cache cleaner as it interferes with these tests
|
|
|
|
opt := DefaultOpt
|
|
|
|
opt.CachePollInterval = 0
|
|
|
|
c, err := newCache(ctx, r.Fremote, &opt)
|
2017-11-06 22:38:52 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
assert.Contains(t, c.root, "vfs")
|
|
|
|
assert.Contains(t, c.f.Root(), filepath.Base(r.Fremote.Root()))
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
2017-11-06 22:38:52 +01:00
|
|
|
|
|
|
|
// mkdir
|
|
|
|
p, err := c.mkdir("potato")
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "potato", filepath.Base(p))
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-06 22:38:52 +01:00
|
|
|
|
|
|
|
fi, err := os.Stat(filepath.Dir(p))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, fi.IsDir())
|
|
|
|
|
|
|
|
// get
|
|
|
|
item := c.get("potato")
|
|
|
|
item2 := c.get("potato")
|
|
|
|
assert.Equal(t, item, item2)
|
|
|
|
assert.WithinDuration(t, time.Now(), item.atime, time.Second)
|
|
|
|
|
|
|
|
// updateTime
|
|
|
|
//.. before
|
|
|
|
t1 := time.Now().Add(-60 * time.Minute)
|
2019-02-02 00:35:03 +01:00
|
|
|
c.updateStat("potato", t1, 0)
|
2017-11-06 22:38:52 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.NotEqual(t, t1, item.atime)
|
|
|
|
assert.Equal(t, 0, item.opens)
|
|
|
|
//..after
|
|
|
|
t2 := time.Now().Add(60 * time.Minute)
|
2019-02-02 00:35:03 +01:00
|
|
|
c.updateStat("potato", t2, 0)
|
2017-11-06 22:38:52 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.Equal(t, t2, item.atime)
|
|
|
|
assert.Equal(t, 0, item.opens)
|
|
|
|
|
|
|
|
// open
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
c.open("/potato")
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-06 22:38:52 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.WithinDuration(t, time.Now(), item.atime, time.Second)
|
|
|
|
assert.Equal(t, 1, item.opens)
|
|
|
|
|
|
|
|
// write the file
|
|
|
|
err = ioutil.WriteFile(p, []byte("hello"), 0600)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// read its atime
|
|
|
|
fi, err = os.Stat(p)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
atime := times.Get(fi).AccessTime()
|
|
|
|
|
|
|
|
// updateAtimes
|
|
|
|
item = c.get("potato")
|
|
|
|
item.atime = time.Now().Add(-24 * time.Hour)
|
2019-02-02 00:35:03 +01:00
|
|
|
err = c.updateStats()
|
2017-11-06 22:38:52 +01:00
|
|
|
require.NoError(t, err)
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=5`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-06 22:38:52 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.Equal(t, atime, item.atime)
|
|
|
|
|
2018-02-02 13:06:42 +01:00
|
|
|
// updateAtimes - not in the cache
|
|
|
|
oldItem := item
|
2018-02-15 22:34:37 +01:00
|
|
|
c.itemMu.Lock()
|
2018-02-02 13:06:42 +01:00
|
|
|
delete(c.item, "potato") // remove from cache
|
2018-02-15 22:34:37 +01:00
|
|
|
c.itemMu.Unlock()
|
2019-02-02 00:35:03 +01:00
|
|
|
err = c.updateStats()
|
2018-02-02 13:06:42 +01:00
|
|
|
require.NoError(t, err)
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=0 size=5`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2018-02-02 13:06:42 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.Equal(t, atime, item.atime)
|
2018-02-15 22:34:37 +01:00
|
|
|
c.itemMu.Lock()
|
2018-02-02 13:06:42 +01:00
|
|
|
c.item["potato"] = oldItem // restore to cache
|
2018-02-15 22:34:37 +01:00
|
|
|
c.itemMu.Unlock()
|
2018-02-02 13:06:42 +01:00
|
|
|
|
2017-11-06 22:38:52 +01:00
|
|
|
// try purging with file open
|
|
|
|
c.purgeOld(10 * time.Second)
|
|
|
|
_, err = os.Stat(p)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// close
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=5`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2019-02-02 00:35:03 +01:00
|
|
|
c.updateStat("potato", t2, 6)
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=6`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
c.close("potato/")
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="potato" isFile=true opens=0 size=5`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-06 22:38:52 +01:00
|
|
|
item = c.get("potato")
|
|
|
|
assert.WithinDuration(t, time.Now(), item.atime, time.Second)
|
|
|
|
assert.Equal(t, 0, item.opens)
|
|
|
|
|
|
|
|
// try purging with file closed
|
|
|
|
c.purgeOld(10 * time.Second)
|
|
|
|
// ...nothing should happend
|
|
|
|
_, err = os.Stat(p)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
//.. purge again with -ve age
|
|
|
|
c.purgeOld(-10 * time.Second)
|
|
|
|
_, err = os.Stat(p)
|
|
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
|
|
|
|
// clean - have tested the internals already
|
|
|
|
c.clean()
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
err = c.cleanUp()
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = os.Stat(c.root)
|
|
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
}
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
func TestCacheOpens(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
c, err := newCache(ctx, r.Fremote, &DefaultOpt)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
c.open("potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
c.open("potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=2 size=0`,
|
|
|
|
`name="potato" isFile=true opens=2 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
c.close("potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
c.close("potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
c.open("potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
c.open("a//b/c/d/one")
|
2017-11-28 15:18:48 +01:00
|
|
|
c.open("a/b/c/d/e/two")
|
|
|
|
c.open("a/b/c/d/e/f/three")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=4 size=0`,
|
|
|
|
`name="a" isFile=false opens=3 size=0`,
|
|
|
|
`name="a/b" isFile=false opens=3 size=0`,
|
|
|
|
`name="a/b/c" isFile=false opens=3 size=0`,
|
|
|
|
`name="a/b/c/d" isFile=false opens=3 size=0`,
|
|
|
|
`name="a/b/c/d/e" isFile=false opens=2 size=0`,
|
|
|
|
`name="a/b/c/d/e/f" isFile=false opens=1 size=0`,
|
|
|
|
`name="a/b/c/d/e/f/three" isFile=true opens=1 size=0`,
|
|
|
|
`name="a/b/c/d/e/two" isFile=true opens=1 size=0`,
|
|
|
|
`name="a/b/c/d/one" isFile=true opens=1 size=0`,
|
|
|
|
`name="potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
c.close("potato")
|
|
|
|
c.close("a/b/c/d/one")
|
|
|
|
c.close("a/b/c/d/e/two")
|
2018-02-26 17:59:14 +01:00
|
|
|
c.close("a/b/c//d/e/f/three")
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="a" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b/c" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b/c/d" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b/c/d/e" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b/c/d/e/f" isFile=false opens=0 size=0`,
|
|
|
|
`name="a/b/c/d/e/f/three" isFile=true opens=0 size=0`,
|
|
|
|
`name="a/b/c/d/e/two" isFile=true opens=0 size=0`,
|
|
|
|
`name="a/b/c/d/one" isFile=true opens=0 size=0`,
|
|
|
|
`name="potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
}
|
|
|
|
|
|
|
|
// test the open, mkdir, purge, close, purge sequence
|
|
|
|
func TestCacheOpenMkdir(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Disable the cache cleaner as it interferes with these tests
|
|
|
|
opt := DefaultOpt
|
|
|
|
opt.CachePollInterval = 0
|
|
|
|
c, err := newCache(ctx, r.Fremote, &opt)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// open
|
|
|
|
c.open("sub/potato")
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub/potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// mkdir
|
|
|
|
p, err := c.mkdir("sub/potato")
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "potato", filepath.Base(p))
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub/potato" isFile=true opens=1 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
// test directory exists
|
|
|
|
fi, err := os.Stat(filepath.Dir(p))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, fi.IsDir())
|
|
|
|
|
|
|
|
// clean the cache
|
|
|
|
c.purgeOld(-10 * time.Second)
|
|
|
|
|
|
|
|
// test directory still exists
|
|
|
|
fi, err = os.Stat(filepath.Dir(p))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, fi.IsDir())
|
|
|
|
|
|
|
|
// close
|
|
|
|
c.close("sub/potato")
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// clean the cache
|
|
|
|
c.purgeOld(-10 * time.Second)
|
2019-02-02 00:35:03 +01:00
|
|
|
c.purgeEmptyDirs()
|
2018-02-26 17:59:14 +01:00
|
|
|
|
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
|
|
|
|
|
|
|
// test directory does not exist
|
|
|
|
fi, err = os.Stat(filepath.Dir(p))
|
|
|
|
require.True(t, os.IsNotExist(err))
|
2017-11-28 15:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCacheCacheDir(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
c, err := newCache(ctx, r.Fremote, &DefaultOpt)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
c.cacheDir("dir")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir" isFile=false opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
c.cacheDir("dir/sub")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir/sub" isFile=false opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
c.cacheDir("dir/sub2/subsub2")
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir/sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir/sub2" isFile=false opens=0 size=0`,
|
|
|
|
`name="dir/sub2/subsub2" isFile=false opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCachePurgeOld(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
c, err := newCache(ctx, r.Fremote, &DefaultOpt)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Test funcs
|
|
|
|
var removed []string
|
|
|
|
removedDir := true
|
|
|
|
removeFile := func(name string) {
|
|
|
|
removed = append(removed, name)
|
|
|
|
}
|
|
|
|
removeDir := func(name string) bool {
|
|
|
|
if removedDir {
|
|
|
|
removed = append(removed, name+"/")
|
|
|
|
}
|
|
|
|
return removedDir
|
|
|
|
}
|
|
|
|
|
|
|
|
removed = nil
|
2019-02-02 00:35:03 +01:00
|
|
|
c._purgeOld(-10*time.Second, removeFile)
|
|
|
|
c._purgeEmptyDirs(removeDir)
|
2017-11-28 15:18:48 +01:00
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
c.open("sub/dir2/potato2")
|
2017-11-28 15:18:48 +01:00
|
|
|
c.open("sub/dir/potato")
|
2018-02-26 17:59:14 +01:00
|
|
|
c.close("sub/dir2/potato2")
|
|
|
|
c.open("sub/dir/potato")
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=2 size=0`,
|
|
|
|
`name="sub" isFile=false opens=2 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=2 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=2 size=0`,
|
|
|
|
`name="sub/dir2" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir2/potato2" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
removed = nil
|
|
|
|
removedDir = true
|
2019-02-02 00:35:03 +01:00
|
|
|
c._purgeOld(-10*time.Second, removeFile)
|
|
|
|
c._purgeEmptyDirs(removeDir)
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
|
|
|
"sub/dir2/potato2",
|
|
|
|
"sub/dir2/",
|
|
|
|
}, removed)
|
|
|
|
|
2017-11-28 15:18:48 +01:00
|
|
|
c.close("sub/dir/potato")
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
removed = nil
|
|
|
|
removedDir = true
|
2019-02-02 00:35:03 +01:00
|
|
|
c._purgeOld(-10*time.Second, removeFile)
|
|
|
|
c._purgeEmptyDirs(removeDir)
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
|
|
|
c.close("sub/dir/potato")
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
removed = nil
|
|
|
|
removedDir = false
|
2019-02-02 00:35:03 +01:00
|
|
|
c._purgeOld(10*time.Second, removeFile)
|
|
|
|
c._purgeEmptyDirs(removeDir)
|
2017-11-28 15:18:48 +01:00
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string{
|
2019-02-02 00:35:03 +01:00
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=0 size=0`,
|
2018-02-26 17:59:14 +01:00
|
|
|
}, itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
|
|
|
|
removed = nil
|
|
|
|
removedDir = true
|
2019-02-02 00:35:03 +01:00
|
|
|
c._purgeOld(-10*time.Second, removeFile)
|
|
|
|
c._purgeEmptyDirs(removeDir)
|
2017-11-28 15:18:48 +01:00
|
|
|
assert.Equal(t, []string{
|
|
|
|
"sub/dir/potato",
|
|
|
|
"sub/dir/",
|
|
|
|
"sub/",
|
|
|
|
"/",
|
|
|
|
}, removed)
|
|
|
|
|
2018-02-26 17:59:14 +01:00
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
2017-11-28 15:18:48 +01:00
|
|
|
}
|
2019-02-02 00:35:03 +01:00
|
|
|
|
|
|
|
func TestCachePurgeOverQuota(t *testing.T) {
|
|
|
|
r := fstest.NewRun(t)
|
|
|
|
defer r.Finalise()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Disable the cache cleaner as it interferes with these tests
|
|
|
|
opt := DefaultOpt
|
|
|
|
opt.CachePollInterval = 0
|
|
|
|
c, err := newCache(ctx, r.Fremote, &opt)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Test funcs
|
|
|
|
var removed []string
|
|
|
|
remove := func(name string) {
|
|
|
|
removed = append(removed, name)
|
|
|
|
c.remove(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(-1, remove)
|
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(0, remove)
|
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(1, remove)
|
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
|
|
|
// Make some test files
|
|
|
|
c.open("sub/dir/potato")
|
|
|
|
p, err := c.mkdir("sub/dir/potato")
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = ioutil.WriteFile(p, []byte("hello"), 0600)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
p, err = c.mkdir("sub/dir2/potato2")
|
|
|
|
c.open("sub/dir2/potato2")
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = ioutil.WriteFile(p, []byte("hello2"), 0600)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
`name="" isFile=false opens=2 size=0`,
|
|
|
|
`name="sub" isFile=false opens=2 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=1 size=0`,
|
|
|
|
`name="sub/dir2" isFile=false opens=1 size=0`,
|
|
|
|
`name="sub/dir2/potato2" isFile=true opens=1 size=0`,
|
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// Check nothing removed
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(1, remove)
|
|
|
|
assert.Equal(t, []string(nil), removed)
|
|
|
|
|
|
|
|
// Close the files
|
|
|
|
c.close("sub/dir/potato")
|
|
|
|
c.close("sub/dir2/potato2")
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=0 size=5`,
|
|
|
|
`name="sub/dir2" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir2/potato2" isFile=true opens=0 size=6`,
|
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// Update the stats to read the total size
|
|
|
|
err = c.updateStats()
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(11), c.used)
|
|
|
|
|
2019-02-02 17:26:55 +01:00
|
|
|
// make potato2 definitely after potato
|
|
|
|
t1 := time.Now().Add(10 * time.Second)
|
|
|
|
c.updateStat("sub/dir2/potato2", t1, 6)
|
|
|
|
|
2019-02-02 00:35:03 +01:00
|
|
|
// Check only potato removed to get below quota
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(10, remove)
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
"sub/dir/potato",
|
|
|
|
}, removed)
|
|
|
|
assert.Equal(t, int64(6), c.used)
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir2" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir2/potato2" isFile=true opens=0 size=6`,
|
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// Put potato back
|
|
|
|
c.open("sub/dir/potato")
|
|
|
|
p, err = c.mkdir("sub/dir/potato")
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = ioutil.WriteFile(p, []byte("hello"), 0600)
|
|
|
|
require.NoError(t, err)
|
|
|
|
c.close("sub/dir/potato")
|
|
|
|
|
|
|
|
// Update the stats to read the total size
|
|
|
|
err = c.updateStats()
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, int64(11), c.used)
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=0 size=5`,
|
|
|
|
`name="sub/dir2" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir2/potato2" isFile=true opens=0 size=6`,
|
|
|
|
}, itemAsString(c))
|
|
|
|
|
2019-02-02 17:26:55 +01:00
|
|
|
// make potato definitely after potato2
|
|
|
|
t2 := t1.Add(20 * time.Second)
|
|
|
|
c.updateStat("sub/dir/potato", t2, 5)
|
|
|
|
|
2019-02-02 00:35:03 +01:00
|
|
|
// Check only potato2 removed to get below quota
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(10, remove)
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
"sub/dir2/potato2",
|
|
|
|
}, removed)
|
|
|
|
assert.Equal(t, int64(5), c.used)
|
|
|
|
c.purgeEmptyDirs()
|
|
|
|
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
`name="" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir" isFile=false opens=0 size=0`,
|
|
|
|
`name="sub/dir/potato" isFile=true opens=0 size=5`,
|
|
|
|
}, itemAsString(c))
|
|
|
|
|
|
|
|
// Now purge everything
|
|
|
|
removed = nil
|
|
|
|
c._purgeOverQuota(1, remove)
|
|
|
|
assert.Equal(t, []string{
|
|
|
|
"sub/dir/potato",
|
|
|
|
}, removed)
|
|
|
|
assert.Equal(t, int64(0), c.used)
|
|
|
|
c.purgeEmptyDirs()
|
|
|
|
|
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
|
|
|
|
|
|
|
// Check nothing left behind
|
|
|
|
c.clean()
|
|
|
|
assert.Equal(t, int64(0), c.used)
|
|
|
|
assert.Equal(t, []string(nil), itemAsString(c))
|
|
|
|
}
|