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