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