github.com/NebulousLabs/Sia@v1.3.7/modules/renter/persist_test.go (about) 1 package renter 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strconv" 9 "testing" 10 11 "github.com/NebulousLabs/Sia/build" 12 "github.com/NebulousLabs/Sia/crypto" 13 "github.com/NebulousLabs/Sia/encoding" 14 "github.com/NebulousLabs/Sia/modules" 15 "github.com/NebulousLabs/Sia/persist" 16 17 "github.com/NebulousLabs/fastrand" 18 ) 19 20 // newTestingFile initializes a file object with random parameters. 21 func newTestingFile() *file { 22 data := fastrand.Bytes(8) 23 nData := fastrand.Intn(10) 24 nParity := fastrand.Intn(10) 25 rsc, _ := NewRSCode(nData+1, nParity+1) 26 27 return &file{ 28 name: "testfile-" + strconv.Itoa(int(data[0])), 29 size: encoding.DecUint64(data[1:5]), 30 masterKey: crypto.GenerateTwofishKey(), 31 erasureCode: rsc, 32 pieceSize: encoding.DecUint64(data[6:8]), 33 staticUID: persist.RandomSuffix(), 34 } 35 } 36 37 // equalFiles is a helper function that compares two files for equality. 38 func equalFiles(f1, f2 *file) error { 39 if f1 == nil || f2 == nil { 40 return fmt.Errorf("one or both files are nil") 41 } 42 if f1.name != f2.name { 43 return fmt.Errorf("names do not match: %v %v", f1.name, f2.name) 44 } 45 if f1.size != f2.size { 46 return fmt.Errorf("sizes do not match: %v %v", f1.size, f2.size) 47 } 48 if f1.masterKey != f2.masterKey { 49 return fmt.Errorf("keys do not match: %v %v", f1.masterKey, f2.masterKey) 50 } 51 if f1.pieceSize != f2.pieceSize { 52 return fmt.Errorf("pieceSizes do not match: %v %v", f1.pieceSize, f2.pieceSize) 53 } 54 return nil 55 } 56 57 // TestFileMarshalling tests the MarshalSia and UnmarshalSia functions of the 58 // file type. 59 func TestFileMarshalling(t *testing.T) { 60 savedFile := newTestingFile() 61 buf := new(bytes.Buffer) 62 savedFile.MarshalSia(buf) 63 64 loadedFile := new(file) 65 err := loadedFile.UnmarshalSia(buf) 66 if err != nil { 67 t.Fatal(err) 68 } 69 70 err = equalFiles(savedFile, loadedFile) 71 if err != nil { 72 t.Fatal(err) 73 } 74 } 75 76 // TestFileShareLoad tests the sharing/loading functions of the renter. 77 func TestFileShareLoad(t *testing.T) { 78 if testing.Short() { 79 t.SkipNow() 80 } 81 rt, err := newRenterTester(t.Name()) 82 if err != nil { 83 t.Fatal(err) 84 } 85 defer rt.Close() 86 87 // Create a file and add it to the renter. 88 savedFile := newTestingFile() 89 id := rt.renter.mu.Lock() 90 rt.renter.files[savedFile.name] = savedFile 91 rt.renter.mu.Unlock(id) 92 93 // Share .sia file to disk. 94 path := filepath.Join(build.SiaTestingDir, "renter", t.Name(), "test.sia") 95 err = rt.renter.ShareFiles([]string{savedFile.name}, path) 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 // Remove the file from the renter. 101 delete(rt.renter.files, savedFile.name) 102 103 // Load the .sia file back into the renter. 104 names, err := rt.renter.LoadSharedFiles(path) 105 if err != nil { 106 t.Fatal(err) 107 } 108 if len(names) != 1 || names[0] != savedFile.name { 109 t.Fatal("nickname not loaded properly:", names) 110 } 111 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 // Share and load multiple files. 117 savedFile2 := newTestingFile() 118 rt.renter.files[savedFile2.name] = savedFile2 119 path = filepath.Join(build.SiaTestingDir, "renter", t.Name(), "test2.sia") 120 err = rt.renter.ShareFiles([]string{savedFile.name, savedFile2.name}, path) 121 if err != nil { 122 t.Fatal(err) 123 } 124 125 // Remove the files from the renter. 126 delete(rt.renter.files, savedFile.name) 127 delete(rt.renter.files, savedFile2.name) 128 129 names, err = rt.renter.LoadSharedFiles(path) 130 if err != nil { 131 t.Fatal(nil) 132 } 133 if len(names) != 2 || (names[0] != savedFile2.name && names[1] != savedFile2.name) { 134 t.Fatal("nicknames not loaded properly:", names) 135 } 136 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 137 if err != nil { 138 t.Fatal(err) 139 } 140 err = equalFiles(rt.renter.files[savedFile2.name], savedFile2) 141 if err != nil { 142 t.Fatal(err) 143 } 144 } 145 146 // TestFileShareLoadASCII tests the ASCII sharing/loading functions. 147 func TestFileShareLoadASCII(t *testing.T) { 148 if testing.Short() { 149 t.SkipNow() 150 } 151 rt, err := newRenterTester(t.Name()) 152 if err != nil { 153 t.Fatal(err) 154 } 155 defer rt.Close() 156 157 // Create a file and add it to the renter. 158 savedFile := newTestingFile() 159 id := rt.renter.mu.Lock() 160 rt.renter.files[savedFile.name] = savedFile 161 rt.renter.mu.Unlock(id) 162 163 ascii, err := rt.renter.ShareFilesASCII([]string{savedFile.name}) 164 if err != nil { 165 t.Fatal(err) 166 } 167 168 // Remove the file from the renter. 169 delete(rt.renter.files, savedFile.name) 170 171 names, err := rt.renter.LoadSharedFilesASCII(ascii) 172 if err != nil { 173 t.Fatal(err) 174 } 175 if len(names) != 1 || names[0] != savedFile.name { 176 t.Fatal("nickname not loaded properly") 177 } 178 179 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 180 if err != nil { 181 t.Fatal(err) 182 } 183 } 184 185 // TestRenterSaveLoad probes the save and load methods of the renter type. 186 func TestRenterSaveLoad(t *testing.T) { 187 if testing.Short() { 188 t.SkipNow() 189 } 190 rt, err := newRenterTester(t.Name()) 191 if err != nil { 192 t.Fatal(err) 193 } 194 defer rt.Close() 195 196 // Check that the default values got set correctly. 197 settings := rt.renter.Settings() 198 if settings.MaxDownloadSpeed != DefaultMaxDownloadSpeed { 199 t.Error("default max download speed not set at init") 200 } 201 if settings.MaxUploadSpeed != DefaultMaxUploadSpeed { 202 t.Error("default max upload speed not set at init") 203 } 204 if settings.StreamCacheSize != DefaultStreamCacheSize { 205 t.Error("default stream cache size not set at init") 206 } 207 208 // Create and save some files 209 var f1, f2, f3 *file 210 f1 = newTestingFile() 211 f2 = newTestingFile() 212 f3 = newTestingFile() 213 // names must not conflict 214 for f2.name == f1.name || f2.name == f3.name { 215 f2 = newTestingFile() 216 } 217 for f3.name == f1.name || f3.name == f2.name { 218 f3 = newTestingFile() 219 } 220 rt.renter.saveFile(f1) 221 rt.renter.saveFile(f2) 222 rt.renter.saveFile(f3) 223 224 // Update the settings of the renter to have a new stream cache size and 225 // download speed. 226 newDownSpeed := int64(300e3) 227 newUpSpeed := int64(500e3) 228 newCacheSize := uint64(3) 229 settings.MaxDownloadSpeed = newDownSpeed 230 settings.MaxUploadSpeed = newUpSpeed 231 settings.StreamCacheSize = newCacheSize 232 rt.renter.SetSettings(settings) 233 234 err = rt.renter.saveSync() // save metadata 235 if err != nil { 236 t.Fatal(err) 237 } 238 err = rt.renter.Close() 239 if err != nil { 240 t.Fatal(err) 241 } 242 243 // load should now load the files into memory. 244 rt.renter, err = New(rt.gateway, rt.cs, rt.wallet, rt.tpool, filepath.Join(rt.dir, modules.RenterDir)) 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil { 250 t.Fatal(err) 251 } 252 if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil { 253 t.Fatal(err) 254 } 255 if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil { 256 t.Fatal(err) 257 } 258 259 newSettings := rt.renter.Settings() 260 if newSettings.MaxDownloadSpeed != newDownSpeed { 261 t.Error("download settings not being persisted correctly") 262 } 263 if newSettings.MaxUploadSpeed != newUpSpeed { 264 t.Error("upload settings not being persisted correctly") 265 } 266 if newSettings.StreamCacheSize != newCacheSize { 267 t.Error("cache settings not being persisted correctly") 268 } 269 } 270 271 // TestRenterPaths checks that the renter properly handles nicknames 272 // containing the path separator ("/"). 273 func TestRenterPaths(t *testing.T) { 274 if testing.Short() { 275 t.SkipNow() 276 } 277 rt, err := newRenterTester(t.Name()) 278 if err != nil { 279 t.Fatal(err) 280 } 281 defer rt.Close() 282 283 // Create and save some files. 284 // The result of saving these files should be a directory containing: 285 // foo.sia 286 // foo/bar.sia 287 // foo/bar/baz.sia 288 f1 := newTestingFile() 289 f1.name = "foo" 290 f2 := newTestingFile() 291 f2.name = "foo/bar" 292 f3 := newTestingFile() 293 f3.name = "foo/bar/baz" 294 rt.renter.saveFile(f1) 295 rt.renter.saveFile(f2) 296 rt.renter.saveFile(f3) 297 298 // Restart the renter to re-do the init cycle. 299 err = rt.renter.Close() 300 if err != nil { 301 t.Fatal(err) 302 } 303 rt.renter, err = New(rt.gateway, rt.cs, rt.wallet, rt.tpool, filepath.Join(rt.dir, modules.RenterDir)) 304 if err != nil { 305 t.Fatal(err) 306 } 307 308 // Check that the files were loaded properly. 309 if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil { 310 t.Fatal(err) 311 } 312 if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil { 313 t.Fatal(err) 314 } 315 if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil { 316 t.Fatal(err) 317 } 318 319 // To confirm that the file structure was preserved, we walk the renter 320 // folder and emit the name of each .sia file encountered (filepath.Walk 321 // is deterministic; it orders the files lexically). 322 var walkStr string 323 filepath.Walk(rt.renter.persistDir, func(path string, _ os.FileInfo, _ error) error { 324 // capture only .sia files 325 if filepath.Ext(path) != ".sia" { 326 return nil 327 } 328 rel, _ := filepath.Rel(rt.renter.persistDir, path) // strip testdir prefix 329 walkStr += rel 330 return nil 331 }) 332 // walk will descend into foo/bar/, reading baz, bar, and finally foo 333 expWalkStr := (f3.name + ".sia") + (f2.name + ".sia") + (f1.name + ".sia") 334 if filepath.ToSlash(walkStr) != expWalkStr { 335 t.Fatalf("Bad walk string: expected %v, got %v", expWalkStr, walkStr) 336 } 337 } 338 339 // TestSiafileCompatibility tests that the renter is able to load v0.4.8 .sia files. 340 func TestSiafileCompatibility(t *testing.T) { 341 if testing.Short() { 342 t.SkipNow() 343 } 344 rt, err := newRenterTester(t.Name()) 345 if err != nil { 346 t.Fatal(err) 347 } 348 defer rt.Close() 349 350 // Load the compatibility file into the renter. 351 path := filepath.Join("..", "..", "compatibility", "siafile_v0.4.8.sia") 352 names, err := rt.renter.LoadSharedFiles(path) 353 if err != nil { 354 t.Fatal(err) 355 } 356 if len(names) != 1 || names[0] != "testfile-183" { 357 t.Fatal("nickname not loaded properly:", names) 358 } 359 }