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 }