gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/host/contractmanager/sectorupdate_test.go (about) 1 package contractmanager 2 3 // TODO: Verify that the code gracefully handles multiple storage folders 4 // failiing, as well as all of them failing. 5 6 // Verify that the actual data stored on disk matches the sector roots that it 7 // is suppsed to match. Especially for multi-storage folder, 8 // post-resize/remove, after renews and exirations (involving viritual 9 // contracts), with large enough amounts of data that storage folders sometimes 10 // filled up entirely (multiple pages of storageFolderGranularity size). 11 12 import ( 13 "bytes" 14 "errors" 15 "os" 16 "path/filepath" 17 "strings" 18 "sync" 19 "testing" 20 21 "gitlab.com/NebulousLabs/fastrand" 22 "gitlab.com/SiaPrime/SiaPrime/crypto" 23 "gitlab.com/SiaPrime/SiaPrime/modules" 24 ) 25 26 // randSector creates a random sector that can be added to the contract 27 // manager. 28 func randSector() (root crypto.Hash, data []byte) { 29 data = fastrand.Bytes(int(modules.SectorSize)) 30 root = crypto.MerkleRoot(data) 31 return 32 } 33 34 // TestAddSector tries to add a sector to the contract manager, blocking until 35 // the add has completed. 36 func TestAddSector(t *testing.T) { 37 if testing.Short() { 38 t.SkipNow() 39 } 40 t.Parallel() 41 cmt, err := newContractManagerTester("TestAddSector") 42 if err != nil { 43 t.Fatal(err) 44 } 45 defer cmt.panicClose() 46 47 // Add a storage folder to the contract manager tester. 48 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 49 // Create the storage folder dir. 50 err = os.MkdirAll(storageFolderDir, 0700) 51 if err != nil { 52 t.Fatal(err) 53 } 54 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 // Fabricate a sector and add it to the contract manager. 60 root, data := randSector() 61 err = cmt.cm.AddSector(root, data) 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 // Check that the sector was successfully added. 67 sfs := cmt.cm.StorageFolders() 68 if len(sfs) != 1 { 69 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 70 } 71 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 72 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 73 } 74 // Break the rules slightly - make the test brittle by looking at the 75 // internals directly to determine that the sector got added to the right 76 // locations, and that the usage information was updated correctly. 77 if len(cmt.cm.sectorLocations) != 1 { 78 t.Fatal("there should be one sector reported in the sectorLocations map") 79 } 80 if len(cmt.cm.storageFolders) != 1 { 81 t.Fatal("storage folder not being reported correctly") 82 } 83 var index uint16 84 for _, sf := range cmt.cm.storageFolders { 85 index = sf.index 86 } 87 for _, sl := range cmt.cm.sectorLocations { 88 if sl.count != 1 { 89 t.Error("Sector location should only be reporting one sector") 90 } 91 if sl.storageFolder != index { 92 t.Error("Sector location is being reported incorrectly - wrong storage folder") 93 } 94 if sl.index > 64 { 95 t.Error("sector index within storage folder also being reported incorrectly") 96 } 97 } 98 // Check the usage. 99 found := false 100 for _, u := range cmt.cm.storageFolders[index].usage { 101 if u != 0 { 102 found = true 103 break 104 } 105 } 106 if !found { 107 t.Error("usage field does not seem to have been updated") 108 } 109 sectorData, err := cmt.cm.ReadSector(root) 110 if err != nil { 111 t.Fatal(err) 112 } 113 if !bytes.Equal(sectorData, data) { 114 t.Fatal("wrong sector provided") 115 } 116 117 // Try reloading the contract manager and see if all of the stateful checks 118 // still hold. 119 err = cmt.cm.Close() 120 if err != nil { 121 t.Fatal(err) 122 } 123 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 124 if err != nil { 125 t.Fatal(err) 126 } 127 128 // Check that the sector was successfully added. 129 sfs = cmt.cm.StorageFolders() 130 if len(sfs) != 1 { 131 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 132 } 133 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 134 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 135 } 136 // Break the rules slightly - make the test brittle by looking at the 137 // internals directly to determine that the sector got added to the right 138 // locations, and that the usage information was updated correctly. 139 if len(cmt.cm.sectorLocations) != 1 { 140 t.Fatal("there should be one sector reported in the sectorLocations map") 141 } 142 if len(cmt.cm.storageFolders) != 1 { 143 t.Fatal("storage folder not being reported correctly") 144 } 145 for _, sf := range cmt.cm.storageFolders { 146 index = sf.index 147 } 148 for _, sl := range cmt.cm.sectorLocations { 149 if sl.count != 1 { 150 t.Error("Sector location should only be reporting one sector:", sl.count) 151 } 152 if sl.storageFolder != index { 153 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 154 } 155 if sl.index > 64 { 156 t.Error("sector index within storage folder also being reported incorrectly") 157 } 158 } 159 // Check the usage. 160 found = false 161 for _, u := range cmt.cm.storageFolders[index].usage { 162 if u != 0 { 163 found = true 164 break 165 } 166 } 167 if !found { 168 t.Error("usage field does not seem to have been updated") 169 } 170 sectorData, err = cmt.cm.ReadSector(root) 171 if err != nil { 172 t.Fatal(err) 173 } 174 if !bytes.Equal(sectorData, data) { 175 t.Fatal("wrong sector provided") 176 } 177 } 178 179 // TestAddSectorFillFolder adds sectors to a 64 sector storage folder until it 180 // is full. 181 func TestAddSectorFillFolder(t *testing.T) { 182 if testing.Short() { 183 t.SkipNow() 184 } 185 t.Parallel() 186 cmt, err := newContractManagerTester("TestAddSectorFillFolder") 187 if err != nil { 188 t.Fatal(err) 189 } 190 defer cmt.panicClose() 191 192 // Add a storage folder to the contract manager tester. 193 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 194 // Create the storage folder dir. 195 err = os.MkdirAll(storageFolderDir, 0700) 196 if err != nil { 197 t.Fatal(err) 198 } 199 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*storageFolderGranularity) 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 // Fabricate 65 sectors for the storage folder, which can only hold 64. 205 roots := make([]crypto.Hash, storageFolderGranularity+1) 206 datas := make([][]byte, storageFolderGranularity+1) 207 var wg sync.WaitGroup 208 for i := 0; i < storageFolderGranularity+1; i++ { 209 wg.Add(1) 210 go func(i int) { 211 defer wg.Done() 212 root, data := randSector() 213 roots[i] = root 214 datas[i] = data 215 }(i) 216 } 217 wg.Wait() 218 219 // Add 64 sectors which should fit cleanly. The sectors are added in 220 // parallel to make use of the batching in the contract manager. 221 for i := 0; i < storageFolderGranularity; i++ { 222 wg.Add(1) 223 go func(i int) { 224 defer wg.Done() 225 err := cmt.cm.AddSector(roots[i], datas[i]) 226 if err != nil { 227 t.Fatal(err) 228 } 229 }(i) 230 } 231 wg.Wait() 232 233 // Check that the sectors were successfully added. 234 sfs := cmt.cm.StorageFolders() 235 if len(sfs) != 1 { 236 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 237 } 238 if sfs[0].CapacityRemaining != 0 { 239 t.Error("Storage folder is supposed to be full", sfs[0].CapacityRemaining) 240 } 241 242 // Try adding a 65th sector, it should not succeed. 243 err = cmt.cm.AddSector(roots[storageFolderGranularity], datas[storageFolderGranularity]) 244 if err == nil { 245 t.Error("expecting the storage folder to be full.") 246 } 247 248 // Try reading each sector. 249 for i := range roots[:storageFolderGranularity] { 250 data, err := cmt.cm.ReadSector(roots[i]) 251 if err != nil { 252 t.Fatal(err) 253 } 254 if !bytes.Equal(data, datas[i]) { 255 t.Error("Contract manager returned the wrong data on a sector request") 256 } 257 } 258 } 259 260 // TestAddSectorFillLargerFolder adds sectors to a 128 sector storage folder 261 // until it is full. 262 func TestAddSectorFillLargerFolder(t *testing.T) { 263 if testing.Short() { 264 t.SkipNow() 265 } 266 t.Parallel() 267 cmt, err := newContractManagerTester("TestAddSectorFillLargerFolder") 268 if err != nil { 269 t.Fatal(err) 270 } 271 defer cmt.panicClose() 272 273 // Add a storage folder to the contract manager tester. 274 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 275 // Create the storage folder dir. 276 err = os.MkdirAll(storageFolderDir, 0700) 277 if err != nil { 278 t.Fatal(err) 279 } 280 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*storageFolderGranularity*2) 281 if err != nil { 282 t.Fatal(err) 283 } 284 285 // Fabricate 65 sectors for the storage folder, which can only hold 64. 286 roots := make([]crypto.Hash, storageFolderGranularity*2+1) 287 datas := make([][]byte, storageFolderGranularity*2+1) 288 var wg sync.WaitGroup 289 for i := 0; i < storageFolderGranularity*2+1; i++ { 290 wg.Add(1) 291 go func(i int) { 292 defer wg.Done() 293 root, data := randSector() 294 roots[i] = root 295 datas[i] = data 296 }(i) 297 } 298 wg.Wait() 299 300 // Add 64 sectors which should fit cleanly. The sectors are added in 301 // parallel to make use of the batching in the contract manager. 302 for i := 0; i < storageFolderGranularity*2; i++ { 303 wg.Add(1) 304 go func(i int) { 305 defer wg.Done() 306 err := cmt.cm.AddSector(roots[i], datas[i]) 307 if err != nil { 308 t.Fatal(err) 309 } 310 }(i) 311 } 312 wg.Wait() 313 314 // Check that the sectors were successfully added. 315 sfs := cmt.cm.StorageFolders() 316 if len(sfs) != 1 { 317 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 318 } 319 if sfs[0].CapacityRemaining != 0 { 320 t.Error("Storage folder is supposed to be full", sfs[0].CapacityRemaining) 321 } 322 323 // Try adding a 65th sector, it should not succeed. 324 err = cmt.cm.AddSector(roots[storageFolderGranularity*2], datas[storageFolderGranularity*2]) 325 if err == nil { 326 t.Error("expecting the storage folder to be full.") 327 } 328 329 // Try reading each sector. 330 for i := range roots[:storageFolderGranularity*2] { 331 data, err := cmt.cm.ReadSector(roots[i]) 332 if err != nil { 333 t.Fatal(err) 334 } 335 if !bytes.Equal(data, datas[i]) { 336 t.Error("Contract manager returned the wrong data on a sector request") 337 } 338 } 339 } 340 341 // dependencyNoSettingsSave is a mocked dependency that will prevent the 342 // settings file from saving. 343 type dependencyNoSettingsSave struct { 344 modules.ProductionDependencies 345 triggered bool 346 mu sync.Mutex 347 } 348 349 // disrupt will disrupt the threadedSyncLoop, causing the loop to terminate as 350 // soon as it is created. 351 func (d *dependencyNoSettingsSave) Disrupt(s string) bool { 352 d.mu.Lock() 353 defer d.mu.Unlock() 354 355 if s == "settingsSyncRename" && d.triggered { 356 // Prevent the settings file from being saved. 357 return true 358 } 359 if s == "walRename" && d.triggered { 360 // Prevent the WAL from being renamed, which will prevent the existing 361 // WAL from being overwritten. 362 return true 363 } 364 if s == "cleanWALFile" { 365 // Prevent the WAL file from being removed. 366 return true 367 } 368 return false 369 } 370 371 // TestAddSectorRecovery checks that the WAL recovery of an added sector is 372 // graceful / correct in the event of unclean shutdown. 373 func TestAddSectorRecovery(t *testing.T) { 374 if testing.Short() { 375 t.SkipNow() 376 } 377 t.Parallel() 378 d := new(dependencyNoSettingsSave) 379 cmt, err := newMockedContractManagerTester(d, "TestAddSectorRecovery") 380 if err != nil { 381 t.Fatal(err) 382 } 383 defer cmt.panicClose() 384 385 // Add a storage folder to the contract manager tester. 386 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 387 // Create the storage folder dir. 388 err = os.MkdirAll(storageFolderDir, 0700) 389 if err != nil { 390 t.Fatal(err) 391 } 392 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 393 if err != nil { 394 t.Fatal(err) 395 } 396 397 // Fabricate a sector and add it to the contract manager. 398 root, data := randSector() 399 // Disrupt the sync loop before adding the sector, such that the add sector 400 // call makes it into the WAL but not into the saved settings. 401 err = cmt.cm.AddSector(root, data) 402 if err != nil { 403 t.Fatal(err) 404 } 405 d.mu.Lock() 406 d.triggered = true 407 d.mu.Unlock() 408 409 // Check that the sector was successfully added. 410 sfs := cmt.cm.StorageFolders() 411 if len(sfs) != 1 { 412 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 413 } 414 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 415 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 416 } 417 // Break the rules slightly - make the test brittle by looking at the 418 // internals directly to determine that the sector got added to the right 419 // locations, and that the usage information was updated correctly. 420 if len(cmt.cm.sectorLocations) != 1 { 421 t.Fatal("there should be one sector reported in the sectorLocations map") 422 } 423 if len(cmt.cm.storageFolders) != 1 { 424 t.Fatal("storage folder not being reported correctly") 425 } 426 var index uint16 427 for _, sf := range cmt.cm.storageFolders { 428 index = sf.index 429 if sf.sectors != 1 { 430 t.Error("the number of sectors is being counted incorrectly") 431 } 432 } 433 for _, sl := range cmt.cm.sectorLocations { 434 if sl.count != 1 { 435 t.Error("Sector location should only be reporting one sector") 436 } 437 if sl.storageFolder != index { 438 t.Error("Sector location is being reported incorrectly - wrong storage folder") 439 } 440 if sl.index > 64 { 441 t.Error("sector index within storage folder also being reported incorrectly") 442 } 443 } 444 // Check the usage. 445 found := false 446 for _, u := range cmt.cm.storageFolders[index].usage { 447 if u != 0 { 448 found = true 449 break 450 } 451 } 452 if !found { 453 t.Error("usage field does not seem to have been updated") 454 } 455 456 // Try reloading the contract manager and see if all of the stateful checks 457 // still hold. 458 err = cmt.cm.Close() 459 if err != nil { 460 t.Fatal(err) 461 } 462 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 463 if err != nil { 464 t.Fatal(err) 465 } 466 467 // Check that the sector was successfully added. 468 sfs = cmt.cm.StorageFolders() 469 if len(sfs) != 1 { 470 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 471 } 472 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 473 t.Error("One sector's worth of capacity should be consumed:", (sfs[0].Capacity-sfs[0].CapacityRemaining)/modules.SectorSize) 474 } 475 // Break the rules slightly - make the test brittle by looking at the 476 // internals directly to determine that the sector got added to the right 477 // locations, and that the usage information was updated correctly. 478 if len(cmt.cm.sectorLocations) != 1 { 479 t.Fatal("there should be one sector reported in the sectorLocations map") 480 } 481 if len(cmt.cm.storageFolders) != 1 { 482 t.Fatal("storage folder not being reported correctly") 483 } 484 for _, sf := range cmt.cm.storageFolders { 485 index = sf.index 486 if sf.sectors != 1 { 487 t.Error("the number of sectors is being counted incorrectly") 488 } 489 } 490 for _, sl := range cmt.cm.sectorLocations { 491 if sl.count != 1 { 492 t.Error("Sector location should only be reporting one sector:", sl.count) 493 } 494 if sl.storageFolder != index { 495 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 496 } 497 if sl.index > 64 { 498 t.Error("sector index within storage folder also being reported incorrectly") 499 } 500 } 501 // Check the usage. 502 found = false 503 for _, u := range cmt.cm.storageFolders[index].usage { 504 if u != 0 { 505 found = true 506 break 507 } 508 } 509 if !found { 510 t.Error("usage field does not seem to have been updated") 511 } 512 } 513 514 // TestAddVirtualSectorSerial adds a sector and a virual sector in serial to 515 // the contract manager. 516 func TestAddVirtualSectorSerial(t *testing.T) { 517 if testing.Short() { 518 t.SkipNow() 519 } 520 t.Parallel() 521 cmt, err := newContractManagerTester("TestAddVirtualSectorSerial") 522 if err != nil { 523 t.Fatal(err) 524 } 525 defer cmt.panicClose() 526 527 // Add a storage folder to the contract manager tester. 528 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 529 // Create the storage folder dir. 530 err = os.MkdirAll(storageFolderDir, 0700) 531 if err != nil { 532 t.Fatal(err) 533 } 534 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 535 if err != nil { 536 t.Fatal(err) 537 } 538 539 // Fabricate a sector and add it to the contract manager. 540 root, data := randSector() 541 // Add the sector twice in serial to verify that virtual sector adding is 542 // working correctly. 543 err = cmt.cm.AddSector(root, data) 544 if err != nil { 545 t.Fatal(err) 546 } 547 err = cmt.cm.AddSector(root, data) 548 if err != nil { 549 t.Fatal(err) 550 } 551 552 // Check that the sector was successfully added. 553 sfs := cmt.cm.StorageFolders() 554 if len(sfs) != 1 { 555 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 556 } 557 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 558 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 559 } 560 // Break the rules slightly - make the test brittle by looking at the 561 // internals directly to determine that the sector got added to the right 562 // locations, and that the usage information was updated correctly. 563 if len(cmt.cm.sectorLocations) != 1 { 564 t.Fatal("there should be one sector reported in the sectorLocations map") 565 } 566 if len(cmt.cm.storageFolders) != 1 { 567 t.Fatal("storage folder not being reported correctly") 568 } 569 var index uint16 570 for _, sf := range cmt.cm.storageFolders { 571 index = sf.index 572 } 573 for _, sl := range cmt.cm.sectorLocations { 574 if sl.count != 2 { 575 t.Error("Sector location should only be reporting one sector") 576 } 577 if sl.storageFolder != index { 578 t.Error("Sector location is being reported incorrectly - wrong storage folder") 579 } 580 if sl.index > 64 { 581 t.Error("sector index within storage folder also being reported incorrectly") 582 } 583 } 584 // Check the usage. 585 found := false 586 for _, u := range cmt.cm.storageFolders[index].usage { 587 if u != 0 { 588 found = true 589 break 590 } 591 } 592 if !found { 593 t.Error("usage field does not seem to have been updated") 594 } 595 596 // Try reloading the contract manager and see if all of the stateful checks 597 // still hold. 598 err = cmt.cm.Close() 599 if err != nil { 600 t.Fatal(err) 601 } 602 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 603 if err != nil { 604 t.Fatal(err) 605 } 606 607 // Check that the sector was successfully added. 608 sfs = cmt.cm.StorageFolders() 609 if len(sfs) != 1 { 610 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 611 } 612 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 613 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 614 } 615 // Break the rules slightly - make the test brittle by looking at the 616 // internals directly to determine that the sector got added to the right 617 // locations, and that the usage information was updated correctly. 618 if len(cmt.cm.sectorLocations) != 1 { 619 t.Fatal("there should be one sector reported in the sectorLocations map") 620 } 621 if len(cmt.cm.storageFolders) != 1 { 622 t.Fatal("storage folder not being reported correctly") 623 } 624 for _, sf := range cmt.cm.storageFolders { 625 index = sf.index 626 } 627 for _, sl := range cmt.cm.sectorLocations { 628 if sl.count != 2 { 629 t.Error("Sector location should only be reporting one sector:", sl.count) 630 } 631 if sl.storageFolder != index { 632 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 633 } 634 if sl.index > 64 { 635 t.Error("sector index within storage folder also being reported incorrectly") 636 } 637 } 638 // Check the usage. 639 found = false 640 for _, u := range cmt.cm.storageFolders[index].usage { 641 if u != 0 { 642 found = true 643 break 644 } 645 } 646 if !found { 647 t.Error("usage field does not seem to have been updated") 648 } 649 } 650 651 // TestAddVirtualSectorParallel adds a sector and a virual sector in parallel 652 // to the contract manager. 653 func TestAddVirtualSectorParallel(t *testing.T) { 654 if testing.Short() { 655 t.SkipNow() 656 } 657 t.Parallel() 658 cmt, err := newContractManagerTester("TestAddVirtualSectorParallel") 659 if err != nil { 660 t.Fatal(err) 661 } 662 defer cmt.panicClose() 663 664 // Add a storage folder to the contract manager tester. 665 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 666 // Create the storage folder dir. 667 err = os.MkdirAll(storageFolderDir, 0700) 668 if err != nil { 669 t.Fatal(err) 670 } 671 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 672 if err != nil { 673 t.Fatal(err) 674 } 675 676 // Fabricate a sector and add it to the contract manager. 677 root, data := randSector() 678 // Add the sector twice in serial to verify that virtual sector adding is 679 // working correctly. 680 var wg sync.WaitGroup 681 wg.Add(2) 682 go func() { 683 defer wg.Done() 684 err := cmt.cm.AddSector(root, data) 685 if err != nil { 686 t.Fatal(err) 687 } 688 }() 689 go func() { 690 defer wg.Done() 691 err := cmt.cm.AddSector(root, data) 692 if err != nil { 693 t.Fatal(err) 694 } 695 }() 696 wg.Wait() 697 698 // Check that the sector was successfully added. 699 sfs := cmt.cm.StorageFolders() 700 if len(sfs) != 1 { 701 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 702 } 703 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 704 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 705 } 706 // Break the rules slightly - make the test brittle by looking at the 707 // internals directly to determine that the sector got added to the right 708 // locations, and that the usage information was updated correctly. 709 if len(cmt.cm.sectorLocations) != 1 { 710 t.Fatal("there should be one sector reported in the sectorLocations map") 711 } 712 if len(cmt.cm.storageFolders) != 1 { 713 t.Fatal("storage folder not being reported correctly") 714 } 715 var index uint16 716 for _, sf := range cmt.cm.storageFolders { 717 index = sf.index 718 } 719 for _, sl := range cmt.cm.sectorLocations { 720 if sl.count != 2 { 721 t.Error("Sector location should be reporting a count of 2 for this sector:", sl.count) 722 } 723 if sl.storageFolder != index { 724 t.Error("Sector location is being reported incorrectly - wrong storage folder") 725 } 726 if sl.index > 64 { 727 t.Error("sector index within storage folder also being reported incorrectly") 728 } 729 } 730 // Check the usage. 731 found := false 732 for _, u := range cmt.cm.storageFolders[index].usage { 733 if u != 0 { 734 found = true 735 break 736 } 737 } 738 if !found { 739 t.Error("usage field does not seem to have been updated") 740 } 741 742 // Try reloading the contract manager and see if all of the stateful checks 743 // still hold. 744 err = cmt.cm.Close() 745 if err != nil { 746 t.Fatal(err) 747 } 748 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 749 if err != nil { 750 t.Fatal(err) 751 } 752 753 // Check that the sector was successfully added. 754 sfs = cmt.cm.StorageFolders() 755 if len(sfs) != 1 { 756 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 757 } 758 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 759 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 760 } 761 // Break the rules slightly - make the test brittle by looking at the 762 // internals directly to determine that the sector got added to the right 763 // locations, and that the usage information was updated correctly. 764 if len(cmt.cm.sectorLocations) != 1 { 765 t.Fatal("there should be one sector reported in the sectorLocations map") 766 } 767 if len(cmt.cm.storageFolders) != 1 { 768 t.Fatal("storage folder not being reported correctly") 769 } 770 for _, sf := range cmt.cm.storageFolders { 771 index = sf.index 772 } 773 for _, sl := range cmt.cm.sectorLocations { 774 if sl.count != 2 { 775 t.Error("Sector location should only be reporting one sector:", sl.count) 776 } 777 if sl.storageFolder != index { 778 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 779 } 780 if sl.index > 64 { 781 t.Error("sector index within storage folder also being reported incorrectly") 782 } 783 } 784 // Check the usage. 785 found = false 786 for _, u := range cmt.cm.storageFolders[index].usage { 787 if u != 0 { 788 found = true 789 break 790 } 791 } 792 if !found { 793 t.Error("usage field does not seem to have been updated") 794 } 795 } 796 797 // TestAddVirtualSectorMassiveParallel adds the same sector many times in 798 // parallel to the contract manager. 799 func TestAddVirtualSectorMassiveParallel(t *testing.T) { 800 if testing.Short() { 801 t.SkipNow() 802 } 803 t.Parallel() 804 cmt, err := newContractManagerTester("TestAddVirtualSectorMassiveParallel") 805 if err != nil { 806 t.Fatal(err) 807 } 808 defer cmt.panicClose() 809 810 // Add a storage folder to the contract manager tester. 811 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 812 // Create the storage folder dir. 813 err = os.MkdirAll(storageFolderDir, 0700) 814 if err != nil { 815 t.Fatal(err) 816 } 817 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 818 if err != nil { 819 t.Fatal(err) 820 } 821 822 // Fabricate a sector and add it to the contract manager. 823 root, data := randSector() 824 // Add the sector many times in parallel to make sure it is handled 825 // gracefully. 826 var wg sync.WaitGroup 827 parallelAdds := uint16(20) 828 for i := uint16(0); i < parallelAdds; i++ { 829 wg.Add(1) 830 go func() { 831 defer wg.Done() 832 err := cmt.cm.AddSector(root, data) 833 if err != nil { 834 t.Fatal(err) 835 } 836 }() 837 } 838 wg.Wait() 839 840 // Check that the sector was successfully added. 841 sfs := cmt.cm.StorageFolders() 842 if len(sfs) != 1 { 843 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 844 } 845 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 846 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 847 } 848 // Break the rules slightly - make the test brittle by looking at the 849 // internals directly to determine that the sector got added to the right 850 // locations, and that the usage information was updated correctly. 851 if len(cmt.cm.sectorLocations) != 1 { 852 t.Fatal("there should be one sector reported in the sectorLocations map") 853 } 854 if len(cmt.cm.storageFolders) != 1 { 855 t.Fatal("storage folder not being reported correctly") 856 } 857 var index uint16 858 for _, sf := range cmt.cm.storageFolders { 859 index = sf.index 860 } 861 for _, sl := range cmt.cm.sectorLocations { 862 if sl.count != parallelAdds { 863 t.Error("Sector location should only be reporting one sector:", sl.count) 864 } 865 if sl.storageFolder != index { 866 t.Error("Sector location is being reported incorrectly - wrong storage folder") 867 } 868 if sl.index > 64 { 869 t.Error("sector index within storage folder also being reported incorrectly") 870 } 871 } 872 // Check the usage. 873 found := false 874 for _, u := range cmt.cm.storageFolders[index].usage { 875 if u != 0 { 876 found = true 877 break 878 } 879 } 880 if !found { 881 t.Error("usage field does not seem to have been updated") 882 } 883 884 // Try reloading the contract manager and see if all of the stateful checks 885 // still hold. 886 err = cmt.cm.Close() 887 if err != nil { 888 t.Fatal(err) 889 } 890 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 891 if err != nil { 892 t.Fatal(err) 893 } 894 895 // Check that the sector was successfully added. 896 sfs = cmt.cm.StorageFolders() 897 if len(sfs) != 1 { 898 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 899 } 900 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 901 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 902 } 903 // Break the rules slightly - make the test brittle by looking at the 904 // internals directly to determine that the sector got added to the right 905 // locations, and that the usage information was updated correctly. 906 if len(cmt.cm.sectorLocations) != 1 { 907 t.Fatal("there should be one sector reported in the sectorLocations map") 908 } 909 if len(cmt.cm.storageFolders) != 1 { 910 t.Fatal("storage folder not being reported correctly") 911 } 912 for _, sf := range cmt.cm.storageFolders { 913 index = sf.index 914 } 915 for _, sl := range cmt.cm.sectorLocations { 916 if sl.count != parallelAdds { 917 t.Error("Sector location should only be reporting one sector:", sl.count) 918 } 919 if sl.storageFolder != index { 920 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 921 } 922 if sl.index > 64 { 923 t.Error("sector index within storage folder also being reported incorrectly") 924 } 925 } 926 // Check the usage. 927 found = false 928 for _, u := range cmt.cm.storageFolders[index].usage { 929 if u != 0 { 930 found = true 931 break 932 } 933 } 934 if !found { 935 t.Error("usage field does not seem to have been updated") 936 } 937 } 938 939 // TestRemoveSector tries to remove a sector from the contract manager. 940 func TestRemoveSector(t *testing.T) { 941 if testing.Short() { 942 t.SkipNow() 943 } 944 t.Parallel() 945 cmt, err := newContractManagerTester("TestRemoveSector") 946 if err != nil { 947 t.Fatal(err) 948 } 949 defer cmt.panicClose() 950 951 // Add a storage folder to the contract manager tester. 952 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 953 // Create the storage folder dir. 954 err = os.MkdirAll(storageFolderDir, 0700) 955 if err != nil { 956 t.Fatal(err) 957 } 958 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 959 if err != nil { 960 t.Fatal(err) 961 } 962 963 // Add two sectors, and then remove one of them. 964 root, data := randSector() 965 err = cmt.cm.AddSector(root, data) 966 if err != nil { 967 t.Fatal(err) 968 } 969 root2, data2 := randSector() 970 err = cmt.cm.AddSector(root2, data2) 971 if err != nil { 972 t.Fatal(err) 973 } 974 err = cmt.cm.RemoveSector(root2) 975 if err != nil { 976 t.Fatal(err) 977 } 978 979 // Check that the sector was successfully added. 980 sfs := cmt.cm.StorageFolders() 981 if len(sfs) != 1 { 982 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 983 } 984 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 985 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 986 } 987 // Break the rules slightly - make the test brittle by looking at the 988 // internals directly to determine that the sector got added to the right 989 // locations, and that the usage information was updated correctly. 990 if len(cmt.cm.sectorLocations) != 1 { 991 t.Fatal("there should be one sector reported in the sectorLocations map") 992 } 993 if len(cmt.cm.storageFolders) != 1 { 994 t.Fatal("storage folder not being reported correctly") 995 } 996 var index uint16 997 for _, sf := range cmt.cm.storageFolders { 998 index = sf.index 999 } 1000 for _, sl := range cmt.cm.sectorLocations { 1001 if sl.count != 1 { 1002 t.Error("Sector location should only be reporting one sector") 1003 } 1004 if sl.storageFolder != index { 1005 t.Error("Sector location is being reported incorrectly - wrong storage folder") 1006 } 1007 if sl.index > 64 { 1008 t.Error("sector index within storage folder also being reported incorrectly") 1009 } 1010 } 1011 // Check the usage. 1012 found := false 1013 for _, u := range cmt.cm.storageFolders[index].usage { 1014 if u != 0 { 1015 found = true 1016 break 1017 } 1018 } 1019 if !found { 1020 t.Error("usage field does not seem to have been updated") 1021 } 1022 1023 // Try reloading the contract manager and see if all of the stateful checks 1024 // still hold. 1025 err = cmt.cm.Close() 1026 if err != nil { 1027 t.Fatal(err) 1028 } 1029 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1030 if err != nil { 1031 t.Fatal(err) 1032 } 1033 1034 // Check that the sector was successfully added. 1035 sfs = cmt.cm.StorageFolders() 1036 if len(sfs) != 1 { 1037 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1038 } 1039 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1040 t.Error("One sector's worth of capacity should be consumed:", (sfs[0].Capacity-sfs[0].CapacityRemaining)/modules.SectorSize) 1041 } 1042 // Break the rules slightly - make the test brittle by looking at the 1043 // internals directly to determine that the sector got added to the right 1044 // locations, and that the usage information was updated correctly. 1045 if len(cmt.cm.sectorLocations) != 1 { 1046 t.Fatal("there should be one sector reported in the sectorLocations map:", len(cmt.cm.sectorLocations)) 1047 } 1048 if len(cmt.cm.storageFolders) != 1 { 1049 t.Fatal("storage folder not being reported correctly") 1050 } 1051 for _, sf := range cmt.cm.storageFolders { 1052 index = sf.index 1053 } 1054 for _, sl := range cmt.cm.sectorLocations { 1055 if sl.count != 1 { 1056 t.Error("Sector location should only be reporting one sector:", sl.count) 1057 } 1058 if sl.storageFolder != index { 1059 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 1060 } 1061 if sl.index > 64 { 1062 t.Error("sector index within storage folder also being reported incorrectly") 1063 } 1064 } 1065 // Check the usage. 1066 found = false 1067 for _, u := range cmt.cm.storageFolders[index].usage { 1068 if u != 0 { 1069 found = true 1070 break 1071 } 1072 } 1073 if !found { 1074 t.Error("usage field does not seem to have been updated") 1075 } 1076 } 1077 1078 // TestRemoveSectorVirtual tries to remove a virtual sector from the contract 1079 // manager. 1080 func TestRemoveSectorVirtual(t *testing.T) { 1081 if testing.Short() { 1082 t.SkipNow() 1083 } 1084 t.Parallel() 1085 cmt, err := newContractManagerTester("TestRemoveSectorVirtual") 1086 if err != nil { 1087 t.Fatal(err) 1088 } 1089 defer cmt.panicClose() 1090 1091 // Add a storage folder to the contract manager tester. 1092 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 1093 // Create the storage folder dir. 1094 err = os.MkdirAll(storageFolderDir, 0700) 1095 if err != nil { 1096 t.Fatal(err) 1097 } 1098 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 1099 if err != nil { 1100 t.Fatal(err) 1101 } 1102 1103 // Add a physical sector, then a virtual sector, and then remove the 1104 // virtual one. 1105 root, data := randSector() 1106 err = cmt.cm.AddSector(root, data) 1107 if err != nil { 1108 t.Fatal(err) 1109 } 1110 err = cmt.cm.AddSector(root, data) 1111 if err != nil { 1112 t.Fatal(err) 1113 } 1114 err = cmt.cm.RemoveSector(root) 1115 if err != nil { 1116 t.Fatal(err) 1117 } 1118 1119 // Check that the sector was successfully added. 1120 sfs := cmt.cm.StorageFolders() 1121 if len(sfs) != 1 { 1122 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1123 } 1124 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1125 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 1126 } 1127 // Break the rules slightly - make the test brittle by looking at the 1128 // internals directly to determine that the sector got added to the right 1129 // locations, and that the usage information was updated correctly. 1130 if len(cmt.cm.sectorLocations) != 1 { 1131 t.Fatal("there should be one sector reported in the sectorLocations map") 1132 } 1133 if len(cmt.cm.storageFolders) != 1 { 1134 t.Fatal("storage folder not being reported correctly") 1135 } 1136 var index uint16 1137 for _, sf := range cmt.cm.storageFolders { 1138 index = sf.index 1139 } 1140 for _, sl := range cmt.cm.sectorLocations { 1141 if sl.count != 1 { 1142 t.Error("Sector location should only be reporting one sector") 1143 } 1144 if sl.storageFolder != index { 1145 t.Error("Sector location is being reported incorrectly - wrong storage folder") 1146 } 1147 if sl.index > 64 { 1148 t.Error("sector index within storage folder also being reported incorrectly") 1149 } 1150 } 1151 // Check the usage. 1152 found := false 1153 for _, u := range cmt.cm.storageFolders[index].usage { 1154 if u != 0 { 1155 found = true 1156 break 1157 } 1158 } 1159 if !found { 1160 t.Error("usage field does not seem to have been updated") 1161 } 1162 1163 // Try reloading the contract manager and see if all of the stateful checks 1164 // still hold. 1165 err = cmt.cm.Close() 1166 if err != nil { 1167 t.Fatal(err) 1168 } 1169 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1170 if err != nil { 1171 t.Fatal(err) 1172 } 1173 1174 // Check that the sector was successfully added. 1175 sfs = cmt.cm.StorageFolders() 1176 if len(sfs) != 1 { 1177 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1178 } 1179 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1180 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 1181 } 1182 // Break the rules slightly - make the test brittle by looking at the 1183 // internals directly to determine that the sector got added to the right 1184 // locations, and that the usage information was updated correctly. 1185 if len(cmt.cm.sectorLocations) != 1 { 1186 t.Fatal("there should be one sector reported in the sectorLocations map") 1187 } 1188 if len(cmt.cm.storageFolders) != 1 { 1189 t.Fatal("storage folder not being reported correctly") 1190 } 1191 for _, sf := range cmt.cm.storageFolders { 1192 index = sf.index 1193 } 1194 for _, sl := range cmt.cm.sectorLocations { 1195 if sl.count != 1 { 1196 t.Error("Sector location should only be reporting one sector:", sl.count) 1197 } 1198 if sl.storageFolder != index { 1199 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 1200 } 1201 if sl.index > 64 { 1202 t.Error("sector index within storage folder also being reported incorrectly") 1203 } 1204 } 1205 // Check the usage. 1206 found = false 1207 for _, u := range cmt.cm.storageFolders[index].usage { 1208 if u != 0 { 1209 found = true 1210 break 1211 } 1212 } 1213 if !found { 1214 t.Error("usage field does not seem to have been updated") 1215 } 1216 } 1217 1218 // TestDeleteSector tries to delete a sector from the contract manager. 1219 func TestDeleteSector(t *testing.T) { 1220 if testing.Short() { 1221 t.SkipNow() 1222 } 1223 t.Parallel() 1224 cmt, err := newContractManagerTester("TestDeleteSector") 1225 if err != nil { 1226 t.Fatal(err) 1227 } 1228 defer cmt.panicClose() 1229 1230 // Add a storage folder to the contract manager tester. 1231 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 1232 // Create the storage folder dir. 1233 err = os.MkdirAll(storageFolderDir, 0700) 1234 if err != nil { 1235 t.Fatal(err) 1236 } 1237 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 1238 if err != nil { 1239 t.Fatal(err) 1240 } 1241 1242 // Add two sectors, and then delete one of them. 1243 root, data := randSector() 1244 err = cmt.cm.AddSector(root, data) 1245 if err != nil { 1246 t.Fatal(err) 1247 } 1248 root2, data2 := randSector() 1249 err = cmt.cm.AddSector(root2, data2) 1250 if err != nil { 1251 t.Fatal(err) 1252 } 1253 err = cmt.cm.DeleteSector(root2) 1254 if err != nil { 1255 t.Fatal(err) 1256 } 1257 1258 // Check that the sector was successfully added. 1259 sfs := cmt.cm.StorageFolders() 1260 if len(sfs) != 1 { 1261 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1262 } 1263 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1264 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 1265 } 1266 // Break the rules slightly - make the test brittle by looking at the 1267 // internals directly to determine that the sector got added to the right 1268 // locations, and that the usage information was updated correctly. 1269 if len(cmt.cm.sectorLocations) != 1 { 1270 t.Fatal("there should be one sector reported in the sectorLocations map") 1271 } 1272 if len(cmt.cm.storageFolders) != 1 { 1273 t.Fatal("storage folder not being reported correctly") 1274 } 1275 var index uint16 1276 for _, sf := range cmt.cm.storageFolders { 1277 index = sf.index 1278 } 1279 for _, sl := range cmt.cm.sectorLocations { 1280 if sl.count != 1 { 1281 t.Error("Sector location should only be reporting one sector") 1282 } 1283 if sl.storageFolder != index { 1284 t.Error("Sector location is being reported incorrectly - wrong storage folder") 1285 } 1286 if sl.index > 64 { 1287 t.Error("sector index within storage folder also being reported incorrectly") 1288 } 1289 } 1290 // Check the usage. 1291 found := false 1292 for _, u := range cmt.cm.storageFolders[index].usage { 1293 if u != 0 { 1294 found = true 1295 break 1296 } 1297 } 1298 if !found { 1299 t.Error("usage field does not seem to have been updated") 1300 } 1301 1302 // Try reloading the contract manager and see if all of the stateful checks 1303 // still hold. 1304 err = cmt.cm.Close() 1305 if err != nil { 1306 t.Fatal(err) 1307 } 1308 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1309 if err != nil { 1310 t.Fatal(err) 1311 } 1312 1313 // Check that the sector was successfully added. 1314 sfs = cmt.cm.StorageFolders() 1315 if len(sfs) != 1 { 1316 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1317 } 1318 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1319 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity/modules.SectorSize, sfs[0].CapacityRemaining/modules.SectorSize) 1320 } 1321 // Break the rules slightly - make the test brittle by looking at the 1322 // internals directly to determine that the sector got added to the right 1323 // locations, and that the usage information was updated correctly. 1324 if len(cmt.cm.sectorLocations) != 1 { 1325 t.Fatal("there should be one sector reported in the sectorLocations map") 1326 } 1327 if len(cmt.cm.storageFolders) != 1 { 1328 t.Fatal("storage folder not being reported correctly") 1329 } 1330 for _, sf := range cmt.cm.storageFolders { 1331 index = sf.index 1332 } 1333 for _, sl := range cmt.cm.sectorLocations { 1334 if sl.count != 1 { 1335 t.Error("Sector location should only be reporting one sector:", sl.count) 1336 } 1337 if sl.storageFolder != index { 1338 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 1339 } 1340 if sl.index > 64 { 1341 t.Error("sector index within storage folder also being reported incorrectly") 1342 } 1343 } 1344 // Check the usage. 1345 found = false 1346 for _, u := range cmt.cm.storageFolders[index].usage { 1347 if u != 0 { 1348 found = true 1349 break 1350 } 1351 } 1352 if !found { 1353 t.Error("usage field does not seem to have been updated") 1354 } 1355 } 1356 1357 // TestDeleteSectorVirtual tries to delete a sector with virtual pieces from 1358 // the contract manager. 1359 func TestDeleteSectorVirtual(t *testing.T) { 1360 if testing.Short() { 1361 t.SkipNow() 1362 } 1363 t.Parallel() 1364 cmt, err := newContractManagerTester("TestDeleteSectorVirtual") 1365 if err != nil { 1366 t.Fatal(err) 1367 } 1368 defer cmt.panicClose() 1369 1370 // Add a storage folder to the contract manager tester. 1371 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 1372 // Create the storage folder dir. 1373 err = os.MkdirAll(storageFolderDir, 0700) 1374 if err != nil { 1375 t.Fatal(err) 1376 } 1377 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 1378 if err != nil { 1379 t.Fatal(err) 1380 } 1381 1382 // Add two sectors, and then delete one of them. 1383 root, data := randSector() 1384 err = cmt.cm.AddSector(root, data) 1385 if err != nil { 1386 t.Fatal(err) 1387 } 1388 root2, data2 := randSector() 1389 err = cmt.cm.AddSector(root2, data2) 1390 if err != nil { 1391 t.Fatal(err) 1392 } 1393 err = cmt.cm.AddSector(root2, data2) 1394 if err != nil { 1395 t.Fatal(err) 1396 } 1397 err = cmt.cm.DeleteSector(root2) 1398 if err != nil { 1399 t.Fatal(err) 1400 } 1401 1402 // Check that the sector was successfully added. 1403 sfs := cmt.cm.StorageFolders() 1404 if len(sfs) != 1 { 1405 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1406 } 1407 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1408 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 1409 } 1410 // Break the rules slightly - make the test brittle by looking at the 1411 // internals directly to determine that the sector got added to the right 1412 // locations, and that the usage information was updated correctly. 1413 if len(cmt.cm.sectorLocations) != 1 { 1414 t.Fatal("there should be one sector reported in the sectorLocations map") 1415 } 1416 if len(cmt.cm.storageFolders) != 1 { 1417 t.Fatal("storage folder not being reported correctly") 1418 } 1419 var index uint16 1420 for _, sf := range cmt.cm.storageFolders { 1421 index = sf.index 1422 } 1423 for _, sl := range cmt.cm.sectorLocations { 1424 if sl.count != 1 { 1425 t.Error("Sector location should only be reporting one sector") 1426 } 1427 if sl.storageFolder != index { 1428 t.Error("Sector location is being reported incorrectly - wrong storage folder") 1429 } 1430 if sl.index > 64 { 1431 t.Error("sector index within storage folder also being reported incorrectly") 1432 } 1433 } 1434 // Check the usage. 1435 found := false 1436 for _, u := range cmt.cm.storageFolders[index].usage { 1437 if u != 0 { 1438 found = true 1439 break 1440 } 1441 } 1442 if !found { 1443 t.Error("usage field does not seem to have been updated") 1444 } 1445 1446 // Try reloading the contract manager and see if all of the stateful checks 1447 // still hold. 1448 err = cmt.cm.Close() 1449 if err != nil { 1450 t.Fatal(err) 1451 } 1452 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1453 if err != nil { 1454 t.Fatal(err) 1455 } 1456 1457 // Check that the sector was successfully added. 1458 sfs = cmt.cm.StorageFolders() 1459 if len(sfs) != 1 { 1460 t.Fatal("There should be one storage folder in the contract manager", len(sfs)) 1461 } 1462 if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize { 1463 t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining) 1464 } 1465 // Break the rules slightly - make the test brittle by looking at the 1466 // internals directly to determine that the sector got added to the right 1467 // locations, and that the usage information was updated correctly. 1468 if len(cmt.cm.sectorLocations) != 1 { 1469 t.Fatal("there should be one sector reported in the sectorLocations map") 1470 } 1471 if len(cmt.cm.storageFolders) != 1 { 1472 t.Fatal("storage folder not being reported correctly") 1473 } 1474 for _, sf := range cmt.cm.storageFolders { 1475 index = sf.index 1476 } 1477 for _, sl := range cmt.cm.sectorLocations { 1478 if sl.count != 1 { 1479 t.Error("Sector location should only be reporting one sector:", sl.count) 1480 } 1481 if sl.storageFolder != index { 1482 t.Error("Sector location is being reported incorrectly - wrong storage folder", sl.storageFolder, index) 1483 } 1484 if sl.index > 64 { 1485 t.Error("sector index within storage folder also being reported incorrectly") 1486 } 1487 } 1488 // Check the usage. 1489 found = false 1490 for _, u := range cmt.cm.storageFolders[index].usage { 1491 if u != 0 { 1492 found = true 1493 break 1494 } 1495 } 1496 if !found { 1497 t.Error("usage field does not seem to have been updated") 1498 } 1499 } 1500 1501 // TestSectorBalancing checks that the contract manager evenly balances sectors 1502 // between storage folders. 1503 func TestSectorBalancing(t *testing.T) { 1504 if testing.Short() { 1505 t.SkipNow() 1506 } 1507 t.Parallel() 1508 cmt, err := newContractManagerTester("TestSectorBalancing") 1509 if err != nil { 1510 t.Fatal(err) 1511 } 1512 defer cmt.panicClose() 1513 1514 // Add a storage folder to the contract manager tester. 1515 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 1516 err = os.MkdirAll(storageFolderDir, 0700) 1517 if err != nil { 1518 t.Fatal(err) 1519 } 1520 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64) 1521 if err != nil { 1522 t.Fatal(err) 1523 } 1524 // Add a second storage folder. 1525 storageFolderDir2 := filepath.Join(cmt.persistDir, "storageFolderTwo") 1526 err = os.MkdirAll(storageFolderDir2, 0700) 1527 if err != nil { 1528 t.Fatal(err) 1529 } 1530 err = cmt.cm.AddStorageFolder(storageFolderDir2, modules.SectorSize*64) 1531 if err != nil { 1532 t.Fatal(err) 1533 } 1534 // Add a third storage folder, twice as large. 1535 storageFolderDir3 := filepath.Join(cmt.persistDir, "storageFolderThree") 1536 err = os.MkdirAll(storageFolderDir3, 0700) 1537 if err != nil { 1538 t.Fatal(err) 1539 } 1540 err = cmt.cm.AddStorageFolder(storageFolderDir3, modules.SectorSize*64*2) 1541 if err != nil { 1542 t.Fatal(err) 1543 } 1544 1545 // Add 20 sectors. 1546 var wg sync.WaitGroup 1547 for i := 0; i < 20; i++ { 1548 wg.Add(1) 1549 go func() { 1550 defer wg.Done() 1551 err := cmt.cm.AddSector(randSector()) 1552 if err != nil { 1553 t.Fatal(err) 1554 } 1555 }() 1556 } 1557 wg.Wait() 1558 1559 // Verify that that all 20 sectors were accepted. 1560 sfs := cmt.cm.StorageFolders() 1561 if len(sfs) != 3 { 1562 t.Fatal("There should be two storage folders in the contract manager", len(sfs)) 1563 } 1564 if sfs[0].Capacity+sfs[1].Capacity+sfs[2].Capacity != sfs[0].CapacityRemaining+sfs[1].CapacityRemaining+sfs[2].CapacityRemaining+modules.SectorSize*20 { 1565 t.Error("sectors do not appear to have been added correctly") 1566 } 1567 // Break the rules slightly - make the test brittle by looking at the 1568 // internals directly to determine that the sector got added to the right 1569 // locations, and that the usage information was updated correctly. 1570 if len(cmt.cm.sectorLocations) != 20 { 1571 t.Fatal("there should be one sector reported in the sectorLocations map") 1572 } 1573 if len(cmt.cm.storageFolders) != 3 { 1574 t.Fatal("storage folder not being reported correctly") 1575 } 1576 // Check a storage folder at random, verify that the sectors are sane. 1577 var index uint16 1578 for _, sf := range cmt.cm.storageFolders { 1579 index = sf.index 1580 } 1581 for _, sl := range cmt.cm.sectorLocations { 1582 if sl.storageFolder != index { 1583 continue 1584 } 1585 if sl.count != 1 { 1586 t.Error("Sector location should only be reporting one sector") 1587 } 1588 if sl.index > 64*2 { 1589 t.Error("sector index within storage folder also being reported incorrectly") 1590 } 1591 } 1592 1593 // Try reloading the contract manager and see if all of the stateful checks 1594 // still hold. 1595 err = cmt.cm.Close() 1596 if err != nil { 1597 t.Fatal(err) 1598 } 1599 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1600 if err != nil { 1601 t.Fatal(err) 1602 } 1603 1604 // Verify that that all 20 sectors were accepted, and that they have been 1605 // distributed evenly between storage folders. 1606 sfs = cmt.cm.StorageFolders() 1607 if len(sfs) != 3 { 1608 t.Fatal("There should be two storage folders in the contract manager", len(sfs)) 1609 } 1610 if sfs[0].Capacity+sfs[1].Capacity+sfs[2].Capacity != sfs[0].CapacityRemaining+sfs[1].CapacityRemaining+sfs[2].CapacityRemaining+modules.SectorSize*20 { 1611 t.Error("sectors do not appear to have been added correctly") 1612 } 1613 // Break the rules slightly - make the test brittle by looking at the 1614 // internals directly to determine that the sector got added to the right 1615 // locations, and that the usage information was updated correctly. 1616 if len(cmt.cm.sectorLocations) != 20 { 1617 t.Fatal("there should be twenty sectors reported in the sectorLocations map:", len(cmt.cm.sectorLocations)) 1618 } 1619 if len(cmt.cm.storageFolders) != 3 { 1620 t.Fatal("storage folder not being reported correctly") 1621 } 1622 // Check a storage folder at random, verify that the sectors are sane. 1623 for _, sf := range cmt.cm.storageFolders { 1624 index = sf.index 1625 } 1626 for _, sl := range cmt.cm.sectorLocations { 1627 if sl.storageFolder != index { 1628 continue 1629 } 1630 if sl.count != 1 { 1631 t.Error("Sector location should only be reporting one sector") 1632 } 1633 if sl.index > 64*2 { 1634 t.Error("sector index within storage folder also being reported incorrectly") 1635 } 1636 } 1637 } 1638 1639 // dependencyFailingWrites is a mocked dependency that will prevent file writes 1640 // for some files. 1641 type dependencyFailingWrites struct { 1642 modules.ProductionDependencies 1643 triggered *bool 1644 mu *sync.Mutex 1645 } 1646 1647 // failureProneFile will begin returning failures on Write for files with 1648 // names/paths containing the string "storageFolderOne" after d.triggered has 1649 // been set to "true". 1650 type failureProneFile struct { 1651 triggered *bool 1652 mu *sync.Mutex 1653 *os.File 1654 sync.Mutex 1655 } 1656 1657 // createFile will return a file which will cause errors on Write calls if 1658 // "storageFolderOne" is in the filepath. 1659 func (d *dependencyFailingWrites) CreateFile(s string) (modules.File, error) { 1660 osfile, err := os.Create(s) 1661 if err != nil { 1662 return nil, err 1663 } 1664 1665 fpf := &failureProneFile{ 1666 triggered: d.triggered, 1667 mu: d.mu, 1668 File: osfile, 1669 } 1670 return fpf, nil 1671 } 1672 1673 // Write returns an error if the errors in the dependency have been triggered, 1674 // and if this file belongs to "storageFolderOne". 1675 func (fpf *failureProneFile) WriteAt(b []byte, offset int64) (int, error) { 1676 fpf.mu.Lock() 1677 triggered := *fpf.triggered 1678 fpf.mu.Unlock() 1679 1680 name := fpf.Name() 1681 if triggered && strings.Contains(name, "storageFolderOne") { 1682 return 0, errors.New("storage folder is failing") 1683 } 1684 return fpf.File.WriteAt(b, offset) 1685 } 1686 1687 // TestFailingStorageFolder checks that the contract manager can continue when 1688 // a storage folder is failing. 1689 func TestFailingStorageFolder(t *testing.T) { 1690 if testing.Short() { 1691 t.SkipNow() 1692 } 1693 t.Parallel() 1694 d := new(dependencyFailingWrites) 1695 d.mu = new(sync.Mutex) 1696 d.triggered = new(bool) 1697 cmt, err := newMockedContractManagerTester(d, "TestFailingStorageFolder") 1698 if err != nil { 1699 t.Fatal(err) 1700 } 1701 defer cmt.panicClose() 1702 1703 // Add a storage folder to the contract manager tester. 1704 storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne") 1705 err = os.MkdirAll(storageFolderDir, 0700) 1706 if err != nil { 1707 t.Fatal(err) 1708 } 1709 err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*64*2) 1710 if err != nil { 1711 t.Fatal(err) 1712 } 1713 // Add a second storage folder. 1714 storageFolderDir2 := filepath.Join(cmt.persistDir, "storageFolderTwo") 1715 err = os.MkdirAll(storageFolderDir2, 0700) 1716 if err != nil { 1717 t.Fatal(err) 1718 } 1719 err = cmt.cm.AddStorageFolder(storageFolderDir2, modules.SectorSize*64*2) 1720 if err != nil { 1721 t.Fatal(err) 1722 } 1723 1724 // Add 50 sectors. 1725 var wg sync.WaitGroup 1726 for i := 0; i < 50; i++ { 1727 wg.Add(1) 1728 go func() { 1729 defer wg.Done() 1730 err := cmt.cm.AddSector(randSector()) 1731 if err != nil { 1732 t.Fatal(err) 1733 } 1734 }() 1735 } 1736 wg.Wait() 1737 1738 // Verify that that all 20 sectors were accepted, and that they have been 1739 // distributed evenly between storage folders. 1740 sfs := cmt.cm.StorageFolders() 1741 if len(sfs) != 2 { 1742 t.Fatal("There should be two storage folders in the contract manager", len(sfs)) 1743 } 1744 if sfs[0].Capacity+sfs[1].Capacity != sfs[0].CapacityRemaining+sfs[1].CapacityRemaining+modules.SectorSize*50 { 1745 t.Error("expecting 20 sectors consumed:", sfs[0].Capacity+sfs[1].Capacity, sfs[0].CapacityRemaining+sfs[1].CapacityRemaining-modules.SectorSize*50) 1746 } 1747 // Break the rules slightly - make the test brittle by looking at the 1748 // internals directly to determine that the sector got added to the right 1749 // locations, and that the usage information was updated correctly. 1750 if len(cmt.cm.sectorLocations) != 50 { 1751 t.Fatal("there should be one sector reported in the sectorLocations map") 1752 } 1753 if len(cmt.cm.storageFolders) != 2 { 1754 t.Fatal("storage folder not being reported correctly") 1755 } 1756 // Check a storage folder at random, verify that the sectors are sane. 1757 var index uint16 1758 for _, sf := range cmt.cm.storageFolders { 1759 index = sf.index 1760 } 1761 for _, sl := range cmt.cm.sectorLocations { 1762 if sl.storageFolder != index { 1763 continue 1764 } 1765 if sl.count != 1 { 1766 t.Error("Sector location should only be reporting one sector") 1767 } 1768 if sl.index > 128 { 1769 t.Error("sector index within storage folder also being reported incorrectly") 1770 } 1771 } 1772 1773 // Trigger one of the storage folders to begin failing. 1774 d.mu.Lock() 1775 *d.triggered = true 1776 d.mu.Unlock() 1777 1778 // Add 50 more sectors. 1779 for i := 0; i < 50; i++ { 1780 wg.Add(1) 1781 go func() { 1782 defer wg.Done() 1783 err := cmt.cm.AddSector(randSector()) 1784 if err != nil { 1785 t.Fatal(err) 1786 } 1787 }() 1788 } 1789 wg.Wait() 1790 1791 // Verify that that all 20 sectors were accepted, and that they have been 1792 // added to storageFolderTwo. 1793 sfs = cmt.cm.StorageFolders() 1794 if len(sfs) != 2 { 1795 t.Fatal("There should be two storage folders in the contract manager", len(sfs)) 1796 } 1797 if strings.Contains(sfs[0].Path, "storageFolderTwo") { 1798 // sfs[0] is the working one, should have strictly more than 50 1799 // sectors. 1800 if sfs[0].CapacityRemaining+modules.SectorSize*50 >= sfs[0].Capacity { 1801 t.Error("expecting more than 50 sectors in sfs0") 1802 } 1803 if sfs[1].CapacityRemaining+modules.SectorSize*50 <= sfs[1].Capacity { 1804 t.Error("expecting less than 50 sectors in sfs1") 1805 } 1806 if sfs[1].FailedWrites == 0 { 1807 t.Error("failed write not reported in storage folder stats") 1808 } 1809 } else { 1810 // sfs[1] is the working one, should have strictly more than 50 1811 // sectors. 1812 if sfs[1].CapacityRemaining+modules.SectorSize*50 >= sfs[1].Capacity { 1813 t.Error("expecting more than 50 sectors in sfs1") 1814 } 1815 if sfs[0].CapacityRemaining+modules.SectorSize*50 <= sfs[0].Capacity { 1816 t.Error("expecting less than 50 sectors in sfs0") 1817 } 1818 if sfs[0].FailedWrites == 0 { 1819 t.Error("failed write not reported in storage folder stats") 1820 } 1821 } 1822 // Break the rules slightly - make the test brittle by looking at the 1823 // internals directly to determine that the sector got added to the right 1824 // locations, and that the usage information was updated correctly. 1825 if len(cmt.cm.sectorLocations) != 100 { 1826 t.Fatal("there should be one sector reported in the sectorLocations map") 1827 } 1828 if len(cmt.cm.storageFolders) != 2 { 1829 t.Fatal("storage folder not being reported correctly") 1830 } 1831 // Check a storage folder at random, verify that the sectors are sane. 1832 for _, sf := range cmt.cm.storageFolders { 1833 index = sf.index 1834 } 1835 for _, sl := range cmt.cm.sectorLocations { 1836 if sl.storageFolder != index { 1837 continue 1838 } 1839 if sl.count != 1 { 1840 t.Error("Sector location should only be reporting one sector") 1841 } 1842 if sl.index > 128 { 1843 t.Error("sector index within storage folder also being reported incorrectly") 1844 } 1845 } 1846 1847 // Try reloading the contract manager and see if all of the stateful checks 1848 // still hold. 1849 err = cmt.cm.Close() 1850 if err != nil { 1851 t.Fatal(err) 1852 } 1853 cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir)) 1854 if err != nil { 1855 t.Fatal(err) 1856 } 1857 1858 // Verify that that all 20 sectors were accepted, and that they have been 1859 // added to storageFolderTwo. 1860 sfs = cmt.cm.StorageFolders() 1861 if len(sfs) != 2 { 1862 t.Fatal("There should be two storage folders in the contract manager", len(sfs)) 1863 } 1864 if strings.Contains(sfs[0].Path, "storageFolderTwo") { 1865 // sfs[0] is the working one, should have strictly more than 50 1866 // sectors. 1867 if sfs[0].CapacityRemaining+modules.SectorSize*50 >= sfs[0].Capacity { 1868 t.Error("expecting more than 50 sectors in sfs0") 1869 } 1870 if sfs[1].CapacityRemaining+modules.SectorSize*50 <= sfs[1].Capacity { 1871 t.Error("expecting less than 50 sectors in sfs1") 1872 } 1873 } else { 1874 // sfs[1] is the working one, should have strictly more than 50 1875 // sectors. 1876 if sfs[1].CapacityRemaining+modules.SectorSize*50 >= sfs[1].Capacity { 1877 t.Error("expecting more than 50 sectors in sfs1") 1878 } 1879 if sfs[0].CapacityRemaining+modules.SectorSize*50 <= sfs[0].Capacity { 1880 t.Error("expecting less than 50 sectors in sfs0") 1881 } 1882 } 1883 1884 // Break the rules slightly - make the test brittle by looking at the 1885 // internals directly to determine that the sector got added to the right 1886 // locations, and that the usage information was updated correctly. 1887 if len(cmt.cm.sectorLocations) != 100 { 1888 t.Fatal("there should be one sector reported in the sectorLocations map") 1889 } 1890 if len(cmt.cm.storageFolders) != 2 { 1891 t.Fatal("storage folder not being reported correctly") 1892 } 1893 // Check a storage folder at random, verify that the sectors are sane. 1894 for _, sf := range cmt.cm.storageFolders { 1895 index = sf.index 1896 } 1897 for _, sl := range cmt.cm.sectorLocations { 1898 if sl.storageFolder != index { 1899 continue 1900 } 1901 if sl.count != 1 { 1902 t.Error("Sector location should only be reporting one sector") 1903 } 1904 if sl.index > 128 { 1905 t.Error("sector index within storage folder also being reported incorrectly") 1906 } 1907 } 1908 }