diff --git a/cmd/mountlib/rc_test.go b/cmd/mountlib/rc_test.go index c1c040b18..5aa05114d 100644 --- a/cmd/mountlib/rc_test.go +++ b/cmd/mountlib/rc_test.go @@ -2,6 +2,7 @@ package mountlib_test import ( "context" + "errors" "os" "path/filepath" "runtime" @@ -18,6 +19,8 @@ import ( "github.com/rclone/rclone/fs/rc" "github.com/rclone/rclone/fstest" "github.com/rclone/rclone/fstest/testy" + "github.com/rclone/rclone/vfs" + "github.com/rclone/rclone/vfs/vfscommon" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -197,3 +200,21 @@ func TestRc(t *testing.T) { require.True(t, os.IsNotExist(err)) }) } + +func TestMountFailureVFSRelease(t *testing.T) { + localDir := t.TempDir() + f, err := fs.NewFs(context.Background(), localDir) + require.NoError(t, err) + + failingMountFn := func(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (<-chan error, func() error, string, error) { + return nil, nil, "", errors.New("simulated mount error") + } + + mnt := mountlib.NewMountPoint(failingMountFn, "/invalid/mountpoint", f, &mountlib.Opt, &vfscommon.Opt) + initialActive := vfs.ActiveCount() + + _, err = mnt.Mount() + require.Error(t, err) + assert.Contains(t, err.Error(), "simulated mount error") + assert.Equal(t, initialActive, vfs.ActiveCount(), "VFS should be shut down when MountFn fails") +} diff --git a/cmd/serve/servetest/rc.go b/cmd/serve/servetest/rc.go index bd88c173a..ff2152eb5 100644 --- a/cmd/serve/servetest/rc.go +++ b/cmd/serve/servetest/rc.go @@ -9,6 +9,7 @@ import ( "time" "github.com/rclone/rclone/fs/rc" + "github.com/rclone/rclone/vfs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -52,6 +53,9 @@ func TestRc(t *testing.T, in rc.Params) { name := in["type"].(string) addr := GetEphemeralPort(t) + // Track active VFS count before starting server + initialActive := vfs.ActiveCount() + // Start the server in["fs"] = dir in["addr"] = addr @@ -71,7 +75,10 @@ func TestRc(t *testing.T, in rc.Params) { _, err = serveStop.Fn(ctx, rc.Params{"id": id}) require.NoError(t, err) - // Check we can make no longer make connections to the server + // Check the VFS was properly released + assert.Equal(t, initialActive, vfs.ActiveCount(), "VFS should have been shut down after server stop") + + // Check we can no longer make connections to the server err = checkTCP(addr) assert.Error(t, err) } diff --git a/vfs/vfs.go b/vfs/vfs.go index 79c352a54..4d238dc57 100644 --- a/vfs/vfs.go +++ b/vfs/vfs.go @@ -357,6 +357,12 @@ func activeCacheEntries() (vfs *VFS, count int) { return vfs, count } +// ActiveCount returns the total number of VFS instances in the active cache. +func ActiveCount() int { + _, count := activeCacheEntries() + return count +} + // Fs returns the Fs passed into the New call func (vfs *VFS) Fs() fs.Fs { return vfs.f