diff options
Diffstat (limited to 'tailfs/webdavfs/stat_cache_test.go')
| -rw-r--r-- | tailfs/webdavfs/stat_cache_test.go | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/tailfs/webdavfs/stat_cache_test.go b/tailfs/webdavfs/stat_cache_test.go new file mode 100644 index 000000000..3646382a5 --- /dev/null +++ b/tailfs/webdavfs/stat_cache_test.go @@ -0,0 +1,104 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package webdavfs + +import ( + "io/fs" + "os" + "path/filepath" + "testing" + "time" + + "tailscale.com/tailfs/shared" + "tailscale.com/tstest" +) + +func TestStatCache(t *testing.T) { + // Make sure we don't leak goroutines + tstest.ResourceCheck(t) + + dir, err := os.MkdirTemp("", "") + if err != nil { + t.Fatal(err) + } + + // create file of size 1 + filename := filepath.Join(dir, "thefile") + err = os.WriteFile(filename, []byte("1"), 0644) + if err != nil { + t.Fatal(err) + } + + stat := func(name string) (os.FileInfo, error) { + return os.Stat(name) + } + ttl := 1 * time.Second + c := newStatCache(ttl) + + // fetch new stat + fi, err := c.getOrFetch(filename, stat) + if err != nil { + t.Fatal(err) + } + if fi.Size() != 1 { + t.Errorf("got size %d, want 1", fi.Size()) + } + // save original FileInfo as a StaticFileInfo so we can reuse it later + // without worrying about the underlying FileInfo changing. + originalFI := &shared.StaticFileInfo{ + Named: fi.Name(), + Sized: fi.Size(), + Moded: fi.Mode(), + ModdedTime: fi.ModTime(), + Dir: fi.IsDir(), + } + + // update file to size 2 + err = os.WriteFile(filename, []byte("12"), 0644) + if err != nil { + t.Fatal(err) + } + + // fetch stat again, should still be cached + fi, err = c.getOrFetch(filename, stat) + if err != nil { + t.Fatal(err) + } + if fi.Size() != 1 { + t.Errorf("got size %d, want 1", fi.Size()) + } + + // wait for cache to expire and refetch stat, size should reflect new size + time.Sleep(ttl * 2) + + fi, err = c.getOrFetch(filename, stat) + if err != nil { + t.Fatal(err) + } + if fi.Size() != 2 { + t.Errorf("got size %d, want 2", fi.Size()) + } + + // explicitly set the original FileInfo and make sure it's returned + c.set(dir, []fs.FileInfo{originalFI}) + fi, err = c.getOrFetch(filename, stat) + if err != nil { + t.Fatal(err) + } + if fi.Size() != 1 { + t.Errorf("got size %d, want 1", fi.Size()) + } + + // invalidate the cache and make sure the new size is returned + c.invalidate() + fi, err = c.getOrFetch(filename, stat) + if err != nil { + t.Fatal(err) + } + if fi.Size() != 2 { + t.Errorf("got size %d, want 2", fi.Size()) + } + + c.stop() +} |
