func TestAddStorageFolderConsecutive(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	cmt, err := newContractManagerTester("TestAddStorageFolderConsecutive")
	if err != nil {
		t.Fatal(err)
	}
	defer cmt.panicClose()
	storageFolderOne := filepath.Join(cmt.persistDir, "storageFolderOne")
	storageFolderTwo := filepath.Join(cmt.persistDir, "storageFolderTwo")
	storageFolderThree := filepath.Join(cmt.persistDir, "storageFolderThree")
	err = os.MkdirAll(storageFolderOne, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderTwo, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderThree, 0700)
	if err != nil {
		t.Fatal(err)
	}
	sfSize := modules.SectorSize * storageFolderGranularity * 8
	err = cmt.cm.AddStorageFolder(storageFolderOne, sfSize)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderTwo, sfSize)
	if err != nil {
		t.Fatal(err)
	}
	err = cmt.cm.AddStorageFolder(storageFolderThree, sfSize)
	if err != nil {
		t.Fatal(err)
	}
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 3 {
		t.Fatal("There should be one storage folder reported")
	}
	for _, sf := range sfs {
		if sf.ProgressDenominator != 0 {
			t.Error("ProgressDenominator is indicating that actions still remain")
		}
	}
}
TestAddStorageFolderConsecutive adds multiple storage folders consecutively
to the contract manager, blocking on the first one to make sure that the
others are still allowed to complete.
package contractmanager
import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"
	"github.com/NebulousLabs/Sia/modules"
)
func TestAddStorageFolder(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	cmt, err := newContractManagerTester("TestAddStorageFolder")
	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")
	}
}
type dependencyLargeFolder struct {
	modules.ProductionDependencies
}
type limitFile struct {
	throughput int64
	mu         sync.Mutex
	*os.File
	sync.Mutex
}
func (*dependencyLargeFolder) CreateFile(s string) (modules.File, error) {
	osFile, err := os.Create(s)
	if err != nil {
		return nil, err
	}
	lf := &limitFile{
		File: osFile,
	}
	return lf, nil
}
func (l *limitFile) Truncate(offset int64) error {
	l.mu.Lock()
	defer l.mu.Unlock()
	if l.throughput >= 1<<20 {
		return errors.New("limitFile throughput limit reached earlier")
	}
	fi, err := l.Stat()
	if err != nil {
		return errors.New("limitFile could not fetch fileinfo: " + err.Error())
	}
	if fi.Size() > offset {
		return l.File.Truncate(offset)
	}
	writeSize := offset - fi.Size()
	if l.throughput+writeSize <= 1<<20 {
		l.throughput += writeSize
		return l.File.Truncate(offset)
	}
	return errors.New("limitFile throughput limit reached before all input was written to disk")
}
func TestAddLargeStorageFolder(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	d := new(dependencyLargeFolder)
	cmt, err := newMockedContractManagerTester(d, "TestAddLargeStorageFolder")
	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)
	}
	addErr := cmt.cm.AddStorageFolder(storageFolderDir, modules.SectorSize*storageFolderGranularity*16)  
	if addErr == nil {
		t.Fatal(err)
	}
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 0 {
		t.Fatal("Storage folder add should have failed.")
	}
	files, err := ioutil.ReadDir(storageFolderDir)
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 0 {
		t.Log(addErr)
		t.Error("there should not be any files in the storage folder because the AddStorageFolder operation failed.")
		t.Error(len(files))
		for _, file := range files {
			t.Error(file.Name())
		}
	}
}
func TestAddStorageFolderConcurrent(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	cmt, err := newContractManagerTester("TestAddStorageFolderConcurrent")
	if err != nil {
		t.Fatal(err)
	}
	defer cmt.panicClose()
	storageFolderOne := filepath.Join(cmt.persistDir, "storageFolderOne")
	storageFolderTwo := filepath.Join(cmt.persistDir, "storageFolderTwo")
	storageFolderThree := filepath.Join(cmt.persistDir, "storageFolderThree")
	err = os.MkdirAll(storageFolderOne, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderTwo, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderThree, 0700)
	if err != nil {
		t.Fatal(err)
	}
	var wg sync.WaitGroup
	wg.Add(3)
	go func() {
		defer wg.Done()
		err := cmt.cm.AddStorageFolder(storageFolderOne, modules.SectorSize*storageFolderGranularity*8)
		if err != nil {
			t.Fatal(err)
		}
	}()
	go func() {
		defer wg.Done()
		err := cmt.cm.AddStorageFolder(storageFolderTwo, modules.SectorSize*storageFolderGranularity*8)
		if err != nil {
			t.Fatal(err)
		}
	}()
	go func() {
		defer wg.Done()
		err = cmt.cm.AddStorageFolder(storageFolderThree, modules.SectorSize*storageFolderGranularity*8)
		if err != nil {
			t.Fatal(err)
		}
	}()
	wg.Wait()
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 3 {
		t.Fatal("There should be one storage folder reported")
	}
}
type dependencyBlockSFOne struct {
	blockLifted chan struct{}
	writeCalled chan struct{}
	modules.ProductionDependencies
}
type blockedFile struct {
	blockLifted chan struct{}
	writeCalled chan struct{}
	*os.File
	sync.Mutex
}
func (bf *blockedFile) Truncate(offset int64) error {
	if !strings.Contains(bf.File.Name(), "storageFolderOne") || strings.Contains(bf.File.Name(), "siahostmetadata.dat") {
		return bf.File.Truncate(offset)
	}
	close(bf.writeCalled)
	<-bf.blockLifted
	return bf.File.Truncate(offset)
}
func (d *dependencyBlockSFOne) CreateFile(s string) (modules.File, error) {
	if strings.Contains(s, "storageFolderOne") {
		file, err := os.Create(s)
		if err != nil {
			return nil, err
		}
		bf := &blockedFile{
			blockLifted: d.blockLifted,
			writeCalled: d.writeCalled,
			File:        file,
		}
		return bf, nil
	}
	return os.Create(s)
}
func TestAddStorageFolderBlocking(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	d := &dependencyBlockSFOne{
		blockLifted: make(chan struct{}),
		writeCalled: make(chan struct{}),
	}
	cmt, err := newMockedContractManagerTester(d, "TestAddStorageFolderBlocking")
	if err != nil {
		t.Fatal(err)
	}
	defer cmt.panicClose()
	storageFolderOne := filepath.Join(cmt.persistDir, "storageFolderOne")
	storageFolderTwo := filepath.Join(cmt.persistDir, "storageFolderTwo")
	storageFolderThree := filepath.Join(cmt.persistDir, "storageFolderThree")
	err = os.MkdirAll(storageFolderOne, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderTwo, 0700)
	if err != nil {
		t.Fatal(err)
	}
	err = os.MkdirAll(storageFolderThree, 0700)
	if err != nil {
		t.Fatal(err)
	}
	sfOneSize := modules.SectorSize * storageFolderGranularity * 8
	go func() {
		err := cmt.cm.AddStorageFolder(storageFolderOne, sfOneSize)
		if err != nil {
			t.Fatal(err)
		}
	}()
	select {
	case <-time.After(time.Second * 5):
		t.Fatal("storage folder not written out")
	case <-d.writeCalled:
	}
	sfs := cmt.cm.StorageFolders()
	if len(sfs) != 1 {
		t.Fatal("there should be one storage folder reported")
	}
	if sfs[0].ProgressNumerator != 0 {
		t.Error("storage folder is showing progress despite being blocked")
	}
	if sfs[0].ProgressDenominator != sfOneSize+sectorMetadataDiskSize*storageFolderGranularity*8 {
		t.Error("storage folder is not showing that an action is in progress, though one is", sfs[0].ProgressDenominator, sfOneSize)
	}
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		err := cmt.cm.AddStorageFolder(storageFolderTwo, modules.SectorSize*storageFolderGranularity*8)
		if err != nil {
			t.Fatal(err)
		}
	}()
	go func() {
		defer wg.Done()
		err = cmt.cm.AddStorageFolder(storageFolderThree, modules.SectorSize*storageFolderGranularity*8)
		if err != nil {
			t.Fatal(err)
		}
	}()
	wg.Wait()
	close(d.blockLifted)
	cmt.cm.tg.Flush()
	sfs = cmt.cm.StorageFolders()
	if len(sfs) != 3 {
		t.Fatal("There should be one storage folder reported")
	}
	for _, sf := range sfs {
		if sf.ProgressDenominator != 0 {
			t.Error("ProgressDenominator is indicating that actions still remain")
		}
	}
}