github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/local/local_internal_test.go (about) 1 package local 2 3 import ( 4 "context" 5 "io/ioutil" 6 "os" 7 "path" 8 "path/filepath" 9 "runtime" 10 "testing" 11 "time" 12 13 "github.com/rclone/rclone/fs" 14 "github.com/rclone/rclone/fs/config/configmap" 15 "github.com/rclone/rclone/fs/hash" 16 "github.com/rclone/rclone/fstest" 17 "github.com/rclone/rclone/lib/file" 18 "github.com/rclone/rclone/lib/readers" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 ) 22 23 // TestMain drives the tests 24 func TestMain(m *testing.M) { 25 fstest.TestMain(m) 26 } 27 28 // Test copy with source file that's updating 29 func TestUpdatingCheck(t *testing.T) { 30 r := fstest.NewRun(t) 31 defer r.Finalise() 32 filePath := "sub dir/local test" 33 r.WriteFile(filePath, "content", time.Now()) 34 35 fd, err := file.Open(path.Join(r.LocalName, filePath)) 36 if err != nil { 37 t.Fatalf("failed opening file %q: %v", filePath, err) 38 } 39 defer func() { 40 require.NoError(t, fd.Close()) 41 }() 42 43 fi, err := fd.Stat() 44 require.NoError(t, err) 45 o := &Object{size: fi.Size(), modTime: fi.ModTime(), fs: &Fs{}} 46 wrappedFd := readers.NewLimitedReadCloser(fd, -1) 47 hash, err := hash.NewMultiHasherTypes(hash.Supported()) 48 require.NoError(t, err) 49 in := localOpenFile{ 50 o: o, 51 in: wrappedFd, 52 hash: hash, 53 fd: fd, 54 } 55 56 buf := make([]byte, 1) 57 _, err = in.Read(buf) 58 require.NoError(t, err) 59 60 r.WriteFile(filePath, "content updated", time.Now()) 61 _, err = in.Read(buf) 62 require.Errorf(t, err, "can't copy - source file is being updated") 63 64 // turn the checking off and try again 65 in.o.fs.opt.NoCheckUpdated = true 66 67 r.WriteFile(filePath, "content updated", time.Now()) 68 _, err = in.Read(buf) 69 require.NoError(t, err) 70 71 } 72 73 func TestSymlink(t *testing.T) { 74 ctx := context.Background() 75 r := fstest.NewRun(t) 76 defer r.Finalise() 77 f := r.Flocal.(*Fs) 78 dir := f.root 79 80 // Write a file 81 modTime1 := fstest.Time("2001-02-03T04:05:10.123123123Z") 82 file1 := r.WriteFile("file.txt", "hello", modTime1) 83 84 // Write a symlink 85 modTime2 := fstest.Time("2002-02-03T04:05:10.123123123Z") 86 symlinkPath := filepath.Join(dir, "symlink.txt") 87 require.NoError(t, os.Symlink("file.txt", symlinkPath)) 88 require.NoError(t, lChtimes(symlinkPath, modTime2, modTime2)) 89 90 // Object viewed as symlink 91 file2 := fstest.NewItem("symlink.txt"+linkSuffix, "file.txt", modTime2) 92 if runtime.GOOS == "windows" { 93 file2.Size = 0 // symlinks are 0 length under Windows 94 } 95 96 // Object viewed as destination 97 file2d := fstest.NewItem("symlink.txt", "hello", modTime1) 98 99 // Check with no symlink flags 100 fstest.CheckItems(t, r.Flocal, file1) 101 fstest.CheckItems(t, r.Fremote) 102 103 // Set fs into "-L" mode 104 f.opt.FollowSymlinks = true 105 f.opt.TranslateSymlinks = false 106 f.lstat = os.Stat 107 108 fstest.CheckItems(t, r.Flocal, file1, file2d) 109 fstest.CheckItems(t, r.Fremote) 110 111 // Set fs into "-l" mode 112 f.opt.FollowSymlinks = false 113 f.opt.TranslateSymlinks = true 114 f.lstat = os.Lstat 115 116 fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1, file2}, nil, fs.ModTimeNotSupported) 117 if haveLChtimes { 118 fstest.CheckItems(t, r.Flocal, file1, file2) 119 } 120 121 // Create a symlink 122 modTime3 := fstest.Time("2002-03-03T04:05:10.123123123Z") 123 file3 := r.WriteObjectTo(ctx, r.Flocal, "symlink2.txt"+linkSuffix, "file.txt", modTime3, false) 124 if runtime.GOOS == "windows" { 125 file3.Size = 0 // symlinks are 0 length under Windows 126 } 127 fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1, file2, file3}, nil, fs.ModTimeNotSupported) 128 if haveLChtimes { 129 fstest.CheckItems(t, r.Flocal, file1, file2, file3) 130 } 131 132 // Check it got the correct contents 133 symlinkPath = filepath.Join(dir, "symlink2.txt") 134 fi, err := os.Lstat(symlinkPath) 135 require.NoError(t, err) 136 assert.False(t, fi.Mode().IsRegular()) 137 linkText, err := os.Readlink(symlinkPath) 138 require.NoError(t, err) 139 assert.Equal(t, "file.txt", linkText) 140 141 // Check that NewObject gets the correct object 142 o, err := r.Flocal.NewObject(ctx, "symlink2.txt"+linkSuffix) 143 require.NoError(t, err) 144 assert.Equal(t, "symlink2.txt"+linkSuffix, o.Remote()) 145 if runtime.GOOS != "windows" { 146 assert.Equal(t, int64(8), o.Size()) 147 } 148 149 // Check that NewObject doesn't see the non suffixed version 150 _, err = r.Flocal.NewObject(ctx, "symlink2.txt") 151 require.Equal(t, fs.ErrorObjectNotFound, err) 152 153 // Check reading the object 154 in, err := o.Open(ctx) 155 require.NoError(t, err) 156 contents, err := ioutil.ReadAll(in) 157 require.NoError(t, err) 158 require.Equal(t, "file.txt", string(contents)) 159 require.NoError(t, in.Close()) 160 161 // Check reading the object with range 162 in, err = o.Open(ctx, &fs.RangeOption{Start: 2, End: 5}) 163 require.NoError(t, err) 164 contents, err = ioutil.ReadAll(in) 165 require.NoError(t, err) 166 require.Equal(t, "file.txt"[2:5+1], string(contents)) 167 require.NoError(t, in.Close()) 168 } 169 170 func TestSymlinkError(t *testing.T) { 171 m := configmap.Simple{ 172 "links": "true", 173 "copy_links": "true", 174 } 175 _, err := NewFs("local", "/", m) 176 assert.Equal(t, errLinksAndCopyLinks, err) 177 }