vfs_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // Test suite for vfs
  2. package vfs
  3. import (
  4. "context"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "os"
  9. "testing"
  10. "time"
  11. _ "github.com/rclone/rclone/backend/all" // import all the backends
  12. "github.com/rclone/rclone/fs"
  13. "github.com/rclone/rclone/fstest"
  14. "github.com/rclone/rclone/vfs/vfscommon"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. )
  18. // Some times used in the tests
  19. var (
  20. t1 = fstest.Time("2001-02-03T04:05:06.499999999Z")
  21. t2 = fstest.Time("2011-12-25T12:59:59.123456789Z")
  22. t3 = fstest.Time("2011-12-30T12:59:59.000000000Z")
  23. )
  24. // Constants uses in the tests
  25. const (
  26. writeBackDelay = 100 * time.Millisecond // A short writeback delay for testing
  27. waitForWritersDelay = 30 * time.Second // time to wait for existing writers
  28. )
  29. // TestMain drives the tests
  30. func TestMain(m *testing.M) {
  31. fstest.TestMain(m)
  32. }
  33. // Clean up a test VFS
  34. func cleanupVFS(t *testing.T, vfs *VFS) {
  35. vfs.WaitForWriters(waitForWritersDelay)
  36. err := vfs.CleanUp()
  37. require.NoError(t, err)
  38. vfs.Shutdown()
  39. }
  40. // Create a new VFS
  41. func newTestVFSOpt(t *testing.T, opt *vfscommon.Options) (r *fstest.Run, vfs *VFS) {
  42. r = fstest.NewRun(t)
  43. vfs = New(r.Fremote, opt)
  44. t.Cleanup(func() {
  45. cleanupVFS(t, vfs)
  46. })
  47. return r, vfs
  48. }
  49. // Create a new VFS with default options
  50. func newTestVFS(t *testing.T) (r *fstest.Run, vfs *VFS) {
  51. return newTestVFSOpt(t, nil)
  52. }
  53. // Check baseHandle performs as advertised
  54. func TestVFSbaseHandle(t *testing.T) {
  55. fh := baseHandle{}
  56. err := fh.Chdir()
  57. assert.Equal(t, ENOSYS, err)
  58. err = fh.Chmod(0)
  59. assert.Equal(t, ENOSYS, err)
  60. err = fh.Chown(0, 0)
  61. assert.Equal(t, ENOSYS, err)
  62. err = fh.Close()
  63. assert.Equal(t, ENOSYS, err)
  64. fd := fh.Fd()
  65. assert.Equal(t, uintptr(0), fd)
  66. name := fh.Name()
  67. assert.Equal(t, "", name)
  68. _, err = fh.Read(nil)
  69. assert.Equal(t, ENOSYS, err)
  70. _, err = fh.ReadAt(nil, 0)
  71. assert.Equal(t, ENOSYS, err)
  72. _, err = fh.Readdir(0)
  73. assert.Equal(t, ENOSYS, err)
  74. _, err = fh.Readdirnames(0)
  75. assert.Equal(t, ENOSYS, err)
  76. _, err = fh.Seek(0, io.SeekStart)
  77. assert.Equal(t, ENOSYS, err)
  78. _, err = fh.Stat()
  79. assert.Equal(t, ENOSYS, err)
  80. err = fh.Sync()
  81. assert.Equal(t, nil, err)
  82. err = fh.Truncate(0)
  83. assert.Equal(t, ENOSYS, err)
  84. _, err = fh.Write(nil)
  85. assert.Equal(t, ENOSYS, err)
  86. _, err = fh.WriteAt(nil, 0)
  87. assert.Equal(t, ENOSYS, err)
  88. _, err = fh.WriteString("")
  89. assert.Equal(t, ENOSYS, err)
  90. err = fh.Flush()
  91. assert.Equal(t, ENOSYS, err)
  92. err = fh.Release()
  93. assert.Equal(t, ENOSYS, err)
  94. node := fh.Node()
  95. assert.Nil(t, node)
  96. }
  97. // TestNew sees if the New command works properly
  98. func TestVFSNew(t *testing.T) {
  99. // Check active cache has this many entries
  100. checkActiveCacheEntries := func(i int) {
  101. _, count := activeCacheEntries()
  102. assert.Equal(t, i, count)
  103. }
  104. checkActiveCacheEntries(0)
  105. r, vfs := newTestVFS(t)
  106. // Check making a VFS with nil options
  107. var defaultOpt = vfscommon.DefaultOpt
  108. defaultOpt.DirPerms |= os.ModeDir
  109. assert.Equal(t, vfs.Opt, defaultOpt)
  110. assert.Equal(t, vfs.f, r.Fremote)
  111. checkActiveCacheEntries(1)
  112. // Check that we get the same VFS if we ask for it again with
  113. // the same options
  114. vfs2 := New(r.Fremote, nil)
  115. assert.Equal(t, fmt.Sprintf("%p", vfs), fmt.Sprintf("%p", vfs2))
  116. checkActiveCacheEntries(1)
  117. // Shut the new VFS down and check the cache still has stuff in
  118. vfs2.Shutdown()
  119. checkActiveCacheEntries(1)
  120. cleanupVFS(t, vfs)
  121. checkActiveCacheEntries(0)
  122. }
  123. // TestNew sees if the New command works properly
  124. func TestVFSNewWithOpts(t *testing.T) {
  125. var opt = vfscommon.DefaultOpt
  126. opt.DirPerms = 0777
  127. opt.FilePerms = 0666
  128. opt.Umask = 0002
  129. _, vfs := newTestVFSOpt(t, &opt)
  130. assert.Equal(t, os.FileMode(0775)|os.ModeDir, vfs.Opt.DirPerms)
  131. assert.Equal(t, os.FileMode(0664), vfs.Opt.FilePerms)
  132. }
  133. // TestRoot checks root directory is present and correct
  134. func TestVFSRoot(t *testing.T) {
  135. _, vfs := newTestVFS(t)
  136. root, err := vfs.Root()
  137. require.NoError(t, err)
  138. assert.Equal(t, vfs.root, root)
  139. assert.True(t, root.IsDir())
  140. assert.Equal(t, vfs.Opt.DirPerms.Perm(), root.Mode().Perm())
  141. }
  142. func TestVFSStat(t *testing.T) {
  143. r, vfs := newTestVFS(t)
  144. file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
  145. file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
  146. r.CheckRemoteItems(t, file1, file2)
  147. node, err := vfs.Stat("file1")
  148. require.NoError(t, err)
  149. assert.True(t, node.IsFile())
  150. assert.Equal(t, "file1", node.Name())
  151. node, err = vfs.Stat("dir")
  152. require.NoError(t, err)
  153. assert.True(t, node.IsDir())
  154. assert.Equal(t, "dir", node.Name())
  155. node, err = vfs.Stat("dir/file2")
  156. require.NoError(t, err)
  157. assert.True(t, node.IsFile())
  158. assert.Equal(t, "file2", node.Name())
  159. _, err = vfs.Stat("not found")
  160. assert.Equal(t, os.ErrNotExist, err)
  161. _, err = vfs.Stat("dir/not found")
  162. assert.Equal(t, os.ErrNotExist, err)
  163. _, err = vfs.Stat("not found/not found")
  164. assert.Equal(t, os.ErrNotExist, err)
  165. _, err = vfs.Stat("file1/under a file")
  166. assert.Equal(t, os.ErrNotExist, err)
  167. }
  168. func TestVFSStatParent(t *testing.T) {
  169. r, vfs := newTestVFS(t)
  170. file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
  171. file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
  172. r.CheckRemoteItems(t, file1, file2)
  173. node, leaf, err := vfs.StatParent("file1")
  174. require.NoError(t, err)
  175. assert.True(t, node.IsDir())
  176. assert.Equal(t, "/", node.Name())
  177. assert.Equal(t, "file1", leaf)
  178. node, leaf, err = vfs.StatParent("dir/file2")
  179. require.NoError(t, err)
  180. assert.True(t, node.IsDir())
  181. assert.Equal(t, "dir", node.Name())
  182. assert.Equal(t, "file2", leaf)
  183. node, leaf, err = vfs.StatParent("not found")
  184. require.NoError(t, err)
  185. assert.True(t, node.IsDir())
  186. assert.Equal(t, "/", node.Name())
  187. assert.Equal(t, "not found", leaf)
  188. _, _, err = vfs.StatParent("not found dir/not found")
  189. assert.Equal(t, os.ErrNotExist, err)
  190. _, _, err = vfs.StatParent("file1/under a file")
  191. assert.Equal(t, os.ErrExist, err)
  192. }
  193. func TestVFSOpenFile(t *testing.T) {
  194. r, vfs := newTestVFS(t)
  195. file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
  196. file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
  197. r.CheckRemoteItems(t, file1, file2)
  198. fd, err := vfs.OpenFile("file1", os.O_RDONLY, 0777)
  199. require.NoError(t, err)
  200. assert.NotNil(t, fd)
  201. require.NoError(t, fd.Close())
  202. fd, err = vfs.OpenFile("dir", os.O_RDONLY, 0777)
  203. require.NoError(t, err)
  204. assert.NotNil(t, fd)
  205. require.NoError(t, fd.Close())
  206. fd, err = vfs.OpenFile("dir/new_file.txt", os.O_RDONLY, 0777)
  207. assert.Equal(t, os.ErrNotExist, err)
  208. assert.Nil(t, fd)
  209. fd, err = vfs.OpenFile("dir/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
  210. require.NoError(t, err)
  211. assert.NotNil(t, fd)
  212. err = fd.Close()
  213. if !errors.Is(err, fs.ErrorCantUploadEmptyFiles) {
  214. require.NoError(t, err)
  215. }
  216. fd, err = vfs.OpenFile("not found/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
  217. assert.Equal(t, os.ErrNotExist, err)
  218. assert.Nil(t, fd)
  219. }
  220. func TestVFSRename(t *testing.T) {
  221. r, vfs := newTestVFS(t)
  222. features := r.Fremote.Features()
  223. if features.Move == nil && features.Copy == nil {
  224. t.Skip("skip as can't rename files")
  225. }
  226. file1 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
  227. r.CheckRemoteItems(t, file1)
  228. err := vfs.Rename("dir/file2", "dir/file1")
  229. require.NoError(t, err)
  230. file1.Path = "dir/file1"
  231. r.CheckRemoteItems(t, file1)
  232. err = vfs.Rename("dir/file1", "file0")
  233. require.NoError(t, err)
  234. file1.Path = "file0"
  235. r.CheckRemoteItems(t, file1)
  236. err = vfs.Rename("not found/file0", "file0")
  237. assert.Equal(t, os.ErrNotExist, err)
  238. err = vfs.Rename("file0", "not found/file0")
  239. assert.Equal(t, os.ErrNotExist, err)
  240. }
  241. func TestVFSStatfs(t *testing.T) {
  242. r, vfs := newTestVFS(t)
  243. // pre-conditions
  244. assert.Nil(t, vfs.usage)
  245. assert.True(t, vfs.usageTime.IsZero())
  246. aboutSupported := r.Fremote.Features().About != nil
  247. // read
  248. total, used, free := vfs.Statfs()
  249. if !aboutSupported {
  250. assert.Equal(t, int64(unknownFreeBytes), total)
  251. assert.Equal(t, int64(unknownFreeBytes), free)
  252. assert.Equal(t, int64(0), used)
  253. return // can't test anything else if About not supported
  254. }
  255. require.NotNil(t, vfs.usage)
  256. assert.False(t, vfs.usageTime.IsZero())
  257. if vfs.usage.Total != nil {
  258. assert.Equal(t, *vfs.usage.Total, total)
  259. } else {
  260. assert.True(t, total >= int64(unknownFreeBytes))
  261. }
  262. if vfs.usage.Free != nil {
  263. assert.Equal(t, *vfs.usage.Free, free)
  264. } else {
  265. if vfs.usage.Total != nil && vfs.usage.Used != nil {
  266. assert.Equal(t, free, total-used)
  267. } else {
  268. assert.True(t, free >= int64(unknownFreeBytes))
  269. }
  270. }
  271. if vfs.usage.Used != nil {
  272. assert.Equal(t, *vfs.usage.Used, used)
  273. } else {
  274. assert.Equal(t, int64(0), used)
  275. }
  276. // read cached
  277. oldUsage := vfs.usage
  278. oldTime := vfs.usageTime
  279. total2, used2, free2 := vfs.Statfs()
  280. assert.Equal(t, oldUsage, vfs.usage)
  281. assert.Equal(t, total, total2)
  282. assert.Equal(t, used, used2)
  283. assert.Equal(t, free, free2)
  284. assert.Equal(t, oldTime, vfs.usageTime)
  285. }
  286. func TestVFSMkdir(t *testing.T) {
  287. r, vfs := newTestVFS(t)
  288. if !r.Fremote.Features().CanHaveEmptyDirectories {
  289. return // can't test if can't have empty directories
  290. }
  291. r.CheckRemoteListing(t, nil, []string{})
  292. // Try making the root
  293. err := vfs.Mkdir("", 0777)
  294. require.NoError(t, err)
  295. r.CheckRemoteListing(t, nil, []string{})
  296. // Try making a sub directory
  297. err = vfs.Mkdir("a", 0777)
  298. require.NoError(t, err)
  299. r.CheckRemoteListing(t, nil, []string{"a"})
  300. // Try making an existing directory
  301. err = vfs.Mkdir("a", 0777)
  302. require.NoError(t, err)
  303. r.CheckRemoteListing(t, nil, []string{"a"})
  304. // Try making a new directory
  305. err = vfs.Mkdir("b/", 0777)
  306. require.NoError(t, err)
  307. r.CheckRemoteListing(t, nil, []string{"a", "b"})
  308. // Try making a new directory
  309. err = vfs.Mkdir("/c", 0777)
  310. require.NoError(t, err)
  311. r.CheckRemoteListing(t, nil, []string{"a", "b", "c"})
  312. // Try making a new directory
  313. err = vfs.Mkdir("/d/", 0777)
  314. require.NoError(t, err)
  315. r.CheckRemoteListing(t, nil, []string{"a", "b", "c", "d"})
  316. }
  317. func TestVFSMkdirAll(t *testing.T) {
  318. r, vfs := newTestVFS(t)
  319. if !r.Fremote.Features().CanHaveEmptyDirectories {
  320. return // can't test if can't have empty directories
  321. }
  322. r.CheckRemoteListing(t, nil, []string{})
  323. // Try making the root
  324. err := vfs.MkdirAll("", 0777)
  325. require.NoError(t, err)
  326. r.CheckRemoteListing(t, nil, []string{})
  327. // Try making a sub directory
  328. err = vfs.MkdirAll("a/b/c/d", 0777)
  329. require.NoError(t, err)
  330. r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
  331. // Try making an existing directory
  332. err = vfs.MkdirAll("a/b/c", 0777)
  333. require.NoError(t, err)
  334. r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
  335. // Try making an existing directory
  336. err = vfs.MkdirAll("/a/b/c/", 0777)
  337. require.NoError(t, err)
  338. r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
  339. }
  340. func TestFillInMissingSizes(t *testing.T) {
  341. const unknownFree = 10
  342. for _, test := range []struct {
  343. total, free, used int64
  344. wantTotal, wantUsed, wantFree int64
  345. }{
  346. {
  347. total: 20, free: 5, used: 15,
  348. wantTotal: 20, wantFree: 5, wantUsed: 15,
  349. },
  350. {
  351. total: 20, free: 5, used: -1,
  352. wantTotal: 20, wantFree: 5, wantUsed: 15,
  353. },
  354. {
  355. total: 20, free: -1, used: 15,
  356. wantTotal: 20, wantFree: 5, wantUsed: 15,
  357. },
  358. {
  359. total: 20, free: -1, used: -1,
  360. wantTotal: 20, wantFree: 20, wantUsed: 0,
  361. },
  362. {
  363. total: -1, free: 5, used: 15,
  364. wantTotal: 20, wantFree: 5, wantUsed: 15,
  365. },
  366. {
  367. total: -1, free: 15, used: -1,
  368. wantTotal: 15, wantFree: 15, wantUsed: 0,
  369. },
  370. {
  371. total: -1, free: -1, used: 15,
  372. wantTotal: 25, wantFree: 10, wantUsed: 15,
  373. },
  374. {
  375. total: -1, free: -1, used: -1,
  376. wantTotal: 10, wantFree: 10, wantUsed: 0,
  377. },
  378. } {
  379. t.Run(fmt.Sprintf("total=%d,free=%d,used=%d", test.total, test.free, test.used), func(t *testing.T) {
  380. gotTotal, gotUsed, gotFree := fillInMissingSizes(test.total, test.used, test.free, unknownFree)
  381. assert.Equal(t, test.wantTotal, gotTotal, "total")
  382. assert.Equal(t, test.wantUsed, gotUsed, "used")
  383. assert.Equal(t, test.wantFree, gotFree, "free")
  384. })
  385. }
  386. }