github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/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-wtc 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-wtc 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/wtc/go-wtc/swarm/api"
    31  	"github.com/wtc/go-wtc/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  }