summaryrefslogtreecommitdiffhomepage
path: root/tailfs/webdavfs/stat_cache_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'tailfs/webdavfs/stat_cache_test.go')
-rw-r--r--tailfs/webdavfs/stat_cache_test.go104
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()
+}