github.com/gochain-io/gochain@v2.2.26+incompatible/swarm/fuse/swarmfs_test.go (about) 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 17 // +build linux darwin freebsd 18 19 package fuse 20 21 import ( 22 "bytes" 23 "crypto/rand" 24 "io" 25 "io/ioutil" 26 "os" 27 "path/filepath" 28 "testing" 29 30 "github.com/gochain-io/gochain/swarm/api" 31 "github.com/gochain-io/gochain/swarm/storage" 32 ) 33 34 type fileInfo struct { 35 perm uint64 36 uid int 37 gid int 38 contents []byte 39 } 40 41 func createTestFilesAndUploadToSwarm(t *testing.T, api *api.Api, files map[string]fileInfo, uploadDir string) string { 42 os.RemoveAll(uploadDir) 43 44 for fname, finfo := range files { 45 actualPath := filepath.Join(uploadDir, fname) 46 filePath := filepath.Dir(actualPath) 47 48 err := os.MkdirAll(filePath, 0777) 49 if err != nil { 50 t.Fatalf("Error creating directory '%v' : %v", filePath, err) 51 } 52 53 fd, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(finfo.perm)) 54 if err1 != nil { 55 t.Fatalf("Error creating file %v: %v", actualPath, err1) 56 } 57 58 fd.Write(finfo.contents) 59 fd.Chown(finfo.uid, finfo.gid) 60 fd.Chmod(os.FileMode(finfo.perm)) 61 fd.Sync() 62 fd.Close() 63 } 64 65 bzzhash, err := api.Upload(uploadDir, "") 66 if err != nil { 67 t.Fatalf("Error uploading directory %v: %v", uploadDir, err) 68 } 69 70 return bzzhash 71 } 72 73 func mountDir(t *testing.T, api *api.Api, files map[string]fileInfo, bzzHash string, mountDir string) *SwarmFS { 74 os.RemoveAll(mountDir) 75 os.MkdirAll(mountDir, 0777) 76 swarmfs := NewSwarmFS(api) 77 _, err := swarmfs.Mount(bzzHash, mountDir) 78 if isFUSEUnsupportedError(err) { 79 t.Skip("FUSE not supported:", err) 80 } else if err != nil { 81 t.Fatalf("Error mounting hash %v: %v", bzzHash, err) 82 } 83 84 found := false 85 mi := swarmfs.Listmounts() 86 for _, minfo := range mi { 87 if minfo.MountPoint == mountDir { 88 minfo.LatestManifestMu.RLock() 89 lm := minfo.LatestManifest 90 minfo.LatestManifestMu.RUnlock() 91 if minfo.StartManifest != bzzHash || lm != bzzHash || minfo.fuseConnection == nil { 92 t.Fatalf("Error mounting: exp(%s): act(%s)", bzzHash, minfo.StartManifest) 93 } 94 found = true 95 } 96 } 97 98 // Test listMounts 99 if !found { 100 t.Fatalf("Error getting mounts information for %v: %v", mountDir, err) 101 } 102 103 // Check if file and their attributes are as expected 104 compareGeneratedFileWithFileInMount(t, files, mountDir) 105 106 return swarmfs 107 } 108 109 func compareGeneratedFileWithFileInMount(t *testing.T, files map[string]fileInfo, mountDir string) { 110 err := filepath.Walk(mountDir, func(path string, f os.FileInfo, err error) error { 111 if f.IsDir() { 112 return nil 113 } 114 fname := path[len(mountDir)+1:] 115 if _, ok := files[fname]; !ok { 116 t.Fatalf(" file %v present in mount dir and is not expected", fname) 117 } 118 return nil 119 }) 120 if err != nil { 121 t.Fatalf("Error walking dir %v", mountDir) 122 } 123 124 for fname, finfo := range files { 125 destinationFile := filepath.Join(mountDir, fname) 126 127 dfinfo, err := os.Stat(destinationFile) 128 if err != nil { 129 t.Fatalf("Destination file %v missing in mount: %v", fname, err) 130 } 131 132 if int64(len(finfo.contents)) != dfinfo.Size() { 133 t.Fatalf("file %v Size mismatch source (%v) vs destination(%v)", fname, int64(len(finfo.contents)), dfinfo.Size()) 134 } 135 136 if dfinfo.Mode().Perm().String() != "-rwx------" { 137 t.Fatalf("file %v Permission mismatch source (-rwx------) vs destination(%v)", fname, dfinfo.Mode().Perm()) 138 } 139 140 fileContents, err := ioutil.ReadFile(filepath.Join(mountDir, fname)) 141 if err != nil { 142 t.Fatalf("Could not readfile %v : %v", fname, err) 143 } 144 if !bytes.Equal(fileContents, finfo.contents) { 145 t.Fatalf("File %v contents mismatch: %v , %v", fname, fileContents, finfo.contents) 146 147 } 148 // TODO: check uid and gid 149 } 150 } 151 152 func checkFile(t *testing.T, testMountDir, fname string, contents []byte) { 153 destinationFile := filepath.Join(testMountDir, fname) 154 dfinfo, err1 := os.Stat(destinationFile) 155 if err1 != nil { 156 t.Fatalf("Could not stat file %v", destinationFile) 157 } 158 if dfinfo.Size() != int64(len(contents)) { 159 t.Fatalf("Mismatch in size actual(%v) vs expected(%v)", dfinfo.Size(), int64(len(contents))) 160 } 161 162 fd, err2 := os.OpenFile(destinationFile, os.O_RDONLY, os.FileMode(0665)) 163 if err2 != nil { 164 t.Fatalf("Could not open file %v", destinationFile) 165 } 166 newcontent := make([]byte, len(contents)) 167 fd.Read(newcontent) 168 fd.Close() 169 170 if !bytes.Equal(contents, newcontent) { 171 t.Fatalf("File content mismatch expected (%v): received (%v) ", contents, newcontent) 172 } 173 } 174 175 func getRandomBtes(size int) []byte { 176 contents := make([]byte, size) 177 rand.Read(contents) 178 return contents 179 } 180 181 func isDirEmpty(name string) bool { 182 f, err := os.Open(name) 183 if err != nil { 184 return false 185 } 186 defer f.Close() 187 188 _, err = f.Readdirnames(1) 189 190 return err == io.EOF 191 } 192 193 type testAPI struct { 194 api *api.Api 195 } 196 197 func (ta *testAPI) mountListAndUnmount(t *testing.T) { 198 files := make(map[string]fileInfo) 199 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "fuse-source") 200 testMountDir, _ := ioutil.TempDir(os.TempDir(), "fuse-dest") 201 202 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 203 files["2.txt"] = fileInfo{0711, 333, 444, getRandomBtes(10)} 204 files["3.txt"] = fileInfo{0622, 333, 444, getRandomBtes(100)} 205 files["4.txt"] = fileInfo{0533, 333, 444, getRandomBtes(1024)} 206 files["5.txt"] = fileInfo{0544, 333, 444, getRandomBtes(10)} 207 files["6.txt"] = fileInfo{0555, 333, 444, getRandomBtes(10)} 208 files["7.txt"] = fileInfo{0666, 333, 444, getRandomBtes(10)} 209 files["8.txt"] = fileInfo{0777, 333, 333, getRandomBtes(10)} 210 files["11.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)} 211 files["111.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)} 212 files["two/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)} 213 files["two/2/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)} 214 files["two/2./2.txt"] = fileInfo{0777, 444, 444, getRandomBtes(10)} 215 files["twice/2.txt"] = fileInfo{0777, 444, 333, getRandomBtes(200)} 216 files["one/two/three/four/five/six/seven/eight/nine/10.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10240)} 217 files["one/two/three/four/five/six/six"] = fileInfo{0777, 333, 444, getRandomBtes(10)} 218 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 219 220 swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir) 221 defer swarmfs.Stop() 222 223 // Check unmount 224 _, err := swarmfs.Unmount(testMountDir) 225 if err != nil { 226 t.Fatalf("could not unmount %v", bzzHash) 227 } 228 if !isDirEmpty(testMountDir) { 229 t.Fatalf("unmount didnt work for %v", testMountDir) 230 } 231 232 } 233 234 func (ta *testAPI) maxMounts(t *testing.T) { 235 files := make(map[string]fileInfo) 236 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 237 uploadDir1, _ := ioutil.TempDir(os.TempDir(), "max-upload1") 238 bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1) 239 mount1, _ := ioutil.TempDir(os.TempDir(), "max-mount1") 240 swarmfs1 := mountDir(t, ta.api, files, bzzHash1, mount1) 241 defer swarmfs1.Stop() 242 243 files["2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 244 uploadDir2, _ := ioutil.TempDir(os.TempDir(), "max-upload2") 245 bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2) 246 mount2, _ := ioutil.TempDir(os.TempDir(), "max-mount2") 247 swarmfs2 := mountDir(t, ta.api, files, bzzHash2, mount2) 248 defer swarmfs2.Stop() 249 250 files["3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 251 uploadDir3, _ := ioutil.TempDir(os.TempDir(), "max-upload3") 252 bzzHash3 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir3) 253 mount3, _ := ioutil.TempDir(os.TempDir(), "max-mount3") 254 swarmfs3 := mountDir(t, ta.api, files, bzzHash3, mount3) 255 defer swarmfs3.Stop() 256 257 files["4.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 258 uploadDir4, _ := ioutil.TempDir(os.TempDir(), "max-upload4") 259 bzzHash4 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir4) 260 mount4, _ := ioutil.TempDir(os.TempDir(), "max-mount4") 261 swarmfs4 := mountDir(t, ta.api, files, bzzHash4, mount4) 262 defer swarmfs4.Stop() 263 264 files["5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 265 uploadDir5, _ := ioutil.TempDir(os.TempDir(), "max-upload5") 266 bzzHash5 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir5) 267 mount5, _ := ioutil.TempDir(os.TempDir(), "max-mount5") 268 swarmfs5 := mountDir(t, ta.api, files, bzzHash5, mount5) 269 defer swarmfs5.Stop() 270 271 files["6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 272 uploadDir6, _ := ioutil.TempDir(os.TempDir(), "max-upload6") 273 bzzHash6 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir6) 274 mount6, _ := ioutil.TempDir(os.TempDir(), "max-mount6") 275 276 os.RemoveAll(mount6) 277 os.MkdirAll(mount6, 0777) 278 _, err := swarmfs.Mount(bzzHash6, mount6) 279 if err == nil { 280 t.Fatalf("Error: Going beyond max mounts %v", bzzHash6) 281 } 282 283 } 284 285 func (ta *testAPI) remount(t *testing.T) { 286 files := make(map[string]fileInfo) 287 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 288 uploadDir1, _ := ioutil.TempDir(os.TempDir(), "re-upload1") 289 bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1) 290 testMountDir1, _ := ioutil.TempDir(os.TempDir(), "re-mount1") 291 swarmfs := mountDir(t, ta.api, files, bzzHash1, testMountDir1) 292 defer swarmfs.Stop() 293 294 uploadDir2, _ := ioutil.TempDir(os.TempDir(), "re-upload2") 295 bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2) 296 testMountDir2, _ := ioutil.TempDir(os.TempDir(), "re-mount2") 297 298 // try mounting the same hash second time 299 os.RemoveAll(testMountDir2) 300 os.MkdirAll(testMountDir2, 0777) 301 _, err := swarmfs.Mount(bzzHash1, testMountDir2) 302 if err != nil { 303 t.Fatalf("Error mounting hash %v", bzzHash1) 304 } 305 306 // mount a different hash in already mounted point 307 _, err = swarmfs.Mount(bzzHash2, testMountDir1) 308 if err == nil { 309 t.Fatalf("Error mounting hash %v", bzzHash2) 310 } 311 312 // mount nonexistent hash 313 _, err = swarmfs.Mount("0xfea11223344", testMountDir1) 314 if err == nil { 315 t.Fatalf("Error mounting hash %v", bzzHash2) 316 } 317 } 318 319 func (ta *testAPI) unmount(t *testing.T) { 320 files := make(map[string]fileInfo) 321 uploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload") 322 testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount") 323 324 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 325 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir) 326 327 swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir) 328 defer swarmfs.Stop() 329 330 swarmfs.Unmount(testMountDir) 331 332 mi := swarmfs.Listmounts() 333 for _, minfo := range mi { 334 if minfo.MountPoint == testMountDir { 335 t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir) 336 } 337 } 338 } 339 340 func (ta *testAPI) unmountWhenResourceBusy(t *testing.T) { 341 files := make(map[string]fileInfo) 342 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload") 343 testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount") 344 345 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 346 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 347 348 swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir) 349 defer swarmfs.Stop() 350 351 actualPath := filepath.Join(testMountDir, "2.txt") 352 d, err := os.OpenFile(actualPath, os.O_RDWR, os.FileMode(0700)) 353 d.Write(getRandomBtes(10)) 354 355 _, err = swarmfs.Unmount(testMountDir) 356 if err != nil { 357 t.Fatalf("could not unmount %v", bzzHash) 358 } 359 d.Close() 360 361 mi := swarmfs.Listmounts() 362 for _, minfo := range mi { 363 if minfo.MountPoint == testMountDir { 364 t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir) 365 } 366 } 367 } 368 369 func (ta *testAPI) seekInMultiChunkFile(t *testing.T) { 370 files := make(map[string]fileInfo) 371 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "seek-upload") 372 testMountDir, _ := ioutil.TempDir(os.TempDir(), "seek-mount") 373 374 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10240)} 375 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 376 377 swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir) 378 defer swarmfs.Stop() 379 380 // Create a new file seek the second chunk 381 actualPath := filepath.Join(testMountDir, "1.txt") 382 d, _ := os.OpenFile(actualPath, os.O_RDONLY, os.FileMode(0700)) 383 384 d.Seek(5000, 0) 385 386 contents := make([]byte, 1024) 387 d.Read(contents) 388 finfo := files["1.txt"] 389 390 if !bytes.Equal(finfo.contents[:6024][5000:], contents) { 391 t.Fatalf("File seek contents mismatch") 392 } 393 d.Close() 394 } 395 396 func (ta *testAPI) createNewFile(t *testing.T) { 397 files := make(map[string]fileInfo) 398 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "create-upload") 399 testMountDir, _ := ioutil.TempDir(os.TempDir(), "create-mount") 400 401 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 402 files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 403 files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 404 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 405 406 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 407 defer swarmfs1.Stop() 408 409 // Create a new file in the root dir and check 410 actualPath := filepath.Join(testMountDir, "2.txt") 411 d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665)) 412 if err1 != nil { 413 t.Fatalf("Could not create file %s : %v", actualPath, err1) 414 } 415 contents := make([]byte, 11) 416 rand.Read(contents) 417 d.Write(contents) 418 d.Close() 419 420 mi, err2 := swarmfs1.Unmount(testMountDir) 421 if err2 != nil { 422 t.Fatalf("Could not unmount %v", err2) 423 } 424 425 // mount again and see if things are okay 426 files["2.txt"] = fileInfo{0700, 333, 444, contents} 427 mi.LatestManifestMu.RLock() 428 lm := mi.LatestManifest 429 mi.LatestManifestMu.RUnlock() 430 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 431 defer swarmfs2.Stop() 432 433 checkFile(t, testMountDir, "2.txt", contents) 434 } 435 436 func (ta *testAPI) createNewFileInsideDirectory(t *testing.T) { 437 files := make(map[string]fileInfo) 438 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-upload") 439 testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-mount") 440 441 files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 442 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 443 444 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 445 defer swarmfs1.Stop() 446 447 // Create a new file inside a existing dir and check 448 dirToCreate := filepath.Join(testMountDir, "one") 449 actualPath := filepath.Join(dirToCreate, "2.txt") 450 d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665)) 451 if err1 != nil { 452 t.Fatalf("Could not create file %s : %v", actualPath, err1) 453 } 454 contents := make([]byte, 11) 455 rand.Read(contents) 456 d.Write(contents) 457 d.Close() 458 459 mi, err2 := swarmfs1.Unmount(testMountDir) 460 if err2 != nil { 461 t.Fatalf("Could not unmount %v", err2) 462 } 463 464 // mount again and see if things are okay 465 files["one/2.txt"] = fileInfo{0700, 333, 444, contents} 466 mi.LatestManifestMu.RLock() 467 lm := mi.LatestManifest 468 mi.LatestManifestMu.RUnlock() 469 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 470 defer swarmfs2.Stop() 471 472 checkFile(t, testMountDir, "one/2.txt", contents) 473 } 474 475 func (ta *testAPI) createNewFileInsideNewDirectory(t *testing.T) { 476 files := make(map[string]fileInfo) 477 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-upload") 478 testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-mount") 479 480 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 481 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 482 483 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 484 defer swarmfs1.Stop() 485 486 // Create a new file inside a existing dir and check 487 dirToCreate := filepath.Join(testMountDir, "one") 488 os.MkdirAll(dirToCreate, 0777) 489 actualPath := filepath.Join(dirToCreate, "2.txt") 490 d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665)) 491 if err1 != nil { 492 t.Fatalf("Could not create file %s : %v", actualPath, err1) 493 } 494 contents := make([]byte, 11) 495 rand.Read(contents) 496 d.Write(contents) 497 d.Close() 498 499 mi, err2 := swarmfs1.Unmount(testMountDir) 500 if err2 != nil { 501 t.Fatalf("Could not unmount %v", err2) 502 } 503 504 // mount again and see if things are okay 505 files["one/2.txt"] = fileInfo{0700, 333, 444, contents} 506 mi.LatestManifestMu.RLock() 507 lm := mi.LatestManifest 508 mi.LatestManifestMu.RUnlock() 509 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 510 defer swarmfs2.Stop() 511 512 checkFile(t, testMountDir, "one/2.txt", contents) 513 } 514 515 func (ta *testAPI) removeExistingFile(t *testing.T) { 516 files := make(map[string]fileInfo) 517 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload") 518 testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount") 519 520 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 521 files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 522 files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 523 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 524 525 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 526 defer swarmfs1.Stop() 527 528 // Remove a file in the root dir and check 529 actualPath := filepath.Join(testMountDir, "five.txt") 530 os.Remove(actualPath) 531 532 mi, err2 := swarmfs1.Unmount(testMountDir) 533 if err2 != nil { 534 t.Fatalf("Could not unmount %v", err2) 535 } 536 537 // mount again and see if things are okay 538 delete(files, "five.txt") 539 mi.LatestManifestMu.RLock() 540 lm := mi.LatestManifest 541 mi.LatestManifestMu.RUnlock() 542 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 543 defer swarmfs2.Stop() 544 } 545 546 func (ta *testAPI) removeExistingFileInsideDir(t *testing.T) { 547 files := make(map[string]fileInfo) 548 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload") 549 testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount") 550 551 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 552 files["one/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 553 files["one/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 554 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 555 556 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 557 defer swarmfs1.Stop() 558 559 // Remove a file in the root dir and check 560 actualPath := filepath.Join(testMountDir, "one/five.txt") 561 os.Remove(actualPath) 562 563 mi, err2 := swarmfs1.Unmount(testMountDir) 564 if err2 != nil { 565 t.Fatalf("Could not unmount %v", err2) 566 } 567 568 // mount again and see if things are okay 569 delete(files, "one/five.txt") 570 mi.LatestManifestMu.RLock() 571 lm := mi.LatestManifest 572 mi.LatestManifestMu.RUnlock() 573 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 574 defer swarmfs2.Stop() 575 } 576 577 func (ta *testAPI) removeNewlyAddedFile(t *testing.T) { 578 579 files := make(map[string]fileInfo) 580 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "removenew-upload") 581 testMountDir, _ := ioutil.TempDir(os.TempDir(), "removenew-mount") 582 583 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 584 files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 585 files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 586 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 587 588 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 589 defer swarmfs1.Stop() 590 591 // Adda a new file and remove it 592 dirToCreate := filepath.Join(testMountDir, "one") 593 os.MkdirAll(dirToCreate, os.FileMode(0665)) 594 actualPath := filepath.Join(dirToCreate, "2.txt") 595 d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665)) 596 if err1 != nil { 597 t.Fatalf("Could not create file %s : %v", actualPath, err1) 598 } 599 contents := make([]byte, 11) 600 rand.Read(contents) 601 d.Write(contents) 602 d.Close() 603 604 checkFile(t, testMountDir, "one/2.txt", contents) 605 606 os.Remove(actualPath) 607 608 mi, err2 := swarmfs1.Unmount(testMountDir) 609 if err2 != nil { 610 t.Fatalf("Could not unmount %v", err2) 611 } 612 613 // mount again and see if things are okay 614 mi.LatestManifestMu.RLock() 615 lm := mi.LatestManifest 616 mi.LatestManifestMu.RUnlock() 617 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 618 defer swarmfs2.Stop() 619 620 if bzzHash != lm { 621 t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, lm) 622 } 623 } 624 625 func (ta *testAPI) addNewFileAndModifyContents(t *testing.T) { 626 files := make(map[string]fileInfo) 627 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-upload") 628 testMountDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-mount") 629 630 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 631 files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 632 files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 633 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 634 635 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 636 defer swarmfs1.Stop() 637 638 // Create a new file in the root dir and check 639 actualPath := filepath.Join(testMountDir, "2.txt") 640 d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665)) 641 if err1 != nil { 642 t.Fatalf("Could not create file %s : %v", actualPath, err1) 643 } 644 line1 := []byte("Line 1") 645 rand.Read(line1) 646 d.Write(line1) 647 d.Close() 648 649 mi1, err2 := swarmfs1.Unmount(testMountDir) 650 if err2 != nil { 651 t.Fatalf("Could not unmount %v", err2) 652 } 653 654 // mount again and see if things are okay 655 files["2.txt"] = fileInfo{0700, 333, 444, line1} 656 mi1.LatestManifestMu.RLock() 657 lm := mi1.LatestManifest 658 mi1.LatestManifestMu.RUnlock() 659 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 660 defer swarmfs2.Stop() 661 662 checkFile(t, testMountDir, "2.txt", line1) 663 664 mi2, err3 := swarmfs2.Unmount(testMountDir) 665 if err3 != nil { 666 t.Fatalf("Could not unmount %v", err3) 667 } 668 669 // mount again and modify 670 mi2.LatestManifestMu.RLock() 671 lm = mi2.LatestManifest 672 mi2.LatestManifestMu.RUnlock() 673 swarmfs3 := mountDir(t, ta.api, files, lm, testMountDir) 674 defer swarmfs3.Stop() 675 676 fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665)) 677 if err4 != nil { 678 t.Fatalf("Could not create file %s : %v", actualPath, err4) 679 } 680 line2 := []byte("Line 2") 681 rand.Read(line2) 682 fd.Seek(int64(len(line1)), 0) 683 fd.Write(line2) 684 fd.Close() 685 686 mi3, err5 := swarmfs3.Unmount(testMountDir) 687 if err5 != nil { 688 t.Fatalf("Could not unmount %v", err5) 689 } 690 691 // mount again and see if things are okay 692 b := [][]byte{line1, line2} 693 line1and2 := bytes.Join(b, []byte("")) 694 files["2.txt"] = fileInfo{0700, 333, 444, line1and2} 695 mi3.LatestManifestMu.RLock() 696 lm = mi3.LatestManifest 697 mi3.LatestManifestMu.RUnlock() 698 swarmfs4 := mountDir(t, ta.api, files, lm, testMountDir) 699 defer swarmfs4.Stop() 700 701 checkFile(t, testMountDir, "2.txt", line1and2) 702 } 703 704 func (ta *testAPI) removeEmptyDir(t *testing.T) { 705 files := make(map[string]fileInfo) 706 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload") 707 testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount") 708 709 files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 710 files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 711 files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 712 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 713 714 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 715 defer swarmfs1.Stop() 716 717 os.MkdirAll(filepath.Join(testMountDir, "newdir"), 0777) 718 719 mi, err3 := swarmfs1.Unmount(testMountDir) 720 if err3 != nil { 721 t.Fatalf("Could not unmount %v", err3) 722 } 723 mi.LatestManifestMu.RLock() 724 lm := mi.LatestManifest 725 mi.LatestManifestMu.RUnlock() 726 if bzzHash != lm { 727 t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, lm) 728 } 729 } 730 731 func (ta *testAPI) removeDirWhichHasFiles(t *testing.T) { 732 files := make(map[string]fileInfo) 733 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload") 734 testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount") 735 736 files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 737 files["two/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 738 files["two/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 739 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 740 741 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 742 defer swarmfs1.Stop() 743 744 dirPath := filepath.Join(testMountDir, "two") 745 os.RemoveAll(dirPath) 746 747 mi, err2 := swarmfs1.Unmount(testMountDir) 748 if err2 != nil { 749 t.Fatalf("Could not unmount %v ", err2) 750 } 751 752 // mount again and see if things are okay 753 delete(files, "two/five.txt") 754 delete(files, "two/six.txt") 755 756 mi.LatestManifestMu.RLock() 757 lm := mi.LatestManifest 758 mi.LatestManifestMu.RUnlock() 759 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 760 defer swarmfs2.Stop() 761 } 762 763 func (ta *testAPI) removeDirWhichHasSubDirs(t *testing.T) { 764 files := make(map[string]fileInfo) 765 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-upload") 766 testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-mount") 767 768 files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 769 files["two/three/2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 770 files["two/three/3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 771 files["two/four/5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 772 files["two/four/6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 773 files["two/four/six/7.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)} 774 775 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 776 777 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 778 defer swarmfs1.Stop() 779 780 dirPath := filepath.Join(testMountDir, "two") 781 os.RemoveAll(dirPath) 782 783 mi, err2 := swarmfs1.Unmount(testMountDir) 784 if err2 != nil { 785 t.Fatalf("Could not unmount %v ", err2) 786 } 787 788 // mount again and see if things are okay 789 delete(files, "two/three/2.txt") 790 delete(files, "two/three/3.txt") 791 delete(files, "two/four/5.txt") 792 delete(files, "two/four/6.txt") 793 delete(files, "two/four/six/7.txt") 794 795 mi.LatestManifestMu.RLock() 796 lm := mi.LatestManifest 797 mi.LatestManifestMu.RUnlock() 798 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 799 defer swarmfs2.Stop() 800 } 801 802 func (ta *testAPI) appendFileContentsToEnd(t *testing.T) { 803 files := make(map[string]fileInfo) 804 testUploadDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-upload") 805 testMountDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-mount") 806 807 line1 := make([]byte, 10) 808 rand.Read(line1) 809 files["1.txt"] = fileInfo{0700, 333, 444, line1} 810 bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir) 811 812 swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir) 813 defer swarmfs1.Stop() 814 815 actualPath := filepath.Join(testMountDir, "1.txt") 816 fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665)) 817 if err4 != nil { 818 t.Fatalf("Could not create file %s : %v", actualPath, err4) 819 } 820 line2 := make([]byte, 5) 821 rand.Read(line2) 822 fd.Seek(int64(len(line1)), 0) 823 fd.Write(line2) 824 fd.Close() 825 826 mi1, err5 := swarmfs1.Unmount(testMountDir) 827 if err5 != nil { 828 t.Fatalf("Could not unmount %v ", err5) 829 } 830 831 // mount again and see if things are okay 832 b := [][]byte{line1, line2} 833 line1and2 := bytes.Join(b, []byte("")) 834 files["1.txt"] = fileInfo{0700, 333, 444, line1and2} 835 mi1.LatestManifestMu.RLock() 836 lm := mi1.LatestManifest 837 mi1.LatestManifestMu.RUnlock() 838 swarmfs2 := mountDir(t, ta.api, files, lm, testMountDir) 839 defer swarmfs2.Stop() 840 841 checkFile(t, testMountDir, "1.txt", line1and2) 842 } 843 844 func TestFUSE(t *testing.T) { 845 datadir, err := ioutil.TempDir("", "fuse") 846 if err != nil { 847 t.Fatalf("unable to create temp dir: %v", err) 848 } 849 os.RemoveAll(datadir) 850 851 dpa, err := storage.NewLocalDPA(datadir) 852 if err != nil { 853 t.Fatal(err) 854 } 855 ta := &testAPI{api: api.NewApi(dpa, nil)} 856 dpa.Start() 857 defer dpa.Stop() 858 859 t.Run("mountListAndUmount", ta.mountListAndUnmount) 860 t.Run("maxMounts", ta.maxMounts) 861 t.Run("remount", ta.remount) 862 t.Run("unmount", ta.unmount) 863 t.Run("unmountWhenResourceBusy", ta.unmountWhenResourceBusy) 864 t.Run("seekInMultiChunkFile", ta.seekInMultiChunkFile) 865 t.Run("createNewFile", ta.createNewFile) 866 t.Run("createNewFileInsideDirectory", ta.createNewFileInsideDirectory) 867 t.Run("createNewFileInsideNewDirectory", ta.createNewFileInsideNewDirectory) 868 t.Run("removeExistingFile", ta.removeExistingFile) 869 t.Run("removeExistingFileInsideDir", ta.removeExistingFileInsideDir) 870 t.Run("removeNewlyAddedFile", ta.removeNewlyAddedFile) 871 t.Run("addNewFileAndModifyContents", ta.addNewFileAndModifyContents) 872 t.Run("removeEmptyDir", ta.removeEmptyDir) 873 t.Run("removeDirWhichHasFiles", ta.removeDirWhichHasFiles) 874 t.Run("removeDirWhichHasSubDirs", ta.removeDirWhichHasSubDirs) 875 t.Run("appendFileContentsToEnd", ta.appendFileContentsToEnd) 876 }