func TestFolderRechecker(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	cmt, err := newContractManagerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer cmt.panicClose()
	storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne")
	err = os.MkdirAll(storageFolderDir, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*storageFolderGranularity*2)
	if err != nil {
		t.Fatal(err)
	}
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("There should be one storage folder reported")
	}
	if sfs[0].Path != storageFolderDir {
		t.Error("storage folder reported with wrong path")
	}
	if sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("storage folder reported with wrong sector size")
	}
	root, data := randSector()
	err = cmt.cm.AddSector(root, data)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("There should be one storage folder in the contract manager", len(sfs))
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	err = os.Rename(storageFolderDir, storageFolderDir+"-moved")
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].FailedReads < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].FailedWrites < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	err = os.Rename(storageFolderDir+"-moved", storageFolderDir)
	if err != nil {
		t.Fatal(err)
	}
	time.Sleep(maxFolderRecheckInterval)
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].FailedReads != 0 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].FailedWrites != 0 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	recoveredData, err := cmt.cm.ReadSector(root)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(recoveredData, data) {
		t.Error("recovered data does not equal original data")
	}
	root2, data2 := randSector()
	err = cmt.cm.AddSector(root2, data2)
	if err != nil {
		t.Error("should not be able to add sector")
	}
	recoveredData, err = cmt.cm.ReadSector(root2)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(recoveredData, data2) {
		t.Error("recovered data does not equal original data")
	}
	err = cmt.cm.ResizeStorageFolder(sfs[0].Index, modules.SectorSize*storageFolderGranularity*4, false)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize*2 {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	if sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*4 {
		t.Error("the storage folder growth does not seem to have worked")
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = New(filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	recoveredData, err = cmt.cm.ReadSector(root)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(recoveredData, data) {
		t.Error("recovered data does not equal original data")
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize*2 {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	if sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*4 {
		t.Error("the storage folder growth does not seem to have worked")
	}
}
TestFolderRechecker verifies that the folder rechecker is able to discover
when a storage folder has become available again.
package contractmanager
import (
	"bytes"
	"os"
	"path/filepath"
	"sync"
	"testing"
	"time"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
)
type dependencyNoRecheck struct {
	modules.ProductionDependencies
}
func (*dependencyNoRecheck) Disrupt(s string) bool {
	if s == "noRecheck" {
		return true
	}
	return false
}
func TestLoadMissingStorageFolder(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	cmt, err := newContractManagerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer cmt.panicClose()
	storageFolderDir := filepath.Join(cmt.persistDir, "storageFolderOne")
	err = os.MkdirAll(storageFolderDir, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*storageFolderGranularity*2)
	if err != nil {
		t.Fatal(err)
	}
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("There should be one storage folder reported")
	}
	if sfs[0].Path != storageFolderDir {
		t.Error("storage folder reported with wrong path")
	}
	if sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("storage folder reported with wrong sector size")
	}
	root, data := randSector()
	err = cmt.cm.AddSector(root, data)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("There should be one storage folder in the contract manager", len(sfs))
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	sfOneIndex := sfs[0].Index
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	err = os.Rename(storageFolderDir, storageFolderDir+"-moved")
	if err != nil {
		t.Fatal(err)
	}
	d := new(dependencyNoRecheck)
	cmt.cm, err = newContractManager(d, filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].FailedReads < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].FailedWrites < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize {
		t.Error("One sector's worth of capacity should be consumed:", sfs[0].Capacity, sfs[0].CapacityRemaining)
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = newContractManager(d, filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("wrong number of storage folders being reported")
	}
	if sfs[0].FailedReads < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	if sfs[0].FailedWrites < 100000000 {
		t.Error("Not enough failures reported for absent storage folder")
	}
	_, err = cmt.cm.ReadSector(root)
	if err == nil {
		t.Fatal("Expecting error when reading missing sector.")
	}
	rootF, dataF := randSector()
	err = cmt.cm.AddSector(rootF, dataF)
	if err == nil {
		t.Error("should not be able to add sector")
	}
	storageFolderTwo := filepath.Join(cmt.persistDir, "storageFolderTwo")
	err = os.MkdirAll(storageFolderTwo, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderTwo, modules.SectorSize*storageFolderGranularity*2)
	if err != nil {
		t.Fatal(err)
	}
	root2, data2 := randSector()
	err = cmt.cm.AddSector(root2, data2)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("There should be one storage folder in the contract manager", len(sfs))
	}
	for i := range sfs {
		if sfs[i].Capacity != sfs[i].CapacityRemaining+modules.SectorSize {
			t.Error("One sector's worth of capacity should be consumed:", sfs[i].Capacity, sfs[i].CapacityRemaining, sfs[i].Path)
		}
	}
	var sfTwoIndex uint16
	if sfs[0].Index == sfOneIndex {
		sfTwoIndex = sfs[1].Index
	} else {
		sfTwoIndex = sfs[0].Index
	}
	root3, data3 := randSector()
	err = cmt.cm.AddSector(root3, data3)
	if err != nil {
		t.Fatal(err)
	}
	root4, data4 := randSector()
	err = cmt.cm.AddSector(root4, data4)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("There should be one storage folder in the contract manager", len(sfs))
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining+modules.SectorSize*3 && sfs[1].Capacity != sfs[1].CapacityRemaining+modules.SectorSize*3 {
		t.Error("One sector's worth of capacity should be consumed")
	}
	err = cmt.cm.ResizeStorageFolder(sfOneIndex, modules.SectorSize*storageFolderGranularity, false)
	if err == nil {
		t.Fatal("should not be able to resize a missing storage folder")
	}
	err = cmt.cm.ResizeStorageFolder(sfOneIndex, modules.SectorSize*storageFolderGranularity, true)
	if err == nil {
		t.Fatal("should not be able to resize a missing storage folder")
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("wrong storage folder count")
	}
	if sfs[0].Index == sfOneIndex && sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("Storage folder has wrong size after failing to resize")
	}
	if sfs[1].Index == sfOneIndex && sfs[1].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("Storage folder has wrong size after failing to resize")
	}
	err = cmt.cm.ResizeStorageFolder(sfOneIndex, modules.SectorSize*storageFolderGranularity*4, false)
	if err == nil {
		t.Fatal("should not be able to resize a missing storage folder")
	}
	err = cmt.cm.ResizeStorageFolder(sfOneIndex, modules.SectorSize*storageFolderGranularity*4, true)
	if err == nil {
		t.Fatal("should not be able to resize a missing storage folder")
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("wrong storage folder count")
	}
	if sfs[0].Index == sfOneIndex && sfs[0].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("Storage folder has wrong size after failing to resize")
	}
	if sfs[1].Index == sfOneIndex && sfs[1].Capacity != modules.SectorSize*storageFolderGranularity*2 {
		t.Error("Storage folder has wrong size after failing to resize")
	}
	err = cmt.cm.DeleteSector(root2)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.DeleteSector(root3)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.DeleteSector(root4)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("There should be one storage folder in the contract manager", len(sfs))
	}
	if sfs[0].Capacity != sfs[0].CapacityRemaining && sfs[1].Capacity != sfs[1].CapacityRemaining {
		t.Error("Deleted sector does not seem to have been deleted correctly.")
	}
	_, err = cmt.cm.ReadSector(root2)
	if err == nil {
		t.Fatal("should get an error when reading a deleted sector")
	}
	err = cmt.cm.ResizeStorageFolder(sfTwoIndex, modules.SectorSize*storageFolderGranularity*4, false)
	if err != nil {
		t.Fatal(err)
	}
	num := int(storageFolderGranularity*3 + 2)
	roots := make([]crypto.Hash, num)
	datas := make([][]byte, num)
	var wg sync.WaitGroup  
	for i := 0; i < num; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			rootI, dataI := randSector()
			roots[i] = rootI
			datas[i] = dataI
			err := cmt.cm.AddSector(rootI, dataI)
			if err != nil {
				t.Fatal(err)
			}
		}(i)
	}
	wg.Wait()
	storageFolderThree := filepath.Join(cmt.persistDir, "storageFolderThree")
	err = os.MkdirAll(storageFolderThree, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderThree, modules.SectorSize*storageFolderGranularity)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.ResizeStorageFolder(sfTwoIndex, modules.SectorSize*storageFolderGranularity*3, false)
	if err != nil {
		t.Fatal(err)
	}
	for i := range roots {
		data, err := cmt.cm.ReadSector(roots[i])
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(data, datas[i]) {
			t.Error("read sector does not have the same data that was inserted")
		}
	}
	err = cmt.cm.ResizeStorageFolder(sfTwoIndex, modules.SectorSize*storageFolderGranularity*2, false)
	if err == nil {
		t.Fatal("expected an error")
	}
	for i := range roots {
		data, err := cmt.cm.ReadSector(roots[i])
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(data, datas[i]) {
			t.Error("read sector does not have the same data that was inserted")
		}
	}
	err = cmt.cm.ResizeStorageFolder(sfTwoIndex, modules.SectorSize*storageFolderGranularity, true)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.RemoveStorageFolder(sfTwoIndex, false)
	if err == nil {
		t.Fatal("should have gotten an error when trying to remove the storage folder.")
	}
	err = cmt.cm.RemoveStorageFolder(sfTwoIndex, true)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	err = os.Rename(storageFolderDir+"-moved", storageFolderDir)
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = newContractManager(d, filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Fatal("wrong number of storage folders being reported")
	}
	var sfOne modules.StorageFolderMetadata
	for _, sf := range sfs {
		if sf.Index == sfOneIndex {
			sfOne = sf
		}
	}
	if sfOne.FailedReads > 0 {
		t.Error("folder should be visible again")
	}
	if sfOne.FailedWrites > 0 {
		t.Error("folder should be visible again")
	}
	if sfOne.Capacity != sfOne.CapacityRemaining+modules.SectorSize {
		cmt.cm.wal.mu.Lock()
		t.Log("Usage len:", len(cmt.cm.storageFolders[sfOne.Index].usage))
		t.Log("Reported Sectors:", cmt.cm.storageFolders[sfOne.Index].sectors)
		t.Log("Avail:", len(cmt.cm.storageFolders[sfOne.Index].availableSectors))
		cmt.cm.wal.mu.Unlock()
		t.Error("One sector's worth of capacity should be consumed:", sfOne.Capacity, sfOne.CapacityRemaining)
	}
	recoveredData, err := cmt.cm.ReadSector(root)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(recoveredData, data) {
		t.Error("recovered data is not equal to original data")
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	err = os.Rename(storageFolderDir, storageFolderDir+"-moved")
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = newContractManager(d, filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.RemoveStorageFolder(sfOneIndex, false)
	if err == nil {
		t.Fatal("should have gotten an error")
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 2 {
		t.Error("there should be two storage folders after a removal failed.")
	}
	err = cmt.cm.RemoveStorageFolder(sfOneIndex, true)
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Error("there should be only one storage folder remaining")
	}
	err = cmt.cm.Close()
	if err != nil {
		t.Fatal(err)
	}
	cmt.cm, err = newContractManager(d, filepath.Join(cmt.persistDir, modules.ContractManagerDir))
	if err != nil {
		t.Fatal(err)
	}
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Error("there should be only one storage folder remaining")
	}
}