swarmfs_test.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. // Copyright 2017 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. // +build linux darwin freebsd
  17. package fuse
  18. import (
  19. "bytes"
  20. "crypto/rand"
  21. "io"
  22. "io/ioutil"
  23. "os"
  24. "path/filepath"
  25. "testing"
  26. "github.com/ethereum/go-ethereum/swarm/api"
  27. "github.com/ethereum/go-ethereum/swarm/storage"
  28. )
  29. type fileInfo struct {
  30. perm uint64
  31. uid int
  32. gid int
  33. contents []byte
  34. }
  35. func createTestFilesAndUploadToSwarm(t *testing.T, api *api.Api, files map[string]fileInfo, uploadDir string) string {
  36. os.RemoveAll(uploadDir)
  37. for fname, finfo := range files {
  38. actualPath := filepath.Join(uploadDir, fname)
  39. filePath := filepath.Dir(actualPath)
  40. err := os.MkdirAll(filePath, 0777)
  41. if err != nil {
  42. t.Fatalf("Error creating directory '%v' : %v", filePath, err)
  43. }
  44. fd, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(finfo.perm))
  45. if err1 != nil {
  46. t.Fatalf("Error creating file %v: %v", actualPath, err1)
  47. }
  48. fd.Write(finfo.contents)
  49. fd.Chown(finfo.uid, finfo.gid)
  50. fd.Chmod(os.FileMode(finfo.perm))
  51. fd.Sync()
  52. fd.Close()
  53. }
  54. bzzhash, err := api.Upload(uploadDir, "")
  55. if err != nil {
  56. t.Fatalf("Error uploading directory %v: %v", uploadDir, err)
  57. }
  58. return bzzhash
  59. }
  60. func mountDir(t *testing.T, api *api.Api, files map[string]fileInfo, bzzHash string, mountDir string) *SwarmFS {
  61. os.RemoveAll(mountDir)
  62. os.MkdirAll(mountDir, 0777)
  63. swarmfs := NewSwarmFS(api)
  64. _, err := swarmfs.Mount(bzzHash, mountDir)
  65. if isFUSEUnsupportedError(err) {
  66. t.Skip("FUSE not supported:", err)
  67. } else if err != nil {
  68. t.Fatalf("Error mounting hash %v: %v", bzzHash, err)
  69. }
  70. found := false
  71. mi := swarmfs.Listmounts()
  72. for _, minfo := range mi {
  73. if minfo.MountPoint == mountDir {
  74. if minfo.StartManifest != bzzHash ||
  75. minfo.LatestManifest != bzzHash ||
  76. minfo.fuseConnection == nil {
  77. t.Fatalf("Error mounting: exp(%s): act(%s)", bzzHash, minfo.StartManifest)
  78. }
  79. found = true
  80. }
  81. }
  82. // Test listMounts
  83. if !found {
  84. t.Fatalf("Error getting mounts information for %v: %v", mountDir, err)
  85. }
  86. // Check if file and their attributes are as expected
  87. compareGeneratedFileWithFileInMount(t, files, mountDir)
  88. return swarmfs
  89. }
  90. func compareGeneratedFileWithFileInMount(t *testing.T, files map[string]fileInfo, mountDir string) {
  91. err := filepath.Walk(mountDir, func(path string, f os.FileInfo, err error) error {
  92. if f.IsDir() {
  93. return nil
  94. }
  95. fname := path[len(mountDir)+1:]
  96. if _, ok := files[fname]; !ok {
  97. t.Fatalf(" file %v present in mount dir and is not expected", fname)
  98. }
  99. return nil
  100. })
  101. if err != nil {
  102. t.Fatalf("Error walking dir %v", mountDir)
  103. }
  104. for fname, finfo := range files {
  105. destinationFile := filepath.Join(mountDir, fname)
  106. dfinfo, err := os.Stat(destinationFile)
  107. if err != nil {
  108. t.Fatalf("Destination file %v missing in mount: %v", fname, err)
  109. }
  110. if int64(len(finfo.contents)) != dfinfo.Size() {
  111. t.Fatalf("file %v Size mismatch source (%v) vs destination(%v)", fname, int64(len(finfo.contents)), dfinfo.Size())
  112. }
  113. if dfinfo.Mode().Perm().String() != "-rwx------" {
  114. t.Fatalf("file %v Permission mismatch source (-rwx------) vs destination(%v)", fname, dfinfo.Mode().Perm())
  115. }
  116. fileContents, err := ioutil.ReadFile(filepath.Join(mountDir, fname))
  117. if err != nil {
  118. t.Fatalf("Could not readfile %v : %v", fname, err)
  119. }
  120. if !bytes.Equal(fileContents, finfo.contents) {
  121. t.Fatalf("File %v contents mismatch: %v , %v", fname, fileContents, finfo.contents)
  122. }
  123. // TODO: check uid and gid
  124. }
  125. }
  126. func checkFile(t *testing.T, testMountDir, fname string, contents []byte) {
  127. destinationFile := filepath.Join(testMountDir, fname)
  128. dfinfo, err1 := os.Stat(destinationFile)
  129. if err1 != nil {
  130. t.Fatalf("Could not stat file %v", destinationFile)
  131. }
  132. if dfinfo.Size() != int64(len(contents)) {
  133. t.Fatalf("Mismatch in size actual(%v) vs expected(%v)", dfinfo.Size(), int64(len(contents)))
  134. }
  135. fd, err2 := os.OpenFile(destinationFile, os.O_RDONLY, os.FileMode(0665))
  136. if err2 != nil {
  137. t.Fatalf("Could not open file %v", destinationFile)
  138. }
  139. newcontent := make([]byte, len(contents))
  140. fd.Read(newcontent)
  141. fd.Close()
  142. if !bytes.Equal(contents, newcontent) {
  143. t.Fatalf("File content mismatch expected (%v): received (%v) ", contents, newcontent)
  144. }
  145. }
  146. func getRandomBtes(size int) []byte {
  147. contents := make([]byte, size)
  148. rand.Read(contents)
  149. return contents
  150. }
  151. func isDirEmpty(name string) bool {
  152. f, err := os.Open(name)
  153. if err != nil {
  154. return false
  155. }
  156. defer f.Close()
  157. _, err = f.Readdirnames(1)
  158. return err == io.EOF
  159. }
  160. type testAPI struct {
  161. api *api.Api
  162. }
  163. func (ta *testAPI) mountListAndUnmount(t *testing.T) {
  164. files := make(map[string]fileInfo)
  165. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "fuse-source")
  166. testMountDir, _ := ioutil.TempDir(os.TempDir(), "fuse-dest")
  167. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  168. files["2.txt"] = fileInfo{0711, 333, 444, getRandomBtes(10)}
  169. files["3.txt"] = fileInfo{0622, 333, 444, getRandomBtes(100)}
  170. files["4.txt"] = fileInfo{0533, 333, 444, getRandomBtes(1024)}
  171. files["5.txt"] = fileInfo{0544, 333, 444, getRandomBtes(10)}
  172. files["6.txt"] = fileInfo{0555, 333, 444, getRandomBtes(10)}
  173. files["7.txt"] = fileInfo{0666, 333, 444, getRandomBtes(10)}
  174. files["8.txt"] = fileInfo{0777, 333, 333, getRandomBtes(10)}
  175. files["11.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
  176. files["111.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
  177. files["two/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
  178. files["two/2/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
  179. files["two/2./2.txt"] = fileInfo{0777, 444, 444, getRandomBtes(10)}
  180. files["twice/2.txt"] = fileInfo{0777, 444, 333, getRandomBtes(200)}
  181. files["one/two/three/four/five/six/seven/eight/nine/10.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10240)}
  182. files["one/two/three/four/five/six/six"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
  183. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  184. swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
  185. defer swarmfs.Stop()
  186. // Check unmount
  187. _, err := swarmfs.Unmount(testMountDir)
  188. if err != nil {
  189. t.Fatalf("could not unmount %v", bzzHash)
  190. }
  191. if !isDirEmpty(testMountDir) {
  192. t.Fatalf("unmount didnt work for %v", testMountDir)
  193. }
  194. }
  195. func (ta *testAPI) maxMounts(t *testing.T) {
  196. files := make(map[string]fileInfo)
  197. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  198. uploadDir1, _ := ioutil.TempDir(os.TempDir(), "max-upload1")
  199. bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1)
  200. mount1, _ := ioutil.TempDir(os.TempDir(), "max-mount1")
  201. swarmfs1 := mountDir(t, ta.api, files, bzzHash1, mount1)
  202. defer swarmfs1.Stop()
  203. files["2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  204. uploadDir2, _ := ioutil.TempDir(os.TempDir(), "max-upload2")
  205. bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2)
  206. mount2, _ := ioutil.TempDir(os.TempDir(), "max-mount2")
  207. swarmfs2 := mountDir(t, ta.api, files, bzzHash2, mount2)
  208. defer swarmfs2.Stop()
  209. files["3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  210. uploadDir3, _ := ioutil.TempDir(os.TempDir(), "max-upload3")
  211. bzzHash3 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir3)
  212. mount3, _ := ioutil.TempDir(os.TempDir(), "max-mount3")
  213. swarmfs3 := mountDir(t, ta.api, files, bzzHash3, mount3)
  214. defer swarmfs3.Stop()
  215. files["4.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  216. uploadDir4, _ := ioutil.TempDir(os.TempDir(), "max-upload4")
  217. bzzHash4 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir4)
  218. mount4, _ := ioutil.TempDir(os.TempDir(), "max-mount4")
  219. swarmfs4 := mountDir(t, ta.api, files, bzzHash4, mount4)
  220. defer swarmfs4.Stop()
  221. files["5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  222. uploadDir5, _ := ioutil.TempDir(os.TempDir(), "max-upload5")
  223. bzzHash5 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir5)
  224. mount5, _ := ioutil.TempDir(os.TempDir(), "max-mount5")
  225. swarmfs5 := mountDir(t, ta.api, files, bzzHash5, mount5)
  226. defer swarmfs5.Stop()
  227. files["6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  228. uploadDir6, _ := ioutil.TempDir(os.TempDir(), "max-upload6")
  229. bzzHash6 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir6)
  230. mount6, _ := ioutil.TempDir(os.TempDir(), "max-mount6")
  231. os.RemoveAll(mount6)
  232. os.MkdirAll(mount6, 0777)
  233. _, err := swarmfs.Mount(bzzHash6, mount6)
  234. if err == nil {
  235. t.Fatalf("Error: Going beyond max mounts %v", bzzHash6)
  236. }
  237. }
  238. func (ta *testAPI) remount(t *testing.T) {
  239. files := make(map[string]fileInfo)
  240. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  241. uploadDir1, _ := ioutil.TempDir(os.TempDir(), "re-upload1")
  242. bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1)
  243. testMountDir1, _ := ioutil.TempDir(os.TempDir(), "re-mount1")
  244. swarmfs := mountDir(t, ta.api, files, bzzHash1, testMountDir1)
  245. defer swarmfs.Stop()
  246. uploadDir2, _ := ioutil.TempDir(os.TempDir(), "re-upload2")
  247. bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2)
  248. testMountDir2, _ := ioutil.TempDir(os.TempDir(), "re-mount2")
  249. // try mounting the same hash second time
  250. os.RemoveAll(testMountDir2)
  251. os.MkdirAll(testMountDir2, 0777)
  252. _, err := swarmfs.Mount(bzzHash1, testMountDir2)
  253. if err != nil {
  254. t.Fatalf("Error mounting hash %v", bzzHash1)
  255. }
  256. // mount a different hash in already mounted point
  257. _, err = swarmfs.Mount(bzzHash2, testMountDir1)
  258. if err == nil {
  259. t.Fatalf("Error mounting hash %v", bzzHash2)
  260. }
  261. // mount nonexistent hash
  262. _, err = swarmfs.Mount("0xfea11223344", testMountDir1)
  263. if err == nil {
  264. t.Fatalf("Error mounting hash %v", bzzHash2)
  265. }
  266. }
  267. func (ta *testAPI) unmount(t *testing.T) {
  268. files := make(map[string]fileInfo)
  269. uploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload")
  270. testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount")
  271. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  272. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir)
  273. swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
  274. defer swarmfs.Stop()
  275. swarmfs.Unmount(testMountDir)
  276. mi := swarmfs.Listmounts()
  277. for _, minfo := range mi {
  278. if minfo.MountPoint == testMountDir {
  279. t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir)
  280. }
  281. }
  282. }
  283. func (ta *testAPI) unmountWhenResourceBusy(t *testing.T) {
  284. files := make(map[string]fileInfo)
  285. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload")
  286. testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount")
  287. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  288. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  289. swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
  290. defer swarmfs.Stop()
  291. actualPath := filepath.Join(testMountDir, "2.txt")
  292. d, err := os.OpenFile(actualPath, os.O_RDWR, os.FileMode(0700))
  293. d.Write(getRandomBtes(10))
  294. _, err = swarmfs.Unmount(testMountDir)
  295. if err != nil {
  296. t.Fatalf("could not unmount %v", bzzHash)
  297. }
  298. d.Close()
  299. mi := swarmfs.Listmounts()
  300. for _, minfo := range mi {
  301. if minfo.MountPoint == testMountDir {
  302. t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir)
  303. }
  304. }
  305. }
  306. func (ta *testAPI) seekInMultiChunkFile(t *testing.T) {
  307. files := make(map[string]fileInfo)
  308. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "seek-upload")
  309. testMountDir, _ := ioutil.TempDir(os.TempDir(), "seek-mount")
  310. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10240)}
  311. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  312. swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
  313. defer swarmfs.Stop()
  314. // Create a new file seek the second chunk
  315. actualPath := filepath.Join(testMountDir, "1.txt")
  316. d, _ := os.OpenFile(actualPath, os.O_RDONLY, os.FileMode(0700))
  317. d.Seek(5000, 0)
  318. contents := make([]byte, 1024)
  319. d.Read(contents)
  320. finfo := files["1.txt"]
  321. if !bytes.Equal(finfo.contents[:6024][5000:], contents) {
  322. t.Fatalf("File seek contents mismatch")
  323. }
  324. d.Close()
  325. }
  326. func (ta *testAPI) createNewFile(t *testing.T) {
  327. files := make(map[string]fileInfo)
  328. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "create-upload")
  329. testMountDir, _ := ioutil.TempDir(os.TempDir(), "create-mount")
  330. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  331. files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  332. files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  333. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  334. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  335. defer swarmfs1.Stop()
  336. // Create a new file in the root dir and check
  337. actualPath := filepath.Join(testMountDir, "2.txt")
  338. d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
  339. if err1 != nil {
  340. t.Fatalf("Could not create file %s : %v", actualPath, err1)
  341. }
  342. contents := make([]byte, 11)
  343. rand.Read(contents)
  344. d.Write(contents)
  345. d.Close()
  346. mi, err2 := swarmfs1.Unmount(testMountDir)
  347. if err2 != nil {
  348. t.Fatalf("Could not unmount %v", err2)
  349. }
  350. // mount again and see if things are okay
  351. files["2.txt"] = fileInfo{0700, 333, 444, contents}
  352. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  353. defer swarmfs2.Stop()
  354. checkFile(t, testMountDir, "2.txt", contents)
  355. }
  356. func (ta *testAPI) createNewFileInsideDirectory(t *testing.T) {
  357. files := make(map[string]fileInfo)
  358. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-upload")
  359. testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-mount")
  360. files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  361. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  362. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  363. defer swarmfs1.Stop()
  364. // Create a new file inside a existing dir and check
  365. dirToCreate := filepath.Join(testMountDir, "one")
  366. actualPath := filepath.Join(dirToCreate, "2.txt")
  367. d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
  368. if err1 != nil {
  369. t.Fatalf("Could not create file %s : %v", actualPath, err1)
  370. }
  371. contents := make([]byte, 11)
  372. rand.Read(contents)
  373. d.Write(contents)
  374. d.Close()
  375. mi, err2 := swarmfs1.Unmount(testMountDir)
  376. if err2 != nil {
  377. t.Fatalf("Could not unmount %v", err2)
  378. }
  379. // mount again and see if things are okay
  380. files["one/2.txt"] = fileInfo{0700, 333, 444, contents}
  381. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  382. defer swarmfs2.Stop()
  383. checkFile(t, testMountDir, "one/2.txt", contents)
  384. }
  385. func (ta *testAPI) createNewFileInsideNewDirectory(t *testing.T) {
  386. files := make(map[string]fileInfo)
  387. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-upload")
  388. testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-mount")
  389. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  390. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  391. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  392. defer swarmfs1.Stop()
  393. // Create a new file inside a existing dir and check
  394. dirToCreate := filepath.Join(testMountDir, "one")
  395. os.MkdirAll(dirToCreate, 0777)
  396. actualPath := filepath.Join(dirToCreate, "2.txt")
  397. d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
  398. if err1 != nil {
  399. t.Fatalf("Could not create file %s : %v", actualPath, err1)
  400. }
  401. contents := make([]byte, 11)
  402. rand.Read(contents)
  403. d.Write(contents)
  404. d.Close()
  405. mi, err2 := swarmfs1.Unmount(testMountDir)
  406. if err2 != nil {
  407. t.Fatalf("Could not unmount %v", err2)
  408. }
  409. // mount again and see if things are okay
  410. files["one/2.txt"] = fileInfo{0700, 333, 444, contents}
  411. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  412. defer swarmfs2.Stop()
  413. checkFile(t, testMountDir, "one/2.txt", contents)
  414. }
  415. func (ta *testAPI) removeExistingFile(t *testing.T) {
  416. files := make(map[string]fileInfo)
  417. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload")
  418. testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount")
  419. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  420. files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  421. files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  422. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  423. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  424. defer swarmfs1.Stop()
  425. // Remove a file in the root dir and check
  426. actualPath := filepath.Join(testMountDir, "five.txt")
  427. os.Remove(actualPath)
  428. mi, err2 := swarmfs1.Unmount(testMountDir)
  429. if err2 != nil {
  430. t.Fatalf("Could not unmount %v", err2)
  431. }
  432. // mount again and see if things are okay
  433. delete(files, "five.txt")
  434. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  435. defer swarmfs2.Stop()
  436. }
  437. func (ta *testAPI) removeExistingFileInsideDir(t *testing.T) {
  438. files := make(map[string]fileInfo)
  439. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload")
  440. testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount")
  441. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  442. files["one/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  443. files["one/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  444. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  445. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  446. defer swarmfs1.Stop()
  447. // Remove a file in the root dir and check
  448. actualPath := filepath.Join(testMountDir, "one/five.txt")
  449. os.Remove(actualPath)
  450. mi, err2 := swarmfs1.Unmount(testMountDir)
  451. if err2 != nil {
  452. t.Fatalf("Could not unmount %v", err2)
  453. }
  454. // mount again and see if things are okay
  455. delete(files, "one/five.txt")
  456. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  457. defer swarmfs2.Stop()
  458. }
  459. func (ta *testAPI) removeNewlyAddedFile(t *testing.T) {
  460. files := make(map[string]fileInfo)
  461. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "removenew-upload")
  462. testMountDir, _ := ioutil.TempDir(os.TempDir(), "removenew-mount")
  463. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  464. files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  465. files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  466. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  467. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  468. defer swarmfs1.Stop()
  469. // Adda a new file and remove it
  470. dirToCreate := filepath.Join(testMountDir, "one")
  471. os.MkdirAll(dirToCreate, os.FileMode(0665))
  472. actualPath := filepath.Join(dirToCreate, "2.txt")
  473. d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
  474. if err1 != nil {
  475. t.Fatalf("Could not create file %s : %v", actualPath, err1)
  476. }
  477. contents := make([]byte, 11)
  478. rand.Read(contents)
  479. d.Write(contents)
  480. d.Close()
  481. checkFile(t, testMountDir, "one/2.txt", contents)
  482. os.Remove(actualPath)
  483. mi, err2 := swarmfs1.Unmount(testMountDir)
  484. if err2 != nil {
  485. t.Fatalf("Could not unmount %v", err2)
  486. }
  487. // mount again and see if things are okay
  488. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  489. defer swarmfs2.Stop()
  490. if bzzHash != mi.LatestManifest {
  491. t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, mi.LatestManifest)
  492. }
  493. }
  494. func (ta *testAPI) addNewFileAndModifyContents(t *testing.T) {
  495. files := make(map[string]fileInfo)
  496. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-upload")
  497. testMountDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-mount")
  498. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  499. files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  500. files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  501. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  502. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  503. defer swarmfs1.Stop()
  504. // Create a new file in the root dir and check
  505. actualPath := filepath.Join(testMountDir, "2.txt")
  506. d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
  507. if err1 != nil {
  508. t.Fatalf("Could not create file %s : %v", actualPath, err1)
  509. }
  510. line1 := []byte("Line 1")
  511. rand.Read(line1)
  512. d.Write(line1)
  513. d.Close()
  514. mi1, err2 := swarmfs1.Unmount(testMountDir)
  515. if err2 != nil {
  516. t.Fatalf("Could not unmount %v", err2)
  517. }
  518. // mount again and see if things are okay
  519. files["2.txt"] = fileInfo{0700, 333, 444, line1}
  520. swarmfs2 := mountDir(t, ta.api, files, mi1.LatestManifest, testMountDir)
  521. defer swarmfs2.Stop()
  522. checkFile(t, testMountDir, "2.txt", line1)
  523. mi2, err3 := swarmfs2.Unmount(testMountDir)
  524. if err3 != nil {
  525. t.Fatalf("Could not unmount %v", err3)
  526. }
  527. // mount again and modify
  528. swarmfs3 := mountDir(t, ta.api, files, mi2.LatestManifest, testMountDir)
  529. defer swarmfs3.Stop()
  530. fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665))
  531. if err4 != nil {
  532. t.Fatalf("Could not create file %s : %v", actualPath, err4)
  533. }
  534. line2 := []byte("Line 2")
  535. rand.Read(line2)
  536. fd.Seek(int64(len(line1)), 0)
  537. fd.Write(line2)
  538. fd.Close()
  539. mi3, err5 := swarmfs3.Unmount(testMountDir)
  540. if err5 != nil {
  541. t.Fatalf("Could not unmount %v", err5)
  542. }
  543. // mount again and see if things are okay
  544. b := [][]byte{line1, line2}
  545. line1and2 := bytes.Join(b, []byte(""))
  546. files["2.txt"] = fileInfo{0700, 333, 444, line1and2}
  547. swarmfs4 := mountDir(t, ta.api, files, mi3.LatestManifest, testMountDir)
  548. defer swarmfs4.Stop()
  549. checkFile(t, testMountDir, "2.txt", line1and2)
  550. }
  551. func (ta *testAPI) removeEmptyDir(t *testing.T) {
  552. files := make(map[string]fileInfo)
  553. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload")
  554. testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount")
  555. files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  556. files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  557. files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  558. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  559. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  560. defer swarmfs1.Stop()
  561. os.MkdirAll(filepath.Join(testMountDir, "newdir"), 0777)
  562. mi, err3 := swarmfs1.Unmount(testMountDir)
  563. if err3 != nil {
  564. t.Fatalf("Could not unmount %v", err3)
  565. }
  566. if bzzHash != mi.LatestManifest {
  567. t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, mi.LatestManifest)
  568. }
  569. }
  570. func (ta *testAPI) removeDirWhichHasFiles(t *testing.T) {
  571. files := make(map[string]fileInfo)
  572. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload")
  573. testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount")
  574. files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  575. files["two/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  576. files["two/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  577. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  578. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  579. defer swarmfs1.Stop()
  580. dirPath := filepath.Join(testMountDir, "two")
  581. os.RemoveAll(dirPath)
  582. mi, err2 := swarmfs1.Unmount(testMountDir)
  583. if err2 != nil {
  584. t.Fatalf("Could not unmount %v ", err2)
  585. }
  586. // mount again and see if things are okay
  587. delete(files, "two/five.txt")
  588. delete(files, "two/six.txt")
  589. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  590. defer swarmfs2.Stop()
  591. }
  592. func (ta *testAPI) removeDirWhichHasSubDirs(t *testing.T) {
  593. files := make(map[string]fileInfo)
  594. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-upload")
  595. testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-mount")
  596. files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  597. files["two/three/2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  598. files["two/three/3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  599. files["two/four/5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  600. files["two/four/6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  601. files["two/four/six/7.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
  602. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  603. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  604. defer swarmfs1.Stop()
  605. dirPath := filepath.Join(testMountDir, "two")
  606. os.RemoveAll(dirPath)
  607. mi, err2 := swarmfs1.Unmount(testMountDir)
  608. if err2 != nil {
  609. t.Fatalf("Could not unmount %v ", err2)
  610. }
  611. // mount again and see if things are okay
  612. delete(files, "two/three/2.txt")
  613. delete(files, "two/three/3.txt")
  614. delete(files, "two/four/5.txt")
  615. delete(files, "two/four/6.txt")
  616. delete(files, "two/four/six/7.txt")
  617. swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
  618. defer swarmfs2.Stop()
  619. }
  620. func (ta *testAPI) appendFileContentsToEnd(t *testing.T) {
  621. files := make(map[string]fileInfo)
  622. testUploadDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-upload")
  623. testMountDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-mount")
  624. line1 := make([]byte, 10)
  625. rand.Read(line1)
  626. files["1.txt"] = fileInfo{0700, 333, 444, line1}
  627. bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
  628. swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
  629. defer swarmfs1.Stop()
  630. actualPath := filepath.Join(testMountDir, "1.txt")
  631. fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665))
  632. if err4 != nil {
  633. t.Fatalf("Could not create file %s : %v", actualPath, err4)
  634. }
  635. line2 := make([]byte, 5)
  636. rand.Read(line2)
  637. fd.Seek(int64(len(line1)), 0)
  638. fd.Write(line2)
  639. fd.Close()
  640. mi1, err5 := swarmfs1.Unmount(testMountDir)
  641. if err5 != nil {
  642. t.Fatalf("Could not unmount %v ", err5)
  643. }
  644. // mount again and see if things are okay
  645. b := [][]byte{line1, line2}
  646. line1and2 := bytes.Join(b, []byte(""))
  647. files["1.txt"] = fileInfo{0700, 333, 444, line1and2}
  648. swarmfs2 := mountDir(t, ta.api, files, mi1.LatestManifest, testMountDir)
  649. defer swarmfs2.Stop()
  650. checkFile(t, testMountDir, "1.txt", line1and2)
  651. }
  652. func TestFUSE(t *testing.T) {
  653. datadir, err := ioutil.TempDir("", "fuse")
  654. if err != nil {
  655. t.Fatalf("unable to create temp dir: %v", err)
  656. }
  657. os.RemoveAll(datadir)
  658. dpa, err := storage.NewLocalDPA(datadir)
  659. if err != nil {
  660. t.Fatal(err)
  661. }
  662. ta := &testAPI{api: api.NewApi(dpa, nil)}
  663. dpa.Start()
  664. defer dpa.Stop()
  665. t.Run("mountListAndUmount", ta.mountListAndUnmount)
  666. t.Run("maxMounts", ta.maxMounts)
  667. t.Run("remount", ta.remount)
  668. t.Run("unmount", ta.unmount)
  669. t.Run("unmountWhenResourceBusy", ta.unmountWhenResourceBusy)
  670. t.Run("seekInMultiChunkFile", ta.seekInMultiChunkFile)
  671. t.Run("createNewFile", ta.createNewFile)
  672. t.Run("createNewFileInsideDirectory", ta.createNewFileInsideDirectory)
  673. t.Run("createNewFileInsideNewDirectory", ta.createNewFileInsideNewDirectory)
  674. t.Run("removeExistingFile", ta.removeExistingFile)
  675. t.Run("removeExistingFileInsideDir", ta.removeExistingFileInsideDir)
  676. t.Run("removeNewlyAddedFile", ta.removeNewlyAddedFile)
  677. t.Run("addNewFileAndModifyContents", ta.addNewFileAndModifyContents)
  678. t.Run("removeEmptyDir", ta.removeEmptyDir)
  679. t.Run("removeDirWhichHasFiles", ta.removeDirWhichHasFiles)
  680. t.Run("removeDirWhichHasSubDirs", ta.removeDirWhichHasSubDirs)
  681. t.Run("appendFileContentsToEnd", ta.appendFileContentsToEnd)
  682. }