github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/vfs/vfs_case_test.go (about) 1 package vfs 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 8 "github.com/rclone/rclone/fstest" 9 "github.com/rclone/rclone/vfs/vfscommon" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestCaseSensitivity(t *testing.T) { 15 r := fstest.NewRun(t) 16 defer r.Finalise() 17 18 if r.Fremote.Features().CaseInsensitive { 19 t.Skip("Can't test case sensitivity - this remote is officially not case-sensitive") 20 } 21 22 // Create test files 23 ctx := context.Background() 24 file1 := r.WriteObject(ctx, "FiLeA", "data1", t1) 25 file2 := r.WriteObject(ctx, "FiLeB", "data2", t2) 26 fstest.CheckItems(t, r.Fremote, file1, file2) 27 28 // Create file3 with name differing from file2 name only by case. 29 // On a case-Sensitive remote this will be a separate file. 30 // On a case-INsensitive remote this file will either not exist 31 // or overwrite file2 depending on how file system diverges. 32 // On a box.com remote this step will even fail. 33 file3 := r.WriteObject(ctx, "FilEb", "data3", t3) 34 35 // Create a case-Sensitive and case-INsensitive VFS 36 optCS := vfscommon.DefaultOpt 37 optCS.CaseInsensitive = false 38 vfsCS := New(r.Fremote, &optCS) 39 40 optCI := vfscommon.DefaultOpt 41 optCI.CaseInsensitive = true 42 vfsCI := New(r.Fremote, &optCI) 43 44 // Run basic checks that must pass on VFS of any type. 45 assertFileDataVFS(t, vfsCI, "FiLeA", "data1") 46 assertFileDataVFS(t, vfsCS, "FiLeA", "data1") 47 48 // Detect case sensitivity of the underlying remote. 49 remoteIsOK := true 50 if !checkFileDataVFS(t, vfsCS, "FiLeA", "data1") { 51 remoteIsOK = false 52 } 53 if !checkFileDataVFS(t, vfsCS, "FiLeB", "data2") { 54 remoteIsOK = false 55 } 56 if !checkFileDataVFS(t, vfsCS, "FilEb", "data3") { 57 remoteIsOK = false 58 } 59 60 // The remaining test is only meaningful on a case-Sensitive file system. 61 if !remoteIsOK { 62 t.Skip("Can't test case sensitivity - this remote doesn't comply as case-sensitive") 63 } 64 65 // Continue with test as the underlying remote is fully case-Sensitive. 66 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 67 68 // See how VFS handles case-INsensitive flag 69 assertFileDataVFS(t, vfsCI, "FiLeA", "data1") 70 assertFileDataVFS(t, vfsCI, "fileA", "data1") 71 assertFileDataVFS(t, vfsCI, "filea", "data1") 72 assertFileDataVFS(t, vfsCI, "FILEA", "data1") 73 74 assertFileDataVFS(t, vfsCI, "FiLeB", "data2") 75 assertFileDataVFS(t, vfsCI, "FilEb", "data3") 76 77 fd, err := vfsCI.OpenFile("fileb", os.O_RDONLY, 0777) 78 assert.Nil(t, fd) 79 assert.Error(t, err) 80 assert.NotEqual(t, err, ENOENT) 81 82 fd, err = vfsCI.OpenFile("FILEB", os.O_RDONLY, 0777) 83 assert.Nil(t, fd) 84 assert.Error(t, err) 85 assert.NotEqual(t, err, ENOENT) 86 87 // Run the same set of checks with case-Sensitive VFS, for comparison. 88 assertFileDataVFS(t, vfsCS, "FiLeA", "data1") 89 90 assertFileAbsentVFS(t, vfsCS, "fileA") 91 assertFileAbsentVFS(t, vfsCS, "filea") 92 assertFileAbsentVFS(t, vfsCS, "FILEA") 93 94 assertFileDataVFS(t, vfsCS, "FiLeB", "data2") 95 assertFileDataVFS(t, vfsCS, "FilEb", "data3") 96 97 assertFileAbsentVFS(t, vfsCS, "fileb") 98 assertFileAbsentVFS(t, vfsCS, "FILEB") 99 } 100 101 func checkFileDataVFS(t *testing.T, vfs *VFS, name string, expect string) bool { 102 fd, err := vfs.OpenFile(name, os.O_RDONLY, 0777) 103 if fd == nil || err != nil { 104 return false 105 } 106 defer func() { 107 // File must be closed - otherwise Run.cleanUp() will fail on Windows. 108 _ = fd.Close() 109 }() 110 111 fh, ok := fd.(*ReadFileHandle) 112 if !ok { 113 return false 114 } 115 116 size := len(expect) 117 buf := make([]byte, size) 118 num, err := fh.Read(buf) 119 if err != nil || num != size { 120 return false 121 } 122 123 return string(buf) == expect 124 } 125 126 func assertFileDataVFS(t *testing.T, vfs *VFS, name string, expect string) { 127 fd, errOpen := vfs.OpenFile(name, os.O_RDONLY, 0777) 128 assert.NotNil(t, fd) 129 assert.NoError(t, errOpen) 130 131 defer func() { 132 // File must be closed - otherwise Run.cleanUp() will fail on Windows. 133 if errOpen == nil && fd != nil { 134 _ = fd.Close() 135 } 136 }() 137 138 fh, ok := fd.(*ReadFileHandle) 139 require.True(t, ok) 140 141 size := len(expect) 142 buf := make([]byte, size) 143 numRead, errRead := fh.Read(buf) 144 assert.NoError(t, errRead) 145 assert.Equal(t, numRead, size) 146 147 assert.Equal(t, string(buf), expect) 148 } 149 150 func assertFileAbsentVFS(t *testing.T, vfs *VFS, name string) { 151 fd, err := vfs.OpenFile(name, os.O_RDONLY, 0777) 152 defer func() { 153 // File must be closed - otherwise Run.cleanUp() will fail on Windows. 154 if err == nil && fd != nil { 155 _ = fd.Close() 156 } 157 }() 158 assert.Nil(t, fd) 159 assert.Error(t, err) 160 assert.Equal(t, err, ENOENT) 161 }