github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/swarm/fuse/swarmfs_test.go (about)

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