func TestAddSameFolderTwice(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	addValues := url.Values{}
	addValues.Set("path", st.dir)
	addValues.Set("size", mediumSizeFolderString)
	err = st.stdPostAPI("/host/storage/folders/add", addValues)
	if err != nil {
		t.Fatal(err)
	}
	err = st.stdPostAPI("/host/storage/folders/add", addValues)
	if err == nil || err.Error() != contractmanager.ErrRepeatFolder.Error() {
		t.Fatalf("expected err to be %v, got %v", err, contractmanager.ErrRepeatFolder)
	}
}
TestAddSameFolderTwice tests that an API call that attempts to add a
host storage folder that's already been added is handled gracefully.
package api
import (
	"errors"
	"fmt"
	"io"
	"net/url"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"testing"
	"time"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/host/contractmanager"
	"github.com/NebulousLabs/Sia/types"
)
var (
	minFolderSizeString    = strconv.FormatUint(modules.SectorSize*contractmanager.MinimumSectorsPerStorageFolder, 10)
	maxFolderSizeString    = strconv.FormatUint(modules.SectorSize*contractmanager.MaximumSectorsPerStorageFolder, 10)
	tooSmallFolderString   = strconv.FormatUint(modules.SectorSize*(contractmanager.MinimumSectorsPerStorageFolder-1), 10)
	tooLargeFolderString   = strconv.FormatUint(modules.SectorSize*(contractmanager.MaximumSectorsPerStorageFolder+1), 10)
	mediumSizeFolderString = strconv.FormatUint(modules.SectorSize*contractmanager.MinimumSectorsPerStorageFolder*3, 10)
	resizeTests = []struct {
		sizeString string
		size       uint64
		err        error
	}{
		{"", 0, io.EOF},
		{"0", 0, contractmanager.ErrSmallStorageFolder},
		{tooSmallFolderString, modules.SectorSize * (contractmanager.MinimumSectorsPerStorageFolder - 1), contractmanager.ErrSmallStorageFolder},
		{tooLargeFolderString, modules.SectorSize * (contractmanager.MaximumSectorsPerStorageFolder + 1), contractmanager.ErrLargeStorageFolder},
	}
)
func TestEstimateWeight(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	if err := st.announceHost(); err != nil {
		t.Fatal(err)
	}
	if err := st.acceptContracts(); err != nil {
		t.Fatal(err)
	}
	if err := st.setHostStorage(); err != nil {
		t.Fatal(err)
	}
	var eg HostEstimateScoreGET
	if err := st.getAPI("/host/estimatescore", &eg); err != nil {
		t.Fatal(err)
	}
	originalEstimate := eg.EstimatedScore
	is := st.host.InternalSettings()
	is.MinContractPrice = is.MinContractPrice.Add(types.SiacoinPrecision.Mul64(9999999999))
	if err := st.host.SetInternalSettings(is); err != nil {
		t.Fatal(err)
	}
	if err := st.getAPI("/host/estimatescore", &eg); err != nil {
		t.Fatal(err)
	}
	if eg.EstimatedScore.Cmp(originalEstimate) != -1 {
		t.Fatal("score estimate did not decrease after incrementing mincontractprice")
	}
	st2, err := blankServerTester(t.Name() + "-st2")
	if err != nil {
		t.Fatal(err)
	}
	defer st2.panicClose()
	st3, err := blankServerTester(t.Name() + "-st3")
	if err != nil {
		t.Fatal(err)
	}
	defer st3.panicClose()
	st4, err := blankServerTester(t.Name() + "-st4")
	if err != nil {
		t.Fatal(err)
	}
	defer st4.panicClose()
	sts := []*serverTester{st, st2, st3, st4}
	err = fullyConnectNodes(sts)
	if err != nil {
		t.Fatal(err)
	}
	err = fundAllNodes(sts)
	if err != nil {
		t.Fatal(err)
	}
	for i, tester := range sts {
		is = tester.host.InternalSettings()
		is.MinContractPrice = types.SiacoinPrecision.Mul64(1000 + (1000 * uint64(i)))
		err = tester.host.SetInternalSettings(is)
		if err != nil {
			t.Fatal(err)
		}
	}
	err = announceAllHosts(sts)
	if err != nil {
		t.Fatal(err)
	}
	tests := []struct {
		price             types.Currency
		minConversionRate float64
	}{
		{types.SiacoinPrecision, 100},
		{types.SiacoinPrecision.Mul64(50), 98},
		{types.SiacoinPrecision.Mul64(2500), 50},
		{types.SiacoinPrecision.Mul64(3000), 10},
		{types.SiacoinPrecision.Mul64(30000), 0.00001},
	}
	for i, test := range tests {
		err = st.getAPI(fmt.Sprintf("/host/estimatescore?mincontractprice=%v", test.price.String()), &eg)
		if err != nil {
			t.Fatal("test", i, "failed:", err)
		}
		if eg.ConversionRate < test.minConversionRate {
			t.Fatalf("test %v: incorrect conversion rate: got %v wanted %v\n", i, eg.ConversionRate, test.minConversionRate)
		}
	}
}
func TestHostSettingsHandlerParsing(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	settings := st.host.InternalSettings()
	settingsValues := url.Values{}
	settingsValues.Set("maxdownloadbatchsize", "foo")
	st.stdPostAPI("/host", settingsValues)
	newSettings := st.host.InternalSettings()
	if !reflect.DeepEqual(newSettings, settings) {
		t.Fatal("invalid acceptingcontracts value changed host settings! got", newSettings, "wanted", settings)
	}
}
func TestWorkingStatus(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	if err := st.announceHost(); err != nil {
		t.Fatal(err)
	}
	if err := st.acceptContracts(); err != nil {
		t.Fatal(err)
	}
	if err := st.setHostStorage(); err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", testPeriod)
	allowanceValues.Set("renewwindow", testRenewWindow)
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	if err = st.stdPostAPI("/renter", allowanceValues); err != nil {
		t.Fatal(err)
	}
	err = build.Retry(50, time.Millisecond*250, func() error {
		var rc RenterContracts
		err = st.getAPI("/renter/contracts", &rc)
		if err != nil {
			return errors.New("couldn't get renter stats")
		}
		if len(rc.Contracts) != 1 {
			return errors.New("no contracts")
		}
		return nil
	})
	if err != nil {
		t.Fatal("allowance setting failed")
	}
	path := filepath.Join(st.dir, "test.dat")
	fileBytes := 1024
	if err := createRandFile(path, fileBytes); err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	if err := st.stdPostAPI("/renter/upload/test", uploadValues); err != nil {
		t.Fatal(err)
	}
	var rf RenterFiles
	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(50 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Error(rf.Files[0].UploadProgress)
		t.Fatal("uploading has failed")
	}
	err = build.Retry(30, time.Second, func() error {
		var hg HostGET
		st.getAPI("/host", &hg)
		if hg.WorkingStatus != modules.HostWorkingStatusWorking {
			return errors.New("expected host to be working")
		}
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
}
func TestConnectabilityStatus(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	if err := st.announceHost(); err != nil {
		t.Fatal(err)
	}
	err = build.Retry(30, time.Second, func() error {
		var hg HostGET
		st.getAPI("/host", &hg)
		if hg.ConnectabilityStatus != modules.HostConnectabilityStatusConnectable {
			return errors.New("expected host to be connectable")
		}
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
}
func TestStorageHandler(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	if err := st.announceHost(); err != nil {
		t.Fatal(err)
	}
	if err := st.acceptContracts(); err != nil {
		t.Fatal(err)
	}
	if err := st.setHostStorage(); err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", testPeriod)
	allowanceValues.Set("renewwindow", testRenewWindow)
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	if err = st.stdPostAPI("/renter", allowanceValues); err != nil {
		t.Fatal(err)
	}
	err = build.Retry(50, time.Millisecond*250, func() error {
		var rc RenterContracts
		err = st.getAPI("/renter/contracts", &rc)
		if err != nil {
			return errors.New("couldn't get renter stats")
		}
		if len(rc.Contracts) != 1 {
			return errors.New("no contracts")
		}
		return nil
	})
	if err != nil {
		t.Fatal("allowance setting failed")
	}
	path := filepath.Join(st.dir, "test.dat")
	fileBytes := 1024
	if err := createRandFile(path, fileBytes); err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	if err := st.stdPostAPI("/renter/upload/test", uploadValues); err != nil {
		t.Fatal(err)
	}
	var rf RenterFiles
	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(50 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Error(rf.Files[0].UploadProgress)
		t.Fatal("uploading has failed")
	}
	var sg StorageGET
	if err := st.getAPI("/host/storage", &sg); err != nil {
		t.Fatal(err)
	}
	if sg.Folders[0].SuccessfulWrites != 1 {
		t.Fatalf("expected 1 successful write, got %v", sg.Folders[0].SuccessfulWrites)
	}
	if used := sg.Folders[0].Capacity - sg.Folders[0].CapacityRemaining; used != modules.SectorSize {
		t.Fatalf("expected used capacity to be the size of one sector (%v bytes), got %v bytes", modules.SectorSize, used)
	}
}
func TestAddFolderNoPath(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	addValues := url.Values{}
	addValues.Set("size", mediumSizeFolderString)
	err = st.stdPostAPI("/host/storage/folders/add", addValues)
	if err == nil {
		t.Fatal(err)
	}
	addValues.Set("path", "")
	err = st.stdPostAPI("/host/storage/folders/add", addValues)
	if err == nil {
		t.Fatal(err)
	}
}
func TestAddFolderNoSize(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	addValues := url.Values{}
	addValues.Set("path", st.dir)
	err = st.stdPostAPI("/host/storage/folders/add", addValues)
	if err == nil || err.Error() != io.EOF.Error() {
		t.Fatalf("expected error to be %v, got %v", io.EOF, err)
	}
}