func TestRenterRenew(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	err = st.announceHost()
	if err != nil {
		t.Fatal(err)
	}
	err = st.acceptContracts()
	if err != nil {
		t.Fatal(err)
	}
	err = st.setHostStorage()
	if err != nil {
		t.Fatal(err)
	}
	var ah HostdbActiveGET
	for i := 0; i < 50; i++ {
		if err = st.getAPI("/hostdb/active", &ah); err != nil {
			t.Fatal(err)
		}
		if len(ah.Hosts) == 1 {
			break
		}
		time.Sleep(time.Millisecond * 100)
	}
	if len(ah.Hosts) != 1 {
		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
	}
	allowanceValues := url.Values{}
	testFunds := "10000000000000000000000000000"  
	testPeriod := 10
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", strconv.Itoa(testPeriod))
	allowanceValues.Set("renewwindow", strconv.Itoa(testPeriod/2))
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	err = st.stdPostAPI("/renter", allowanceValues)
	if 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")
	err = createRandFile(path, 1024)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if 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(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
	}
	var rc RenterContracts
	err = st.getAPI("/renter/contracts", &rc)
	if err != nil {
		t.Fatal(err)
	}
	contractID := rc.Contracts[0].ID
	testWindow := testPeriod / 2
	for i := 0; i < testWindow+1; i++ {
		_, err = st.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
	}
	for i := 0; i < 200 && (len(rc.Contracts) != 1 || rc.Contracts[0].ID == contractID); i++ {
		st.getAPI("/renter/contracts", &rc)
		time.Sleep(100 * time.Millisecond)
	}
	if rc.Contracts[0].ID == contractID {
		t.Fatal("contract was not renewed:", rc.Contracts[0])
	}
	downpath := filepath.Join(st.dir, "testdown.dat")
	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
	if err != nil {
		t.Fatal(err)
	}
	orig, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	download, err := ioutil.ReadFile(downpath)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(orig, download) != 0 {
		t.Fatal("data mismatch when downloading a file")
	}
}
TestRenterRenew sets up an integration test where a renter renews a
contract with a host.
package api
import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"testing"
	"time"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/types"
)
func TestHostObligationAcceptingContracts(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.Close()
	err = st.setHostStorage()
	if err != nil {
		t.Fatal(err)
	}
	err = st.acceptContracts()
	if err != nil {
		t.Fatal(err)
	}
	err = st.announceHost()
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	allowanceValues.Set("funds", "50000000000000000000000000000")  
	allowanceValues.Set("hosts", "1")
	allowanceValues.Set("period", "10")
	allowanceValues.Set("renewwindow", "5")
	err = st.stdPostAPI("/renter", allowanceValues)
	if 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")
	}
	filesize := int(1024)
	path := filepath.Join(st.dir, "test.dat")
	err = createRandFile(path, filesize)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	var rf RenterFiles
	err = build.Retry(120, time.Millisecond*250, func() error {
		st.getAPI("/renter/files", &rf)
		if len(rf.Files) >= 1 && rf.Files[0].Available {
			return nil
		}
		return errors.New("file not uploaded")
	})
	if err != nil {
		t.Fatal(err)
	}
	var cts ContractInfoGET
	err = st.getAPI("/host/contracts", &cts)
	if err != nil {
		t.Fatal(err)
	}
	if len(cts.Contracts) == 0 {
		t.Fatal("No contracts returned from /host/contracts API call.")
	}
	if len(cts.Contracts) != len(st.host.StorageObligations()) {
		t.Fatal("Number of contracts returned by API call and host method don't match.")
	}
	settings := st.host.InternalSettings()
	settings.AcceptingContracts = false
	st.host.SetInternalSettings(settings)
	for i := 0; i < 3; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Millisecond * 100)
	}
	downloadPath := filepath.Join(st.dir, "test-downloaded-verify.dat")
	err = st.stdGetAPI("/renter/download/test?destination=" + downloadPath)
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < 15; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Millisecond * 100)
	}
	success := false
	for _, so := range st.host.StorageObligations() {
		if so.ProofConfirmed {
			success = true
			break
		}
	}
	if !success {
		t.Fatal("no successful storage proofs")
	}
}
func TestHostAndRentVanilla(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()
	err = st.announceHost()
	if err != nil {
		t.Fatal(err)
	}
	err = st.setHostStorage()
	if err != nil {
		t.Fatal(err)
	}
	err = st.acceptContracts()
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	testFunds := "10000000000000000000000000000"  
	testPeriod := "20"
	renewWindow := "10"
	testPeriodInt := 20
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", testPeriod)
	allowanceValues.Set("renewwindow", renewWindow)
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	err = st.stdPostAPI("/renter", allowanceValues)
	if 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")
	}
	var cts ContractInfoGET
	err = st.getAPI("/host/contracts", &cts)
	if err != nil {
		t.Fatal(err)
	}
	if len(cts.Contracts) != 1 {
		t.Error("Host has wrong number of obligations:", len(cts.Contracts))
	}
	if cts.Contracts[0].ObligationStatus != "obligationUnresolved" {
		t.Error("Wrong obligation status for new contract:", cts.Contracts[0].ObligationStatus)
	}
	if cts.Contracts[0].SectorRootsCount != 0 {
		t.Error("Wrong number of sector roots for new contract:", cts.Contracts[0].SectorRootsCount)
	}
	if cts.Contracts[0].LockedCollateral.IsZero() {
		t.Error("No locked collateral in contract.")
	}
	if !cts.Contracts[0].RiskedCollateral.IsZero() {
		t.Error("Risked collateral not zero in new contract.")
	}
	if !(cts.Contracts[0].PotentialDownloadRevenue.IsZero() && cts.Contracts[0].PotentialUploadRevenue.IsZero() && cts.Contracts[0].PotentialStorageRevenue.IsZero()) {
		t.Error("Potential values not zero in new contract.")
	}
	path := filepath.Join(st.dir, "test.dat")
	err = createRandFile(path, 1024)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if 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(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
	}
	path2 := filepath.Join(st.dir, "test2.dat")
	test2Size := modules.SectorSize*2 + 1
	err = createRandFile(path2, int(test2Size))
	if err != nil {
		t.Fatal(err)
	}
	uploadValues = url.Values{}
	uploadValues.Set("source", path2)
	err = st.stdPostAPI("/renter/upload/test2", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < 200 && (len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(100 * time.Millisecond)
	}
	if len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0], rf.Files[1])
	}
	downpath := filepath.Join(st.dir, "testdown.dat")
	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
	if err != nil {
		t.Fatal(err)
	}
	orig, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	download, err := ioutil.ReadFile(downpath)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(orig, download) != 0 {
		t.Fatal("data mismatch when downloading a file")
	}
	var queue RenterDownloadQueue
	if err = st.getAPI("/renter/downloads", &queue); err != nil {
		t.Fatal(err)
	}
	if len(queue.Downloads) != 1 {
		t.Fatalf("expected renter to have 1 download in the queue; got %v", len(queue.Downloads))
	}
	downpath2 := filepath.Join(st.dir, "testdown2.dat")
	err = st.stdGetAPI("/renter/download/test2?destination=" + downpath2)
	if err != nil {
		t.Fatal(err)
	}
	orig2, err := ioutil.ReadFile(path2)
	if err != nil {
		t.Fatal(err)
	}
	download2, err := ioutil.ReadFile(downpath2)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(orig2, download2) != 0 {
		t.Fatal("data mismatch when downloading a file")
	}
	if err = st.getAPI("/renter/downloads", &queue); err != nil {
		t.Fatal(err)
	}
	if len(queue.Downloads) != 2 {
		t.Fatalf("expected renter to have 1 download in the queue; got %v", len(queue.Downloads))
	}
	for i := 0; i < 2; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Millisecond * 200)
	}
	cts = ContractInfoGET{}
	err = st.getAPI("/host/contracts", &cts)
	if err != nil {
		t.Fatal(err)
	}
	if len(cts.Contracts) != 1 {
		t.Error("Host has wrong number of obligations:", len(cts.Contracts))
	}
	if !cts.Contracts[0].OriginConfirmed {
		t.Error("Host has not seen the file contract on the blockchain.")
	}
	if cts.Contracts[0].SectorRootsCount == 0 {
		t.Error("Sector roots count is zero for used obligation.")
	}
	if cts.Contracts[0].RiskedCollateral.IsZero() {
		t.Error("Risked collateral is zero for used obligation.")
	}
	if cts.Contracts[0].PotentialDownloadRevenue.IsZero() || cts.Contracts[0].PotentialUploadRevenue.IsZero() || cts.Contracts[0].PotentialStorageRevenue.IsZero() {
		t.Error("Potential revenue value is zero for used obligation.")
	}
	for i := 0; i <= testPeriodInt+5; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Millisecond * 200)
	}
	cts = ContractInfoGET{}
	err = st.getAPI("/host/contracts", &cts)
	if err != nil {
		t.Fatal(err)
	}
	success := false
	for _, contract := range cts.Contracts {
		if contract.ProofConfirmed {
			if contract.SectorRootsCount > 0 {
				t.Error("There are sector roots on completed storage obligation.")
			}
			success = true
			break
		}
	}
	if !success {
		t.Error("does not seem like the host has submitted a storage proof successfully to the network")
	}
}
func TestHostAndRentMultiHost(t *testing.T) {
	if testing.Short() || !build.VLONG {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	stH1, err := blankServerTester(t.Name() + " - Host 2")
	if err != nil {
		t.Fatal(err)
	}
	defer stH1.server.panicClose()
	stH2, err := blankServerTester(t.Name() + " - Host 3")
	if err != nil {
		t.Fatal(err)
	}
	defer stH2.server.panicClose()
	testGroup := []*serverTester{st, stH1, stH2}
	err = fullyConnectNodes(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = fundAllNodes(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = addStorageToAllHosts(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = announceAllHosts(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	allowanceValues.Set("funds", "50000000000000000000000000000")  
	allowanceValues.Set("hosts", "3")
	allowanceValues.Set("period", "10")
	allowanceValues.Set("renewwindow", "2")
	err = st.stdPostAPI("/renter", allowanceValues)
	if err != nil {
		t.Fatal(err)
	}
	filesize := int(45678)
	path := filepath.Join(st.dir, "test.dat")
	err = createRandFile(path, filesize)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	uploadValues.Set("datapieces", "2")
	uploadValues.Set("paritypieces", "4")
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	var rf RenterFiles
	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 50); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 50 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
	}
	downpath := filepath.Join(st.dir, "testdown.dat")
	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
	if err != nil {
		t.Fatal(err)
	}
	orig, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	download, err := ioutil.ReadFile(downpath)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(orig, download) != 0 {
		t.Fatal("data mismatch when downloading a file")
	}
	var queue RenterDownloadQueue
	if err = st.getAPI("/renter/downloads", &queue); err != nil {
		t.Fatal(err)
	}
	if len(queue.Downloads) != 1 {
		t.Fatalf("expected renter to have 1 download in the queue; got %v", len(queue.Downloads))
	}
}
func TestHostAndRentManyFiles(t *testing.T) {
	if testing.Short() || !build.VLONG {
		t.SkipNow()
	}
	t.Parallel()
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	stH1, err := blankServerTester(t.Name() + " - Host 2")
	if err != nil {
		t.Fatal(err)
	}
	defer stH1.server.panicClose()
	stH2, err := blankServerTester(t.Name() + " - Host 3")
	if err != nil {
		t.Fatal(err)
	}
	defer stH2.server.panicClose()
	stH3, err := blankServerTester(t.Name() + " - Host 4")
	if err != nil {
		t.Fatal(err)
	}
	defer stH3.server.panicClose()
	testGroup := []*serverTester{st, stH1, stH2, stH3}
	err = fullyConnectNodes(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = fundAllNodes(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = addStorageToAllHosts(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	err = announceAllHosts(testGroup)
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	allowanceValues.Set("funds", "50000000000000000000000000000")  
	allowanceValues.Set("hosts", "4")
	allowanceValues.Set("period", "5")
	allowanceValues.Set("renewwindow", "2")
	err = st.stdPostAPI("/renter", allowanceValues)
	if err != nil {
		t.Fatal(err)
	}
	filesize1 := int(12347)
	filesize2 := int(22343)
	filesize3 := int(32349)
	path1 := filepath.Join(st.dir, "test1.dat")
	path2 := filepath.Join(st.dir, "test2.dat")
	path3 := filepath.Join(st.dir, "test3.dat")
	err = createRandFile(path1, filesize1)
	if err != nil {
		t.Fatal(err)
	}
	err = createRandFile(path2, filesize2)
	if err != nil {
		t.Fatal(err)
	}
	err = createRandFile(path3, filesize3)
	if err != nil {
		t.Fatal(err)
	}
	var wg sync.WaitGroup
	wg.Add(3)
	go func() {
		defer wg.Done()
		uploadValues := url.Values{}
		uploadValues.Set("source", path1)
		uploadValues.Set("datapieces", "1")
		uploadValues.Set("paritypieces", "3")
		err := st.stdPostAPI("/renter/upload/test1", uploadValues)
		if err != nil {
			t.Error(err)
		}
	}()
	go func() {
		defer wg.Done()
		uploadValues := url.Values{}
		uploadValues.Set("source", path2)
		uploadValues.Set("datapieces", "2")
		uploadValues.Set("paritypieces", "2")
		err := st.stdPostAPI("/renter/upload/test2", uploadValues)
		if err != nil {
			t.Error(err)
		}
	}()
	go func() {
		defer wg.Done()
		uploadValues := url.Values{}
		uploadValues.Set("source", path3)
		uploadValues.Set("datapieces", "3")
		uploadValues.Set("paritypieces", "1")
		err := st.stdPostAPI("/renter/upload/test3", uploadValues)
		if err != nil {
			t.Error(err)
		}
	}()
	wg.Wait()
	var rf RenterFiles
	for i := 0; i < 200 && (len(rf.Files) != 3 || rf.Files[0].UploadProgress < 100 || rf.Files[1].UploadProgress < 100 || rf.Files[2].UploadProgress < 100); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(500 * time.Millisecond)
	}
	if len(rf.Files) != 3 || rf.Files[0].UploadProgress < 100 || rf.Files[1].UploadProgress < 100 || rf.Files[2].UploadProgress < 100 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0], rf.Files[1], rf.Files[2])
	}
	wg.Add(3)
	go func() {
		defer wg.Done()
		downpath := filepath.Join(st.dir, "testdown1.dat")
		err := st.stdGetAPI("/renter/download/test1?destination=" + downpath)
		if err != nil {
			t.Error(err)
		}
		orig, err := ioutil.ReadFile(path1)
		if err != nil {
			t.Error(err)
		}
		download, err := ioutil.ReadFile(downpath)
		if err != nil {
			t.Error(err)
		}
		if bytes.Compare(orig, download) != 0 {
			t.Error("data mismatch when downloading a file")
		}
	}()
	go func() {
		defer wg.Done()
		downpath := filepath.Join(st.dir, "testdown2.dat")
		err := st.stdGetAPI("/renter/download/test2?destination=" + downpath)
		if err != nil {
			t.Error(err)
		}
		orig, err := ioutil.ReadFile(path2)
		if err != nil {
			t.Error(err)
		}
		download, err := ioutil.ReadFile(downpath)
		if err != nil {
			t.Error(err)
		}
		if bytes.Compare(orig, download) != 0 {
			t.Error("data mismatch when downloading a file")
		}
	}()
	go func() {
		defer wg.Done()
		downpath := filepath.Join(st.dir, "testdown3.dat")
		err := st.stdGetAPI("/renter/download/test3?destination=" + downpath)
		if err != nil {
			t.Error(err)
		}
		orig, err := ioutil.ReadFile(path3)
		if err != nil {
			t.Error(err)
		}
		download, err := ioutil.ReadFile(downpath)
		if err != nil {
			t.Error(err)
		}
		if bytes.Compare(orig, download) != 0 {
			t.Error("data mismatch when downloading a file")
		}
	}()
	wg.Wait()
	var queue RenterDownloadQueue
	if err = st.getAPI("/renter/downloads", &queue); err != nil {
		t.Fatal(err)
	}
	if len(queue.Downloads) != 3 {
		t.Fatalf("expected renter to have 1 download in the queue; got %v", len(queue.Downloads))
	}
}
func TestRenterUploadDownload(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	err = st.announceHost()
	if err != nil {
		t.Fatal(err)
	}
	err = st.acceptContracts()
	if err != nil {
		t.Fatal(err)
	}
	err = st.setHostStorage()
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	testFunds := "10000000000000000000000000000"  
	testPeriod := "10"
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", testPeriod)
	allowanceValues.Set("renewwindow", testRenewWindow)
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	err = st.stdPostAPI("/renter", allowanceValues)
	if 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")
	}
	var rg RenterGET
	err = st.getAPI("/renter", &rg)
	if err != nil {
		t.Fatal(err)
	}
	spent := rg.Settings.Allowance.Funds.Sub(rg.FinancialMetrics.Unspent)
	if spent.IsZero() {
		t.Fatal("financial metrics do not reflect contract spending")
	}
	path := filepath.Join(st.dir, "test.dat")
	err = createRandFile(path, 1024)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if 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(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
	}
	path2 := filepath.Join(st.dir, "test2.dat")
	test2Size := modules.SectorSize*2 + 1
	err = createRandFile(path2, int(test2Size))
	if err != nil {
		t.Fatal(err)
	}
	uploadValues = url.Values{}
	uploadValues.Set("source", path2)
	err = st.stdPostAPI("/renter/upload/test2", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	downpath := filepath.Join(st.dir, "testdown.dat")
	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
	if err != nil {
		t.Fatal(err)
	}
	orig, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	download, err := ioutil.ReadFile(downpath)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(orig, download) != 0 {
		t.Fatal("data mismatch when downloading a file")
	}
	for i := 0; i < 200 && (len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(100 * time.Millisecond)
	}
	if len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0], rf.Files[1])
	}
	err = st.getAPI("/renter", &rg)
	if err != nil {
		t.Fatal(err)
	}
	fm := rg.FinancialMetrics
	newSpent := rg.Settings.Allowance.Funds.Sub(fm.Unspent)
	diff := fm.UploadSpending.Add(fm.DownloadSpending).Add(fm.StorageSpending)
	if !diff.Equals(newSpent.Sub(spent)) {
		t.Fatal("all new spending should be reflected in metrics:", diff, newSpent.Sub(spent))
	}
}
func TestRenterParallelDelete(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	st, err := createServerTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}
	defer st.server.panicClose()
	err = st.announceHost()
	if err != nil {
		t.Fatal(err)
	}
	err = st.acceptContracts()
	if err != nil {
		t.Fatal(err)
	}
	err = st.setHostStorage()
	if err != nil {
		t.Fatal(err)
	}
	allowanceValues := url.Values{}
	testFunds := "10000000000000000000000000000"  
	testPeriod := "10"
	allowanceValues.Set("funds", testFunds)
	allowanceValues.Set("period", testPeriod)
	allowanceValues.Set("renewwindow", testRenewWindow)
	allowanceValues.Set("hosts", fmt.Sprint(recommendedHosts))
	err = st.stdPostAPI("/renter", allowanceValues)
	if err != nil {
		t.Fatal(err)
	}
	path := filepath.Join(st.dir, "test.dat")
	err = createRandFile(path, 1024)
	if err != nil {
		t.Fatal(err)
	}
	path2 := filepath.Join(st.dir, "test2.dat")
	err = createRandFile(path2, 1024)
	if err != nil {
		t.Fatal(err)
	}
	uploadValues := url.Values{}
	uploadValues.Set("source", path)
	err = st.stdPostAPI("/renter/upload/test", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	var rf RenterFiles
	for i := 0; i < 200 && len(rf.Files) != 1; i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 {
		t.Fatal("file is not being registered:", rf.Files)
	}
	uploadValues = url.Values{}
	uploadValues.Set("source", path2)
	err = st.stdPostAPI("/renter/upload/test2", uploadValues)
	if err != nil {
		t.Fatal(err)
	}
	err = st.stdPostAPI("/renter/delete/test", url.Values{})
	if err != nil {
		t.Fatal(err)
	}
	st.getAPI("/renter/files", &rf)
	if len(rf.Files) != 1 || rf.Files[0].SiaPath != "test2" {
		t.Fatal("file was not deleted properly:", rf.Files)
	}
	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
		st.getAPI("/renter/files", &rf)
		time.Sleep(100 * time.Millisecond)
	}
	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
		t.Fatal("the uploading is not succeeding for some reason:", rf.Files)
	}
	go st.stdPostAPI("/renter/delete/test2", url.Values{})
	time.Sleep(100 * time.Millisecond)
	downpath := filepath.Join(st.dir, "testdown.dat")
	err = st.stdGetAPI("/renter/download/test2?destination=" + downpath)
	if err == nil {
		t.Fatal("download should fail after delete")
	}
	st.getAPI("/renter/files", &rf)
	if len(rf.Files) != 0 {
		t.Fatal("file was not deleted properly:", rf.Files)
	}
}