github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/fs/operations/rc_test.go (about) 1 package operations_test 2 3 import ( 4 "context" 5 "net/http" 6 "net/http/httptest" 7 "testing" 8 "time" 9 10 "github.com/rclone/rclone/fs" 11 "github.com/rclone/rclone/fs/cache" 12 "github.com/rclone/rclone/fs/operations" 13 "github.com/rclone/rclone/fs/rc" 14 "github.com/rclone/rclone/fstest" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func rcNewRun(t *testing.T, method string) (*fstest.Run, *rc.Call) { 20 if *fstest.RemoteName != "" { 21 t.Skip("Skipping test on non local remote") 22 } 23 r := fstest.NewRun(t) 24 call := rc.Calls.Get(method) 25 assert.NotNil(t, call) 26 cache.Put(r.LocalName, r.Flocal) 27 cache.Put(r.FremoteName, r.Fremote) 28 return r, call 29 } 30 31 // operations/about: Return the space used on the remote 32 func TestRcAbout(t *testing.T) { 33 r, call := rcNewRun(t, "operations/about") 34 defer r.Finalise() 35 r.Mkdir(context.Background(), r.Fremote) 36 37 // Will get an error if remote doesn't support About 38 expectedErr := r.Fremote.Features().About == nil 39 40 in := rc.Params{ 41 "fs": r.FremoteName, 42 } 43 out, err := call.Fn(context.Background(), in) 44 if expectedErr { 45 assert.Error(t, err) 46 return 47 } 48 require.NoError(t, err) 49 50 // Can't really check the output much! 51 assert.NotEqual(t, int64(0), out["Total"]) 52 } 53 54 // operations/cleanup: Remove trashed files in the remote or path 55 func TestRcCleanup(t *testing.T) { 56 r, call := rcNewRun(t, "operations/cleanup") 57 defer r.Finalise() 58 59 in := rc.Params{ 60 "fs": r.LocalName, 61 } 62 out, err := call.Fn(context.Background(), in) 63 require.Error(t, err) 64 assert.Equal(t, rc.Params(nil), out) 65 assert.Contains(t, err.Error(), "doesn't support cleanup") 66 } 67 68 // operations/copyfile: Copy a file from source remote to destination remote 69 func TestRcCopyfile(t *testing.T) { 70 r, call := rcNewRun(t, "operations/copyfile") 71 defer r.Finalise() 72 file1 := r.WriteFile("file1", "file1 contents", t1) 73 r.Mkdir(context.Background(), r.Fremote) 74 fstest.CheckItems(t, r.Flocal, file1) 75 fstest.CheckItems(t, r.Fremote) 76 77 in := rc.Params{ 78 "srcFs": r.LocalName, 79 "srcRemote": "file1", 80 "dstFs": r.FremoteName, 81 "dstRemote": "file1-renamed", 82 } 83 out, err := call.Fn(context.Background(), in) 84 require.NoError(t, err) 85 assert.Equal(t, rc.Params(nil), out) 86 87 fstest.CheckItems(t, r.Flocal, file1) 88 file1.Path = "file1-renamed" 89 fstest.CheckItems(t, r.Fremote, file1) 90 } 91 92 // operations/copyurl: Copy the URL to the object 93 func TestRcCopyurl(t *testing.T) { 94 r, call := rcNewRun(t, "operations/copyurl") 95 defer r.Finalise() 96 contents := "file1 contents\n" 97 file1 := r.WriteFile("file1", contents, t1) 98 r.Mkdir(context.Background(), r.Fremote) 99 fstest.CheckItems(t, r.Fremote) 100 101 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 102 _, err := w.Write([]byte(contents)) 103 assert.NoError(t, err) 104 })) 105 defer ts.Close() 106 107 in := rc.Params{ 108 "fs": r.FremoteName, 109 "remote": "file1", 110 "url": ts.URL, 111 "autoFilename": false, 112 } 113 out, err := call.Fn(context.Background(), in) 114 require.NoError(t, err) 115 assert.Equal(t, rc.Params(nil), out) 116 117 urlFileName := "filename.txt" 118 in = rc.Params{ 119 "fs": r.FremoteName, 120 "remote": "", 121 "url": ts.URL + "/" + urlFileName, 122 "autoFilename": true, 123 } 124 out, err = call.Fn(context.Background(), in) 125 require.NoError(t, err) 126 assert.Equal(t, rc.Params(nil), out) 127 128 in = rc.Params{ 129 "fs": r.FremoteName, 130 "remote": "", 131 "url": ts.URL, 132 "autoFilename": true, 133 } 134 out, err = call.Fn(context.Background(), in) 135 require.Error(t, err) 136 assert.Equal(t, rc.Params(nil), out) 137 138 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1, fstest.NewItem(urlFileName, contents, t1)}, nil, fs.ModTimeNotSupported) 139 } 140 141 // operations/delete: Remove files in the path 142 func TestRcDelete(t *testing.T) { 143 r, call := rcNewRun(t, "operations/delete") 144 defer r.Finalise() 145 146 file1 := r.WriteObject(context.Background(), "small", "1234567890", t2) // 10 bytes 147 file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1) // 60 bytes 148 file3 := r.WriteObject(context.Background(), "large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 100 bytes 149 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 150 151 in := rc.Params{ 152 "fs": r.FremoteName, 153 } 154 out, err := call.Fn(context.Background(), in) 155 require.NoError(t, err) 156 assert.Equal(t, rc.Params(nil), out) 157 158 fstest.CheckItems(t, r.Fremote) 159 } 160 161 // operations/deletefile: Remove the single file pointed to 162 func TestRcDeletefile(t *testing.T) { 163 r, call := rcNewRun(t, "operations/deletefile") 164 defer r.Finalise() 165 166 file1 := r.WriteObject(context.Background(), "small", "1234567890", t2) // 10 bytes 167 file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1) // 60 bytes 168 fstest.CheckItems(t, r.Fremote, file1, file2) 169 170 in := rc.Params{ 171 "fs": r.FremoteName, 172 "remote": "small", 173 } 174 out, err := call.Fn(context.Background(), in) 175 require.NoError(t, err) 176 assert.Equal(t, rc.Params(nil), out) 177 178 fstest.CheckItems(t, r.Fremote, file2) 179 } 180 181 // operations/list: List the given remote and path in JSON format 182 func TestRcList(t *testing.T) { 183 r, call := rcNewRun(t, "operations/list") 184 defer r.Finalise() 185 186 file1 := r.WriteObject(context.Background(), "a", "a", t1) 187 file2 := r.WriteObject(context.Background(), "subdir/b", "bb", t2) 188 189 fstest.CheckItems(t, r.Fremote, file1, file2) 190 191 in := rc.Params{ 192 "fs": r.FremoteName, 193 "remote": "", 194 } 195 out, err := call.Fn(context.Background(), in) 196 require.NoError(t, err) 197 198 list := out["list"].([]*operations.ListJSONItem) 199 assert.Equal(t, 2, len(list)) 200 201 checkFile1 := func(got *operations.ListJSONItem) { 202 assert.WithinDuration(t, t1, got.ModTime.When, time.Second) 203 assert.Equal(t, "a", got.Path) 204 assert.Equal(t, "a", got.Name) 205 assert.Equal(t, int64(1), got.Size) 206 assert.Equal(t, "application/octet-stream", got.MimeType) 207 assert.Equal(t, false, got.IsDir) 208 } 209 checkFile1(list[0]) 210 211 checkSubdir := func(got *operations.ListJSONItem) { 212 assert.Equal(t, "subdir", got.Path) 213 assert.Equal(t, "subdir", got.Name) 214 assert.Equal(t, int64(-1), got.Size) 215 assert.Equal(t, "inode/directory", got.MimeType) 216 assert.Equal(t, true, got.IsDir) 217 } 218 checkSubdir(list[1]) 219 220 in = rc.Params{ 221 "fs": r.FremoteName, 222 "remote": "", 223 "opt": rc.Params{ 224 "recurse": true, 225 }, 226 } 227 out, err = call.Fn(context.Background(), in) 228 require.NoError(t, err) 229 230 list = out["list"].([]*operations.ListJSONItem) 231 assert.Equal(t, 3, len(list)) 232 checkFile1(list[0]) 233 checkSubdir(list[1]) 234 235 checkFile2 := func(got *operations.ListJSONItem) { 236 assert.WithinDuration(t, t2, got.ModTime.When, time.Second) 237 assert.Equal(t, "subdir/b", got.Path) 238 assert.Equal(t, "b", got.Name) 239 assert.Equal(t, int64(2), got.Size) 240 assert.Equal(t, "application/octet-stream", got.MimeType) 241 assert.Equal(t, false, got.IsDir) 242 } 243 checkFile2(list[2]) 244 } 245 246 // operations/mkdir: Make a destination directory or container 247 func TestRcMkdir(t *testing.T) { 248 r, call := rcNewRun(t, "operations/mkdir") 249 defer r.Finalise() 250 r.Mkdir(context.Background(), r.Fremote) 251 252 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote)) 253 254 in := rc.Params{ 255 "fs": r.FremoteName, 256 "remote": "subdir", 257 } 258 out, err := call.Fn(context.Background(), in) 259 require.NoError(t, err) 260 assert.Equal(t, rc.Params(nil), out) 261 262 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote)) 263 } 264 265 // operations/movefile: Move a file from source remote to destination remote 266 func TestRcMovefile(t *testing.T) { 267 r, call := rcNewRun(t, "operations/movefile") 268 defer r.Finalise() 269 file1 := r.WriteFile("file1", "file1 contents", t1) 270 r.Mkdir(context.Background(), r.Fremote) 271 fstest.CheckItems(t, r.Flocal, file1) 272 fstest.CheckItems(t, r.Fremote) 273 274 in := rc.Params{ 275 "srcFs": r.LocalName, 276 "srcRemote": "file1", 277 "dstFs": r.FremoteName, 278 "dstRemote": "file1-renamed", 279 } 280 out, err := call.Fn(context.Background(), in) 281 require.NoError(t, err) 282 assert.Equal(t, rc.Params(nil), out) 283 284 fstest.CheckItems(t, r.Flocal) 285 file1.Path = "file1-renamed" 286 fstest.CheckItems(t, r.Fremote, file1) 287 } 288 289 // operations/purge: Remove a directory or container and all of its contents 290 func TestRcPurge(t *testing.T) { 291 r, call := rcNewRun(t, "operations/purge") 292 defer r.Finalise() 293 file1 := r.WriteObject(context.Background(), "subdir/file1", "subdir/file1 contents", t1) 294 295 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote)) 296 297 in := rc.Params{ 298 "fs": r.FremoteName, 299 "remote": "subdir", 300 } 301 out, err := call.Fn(context.Background(), in) 302 require.NoError(t, err) 303 assert.Equal(t, rc.Params(nil), out) 304 305 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote)) 306 } 307 308 // operations/rmdir: Remove an empty directory or container 309 func TestRcRmdir(t *testing.T) { 310 r, call := rcNewRun(t, "operations/rmdir") 311 defer r.Finalise() 312 r.Mkdir(context.Background(), r.Fremote) 313 assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir")) 314 315 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote)) 316 317 in := rc.Params{ 318 "fs": r.FremoteName, 319 "remote": "subdir", 320 } 321 out, err := call.Fn(context.Background(), in) 322 require.NoError(t, err) 323 assert.Equal(t, rc.Params(nil), out) 324 325 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote)) 326 } 327 328 // operations/rmdirs: Remove all the empty directories in the path 329 func TestRcRmdirs(t *testing.T) { 330 r, call := rcNewRun(t, "operations/rmdirs") 331 defer r.Finalise() 332 r.Mkdir(context.Background(), r.Fremote) 333 assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir")) 334 assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir")) 335 336 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir", "subdir/subsubdir"}, fs.GetModifyWindow(r.Fremote)) 337 338 in := rc.Params{ 339 "fs": r.FremoteName, 340 "remote": "subdir", 341 } 342 out, err := call.Fn(context.Background(), in) 343 require.NoError(t, err) 344 assert.Equal(t, rc.Params(nil), out) 345 346 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote)) 347 348 assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir")) 349 assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir")) 350 351 in = rc.Params{ 352 "fs": r.FremoteName, 353 "remote": "subdir", 354 "leaveRoot": true, 355 } 356 out, err = call.Fn(context.Background(), in) 357 require.NoError(t, err) 358 assert.Equal(t, rc.Params(nil), out) 359 360 fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote)) 361 362 } 363 364 // operations/size: Count the number of bytes and files in remote 365 func TestRcSize(t *testing.T) { 366 r, call := rcNewRun(t, "operations/size") 367 defer r.Finalise() 368 file1 := r.WriteObject(context.Background(), "small", "1234567890", t2) // 10 bytes 369 file2 := r.WriteObject(context.Background(), "subdir/medium", "------------------------------------------------------------", t1) // 60 bytes 370 file3 := r.WriteObject(context.Background(), "subdir/subsubdir/large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 50 bytes 371 fstest.CheckItems(t, r.Fremote, file1, file2, file3) 372 373 in := rc.Params{ 374 "fs": r.FremoteName, 375 } 376 out, err := call.Fn(context.Background(), in) 377 require.NoError(t, err) 378 assert.Equal(t, rc.Params{ 379 "count": int64(3), 380 "bytes": int64(120), 381 }, out) 382 } 383 384 // operations/publiclink: Create or retrieve a public link to the given file or folder. 385 func TestRcPublicLink(t *testing.T) { 386 r, call := rcNewRun(t, "operations/publiclink") 387 defer r.Finalise() 388 in := rc.Params{ 389 "fs": r.FremoteName, 390 "remote": "", 391 } 392 _, err := call.Fn(context.Background(), in) 393 require.Error(t, err) 394 assert.Contains(t, err.Error(), "doesn't support public links") 395 } 396 397 // operations/fsinfo: Return information about the remote 398 func TestRcFsInfo(t *testing.T) { 399 r, call := rcNewRun(t, "operations/fsinfo") 400 defer r.Finalise() 401 in := rc.Params{ 402 "fs": r.FremoteName, 403 } 404 got, err := call.Fn(context.Background(), in) 405 require.NoError(t, err) 406 want := operations.GetFsInfo(r.Fremote) 407 assert.Equal(t, want.Name, got["Name"]) 408 assert.Equal(t, want.Root, got["Root"]) 409 assert.Equal(t, want.String, got["String"]) 410 assert.Equal(t, float64(want.Precision), got["Precision"]) 411 var hashes []interface{} 412 for _, hash := range want.Hashes { 413 hashes = append(hashes, hash) 414 } 415 assert.Equal(t, hashes, got["Hashes"]) 416 var features = map[string]interface{}{} 417 for k, v := range want.Features { 418 features[k] = v 419 } 420 assert.Equal(t, features, got["Features"]) 421 422 }