// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build linux darwin freebsd
package fuse
import (
"bytes"
"crypto/rand"
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/ethereum/go-ethereum/swarm/api"
"github.com/ethereum/go-ethereum/swarm/storage"
)
type fileInfo struct {
perm uint64
uid int
gid int
contents []byte
}
func createTestFilesAndUploadToSwarm(t *testing.T, api *api.Api, files map[string]fileInfo, uploadDir string) string {
os.RemoveAll(uploadDir)
for fname, finfo := range files {
actualPath := filepath.Join(uploadDir, fname)
filePath := filepath.Dir(actualPath)
err := os.MkdirAll(filePath, 0777)
if err != nil {
t.Fatalf("Error creating directory '%v' : %v", filePath, err)
}
fd, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(finfo.perm))
if err1 != nil {
t.Fatalf("Error creating file %v: %v", actualPath, err1)
}
fd.Write(finfo.contents)
fd.Chown(finfo.uid, finfo.gid)
fd.Chmod(os.FileMode(finfo.perm))
fd.Sync()
fd.Close()
}
bzzhash, err := api.Upload(uploadDir, "")
if err != nil {
t.Fatalf("Error uploading directory %v: %v", uploadDir, err)
}
return bzzhash
}
func mountDir(t *testing.T, api *api.Api, files map[string]fileInfo, bzzHash string, mountDir string) *SwarmFS {
os.RemoveAll(mountDir)
os.MkdirAll(mountDir, 0777)
swarmfs := NewSwarmFS(api)
_, err := swarmfs.Mount(bzzHash, mountDir)
if isFUSEUnsupportedError(err) {
t.Skip("FUSE not supported:", err)
} else if err != nil {
t.Fatalf("Error mounting hash %v: %v", bzzHash, err)
}
found := false
mi := swarmfs.Listmounts()
for _, minfo := range mi {
if minfo.MountPoint == mountDir {
if minfo.StartManifest != bzzHash ||
minfo.LatestManifest != bzzHash ||
minfo.fuseConnection == nil {
t.Fatalf("Error mounting: exp(%s): act(%s)", bzzHash, minfo.StartManifest)
}
found = true
}
}
// Test listMounts
if found == false {
t.Fatalf("Error getting mounts information for %v: %v", mountDir, err)
}
// Check if file and their attributes are as expected
compareGeneratedFileWithFileInMount(t, files, mountDir)
return swarmfs
}
func compareGeneratedFileWithFileInMount(t *testing.T, files map[string]fileInfo, mountDir string) {
err := filepath.Walk(mountDir, func(path string, f os.FileInfo, err error) error {
if f.IsDir() {
return nil
}
fname := path[len(mountDir)+1:]
if _, ok := files[fname]; !ok {
t.Fatalf(" file %v present in mount dir and is not expected", fname)
}
return nil
})
if err != nil {
t.Fatalf("Error walking dir %v", mountDir)
}
for fname, finfo := range files {
destinationFile := filepath.Join(mountDir, fname)
dfinfo, err := os.Stat(destinationFile)
if err != nil {
t.Fatalf("Destination file %v missing in mount: %v", fname, err)
}
if int64(len(finfo.contents)) != dfinfo.Size() {
t.Fatalf("file %v Size mismatch source (%v) vs destination(%v)", fname, int64(len(finfo.contents)), dfinfo.Size())
}
if dfinfo.Mode().Perm().String() != "-rwx------" {
t.Fatalf("file %v Permission mismatch source (-rwx------) vs destination(%v)", fname, dfinfo.Mode().Perm())
}
fileContents, err := ioutil.ReadFile(filepath.Join(mountDir, fname))
if err != nil {
t.Fatalf("Could not readfile %v : %v", fname, err)
}
if !bytes.Equal(fileContents, finfo.contents) {
t.Fatalf("File %v contents mismatch: %v , %v", fname, fileContents, finfo.contents)
}
// TODO: check uid and gid
}
}
func checkFile(t *testing.T, testMountDir, fname string, contents []byte) {
destinationFile := filepath.Join(testMountDir, fname)
dfinfo, err1 := os.Stat(destinationFile)
if err1 != nil {
t.Fatalf("Could not stat file %v", destinationFile)
}
if dfinfo.Size() != int64(len(contents)) {
t.Fatalf("Mismatch in size actual(%v) vs expected(%v)", dfinfo.Size(), int64(len(contents)))
}
fd, err2 := os.OpenFile(destinationFile, os.O_RDONLY, os.FileMode(0665))
if err2 != nil {
t.Fatalf("Could not open file %v", destinationFile)
}
newcontent := make([]byte, len(contents))
fd.Read(newcontent)
fd.Close()
if !bytes.Equal(contents, newcontent) {
t.Fatalf("File content mismatch expected (%v): received (%v) ", contents, newcontent)
}
}
func getRandomBtes(size int) []byte {
contents := make([]byte, size)
rand.Read(contents)
return contents
}
func isDirEmpty(name string) bool {
f, err := os.Open(name)
if err != nil {
return false
}
defer f.Close()
_, err = f.Readdirnames(1)
if err == io.EOF {
return true
}
return false
}
type testAPI struct {
api *api.Api
}
func (ta *testAPI) mountListAndUnmount(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "fuse-source")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "fuse-dest")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["2.txt"] = fileInfo{0711, 333, 444, getRandomBtes(10)}
files["3.txt"] = fileInfo{0622, 333, 444, getRandomBtes(100)}
files["4.txt"] = fileInfo{0533, 333, 444, getRandomBtes(1024)}
files["5.txt"] = fileInfo{0544, 333, 444, getRandomBtes(10)}
files["6.txt"] = fileInfo{0555, 333, 444, getRandomBtes(10)}
files["7.txt"] = fileInfo{0666, 333, 444, getRandomBtes(10)}
files["8.txt"] = fileInfo{0777, 333, 333, getRandomBtes(10)}
files["11.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
files["111.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
files["two/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
files["two/2/2.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
files["two/2./2.txt"] = fileInfo{0777, 444, 444, getRandomBtes(10)}
files["twice/2.txt"] = fileInfo{0777, 444, 333, getRandomBtes(200)}
files["one/two/three/four/five/six/seven/eight/nine/10.txt"] = fileInfo{0777, 333, 444, getRandomBtes(10240)}
files["one/two/three/four/five/six/six"] = fileInfo{0777, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs.Stop()
// Check unmount
_, err := swarmfs.Unmount(testMountDir)
if err != nil {
t.Fatalf("could not unmount %v", bzzHash)
}
if !isDirEmpty(testMountDir) {
t.Fatalf("unmount didnt work for %v", testMountDir)
}
}
func (ta *testAPI) maxMounts(t *testing.T) {
files := make(map[string]fileInfo)
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir1, _ := ioutil.TempDir(os.TempDir(), "max-upload1")
bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1)
mount1, _ := ioutil.TempDir(os.TempDir(), "max-mount1")
swarmfs1 := mountDir(t, ta.api, files, bzzHash1, mount1)
defer swarmfs1.Stop()
files["2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir2, _ := ioutil.TempDir(os.TempDir(), "max-upload2")
bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2)
mount2, _ := ioutil.TempDir(os.TempDir(), "max-mount2")
swarmfs2 := mountDir(t, ta.api, files, bzzHash2, mount2)
defer swarmfs2.Stop()
files["3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir3, _ := ioutil.TempDir(os.TempDir(), "max-upload3")
bzzHash3 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir3)
mount3, _ := ioutil.TempDir(os.TempDir(), "max-mount3")
swarmfs3 := mountDir(t, ta.api, files, bzzHash3, mount3)
defer swarmfs3.Stop()
files["4.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir4, _ := ioutil.TempDir(os.TempDir(), "max-upload4")
bzzHash4 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir4)
mount4, _ := ioutil.TempDir(os.TempDir(), "max-mount4")
swarmfs4 := mountDir(t, ta.api, files, bzzHash4, mount4)
defer swarmfs4.Stop()
files["5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir5, _ := ioutil.TempDir(os.TempDir(), "max-upload5")
bzzHash5 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir5)
mount5, _ := ioutil.TempDir(os.TempDir(), "max-mount5")
swarmfs5 := mountDir(t, ta.api, files, bzzHash5, mount5)
defer swarmfs5.Stop()
files["6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir6, _ := ioutil.TempDir(os.TempDir(), "max-upload6")
bzzHash6 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir6)
mount6, _ := ioutil.TempDir(os.TempDir(), "max-mount6")
os.RemoveAll(mount6)
os.MkdirAll(mount6, 0777)
_, err := swarmfs.Mount(bzzHash6, mount6)
if err == nil {
t.Fatalf("Error: Going beyond max mounts %v", bzzHash6)
}
}
func (ta *testAPI) remount(t *testing.T) {
files := make(map[string]fileInfo)
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
uploadDir1, _ := ioutil.TempDir(os.TempDir(), "re-upload1")
bzzHash1 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir1)
testMountDir1, _ := ioutil.TempDir(os.TempDir(), "re-mount1")
swarmfs := mountDir(t, ta.api, files, bzzHash1, testMountDir1)
defer swarmfs.Stop()
uploadDir2, _ := ioutil.TempDir(os.TempDir(), "re-upload2")
bzzHash2 := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir2)
testMountDir2, _ := ioutil.TempDir(os.TempDir(), "re-mount2")
// try mounting the same hash second time
os.RemoveAll(testMountDir2)
os.MkdirAll(testMountDir2, 0777)
_, err := swarmfs.Mount(bzzHash1, testMountDir2)
if err != nil {
t.Fatalf("Error mounting hash %v", bzzHash1)
}
// mount a different hash in already mounted point
_, err = swarmfs.Mount(bzzHash2, testMountDir1)
if err == nil {
t.Fatalf("Error mounting hash %v", bzzHash2)
}
// mount nonexistent hash
_, err = swarmfs.Mount("0xfea11223344", testMountDir1)
if err == nil {
t.Fatalf("Error mounting hash %v", bzzHash2)
}
}
func (ta *testAPI) unmount(t *testing.T) {
files := make(map[string]fileInfo)
uploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, uploadDir)
swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs.Stop()
swarmfs.Unmount(testMountDir)
mi := swarmfs.Listmounts()
for _, minfo := range mi {
if minfo.MountPoint == testMountDir {
t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir)
}
}
}
func (ta *testAPI) unmountWhenResourceBusy(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "ex-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "ex-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs.Stop()
actualPath := filepath.Join(testMountDir, "2.txt")
d, err := os.OpenFile(actualPath, os.O_RDWR, os.FileMode(0700))
d.Write(getRandomBtes(10))
_, err = swarmfs.Unmount(testMountDir)
if err != nil {
t.Fatalf("could not unmount %v", bzzHash)
}
d.Close()
mi := swarmfs.Listmounts()
for _, minfo := range mi {
if minfo.MountPoint == testMountDir {
t.Fatalf("mount state not cleaned up in unmount case %v", testMountDir)
}
}
}
func (ta *testAPI) seekInMultiChunkFile(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "seek-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "seek-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10240)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs.Stop()
// Create a new file seek the second chunk
actualPath := filepath.Join(testMountDir, "1.txt")
d, _ := os.OpenFile(actualPath, os.O_RDONLY, os.FileMode(0700))
d.Seek(5000, 0)
contents := make([]byte, 1024)
d.Read(contents)
finfo := files["1.txt"]
if bytes.Compare(finfo.contents[:6024][5000:], contents) != 0 {
t.Fatalf("File seek contents mismatch")
}
d.Close()
}
func (ta *testAPI) createNewFile(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "create-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "create-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Create a new file in the root dir and check
actualPath := filepath.Join(testMountDir, "2.txt")
d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
if err1 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err1)
}
contents := make([]byte, 11)
rand.Read(contents)
d.Write(contents)
d.Close()
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
files["2.txt"] = fileInfo{0700, 333, 444, contents}
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
checkFile(t, testMountDir, "2.txt", contents)
}
func (ta *testAPI) createNewFileInsideDirectory(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidedir-mount")
files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Create a new file inside a existing dir and check
dirToCreate := filepath.Join(testMountDir, "one")
actualPath := filepath.Join(dirToCreate, "2.txt")
d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
if err1 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err1)
}
contents := make([]byte, 11)
rand.Read(contents)
d.Write(contents)
d.Close()
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
files["one/2.txt"] = fileInfo{0700, 333, 444, contents}
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
checkFile(t, testMountDir, "one/2.txt", contents)
}
func (ta *testAPI) createNewFileInsideNewDirectory(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "createinsidenewdir-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Create a new file inside a existing dir and check
dirToCreate := filepath.Join(testMountDir, "one")
os.MkdirAll(dirToCreate, 0777)
actualPath := filepath.Join(dirToCreate, "2.txt")
d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
if err1 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err1)
}
contents := make([]byte, 11)
rand.Read(contents)
d.Write(contents)
d.Close()
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
files["one/2.txt"] = fileInfo{0700, 333, 444, contents}
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
checkFile(t, testMountDir, "one/2.txt", contents)
}
func (ta *testAPI) removeExistingFile(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Remove a file in the root dir and check
actualPath := filepath.Join(testMountDir, "five.txt")
os.Remove(actualPath)
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
delete(files, "five.txt")
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
}
func (ta *testAPI) removeExistingFileInsideDir(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "remove-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "remove-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["one/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["one/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Remove a file in the root dir and check
actualPath := filepath.Join(testMountDir, "one/five.txt")
os.Remove(actualPath)
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
delete(files, "one/five.txt")
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
}
func (ta *testAPI) removeNewlyAddedFile(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "removenew-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "removenew-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Adda a new file and remove it
dirToCreate := filepath.Join(testMountDir, "one")
os.MkdirAll(dirToCreate, os.FileMode(0665))
actualPath := filepath.Join(dirToCreate, "2.txt")
d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
if err1 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err1)
}
contents := make([]byte, 11)
rand.Read(contents)
d.Write(contents)
d.Close()
checkFile(t, testMountDir, "one/2.txt", contents)
os.Remove(actualPath)
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
if bzzHash != mi.LatestManifest {
t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, mi.LatestManifest)
}
}
func (ta *testAPI) addNewFileAndModifyContents(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "modifyfile-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
// Create a new file in the root dir and check
actualPath := filepath.Join(testMountDir, "2.txt")
d, err1 := os.OpenFile(actualPath, os.O_RDWR|os.O_CREATE, os.FileMode(0665))
if err1 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err1)
}
line1 := []byte("Line 1")
rand.Read(line1)
d.Write(line1)
d.Close()
mi1, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v", err2)
}
// mount again and see if things are okay
files["2.txt"] = fileInfo{0700, 333, 444, line1}
swarmfs2 := mountDir(t, ta.api, files, mi1.LatestManifest, testMountDir)
defer swarmfs2.Stop()
checkFile(t, testMountDir, "2.txt", line1)
mi2, err3 := swarmfs2.Unmount(testMountDir)
if err3 != nil {
t.Fatalf("Could not unmount %v", err3)
}
// mount again and modify
swarmfs3 := mountDir(t, ta.api, files, mi2.LatestManifest, testMountDir)
defer swarmfs3.Stop()
fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665))
if err4 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err4)
}
line2 := []byte("Line 2")
rand.Read(line2)
fd.Seek(int64(len(line1)), 0)
fd.Write(line2)
fd.Close()
mi3, err5 := swarmfs3.Unmount(testMountDir)
if err5 != nil {
t.Fatalf("Could not unmount %v", err5)
}
// mount again and see if things are okay
b := [][]byte{line1, line2}
line1and2 := bytes.Join(b, []byte(""))
files["2.txt"] = fileInfo{0700, 333, 444, line1and2}
swarmfs4 := mountDir(t, ta.api, files, mi3.LatestManifest, testMountDir)
defer swarmfs4.Stop()
checkFile(t, testMountDir, "2.txt", line1and2)
}
func (ta *testAPI) removeEmptyDir(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount")
files["1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
os.MkdirAll(filepath.Join(testMountDir, "newdir"), 0777)
mi, err3 := swarmfs1.Unmount(testMountDir)
if err3 != nil {
t.Fatalf("Could not unmount %v", err3)
}
if bzzHash != mi.LatestManifest {
t.Fatalf("same contents different hash orig(%v): new(%v)", bzzHash, mi.LatestManifest)
}
}
func (ta *testAPI) removeDirWhichHasFiles(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmdir-mount")
files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/five.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/six.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
dirPath := filepath.Join(testMountDir, "two")
os.RemoveAll(dirPath)
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v ", err2)
}
// mount again and see if things are okay
delete(files, "two/five.txt")
delete(files, "two/six.txt")
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
}
func (ta *testAPI) removeDirWhichHasSubDirs(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "rmsubdir-mount")
files["one/1.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/three/2.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/three/3.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/four/5.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/four/6.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
files["two/four/six/7.txt"] = fileInfo{0700, 333, 444, getRandomBtes(10)}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
dirPath := filepath.Join(testMountDir, "two")
os.RemoveAll(dirPath)
mi, err2 := swarmfs1.Unmount(testMountDir)
if err2 != nil {
t.Fatalf("Could not unmount %v ", err2)
}
// mount again and see if things are okay
delete(files, "two/three/2.txt")
delete(files, "two/three/3.txt")
delete(files, "two/four/5.txt")
delete(files, "two/four/6.txt")
delete(files, "two/four/six/7.txt")
swarmfs2 := mountDir(t, ta.api, files, mi.LatestManifest, testMountDir)
defer swarmfs2.Stop()
}
func (ta *testAPI) appendFileContentsToEnd(t *testing.T) {
files := make(map[string]fileInfo)
testUploadDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-upload")
testMountDir, _ := ioutil.TempDir(os.TempDir(), "appendlargefile-mount")
line1 := make([]byte, 10)
rand.Read(line1)
files["1.txt"] = fileInfo{0700, 333, 444, line1}
bzzHash := createTestFilesAndUploadToSwarm(t, ta.api, files, testUploadDir)
swarmfs1 := mountDir(t, ta.api, files, bzzHash, testMountDir)
defer swarmfs1.Stop()
actualPath := filepath.Join(testMountDir, "1.txt")
fd, err4 := os.OpenFile(actualPath, os.O_RDWR|os.O_APPEND, os.FileMode(0665))
if err4 != nil {
t.Fatalf("Could not create file %s : %v", actualPath, err4)
}
line2 := make([]byte, 5)
rand.Read(line2)
fd.Seek(int64(len(line1)), 0)
fd.Write(line2)
fd.Close()
mi1, err5 := swarmfs1.Unmount(testMountDir)
if err5 != nil {
t.Fatalf("Could not unmount %v ", err5)
}
// mount again and see if things are okay
b := [][]byte{line1, line2}
line1and2 := bytes.Join(b, []byte(""))
files["1.txt"] = fileInfo{0700, 333, 444, line1and2}
swarmfs2 := mountDir(t, ta.api, files, mi1.LatestManifest, testMountDir)
defer swarmfs2.Stop()
checkFile(t, testMountDir, "1.txt", line1and2)
}
func TestFUSE(t *testing.T) {
datadir, err := ioutil.TempDir("", "fuse")
if err != nil {
t.Fatalf("unable to create temp dir: %v", err)
}
os.RemoveAll(datadir)
dpa, err := storage.NewLocalDPA(datadir)
if err != nil {
t.Fatal(err)
}
ta := &testAPI{api: api.NewApi(dpa, nil)}
dpa.Start()
defer dpa.Stop()
t.Run("mountListAndUmount", ta.mountListAndUnmount)
t.Run("maxMounts", ta.maxMounts)
t.Run("remount", ta.remount)
t.Run("unmount", ta.unmount)
t.Run("unmountWhenResourceBusy", ta.unmountWhenResourceBusy)
t.Run("seekInMultiChunkFile", ta.seekInMultiChunkFile)
t.Run("createNewFile", ta.createNewFile)
t.Run("createNewFileInsideDirectory", ta.createNewFileInsideDirectory)
t.Run("createNewFileInsideNewDirectory", ta.createNewFileInsideNewDirectory)
t.Run("removeExistingFile", ta.removeExistingFile)
t.Run("removeExistingFileInsideDir", ta.removeExistingFileInsideDir)
t.Run("removeNewlyAddedFile", ta.removeNewlyAddedFile)
t.Run("addNewFileAndModifyContents", ta.addNewFileAndModifyContents)
t.Run("removeEmptyDir", ta.removeEmptyDir)
t.Run("removeDirWhichHasFiles", ta.removeDirWhichHasFiles)
t.Run("removeDirWhichHasSubDirs", ta.removeDirWhichHasSubDirs)
t.Run("appendFileContentsToEnd", ta.appendFileContentsToEnd)
}