github.com/atlassian/jec@v0.0.0-20230613085511-f72200786c0c/worker_pool/worker_pool_test.go (about) 1 package worker_pool 2 3 import ( 4 "github.com/atlassian/jec/conf" 5 "github.com/sirupsen/logrus" 6 "github.com/stretchr/testify/assert" 7 "io/ioutil" 8 "math/cmplx" 9 "os" 10 "strconv" 11 "sync/atomic" 12 "testing" 13 "time" 14 ) 15 16 var testPoolConf = &conf.PoolConf{ 17 MaxNumberOfWorker: 16, 18 MinNumberOfWorker: 2, 19 QueueSize: queueSize, 20 KeepAliveTimeInMillis: keepAliveTimeInMillis, 21 MonitoringPeriodInMillis: monitoringPeriodInMillis, 22 } 23 24 var dummyJob = func() { 25 var dummy complex128 = 17 26 for j := 0; j < 100000; j++ { 27 dummy = cmplx.Sin(dummy) + cmplx.Sinh(dummy) 28 dummy = cmplx.Acos(dummy) + cmplx.Atanh(dummy) 29 dummy = cmplx.Atanh(dummy) + cmplx.Sin(dummy) 30 dummy = cmplx.Conj(dummy) - cmplx.Acos(dummy) 31 dummy = cmplx.Sinh(dummy) - cmplx.Conj(dummy) 32 } 33 return 34 } 35 36 func TestMain(m *testing.M) { 37 logrus.SetOutput(ioutil.Discard) 38 os.Exit(m.Run()) 39 } 40 41 func TestValidateNewWorkerPool(t *testing.T) { 42 configuration := &conf.PoolConf{ 43 -1, 44 -1, 45 -1, 46 -1, 47 -1, 48 } 49 pool := New(configuration).(*workerPool) 50 51 assert.Equal(t, int32(minNumberOfWorker), pool.poolConf.MinNumberOfWorker) 52 assert.Equal(t, int32(maxNumberOfWorker), pool.poolConf.MaxNumberOfWorker) 53 assert.Equal(t, int32(queueSize), pool.poolConf.QueueSize) 54 assert.Equal(t, time.Duration(keepAliveTimeInMillis), pool.poolConf.KeepAliveTimeInMillis) 55 assert.Equal(t, time.Duration(monitoringPeriodInMillis), pool.poolConf.MonitoringPeriodInMillis) 56 } 57 58 func TestValidateWorkerNumbersNewWorkerPool(t *testing.T) { 59 configuration := &conf.PoolConf{ 60 1, 61 2, 62 -1, 63 0, 64 0, 65 } 66 pool := New(configuration).(*workerPool) 67 68 assert.Equal(t, int32(1), pool.poolConf.MinNumberOfWorker) 69 assert.Equal(t, int32(1), pool.poolConf.MaxNumberOfWorker) 70 assert.Equal(t, int32(queueSize), pool.poolConf.QueueSize) 71 assert.Equal(t, time.Duration(keepAliveTimeInMillis), pool.poolConf.KeepAliveTimeInMillis) 72 assert.Equal(t, time.Duration(monitoringPeriodInMillis), pool.poolConf.MonitoringPeriodInMillis) 73 } 74 75 func TestStartPool(t *testing.T) { 76 77 pool := New(testPoolConf).(*workerPool) 78 79 err := pool.Start() 80 81 assert.Nil(t, err) 82 assert.Equal(t, 2, int(pool.numberOfCurrentWorker)) 83 84 var executeJobCallCount int32 = 0 85 86 for i := 0; i < 1000; i++ { 87 job := NewMockJob() 88 id := strconv.Itoa(i) 89 job.JobIdFunc = func() string { 90 return id 91 } 92 job.ExecuteFunc = func() error { 93 atomic.AddInt32(&executeJobCallCount, 1) 94 time.Sleep(time.Nanosecond) 95 return nil 96 } 97 98 for isSubmitted, _ := pool.Submit(job); !isSubmitted; isSubmitted, _ = pool.Submit(job) { 99 } 100 } 101 102 err = pool.Stop() 103 104 assert.Nil(t, err) 105 assert.Equal(t, int32(1000), executeJobCallCount) 106 } 107 108 func BenchmarkWorkerPool(b *testing.B) { 109 110 jobSize1 := 500 111 jobSize2 := 1000 112 113 sizes := []struct { 114 workerSize int 115 jobSize int 116 }{ 117 {2, jobSize1}, 118 {2, jobSize2}, 119 {4, jobSize1}, 120 {4, jobSize2}, 121 {8, jobSize1}, 122 {8, jobSize2}, 123 {16, jobSize1}, 124 {16, jobSize2}, 125 {32, jobSize1}, 126 {32, jobSize2}, 127 {64, jobSize1}, 128 {64, jobSize2}, 129 } 130 131 for _, size := range sizes { 132 133 pool := New( 134 &conf.PoolConf{ 135 int32(size.workerSize), 136 2, 137 queueSize, 138 keepAliveTimeInMillis, 139 monitoringPeriodInMillis, 140 }, 141 ) 142 143 b.Run(strconv.Itoa(size.workerSize)+"MaxWorkers"+strconv.Itoa(size.jobSize)+"Jobs", func(b *testing.B) { 144 145 err := pool.Start() 146 147 assert.Nil(b, err) 148 149 var executeJobCallCount int32 = 0 150 151 for i := 0; i < size.jobSize; i++ { 152 job := NewMockJob() 153 job.ExecuteFunc = func() error { 154 atomic.AddInt32(&executeJobCallCount, 1) 155 dummyJob() 156 return nil 157 } 158 159 for isSubmitted, _ := pool.Submit(job); !isSubmitted; isSubmitted, _ = pool.Submit(job) { 160 //time.Sleep(time.Nanosecond) 161 } 162 } 163 164 err = pool.Stop() 165 166 assert.Nil(b, err) 167 assert.Equal(b, int32(size.jobSize), executeJobCallCount) 168 }) 169 } 170 } 171 172 func BenchmarkDummyJob(b *testing.B) { 173 dummyJob() 174 } 175 176 func BenchmarkWorkerPoolWithComparableFixedWorkerSize(b *testing.B) { 177 178 jobSize := 500 179 180 cases := []struct { 181 maxNumberOfWorker int 182 fixed bool 183 }{ 184 {4, false}, 185 {4, true}, 186 {8, false}, 187 {8, true}, 188 {16, false}, 189 {16, true}, 190 {32, false}, 191 {32, true}, 192 } 193 194 for _, testCase := range cases { 195 minNumberOfWorker := 2 196 maxWorkers := "MaxWorkers" 197 if testCase.fixed { 198 minNumberOfWorker = testCase.maxNumberOfWorker 199 maxWorkers = "FixedWorkers" 200 } 201 202 pool := New( 203 &conf.PoolConf{ 204 int32(testCase.maxNumberOfWorker), 205 int32(minNumberOfWorker), 206 queueSize, 207 keepAliveTimeInMillis, 208 monitoringPeriodInMillis, 209 }, 210 ) 211 212 b.Run(strconv.Itoa(testCase.maxNumberOfWorker)+maxWorkers+strconv.Itoa(jobSize)+"Jobs", func(b *testing.B) { 213 214 err := pool.Start() 215 216 assert.Nil(b, err) 217 218 var executeJobCallCount int32 = 0 219 220 for i := 0; i < jobSize; i++ { 221 job := NewMockJob() 222 job.ExecuteFunc = func() error { 223 atomic.AddInt32(&executeJobCallCount, 1) 224 dummyJob() 225 return nil 226 } 227 228 for isSubmitted, _ := pool.Submit(job); !isSubmitted; isSubmitted, _ = pool.Submit(job) { 229 } 230 } 231 232 err = pool.Stop() 233 234 assert.Nil(b, err) 235 assert.Equal(b, int32(jobSize), executeJobCallCount) 236 }) 237 } 238 } 239 240 // Mock Job 241 type MockJob struct { 242 JobIdFunc func() string 243 ExecuteFunc func() error 244 } 245 246 func NewMockJob() *MockJob { 247 return &MockJob{} 248 } 249 250 func (mj *MockJob) Id() string { 251 if mj.JobIdFunc != nil { 252 return mj.JobIdFunc() 253 } 254 return "mockJobId" 255 } 256 257 func (mj *MockJob) Execute() error { 258 if mj.ExecuteFunc != nil { 259 return mj.ExecuteFunc() 260 } 261 return nil 262 }