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 }