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