mirror of
https://github.com/rclone/rclone.git
synced 2024-12-12 20:33:50 +08:00
7d0d7e66ca
If a file handle is duplicated with dup() and the duplicate handle is flushed, rclone will go ahead and close the file, making the original file handle stale. This change removes the close() call from Flush() and replaces it with FlushWrites() so that the file only gets closed when Release() is called. The new FlushWrites method takes care of actually writing the file back to the underlying storage. Fixes #3381
133 lines
2.8 KiB
Go
133 lines
2.8 KiB
Go
package mounttest
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/rclone/rclone/vfs"
|
|
)
|
|
|
|
// TestWriteFileNoWrite tests writing a file with no write()'s to it
|
|
func TestWriteFileNoWrite(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
fd, err := osCreate(run.path("testnowrite"))
|
|
assert.NoError(t, err)
|
|
|
|
err = fd.Close()
|
|
assert.NoError(t, err)
|
|
|
|
run.waitForWriters()
|
|
|
|
run.checkDir(t, "testnowrite 0")
|
|
|
|
run.rm(t, "testnowrite")
|
|
}
|
|
|
|
// FIXMETestWriteOpenFileInDirListing tests open file in directory listing
|
|
func FIXMETestWriteOpenFileInDirListing(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
fd, err := osCreate(run.path("testnowrite"))
|
|
assert.NoError(t, err)
|
|
|
|
run.checkDir(t, "testnowrite 0")
|
|
|
|
err = fd.Close()
|
|
assert.NoError(t, err)
|
|
|
|
run.waitForWriters()
|
|
|
|
run.rm(t, "testnowrite")
|
|
}
|
|
|
|
// TestWriteFileWrite tests writing a file and reading it back
|
|
func TestWriteFileWrite(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
run.createFile(t, "testwrite", "data")
|
|
run.checkDir(t, "testwrite 4")
|
|
contents := run.readFile(t, "testwrite")
|
|
assert.Equal(t, "data", contents)
|
|
run.rm(t, "testwrite")
|
|
}
|
|
|
|
// TestWriteFileOverwrite tests overwriting a file
|
|
func TestWriteFileOverwrite(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
run.createFile(t, "testwrite", "data")
|
|
run.checkDir(t, "testwrite 4")
|
|
run.createFile(t, "testwrite", "potato")
|
|
contents := run.readFile(t, "testwrite")
|
|
assert.Equal(t, "potato", contents)
|
|
run.rm(t, "testwrite")
|
|
}
|
|
|
|
// TestWriteFileFsync tests Fsync
|
|
//
|
|
// NB the code for this is in file.go rather than write.go
|
|
func TestWriteFileFsync(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
filepath := run.path("to be synced")
|
|
fd, err := osCreate(filepath)
|
|
require.NoError(t, err)
|
|
_, err = fd.Write([]byte("hello"))
|
|
require.NoError(t, err)
|
|
err = fd.Sync()
|
|
require.NoError(t, err)
|
|
err = fd.Close()
|
|
require.NoError(t, err)
|
|
run.waitForWriters()
|
|
run.rm(t, "to be synced")
|
|
}
|
|
|
|
// TestWriteFileDup tests behavior of mmap() in Python by using dup() on a file handle
|
|
func TestWriteFileDup(t *testing.T) {
|
|
run.skipIfNoFUSE(t)
|
|
|
|
if run.vfs.Opt.CacheMode < vfs.CacheModeWrites {
|
|
t.Skip("not supported on vfs-cache-mode < writes")
|
|
return
|
|
}
|
|
|
|
filepath := run.path("to be synced")
|
|
fh, err := osCreate(filepath)
|
|
require.NoError(t, err)
|
|
|
|
testData := []byte("0123456789")
|
|
|
|
err = fh.Truncate(int64(len(testData) + 2))
|
|
require.NoError(t, err)
|
|
|
|
err = fh.Sync()
|
|
require.NoError(t, err)
|
|
|
|
var dupFd uintptr
|
|
dupFd, err = writeTestDup(fh.Fd())
|
|
require.NoError(t, err)
|
|
|
|
dupFile := os.NewFile(dupFd, fh.Name())
|
|
_, err = dupFile.Write(testData)
|
|
require.NoError(t, err)
|
|
|
|
err = dupFile.Close()
|
|
require.NoError(t, err)
|
|
|
|
_, err = fh.Seek(int64(len(testData)), 0)
|
|
require.NoError(t, err)
|
|
|
|
_, err = fh.Write([]byte("10"))
|
|
require.NoError(t, err)
|
|
|
|
err = fh.Close()
|
|
require.NoError(t, err)
|
|
|
|
run.waitForWriters()
|
|
run.rm(t, "to be synced")
|
|
}
|