gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/files_test.go (about)

     1  package renter
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"gitlab.com/NebulousLabs/fastrand"
    12  	"gitlab.com/SiaPrime/writeaheadlog"
    13  
    14  	"gitlab.com/SiaPrime/SiaPrime/crypto"
    15  	"gitlab.com/SiaPrime/SiaPrime/modules"
    16  	"gitlab.com/SiaPrime/SiaPrime/modules/renter/siafile"
    17  )
    18  
    19  // newTestingWal is a helper method to create a wal during testing.
    20  func newTestingWal() *writeaheadlog.WAL {
    21  	walDir := filepath.Join(os.TempDir(), "wals")
    22  	if err := os.MkdirAll(walDir, 0700); err != nil {
    23  		panic(err)
    24  	}
    25  	walPath := filepath.Join(walDir, hex.EncodeToString(fastrand.Bytes(8)))
    26  	_, wal, err := writeaheadlog.New(walPath)
    27  	if err != nil {
    28  		panic(err)
    29  	}
    30  	return wal
    31  }
    32  
    33  // newRenterTestFile creates a test file when the test has a renter so that the
    34  // file is properly added to the renter. It returns the SiaFileSetEntry that the
    35  // SiaFile is stored in
    36  func (r *Renter) newRenterTestFile() (*siafile.SiaFileSetEntry, error) {
    37  	// Generate name and erasure coding
    38  	siaPath, rsc := testingFileParams()
    39  	// create the renter/files dir if it doesn't exist
    40  	siaFilePath := siaPath.SiaFileSysPath(r.staticFilesDir)
    41  	dir, _ := filepath.Split(siaFilePath)
    42  	if err := os.MkdirAll(dir, 0700); err != nil {
    43  		return nil, err
    44  	}
    45  	// Create File
    46  	up := modules.FileUploadParams{
    47  		Source:      "",
    48  		SiaPath:     siaPath,
    49  		ErasureCode: rsc,
    50  	}
    51  	entry, err := r.staticFileSet.NewSiaFile(up, crypto.GenerateSiaKey(crypto.RandomCipherType()), 1000, 0777)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	return entry, nil
    56  }
    57  
    58  // TestRenterFileListLocalPath verifies that FileList() returns the correct
    59  // local path information for an uploaded file.
    60  func TestRenterFileListLocalPath(t *testing.T) {
    61  	if testing.Short() {
    62  		t.SkipNow()
    63  	}
    64  	rt, err := newRenterTester(t.Name())
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	defer rt.Close()
    69  	id := rt.renter.mu.Lock()
    70  	entry, _ := rt.renter.newRenterTestFile()
    71  	if err := entry.SetLocalPath("TestPath"); err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	rt.renter.mu.Unlock(id)
    75  	files, err := rt.renter.FileList(modules.RootSiaPath(), true, false)
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	if len(files) != 1 {
    80  		t.Fatal("wrong number of files, got", len(files), "wanted one")
    81  	}
    82  	if files[0].LocalPath != "TestPath" {
    83  		t.Fatal("file had wrong LocalPath: got", files[0].LocalPath, "wanted TestPath")
    84  	}
    85  }
    86  
    87  // TestRenterDeleteFile probes the DeleteFile method of the renter type.
    88  func TestRenterDeleteFile(t *testing.T) {
    89  	if testing.Short() {
    90  		t.SkipNow()
    91  	}
    92  	rt, err := newRenterTester(t.Name())
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  	defer rt.Close()
    97  
    98  	// Delete a file from an empty renter.
    99  	siaPath, err := modules.NewSiaPath("dne")
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	err = rt.renter.DeleteFile(siaPath)
   104  	if err != siafile.ErrUnknownPath {
   105  		t.Errorf("Expected '%v' got '%v'", siafile.ErrUnknownPath, err)
   106  	}
   107  
   108  	// Put a file in the renter.
   109  	entry, err := rt.renter.newRenterTestFile()
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	// Delete a different file.
   114  	siaPathOne, err := modules.NewSiaPath("one")
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	err = rt.renter.DeleteFile(siaPathOne)
   119  	if err != siafile.ErrUnknownPath {
   120  		t.Errorf("Expected '%v' got '%v'", siafile.ErrUnknownPath, err)
   121  	}
   122  	// Delete the file.
   123  	siapath := rt.renter.staticFileSet.SiaPath(entry)
   124  	err = entry.Close()
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	err = rt.renter.DeleteFile(siapath)
   129  	if err != nil {
   130  		t.Error(err)
   131  	}
   132  	files, err := rt.renter.FileList(modules.RootSiaPath(), true, false)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	if len(files) != 0 {
   137  		t.Error("file was deleted, but is still reported in FileList")
   138  	}
   139  	// Confirm that file was removed from SiaFileSet
   140  	_, err = rt.renter.staticFileSet.Open(siapath)
   141  	if err == nil {
   142  		t.Fatal("Deleted file still found in staticFileSet")
   143  	}
   144  
   145  	// Put a file in the renter, then rename it.
   146  	entry2, err := rt.renter.newRenterTestFile()
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	siaPath1, err := modules.NewSiaPath("1")
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	err = rt.renter.RenameFile(rt.renter.staticFileSet.SiaPath(entry2), siaPath1) // set name to "1"
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	siapath2 := rt.renter.staticFileSet.SiaPath(entry2)
   159  	err = entry2.Close()
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	err = rt.renter.RenameFile(siapath2, siaPathOne)
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  	// Call delete on the previous name.
   168  	err = rt.renter.DeleteFile(siaPath1)
   169  	if err != siafile.ErrUnknownPath {
   170  		t.Errorf("Expected '%v' got '%v'", siafile.ErrUnknownPath, err)
   171  	}
   172  	// Call delete on the new name.
   173  	err = rt.renter.DeleteFile(siaPathOne)
   174  	if err != nil {
   175  		t.Error(err)
   176  	}
   177  
   178  	// Check that all .sia files have been deleted.
   179  	var walkStr string
   180  	filepath.Walk(rt.renter.staticFilesDir, func(path string, _ os.FileInfo, _ error) error {
   181  		// capture only .sia files
   182  		if filepath.Ext(path) == ".sia" {
   183  			rel, _ := filepath.Rel(rt.renter.staticFilesDir, path) // strip testdir prefix
   184  			walkStr += rel
   185  		}
   186  		return nil
   187  	})
   188  	expWalkStr := ""
   189  	if walkStr != expWalkStr {
   190  		t.Fatalf("Bad walk string: expected %q, got %q", expWalkStr, walkStr)
   191  	}
   192  }
   193  
   194  // TestRenterFileList probes the FileList method of the renter type.
   195  func TestRenterFileList(t *testing.T) {
   196  	if testing.Short() {
   197  		t.SkipNow()
   198  	}
   199  	rt, err := newRenterTester(t.Name())
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	defer rt.Close()
   204  
   205  	// Get the file list of an empty renter.
   206  	files, err := rt.renter.FileList(modules.RootSiaPath(), true, false)
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  	if len(files) != 0 {
   211  		t.Fatal("FileList has non-zero length for empty renter?")
   212  	}
   213  
   214  	// Put a file in the renter.
   215  	entry1, _ := rt.renter.newRenterTestFile()
   216  	files, err = rt.renter.FileList(modules.RootSiaPath(), true, false)
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if len(files) != 1 {
   221  		t.Fatal("FileList is not returning the only file in the renter")
   222  	}
   223  	if !files[0].SiaPath.Equals(rt.renter.staticFileSet.SiaPath(entry1)) {
   224  		t.Error("FileList is not returning the correct filename for the only file")
   225  	}
   226  
   227  	// Put multiple files in the renter.
   228  	entry2, _ := rt.renter.newRenterTestFile()
   229  	files, err = rt.renter.FileList(modules.RootSiaPath(), true, false)
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	if len(files) != 2 {
   234  		t.Fatalf("Expected %v files, got %v", 2, len(files))
   235  	}
   236  	files, err = rt.renter.FileList(modules.RootSiaPath(), true, false)
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  	if !((files[0].SiaPath.Equals(rt.renter.staticFileSet.SiaPath(entry1)) || files[0].SiaPath.Equals(rt.renter.staticFileSet.SiaPath(entry2))) &&
   241  		(files[1].SiaPath.Equals(rt.renter.staticFileSet.SiaPath(entry1)) || files[1].SiaPath.Equals(rt.renter.staticFileSet.SiaPath(entry2))) &&
   242  		(files[0].SiaPath != files[1].SiaPath)) {
   243  		t.Log("files[0].SiaPath", files[0].SiaPath)
   244  		t.Log("files[1].SiaPath", files[1].SiaPath)
   245  		t.Log("file1.SiaPath()", rt.renter.staticFileSet.SiaPath(entry1).String())
   246  		t.Log("file2.SiaPath()", rt.renter.staticFileSet.SiaPath(entry2).String())
   247  		t.Error("FileList is returning wrong names for the files")
   248  	}
   249  }
   250  
   251  // TestRenterRenameFile probes the rename method of the renter.
   252  func TestRenterRenameFile(t *testing.T) {
   253  	if testing.Short() {
   254  		t.SkipNow()
   255  	}
   256  	rt, err := newRenterTester(t.Name())
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	defer rt.Close()
   261  
   262  	// Rename a file that doesn't exist.
   263  	siaPath1, err := modules.NewSiaPath("1")
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	siaPath1a, err := modules.NewSiaPath("1a")
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	err = rt.renter.RenameFile(siaPath1, siaPath1a)
   272  	if err.Error() != siafile.ErrUnknownPath.Error() {
   273  		t.Errorf("Expected '%v' got '%v'", siafile.ErrUnknownPath, err)
   274  	}
   275  
   276  	// Get the fileset.
   277  	sfs := rt.renter.staticFileSet
   278  
   279  	// Rename a file that does exist.
   280  	entry, _ := rt.renter.newRenterTestFile()
   281  	err = rt.renter.RenameFile(sfs.SiaPath(entry), siaPath1)
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  	err = rt.renter.RenameFile(siaPath1, siaPath1a)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  	files, err := rt.renter.FileList(modules.RootSiaPath(), true, false)
   290  	if err != nil {
   291  		t.Fatal(err)
   292  	}
   293  	if len(files) != 1 {
   294  		t.Fatal("FileList has unexpected number of files:", len(files))
   295  	}
   296  	if !files[0].SiaPath.Equals(siaPath1a) {
   297  		t.Errorf("RenameFile failed: expected %v, got %v", siaPath1a.String(), files[0].SiaPath)
   298  	}
   299  	// Confirm SiaFileSet was updated
   300  	_, err = rt.renter.staticFileSet.Open(siaPath1a)
   301  	if err != nil {
   302  		t.Fatal("renter staticFileSet not updated to new file name")
   303  	}
   304  	_, err = rt.renter.staticFileSet.Open(siaPath1)
   305  	if err == nil {
   306  		t.Fatal("old name not removed from renter staticFileSet")
   307  	}
   308  
   309  	// Rename a file to an existing name.
   310  	entry2, err := rt.renter.newRenterTestFile()
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	err = rt.renter.RenameFile(rt.renter.staticFileSet.SiaPath(entry2), siaPath1) // Rename to "1"
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	err = entry2.Close()
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  	err = rt.renter.RenameFile(siaPath1, siaPath1a)
   323  	if err != siafile.ErrPathOverload {
   324  		t.Error("Expecting ErrPathOverload, got", err)
   325  	}
   326  
   327  	// Rename a file to the same name.
   328  	err = rt.renter.RenameFile(siaPath1, siaPath1)
   329  	if err != siafile.ErrPathOverload {
   330  		t.Error("Expecting ErrPathOverload, got", err)
   331  	}
   332  
   333  	// Confirm ability to rename file
   334  	siaPath1b, err := modules.NewSiaPath("1b")
   335  	if err != nil {
   336  		t.Fatal(err)
   337  	}
   338  	err = rt.renter.RenameFile(siaPath1, siaPath1b)
   339  	if err != nil {
   340  		t.Fatal(err)
   341  	}
   342  
   343  	// Rename file that would create a directory
   344  	siaPathWithDir, err := modules.NewSiaPath("new/name/with/dir/test")
   345  	if err != nil {
   346  		t.Fatal(err)
   347  	}
   348  	err = rt.renter.RenameFile(siaPath1b, siaPathWithDir)
   349  	if err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	// Confirm directory metadatas exist
   354  	dirSiaPath := siaPathWithDir
   355  	for !dirSiaPath.Equals(modules.RootSiaPath()) {
   356  		dirSiaPath, err = dirSiaPath.Dir()
   357  		if err != nil {
   358  			t.Fatal(err)
   359  		}
   360  		_, err = rt.renter.staticDirSet.Open(dirSiaPath)
   361  		if err != nil {
   362  			t.Fatal(err)
   363  		}
   364  	}
   365  }
   366  
   367  // TestRenterFileDir tests that the renter files are uploaded to the files
   368  // directory and not the root directory of the renter.
   369  func TestRenterFileDir(t *testing.T) {
   370  	if testing.Short() {
   371  		t.SkipNow()
   372  	}
   373  	rt, err := newRenterTester(t.Name())
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  	defer rt.Close()
   378  
   379  	// Create local file to upload
   380  	localDir := filepath.Join(rt.dir, "files")
   381  	if err := os.MkdirAll(localDir, 0700); err != nil {
   382  		t.Fatal(err)
   383  	}
   384  	size := 100
   385  	fileName := fmt.Sprintf("%dbytes %s", size, hex.EncodeToString(fastrand.Bytes(4)))
   386  	source := filepath.Join(localDir, fileName)
   387  	bytes := fastrand.Bytes(size)
   388  	if err := ioutil.WriteFile(source, bytes, 0600); err != nil {
   389  		t.Fatal(err)
   390  	}
   391  
   392  	// Upload local file
   393  	ec, err := siafile.NewRSCode(defaultDataPieces, defaultParityPieces)
   394  	if err != nil {
   395  		t.Fatal(err)
   396  	}
   397  	siaPath, err := modules.NewSiaPath(fileName)
   398  	if err != nil {
   399  		t.Fatal(err)
   400  	}
   401  	params := modules.FileUploadParams{
   402  		Source:      source,
   403  		SiaPath:     siaPath,
   404  		ErasureCode: ec,
   405  	}
   406  	err = rt.renter.Upload(params)
   407  	if err != nil {
   408  		t.Fatal("failed to upload file:", err)
   409  	}
   410  
   411  	// Get file and check siapath
   412  	f, err := rt.renter.File(siaPath)
   413  	if err != nil {
   414  		t.Fatal(err)
   415  	}
   416  	if !f.SiaPath.Equals(siaPath) {
   417  		t.Fatalf("siapath not set as expected: got %v expected %v", f.SiaPath, fileName)
   418  	}
   419  
   420  	// Confirm .sia file exists on disk in the SiapathRoot directory
   421  	renterDir := filepath.Join(rt.dir, modules.RenterDir)
   422  	siapathRootDir := filepath.Join(renterDir, modules.SiapathRoot)
   423  	fullPath := siaPath.SiaFileSysPath(siapathRootDir)
   424  	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
   425  		t.Fatal("No .sia file found on disk")
   426  	}
   427  }