github.com/NebulousLabs/Sia@v1.3.7/modules/renter/contractor/update_test.go (about)

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