gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/workermaintenance_test.go (about)

     1  package renter
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/opentracing/opentracing-go"
    11  	"gitlab.com/SkynetLabs/skyd/build"
    12  	"gitlab.com/SkynetLabs/skyd/siatest/dependencies"
    13  	"gitlab.com/SkynetLabs/skyd/skymodules"
    14  	"go.sia.tech/siad/crypto"
    15  	"go.sia.tech/siad/modules"
    16  	"go.sia.tech/siad/types"
    17  )
    18  
    19  // TestWorkerMaintenanceCoolDown verifies the functionality of the worker's
    20  // cooldown of the RHP3 related subsystems.
    21  func TestWorkerMaintenanceCoolDown(t *testing.T) {
    22  	if testing.Short() {
    23  		t.SkipNow()
    24  	}
    25  	t.Parallel()
    26  
    27  	wt, err := newWorkerTesterCustomDependency(t.Name(), &dependencies.DependencyDisableCriticalOnMaxBalance{}, modules.ProdDependencies)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	defer func() {
    32  		err := wt.Close()
    33  		if err != nil {
    34  			t.Fatal(err)
    35  		}
    36  	}()
    37  	w := wt.worker
    38  
    39  	// verify the worker is not on an maintenance cooldown
    40  	if w.managedOnMaintenanceCooldown() {
    41  		t.Fatal("Unexpected maintenance cooldown")
    42  	}
    43  
    44  	// set a negative balance, tricking the worker into thinking it has to
    45  	// refill
    46  	w.staticAccount.mu.Lock()
    47  	w.staticAccount.negativeBalance = w.staticAccount.balance
    48  	w.staticAccount.mu.Unlock()
    49  
    50  	// manually trigger a refill
    51  	w.managedRefillAccount()
    52  
    53  	// verify the worker has been put on maintenance cooldown
    54  	if !w.managedOnMaintenanceCooldown() {
    55  		t.Fatal("Expected maintenance cooldown")
    56  	}
    57  
    58  	// the workerloop should have synced the account balance
    59  	if err := build.Retry(200, 100*time.Millisecond, func() error {
    60  		w.staticAccount.mu.Lock()
    61  		defer w.staticAccount.mu.Unlock()
    62  		if !w.staticAccount.negativeBalance.IsZero() {
    63  			return fmt.Errorf("worker account balance not reset: %v", w.staticAccount.negativeBalance)
    64  		}
    65  		return nil
    66  	}); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	// create a ctx with test span
    71  	ctx := opentracing.ContextWithSpan(context.Background(), testSpan())
    72  
    73  	// run a couple of has sector jobs to spend money
    74  	rc := make(chan *jobHasSectorResponse)
    75  	jhs := w.newJobHasSector(ctx, rc, skymodules.RenterDefaultNumPieces, crypto.Hash{})
    76  	for i := 0; i < 100; i++ {
    77  		if !w.staticJobHasSectorQueue.callAdd(jhs) {
    78  			t.Fatal("could not add job to queue")
    79  		}
    80  	}
    81  
    82  	// manually trigger a refill
    83  	w.managedRefillAccount()
    84  
    85  	// verify the account is not on cooldown
    86  	if w.managedOnMaintenanceCooldown() {
    87  		t.Fatal("Worker's RHP3 subsystems should not be on cooldown")
    88  	}
    89  }
    90  
    91  // TestWorkerMaintenanceRefillLowContractFunds verifies that a contract with
    92  // less remaining funds than the EA balance target can still be used to refill
    93  // an EA.
    94  func TestWorkerMaintenanceRefillLowContractFunds(t *testing.T) {
    95  	if testing.Short() {
    96  		t.SkipNow()
    97  	}
    98  	t.Parallel()
    99  
   100  	deps := &dependencies.DependencyDisableWorker{}
   101  	wt, err := newWorkerTesterCustomDependency(t.Name(), deps, modules.ProdDependencies)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	defer func() {
   106  		err := wt.Close()
   107  		if err != nil {
   108  			t.Fatal(err)
   109  		}
   110  	}()
   111  
   112  	// allow for a large balance on the host.
   113  	is := wt.host.InternalSettings()
   114  	is.MaxEphemeralAccountBalance = types.SiacoinPrecision.Mul64(math.MaxUint64)
   115  	err = wt.host.SetInternalSettings(is)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	w := wt.worker
   121  	r := w.staticRenter
   122  
   123  	// fetch a pricetable.
   124  	w.staticUpdatePriceTable()
   125  
   126  	// balance should be 0 right now.
   127  	w.staticAccount.mu.Lock()
   128  	accountBalance := w.staticAccount.balance
   129  	w.staticAccount.mu.Unlock()
   130  	if !accountBalance.IsZero() {
   131  		t.Fatal("balance should be zero at beginning of test")
   132  	}
   133  
   134  	// check remaining balance on contract.
   135  	contract, ok := r.staticHostContractor.ContractByPublicKey(wt.staticHostPubKey)
   136  	if !ok {
   137  		t.Fatal("contract not found")
   138  	}
   139  	funds := contract.RenterFunds
   140  
   141  	// set the target to the balance.
   142  	r.staticAccountBalanceTarget = funds
   143  
   144  	// trigger a refill.
   145  	w.managedRefillAccount()
   146  
   147  	// check if the balance increased.
   148  	w.staticAccount.mu.Lock()
   149  	accountBalance = w.staticAccount.balance
   150  	w.staticAccount.mu.Unlock()
   151  	expectedBalance := funds.Sub(wt.staticPriceTable().staticPriceTable.FundAccountCost)
   152  	if !accountBalance.Equals(expectedBalance) {
   153  		t.Fatalf("expected balance %v but got %v", accountBalance, expectedBalance)
   154  	}
   155  }