gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/contractor/update_test.go (about)

     1  package contractor
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"gitlab.com/SiaPrime/SiaPrime/build"
     8  	"gitlab.com/SiaPrime/SiaPrime/crypto"
     9  	"gitlab.com/SiaPrime/SiaPrime/modules"
    10  	"gitlab.com/SiaPrime/SiaPrime/types"
    11  
    12  	"gitlab.com/NebulousLabs/errors"
    13  	"gitlab.com/NebulousLabs/fastrand"
    14  )
    15  
    16  // TestIntegrationAutoRenew tests that contracts are automatically renewed at
    17  // the expected block height.
    18  func TestIntegrationAutoRenew(t *testing.T) {
    19  	if testing.Short() {
    20  		t.SkipNow()
    21  	}
    22  	t.Parallel()
    23  	// create testing trio
    24  	_, c, m, err := newTestingTrio(t.Name())
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	// form a contract with the host
    30  	a := modules.Allowance{
    31  		Funds:              types.SiacoinPrecision.Mul64(100), // 100 SC
    32  		Hosts:              1,
    33  		Period:             50,
    34  		RenewWindow:        10,
    35  		ExpectedStorage:    modules.DefaultAllowance.ExpectedStorage,
    36  		ExpectedUpload:     modules.DefaultAllowance.ExpectedUpload,
    37  		ExpectedDownload:   modules.DefaultAllowance.ExpectedDownload,
    38  		ExpectedRedundancy: modules.DefaultAllowance.ExpectedRedundancy,
    39  	}
    40  	err = c.SetAllowance(a)
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	err = build.Retry(50, 100*time.Millisecond, func() error {
    45  		if len(c.Contracts()) == 0 {
    46  			return errors.New("contracts were not formed")
    47  		}
    48  		return nil
    49  	})
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  	contract := c.Contracts()[0]
    54  
    55  	// revise the contract
    56  	editor, err := c.Editor(contract.HostPublicKey, nil)
    57  	if err != nil {
    58  		t.Fatal(err)
    59  	}
    60  	data := fastrand.Bytes(int(modules.SectorSize))
    61  	// insert the sector
    62  	_, err = editor.Upload(data)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	err = editor.Close()
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  
    71  	// mine until we enter the renew window
    72  	renewHeight := contract.EndHeight - c.allowance.RenewWindow
    73  	for c.blockHeight < renewHeight {
    74  		_, err := m.AddBlock()
    75  		if err != nil {
    76  			t.Fatal(err)
    77  		}
    78  	}
    79  	// wait for goroutine in ProcessConsensusChange to finish
    80  	time.Sleep(100 * time.Millisecond)
    81  	c.maintenanceLock.Lock()
    82  	c.maintenanceLock.Unlock()
    83  
    84  	// check renewed contract
    85  	contract = c.Contracts()[0]
    86  	endHeight := c.contractEndHeight()
    87  	if contract.EndHeight != endHeight {
    88  		t.Fatalf("Wrong end height, expected %v got %v\n", endHeight, contract.EndHeight)
    89  	}
    90  }
    91  
    92  // TestIntegrationRenewInvalidate tests that editors and downloaders are
    93  // properly invalidated when a renew is queued.
    94  func TestIntegrationRenewInvalidate(t *testing.T) {
    95  	if testing.Short() {
    96  		t.SkipNow()
    97  	}
    98  	t.Parallel()
    99  	// create testing trio
   100  	_, c, m, err := newTestingTrio(t.Name())
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  
   105  	// form a contract with the host
   106  	a := modules.Allowance{
   107  		Funds:              types.SiacoinPrecision.Mul64(100), // 100 SC
   108  		Hosts:              1,
   109  		Period:             50,
   110  		RenewWindow:        10,
   111  		ExpectedStorage:    modules.DefaultAllowance.ExpectedStorage,
   112  		ExpectedUpload:     modules.DefaultAllowance.ExpectedUpload,
   113  		ExpectedDownload:   modules.DefaultAllowance.ExpectedDownload,
   114  		ExpectedRedundancy: modules.DefaultAllowance.ExpectedRedundancy,
   115  	}
   116  	err = c.SetAllowance(a)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	err = build.Retry(50, 100*time.Millisecond, func() error {
   121  		if len(c.Contracts()) == 0 {
   122  			return errors.New("contracts were not formed")
   123  		}
   124  		return nil
   125  	})
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	contract := c.Contracts()[0]
   130  
   131  	// revise the contract
   132  	editor, err := c.Editor(contract.HostPublicKey, nil)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	data := fastrand.Bytes(int(modules.SectorSize))
   137  	// insert the sector
   138  	_, err = editor.Upload(data)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	// mine until we enter the renew window; the editor should be invalidated
   144  	renewHeight := contract.EndHeight - c.allowance.RenewWindow
   145  	for c.blockHeight < renewHeight {
   146  		_, err := m.AddBlock()
   147  		if err != nil {
   148  			t.Fatal(err)
   149  		}
   150  	}
   151  	// wait for goroutine in ProcessConsensusChange to finish
   152  	time.Sleep(100 * time.Millisecond)
   153  	c.maintenanceLock.Lock()
   154  	c.maintenanceLock.Unlock()
   155  
   156  	// check renewed contract
   157  	contract = c.Contracts()[0]
   158  	endHeight := c.contractEndHeight()
   159  	c.mu.Lock()
   160  	if contract.EndHeight != endHeight {
   161  		t.Fatalf("Wrong end height, expected %v got %v\n", endHeight, contract.EndHeight)
   162  	}
   163  	c.mu.Unlock()
   164  
   165  	// editor should have been invalidated
   166  	_, err = editor.Upload(make([]byte, modules.SectorSize))
   167  	if err != errInvalidEditor && err != errInvalidSession {
   168  		t.Error("expected invalid editor error; got", err)
   169  	}
   170  	editor.Close()
   171  
   172  	// create a downloader
   173  	downloader, err := c.Downloader(contract.HostPublicKey, nil)
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	// mine until we enter the renew window
   178  	renewHeight = contract.EndHeight - c.allowance.RenewWindow
   179  	for c.blockHeight < renewHeight {
   180  		_, err := m.AddBlock()
   181  		if err != nil {
   182  			t.Fatal(err)
   183  		}
   184  	}
   185  
   186  	// downloader should have been invalidated
   187  	err = build.Retry(50, 100*time.Millisecond, func() error {
   188  		// wait for goroutine in ProcessConsensusChange to finish
   189  		c.maintenanceLock.Lock()
   190  		c.maintenanceLock.Unlock()
   191  		_, err2 := downloader.Download(crypto.Hash{}, 0, 0)
   192  		if err2 != errInvalidDownloader && err2 != errInvalidSession {
   193  			return errors.AddContext(err, "expected invalid downloader error")
   194  		}
   195  		return downloader.Close()
   196  	})
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  }