rclone/vfs/vfs_case_test.go
Ivan Andreev 1c4e33d4ad vfs: add flag --vfs-case-insensitive for windows/macOS mounts
rclone mount when run on Windows & macOS will now default to `--vfs-case-insensitive`.
This means that
2019-09-04 21:30:48 +01:00

156 lines
4.1 KiB
Go

package vfs
import (
"context"
"os"
"testing"
"github.com/rclone/rclone/fstest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCaseSensitivity(t *testing.T) {
r := fstest.NewRun(t)
defer r.Finalise()
// Create test files
ctx := context.Background()
file1 := r.WriteObject(ctx, "FiLeA", "data1", t1)
file2 := r.WriteObject(ctx, "FiLeB", "data2", t2)
fstest.CheckItems(t, r.Fremote, file1, file2)
// Create file3 with name differing from file2 name only by case.
// On a case-Sensitive remote this will be a separate file.
// On a case-INsensitive remote this file will either not exist
// or overwrite file2 depending on how file system diverges.
file3 := r.WriteObject(ctx, "FilEb", "data3", t3)
// Create a case-Sensitive and case-INsensitive VFS
optCS := DefaultOpt
optCS.CaseInsensitive = false
vfsCS := New(r.Fremote, &optCS)
optCI := DefaultOpt
optCI.CaseInsensitive = true
vfsCI := New(r.Fremote, &optCI)
// Run basic checks that must pass on VFS of any type.
assertFileDataVFS(t, vfsCI, "FiLeA", "data1")
assertFileDataVFS(t, vfsCS, "FiLeA", "data1")
// Detect case sensitivity of the underlying remote.
remoteIsOK := true
if !checkFileDataVFS(t, vfsCS, "FiLeA", "data1") {
remoteIsOK = false
}
if !checkFileDataVFS(t, vfsCS, "FiLeB", "data2") {
remoteIsOK = false
}
if !checkFileDataVFS(t, vfsCS, "FilEb", "data3") {
remoteIsOK = false
}
// The remaining test is only meaningful on a case-Sensitive file system.
if !remoteIsOK {
t.Logf("SKIP: TestCaseSensitivity - remote is not fully case-sensitive")
return
}
// Continue with test as the underlying remote is fully case-Sensitive.
fstest.CheckItems(t, r.Fremote, file1, file2, file3)
// See how VFS handles case-INsensitive flag
assertFileDataVFS(t, vfsCI, "FiLeA", "data1")
assertFileDataVFS(t, vfsCI, "fileA", "data1")
assertFileDataVFS(t, vfsCI, "filea", "data1")
assertFileDataVFS(t, vfsCI, "FILEA", "data1")
assertFileDataVFS(t, vfsCI, "FiLeB", "data2")
assertFileDataVFS(t, vfsCI, "FilEb", "data3")
fd, err := vfsCI.OpenFile("fileb", os.O_RDONLY, 0777)
assert.Nil(t, fd)
assert.Error(t, err)
assert.NotEqual(t, err, ENOENT)
fd, err = vfsCI.OpenFile("FILEB", os.O_RDONLY, 0777)
assert.Nil(t, fd)
assert.Error(t, err)
assert.NotEqual(t, err, ENOENT)
// Run the same set of checks with case-Sensitive VFS, for comparison.
assertFileDataVFS(t, vfsCS, "FiLeA", "data1")
assertFileAbsentVFS(t, vfsCS, "fileA")
assertFileAbsentVFS(t, vfsCS, "filea")
assertFileAbsentVFS(t, vfsCS, "FILEA")
assertFileDataVFS(t, vfsCS, "FiLeB", "data2")
assertFileDataVFS(t, vfsCS, "FilEb", "data3")
assertFileAbsentVFS(t, vfsCS, "fileb")
assertFileAbsentVFS(t, vfsCS, "FILEB")
}
func checkFileDataVFS(t *testing.T, vfs *VFS, name string, expect string) bool {
fd, err := vfs.OpenFile(name, os.O_RDONLY, 0777)
if fd == nil || err != nil {
return false
}
defer func() {
// File must be closed - otherwise Run.cleanUp() will fail on Windows.
_ = fd.Close()
}()
fh, ok := fd.(*ReadFileHandle)
if !ok {
return false
}
size := len(expect)
buf := make([]byte, size)
num, err := fh.Read(buf)
if err != nil || num != size {
return false
}
return string(buf) == expect
}
func assertFileDataVFS(t *testing.T, vfs *VFS, name string, expect string) {
fd, errOpen := vfs.OpenFile(name, os.O_RDONLY, 0777)
assert.NotNil(t, fd)
assert.NoError(t, errOpen)
defer func() {
// File must be closed - otherwise Run.cleanUp() will fail on Windows.
if errOpen == nil && fd != nil {
_ = fd.Close()
}
}()
fh, ok := fd.(*ReadFileHandle)
require.True(t, ok)
size := len(expect)
buf := make([]byte, size)
numRead, errRead := fh.Read(buf)
assert.NoError(t, errRead)
assert.Equal(t, numRead, size)
assert.Equal(t, string(buf), expect)
}
func assertFileAbsentVFS(t *testing.T, vfs *VFS, name string) {
fd, err := vfs.OpenFile(name, os.O_RDONLY, 0777)
defer func() {
// File must be closed - otherwise Run.cleanUp() will fail on Windows.
if err == nil && fd != nil {
_ = fd.Close()
}
}()
assert.Nil(t, fd)
assert.Error(t, err)
assert.Equal(t, err, ENOENT)
}