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

     1  package renter
     2  
     3  import (
     4  	"io/ioutil"
     5  	"sync/atomic"
     6  	"testing"
     7  	"unsafe"
     8  
     9  	"gitlab.com/SkynetLabs/skyd/persist"
    10  	"gitlab.com/SkynetLabs/skyd/skymodules"
    11  )
    12  
    13  // newOverloadedWorker will return a worker that is overloaded.
    14  func newOverloadedWorker() *worker {
    15  	// Create and initialize a barebones worker.
    16  	w := new(worker)
    17  	cache := &workerCache{
    18  		staticContractUtility: skymodules.ContractUtility{
    19  			GoodForUpload: true,
    20  		},
    21  	}
    22  	ptr := unsafe.Pointer(cache)
    23  	atomic.StorePointer(&w.atomicCache, ptr)
    24  	w.unprocessedChunks = newUploadChunks()
    25  
    26  	for i := 0; i < workerUploadOverloadedThreshold; i++ {
    27  		w.unprocessedChunks.PushBack(new(unfinishedUploadChunk))
    28  	}
    29  	return w
    30  }
    31  
    32  // TestManagedCheckForUploadWorkers will probe the various edge cases of
    33  // managedSelectWorkersForUploading and ensure that all of the logic is running as
    34  // expected.
    35  func TestManagedCheckForUploadWorkers(t *testing.T) {
    36  	// Test the blank case. Because there are no workers, the function should
    37  	// return a blank set of workers and indicate that the chunk is okay to
    38  	// distribute. We don't want the upload loop freezing if there are no
    39  	// workers.
    40  	uc := new(unfinishedUploadChunk)
    41  	l, err := persist.NewLogger(ioutil.Discard)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	uc.staticRenter = &Renter{staticLog: l}
    46  	var inputWorkers []*worker
    47  	workers, finalized := managedSelectWorkersForUploading(uc, inputWorkers)
    48  	if workers != nil {
    49  		t.Fatal("bad")
    50  	}
    51  	if !finalized {
    52  		t.Fatal("bad")
    53  	}
    54  	// Give the UC some minpieces and needed pieces.
    55  	inputWorkers = append(inputWorkers, newOverloadedWorker())
    56  	inputWorkers[0].unprocessedChunks = newUploadChunks()
    57  	uc.staticPiecesNeeded = 1
    58  	uc.staticMinimumPieces = 1
    59  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
    60  	if len(workers) != 1 {
    61  		t.Fatal("bad")
    62  	}
    63  	if !finalized {
    64  		t.Fatal("bad")
    65  	}
    66  	uc.staticPiecesNeeded = 2
    67  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
    68  	if len(workers) != 1 {
    69  		t.Fatal("bad")
    70  	}
    71  	if !finalized {
    72  		t.Fatal("bad")
    73  	}
    74  
    75  	// Test the use case where there are not enough available workers, but there
    76  	// are enough overloaded workers. This should result in finalized being
    77  	// 'false', as we want to wait for the overloaded workers to finish
    78  	// processing their chunks and become available.
    79  	inputWorkers = append([]*worker{}, newOverloadedWorker())
    80  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
    81  	if workers != nil {
    82  		t.Fatal("bad")
    83  	}
    84  	if finalized {
    85  		t.Fatal("bad")
    86  	}
    87  
    88  	// Test the case where the only worker is busy
    89  	for i := 0; i < workerUploadOverloadedThreshold-workerUploadBusyThreshold; i++ {
    90  		inputWorkers[0].unprocessedChunks.Pop()
    91  	}
    92  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
    93  	if workers != nil {
    94  		t.Fatal("bad")
    95  	}
    96  	if finalized {
    97  		t.Fatal("bad")
    98  	}
    99  
   100  	// Test the case where the only worker is available. Since the only worker
   101  	// is available, the chunk should be good to go.
   102  	for i := 0; i < workerUploadBusyThreshold; i++ {
   103  		inputWorkers[0].unprocessedChunks.Pop()
   104  	}
   105  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
   106  	if len(workers) != 1 {
   107  		t.Fatal("bad")
   108  	}
   109  	if !finalized {
   110  		t.Fatal("bad")
   111  	}
   112  
   113  	// Test what happens when there is an overloaded worker that could be busy.
   114  	inputWorkers = append(inputWorkers, newOverloadedWorker())
   115  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
   116  	if workers != nil {
   117  		t.Fatal("bad")
   118  	}
   119  	if finalized {
   120  		t.Fatal("bad")
   121  	}
   122  	// Now check what happens when it is busy. There are enough available
   123  	// workers to make the chunk available, and enough busy workers to finish
   124  	// the chunk, so it should pass.
   125  	for i := 0; i < workerUploadOverloadedThreshold-workerUploadBusyThreshold; i++ {
   126  		inputWorkers[1].unprocessedChunks.Pop()
   127  	}
   128  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
   129  	if len(workers) != 2 {
   130  		t.Fatal("bad", len(workers))
   131  	}
   132  	if !finalized {
   133  		t.Fatal("bad")
   134  	}
   135  	// Change the number of staticPiecesNeeded in the chunk to 3, so that we now
   136  	// have enough available workers to make the chunk available but not enough
   137  	// busy workers (or workers at all) to make the chunk complete. This should
   138  	// succeed.
   139  	workers, finalized = managedSelectWorkersForUploading(uc, inputWorkers)
   140  	if len(workers) != 2 {
   141  		t.Fatal("bad", len(workers))
   142  	}
   143  	if !finalized {
   144  		t.Fatal("bad")
   145  	}
   146  }