github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/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 ) 15 16 // newTestingFile initializes a file object with random parameters. 17 func newTestingFile() *file { 18 key, _ := crypto.GenerateTwofishKey() 19 data, _ := crypto.RandBytes(8) 20 nData, _ := crypto.RandIntn(10) 21 nParity, _ := crypto.RandIntn(10) 22 rsc, _ := NewRSCode(nData+1, nParity+1) 23 24 return &file{ 25 name: "testfile-" + strconv.Itoa(int(data[0])), 26 size: encoding.DecUint64(data[1:5]), 27 masterKey: key, 28 erasureCode: rsc, 29 pieceSize: encoding.DecUint64(data[6:8]), 30 } 31 } 32 33 // equalFiles is a helper function that compares two files for equality. 34 func equalFiles(f1, f2 *file) error { 35 if f1 == nil || f2 == nil { 36 return fmt.Errorf("one or both files are nil") 37 } 38 if f1.name != f2.name { 39 return fmt.Errorf("names do not match: %v %v", f1.name, f2.name) 40 } 41 if f1.size != f2.size { 42 return fmt.Errorf("sizes do not match: %v %v", f1.size, f2.size) 43 } 44 if f1.masterKey != f2.masterKey { 45 return fmt.Errorf("keys do not match: %v %v", f1.masterKey, f2.masterKey) 46 } 47 if f1.pieceSize != f2.pieceSize { 48 return fmt.Errorf("pieceSizes do not match: %v %v", f1.pieceSize, f2.pieceSize) 49 } 50 return nil 51 } 52 53 // TestFileMarshalling tests the MarshalSia and UnmarshalSia functions of the 54 // file type. 55 func TestFileMarshalling(t *testing.T) { 56 savedFile := newTestingFile() 57 buf := new(bytes.Buffer) 58 savedFile.MarshalSia(buf) 59 60 loadedFile := new(file) 61 err := loadedFile.UnmarshalSia(buf) 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 err = equalFiles(savedFile, loadedFile) 67 if err != nil { 68 t.Fatal(err) 69 } 70 } 71 72 // TestFileShareLoad tests the sharing/loading functions of the renter. 73 func TestFileShareLoad(t *testing.T) { 74 if testing.Short() { 75 t.SkipNow() 76 } 77 rt, err := newRenterTester("TestRenterShareLoad") 78 if err != nil { 79 t.Fatal(err) 80 } 81 defer rt.Close() 82 83 // Create a file and add it to the renter. 84 savedFile := newTestingFile() 85 rt.renter.files[savedFile.name] = savedFile 86 87 // Share .sia file to disk. 88 path := filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test.sia") 89 err = rt.renter.ShareFiles([]string{savedFile.name}, path) 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 // Remove the file from the renter. 95 delete(rt.renter.files, savedFile.name) 96 97 // Load the .sia file back into the renter. 98 names, err := rt.renter.LoadSharedFiles(path) 99 if err != nil { 100 t.Fatal(err) 101 } 102 if len(names) != 1 || names[0] != savedFile.name { 103 t.Fatal("nickname not loaded properly:", names) 104 } 105 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 106 if err != nil { 107 t.Fatal(err) 108 } 109 110 // Share and load multiple files. 111 savedFile2 := newTestingFile() 112 rt.renter.files[savedFile2.name] = savedFile2 113 path = filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test2.sia") 114 err = rt.renter.ShareFiles([]string{savedFile.name, savedFile2.name}, path) 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 // Remove the files from the renter. 120 delete(rt.renter.files, savedFile.name) 121 delete(rt.renter.files, savedFile2.name) 122 123 names, err = rt.renter.LoadSharedFiles(path) 124 if err != nil { 125 t.Fatal(nil) 126 } 127 if len(names) != 2 || (names[0] != savedFile2.name && names[1] != savedFile2.name) { 128 t.Fatal("nicknames not loaded properly:", names) 129 } 130 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 131 if err != nil { 132 t.Fatal(err) 133 } 134 err = equalFiles(rt.renter.files[savedFile2.name], savedFile2) 135 if err != nil { 136 t.Fatal(err) 137 } 138 } 139 140 // TestFileShareLoadASCII tests the ASCII sharing/loading functions. 141 func TestFileShareLoadASCII(t *testing.T) { 142 if testing.Short() { 143 t.SkipNow() 144 } 145 rt, err := newRenterTester("TestRenterShareLoadASCII") 146 if err != nil { 147 t.Fatal(err) 148 } 149 defer rt.Close() 150 151 // Create a file and add it to the renter. 152 savedFile := newTestingFile() 153 rt.renter.files[savedFile.name] = savedFile 154 155 ascii, err := rt.renter.ShareFilesAscii([]string{savedFile.name}) 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 // Remove the file from the renter. 161 delete(rt.renter.files, savedFile.name) 162 163 names, err := rt.renter.LoadSharedFilesAscii(ascii) 164 if err != nil { 165 t.Fatal(err) 166 } 167 if len(names) != 1 || names[0] != savedFile.name { 168 t.Fatal("nickname not loaded properly") 169 } 170 171 err = equalFiles(rt.renter.files[savedFile.name], savedFile) 172 if err != nil { 173 t.Fatal(err) 174 } 175 } 176 177 // TestRenterSaveLoad probes the save and load methods of the renter type. 178 func TestRenterSaveLoad(t *testing.T) { 179 if testing.Short() { 180 t.SkipNow() 181 } 182 rt, err := newRenterTester("TestRenterSaveLoad") 183 if err != nil { 184 t.Fatal(err) 185 } 186 defer rt.Close() 187 188 // Create and save some files 189 var f1, f2, f3 *file 190 f1 = newTestingFile() 191 f2 = newTestingFile() 192 f3 = newTestingFile() 193 // names must not conflict 194 for f2.name == f1.name || f2.name == f3.name { 195 f2 = newTestingFile() 196 } 197 for f3.name == f1.name || f3.name == f2.name { 198 f3 = newTestingFile() 199 } 200 rt.renter.saveFile(f1) 201 rt.renter.saveFile(f2) 202 rt.renter.saveFile(f3) 203 204 err = rt.renter.save() // save metadata 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 // load should now load the files into memory. 210 id := rt.renter.mu.Lock() 211 err = rt.renter.load() 212 rt.renter.mu.Unlock(id) 213 if err != nil && !os.IsNotExist(err) { 214 t.Fatal(err) 215 } 216 217 if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil { 218 t.Fatal(err) 219 } 220 if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil { 221 t.Fatal(err) 222 } 223 if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil { 224 t.Fatal(err) 225 } 226 } 227 228 // TestRenterPaths checks that the renter properly handles nicknames 229 // containing the path separator ("/"). 230 func TestRenterPaths(t *testing.T) { 231 if testing.Short() { 232 t.SkipNow() 233 } 234 rt, err := newRenterTester("TestRenterPaths") 235 if err != nil { 236 t.Fatal(err) 237 } 238 defer rt.Close() 239 240 // Create and save some files. 241 // The result of saving these files should be a directory containing: 242 // foo.sia 243 // foo/bar.sia 244 // foo/bar/baz.sia 245 f1 := newTestingFile() 246 f1.name = "foo" 247 f2 := newTestingFile() 248 f2.name = "foo/bar" 249 f3 := newTestingFile() 250 f3.name = "foo/bar/baz" 251 rt.renter.saveFile(f1) 252 rt.renter.saveFile(f2) 253 rt.renter.saveFile(f3) 254 255 // Load the files into the renter. 256 id := rt.renter.mu.Lock() 257 err = rt.renter.load() 258 rt.renter.mu.Unlock(id) 259 if err != nil && !os.IsNotExist(err) { 260 t.Fatal(err) 261 } 262 // Check that the files were loaded properly. 263 if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil { 264 t.Fatal(err) 265 } 266 if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil { 267 t.Fatal(err) 268 } 269 if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil { 270 t.Fatal(err) 271 } 272 273 // To confirm that the file structure was preserved, we walk the renter 274 // folder and emit the name of each .sia file encountered (filepath.Walk 275 // is deterministic; it orders the files lexically). 276 var walkStr string 277 filepath.Walk(rt.renter.persistDir, func(path string, _ os.FileInfo, _ error) error { 278 // capture only .sia files 279 if filepath.Ext(path) != ".sia" { 280 return nil 281 } 282 rel, _ := filepath.Rel(rt.renter.persistDir, path) // strip testdir prefix 283 walkStr += rel 284 return nil 285 }) 286 // walk will descend into foo/bar/, reading baz, bar, and finally foo 287 expWalkStr := (f3.name + ".sia") + (f2.name + ".sia") + (f1.name + ".sia") 288 if walkStr != expWalkStr { 289 t.Fatalf("Bad walk string: expected %v, got %v", expWalkStr, walkStr) 290 } 291 } 292 293 // TestSiafileCompatibility tests that the renter is able to load v0.4.8 .sia files. 294 func TestSiafileCompatibility(t *testing.T) { 295 if testing.Short() { 296 t.SkipNow() 297 } 298 rt, err := newRenterTester("TestSiafileCompatibility") 299 if err != nil { 300 t.Fatal(err) 301 } 302 defer rt.Close() 303 304 // Load the compatibility file into the renter. 305 path := filepath.Join("..", "..", "compatibility", "siafile_v0.4.8.sia") 306 names, err := rt.renter.LoadSharedFiles(path) 307 if err != nil { 308 t.Fatal(err) 309 } 310 if len(names) != 1 || names[0] != "testfile-183" { 311 t.Fatal("nickname not loaded properly:", names) 312 } 313 }