Merge dependabot/npm_and_yarn/examples/typescript/http-server-pool/fastify-hybrid...
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
index 8894ba3126102faef6ab1dbea23ef20676c21a37..51478a0620767d03730d8c441baf9e5ab4c18ea4 100644 (file)
@@ -1,13 +1,12 @@
 const { expect } = require('expect')
 const {
+  DynamicClusterPool,
   DynamicThreadPool,
   FixedClusterPool,
   FixedThreadPool,
-  PoolEvents,
   WorkerChoiceStrategies
 } = require('../../../lib')
 const { CircularArray } = require('../../../lib/circular-array')
-const { waitPoolEvents } = require('../../test-utils')
 
 describe('Selection strategies test suite', () => {
   const min = 0
@@ -67,6 +66,43 @@ describe('Selection strategies test suite', () => {
       expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
         workerChoiceStrategy
       )
+      expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
+        retries: 6,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
+        retries: 6,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      await pool.destroy()
+    }
+    for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
+      const pool = new DynamicClusterPool(
+        min,
+        max,
+        './tests/worker-files/cluster/testWorker.js'
+      )
+      pool.setWorkerChoiceStrategy(workerChoiceStrategy, { retries: 3 })
+      expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
+      expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
+        workerChoiceStrategy
+      )
+      expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
+        retries: 3,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
+        retries: 3,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
       await pool.destroy()
     }
   })
@@ -77,41 +113,68 @@ describe('Selection strategies test suite', () => {
       './tests/worker-files/thread/testWorker.js'
     )
     for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
-      if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).nextWorkerNodeKey
+      ).toBe(0)
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).previousWorkerNodeKey
+      ).toBe(0)
+      if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).nextWorkerNodeKey
-        ).toBe(0)
-      } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
+          ).workersVirtualTaskEndTimestamp
+        ).toStrictEqual([])
+      } else if (
+        workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
+      ) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workersVirtualTaskEndTimestamp
-        ).toBeInstanceOf(Array)
+          ).defaultWorkerWeight
+        ).toBeGreaterThan(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workersVirtualTaskEndTimestamp.length
+          ).workerVirtualTaskRunTime
         ).toBe(0)
       } else if (
-        workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
+        workerChoiceStrategy ===
+        WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
       ) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).nextWorkerNodeKey
+          ).defaultWorkerWeight
+        ).toBeGreaterThan(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).workerVirtualTaskRunTime
         ).toBe(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).defaultWorkerWeight
-        ).toBeGreaterThan(0)
+          ).roundId
+        ).toBe(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workerVirtualTaskRunTime
+          ).workerNodeId
         ).toBe(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).roundWeights
+        ).toStrictEqual([
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).defaultWorkerWeight
+        ])
       }
     }
     await pool.destroy()
@@ -125,7 +188,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -135,7 +199,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -198,10 +263,11 @@ describe('Selection strategies test suite', () => {
   })
 
   it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
+    const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
     const pool = new FixedThreadPool(
       max,
       './tests/worker-files/thread/testWorker.js',
-      { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
+      { workerChoiceStrategy }
     )
     // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
     const promises = new Set()
@@ -217,39 +283,46 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        WorkerChoiceStrategies.ROUND_ROBIN
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
 
   it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
+    const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
     const pool = new DynamicThreadPool(
       min,
       max,
       './tests/worker-files/thread/testWorker.js',
-      { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
+      { workerChoiceStrategy }
     )
     // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
     const promises = new Set()
@@ -261,33 +334,43 @@ describe('Selection strategies test suite', () => {
     for (const workerNode of pool.workerNodes) {
       expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        WorkerChoiceStrategies.ROUND_ROBIN
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -327,15 +410,25 @@ describe('Selection strategies test suite', () => {
     )
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     await pool.destroy()
     pool = new DynamicThreadPool(
       min,
@@ -345,15 +438,25 @@ describe('Selection strategies test suite', () => {
     )
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -366,7 +469,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -376,7 +480,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -458,20 +563,21 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -480,6 +586,16 @@ describe('Selection strategies test suite', () => {
         max * maxMultiplier
       )
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -505,20 +621,21 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -527,6 +644,16 @@ describe('Selection strategies test suite', () => {
         max * maxMultiplier
       )
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -539,7 +666,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -549,7 +677,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -625,26 +754,27 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -663,6 +793,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -682,26 +822,27 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -720,6 +861,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -732,7 +883,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -742,7 +894,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -818,33 +971,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
+        elu: expect.objectContaining({
           idle: expect.objectContaining({
             history: expect.any(CircularArray)
           }),
           active: expect.objectContaining({
             history: expect.any(CircularArray)
           })
-        }
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
       if (workerNode.usage.elu.utilization == null) {
         expect(workerNode.usage.elu.utilization).toBeUndefined()
       } else {
@@ -852,6 +1016,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -871,33 +1045,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
+        elu: expect.objectContaining({
           idle: expect.objectContaining({
             history: expect.any(CircularArray)
           }),
           active: expect.objectContaining({
             history: expect.any(CircularArray)
           })
-        }
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
       if (workerNode.usage.elu.utilization == null) {
         expect(workerNode.usage.elu.utilization).toBeUndefined()
       } else {
@@ -905,6 +1090,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -917,7 +1112,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -927,7 +1123,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1003,28 +1200,29 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: expect.objectContaining({
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
+        elu: expect.objectContaining({
           idle: expect.objectContaining({
             history: expect.any(CircularArray)
           }),
           active: expect.objectContaining({
             history: expect.any(CircularArray)
           })
-        }
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1040,6 +1238,16 @@ describe('Selection strategies test suite', () => {
       } else {
         expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
       }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
       if (workerNode.usage.elu.utilization == null) {
         expect(workerNode.usage.elu.utilization).toBeUndefined()
       } else {
@@ -1047,6 +1255,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1071,28 +1289,29 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: expect.objectContaining({
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
+        elu: expect.objectContaining({
           idle: expect.objectContaining({
             history: expect.any(CircularArray)
           }),
           active: expect.objectContaining({
             history: expect.any(CircularArray)
           })
-        }
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1108,6 +1327,16 @@ describe('Selection strategies test suite', () => {
       } else {
         expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
       }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
       if (workerNode.usage.elu.utilization == null) {
         expect(workerNode.usage.elu.utilization).toBeUndefined()
       } else {
@@ -1115,6 +1344,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1144,28 +1383,29 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: expect.objectContaining({
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
+        elu: expect.objectContaining({
           idle: expect.objectContaining({
             history: expect.any(CircularArray)
           }),
           active: expect.objectContaining({
             history: expect.any(CircularArray)
           })
-        }
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1181,6 +1421,16 @@ describe('Selection strategies test suite', () => {
       } else {
         expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
       }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
       if (workerNode.usage.elu.utilization == null) {
         expect(workerNode.usage.elu.utilization).toBeUndefined()
       } else {
@@ -1188,6 +1438,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1224,12 +1484,12 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp
     ).toBeInstanceOf(Array)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp.length
     ).toBe(0)
     await pool.destroy()
@@ -1259,12 +1519,12 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp
     ).toBeInstanceOf(Array)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp.length
     ).toBe(0)
     // We need to clean up the resources after our test
@@ -1279,7 +1539,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -1289,7 +1550,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1371,20 +1633,21 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: expect.objectContaining({
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1403,6 +1666,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1438,24 +1711,21 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          maximum: expect.any(Number),
-          minimum: expect.any(Number),
-          average: expect.any(Number),
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1463,9 +1733,27 @@ describe('Selection strategies test suite', () => {
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.average == null) {
+        expect(workerNode.usage.runTime.average).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1506,24 +1794,21 @@ describe('Selection strategies test suite', () => {
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          maximum: expect.any(Number),
-          minimum: expect.any(Number),
-          median: expect.any(Number),
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1531,9 +1816,27 @@ describe('Selection strategies test suite', () => {
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.median == null) {
+        expect(workerNode.usage.runTime.median).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
+      }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1559,6 +1862,11 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1575,6 +1883,11 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1582,7 +1895,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workerVirtualTaskRunTime
     ).toBe(0)
     await pool.destroy()
@@ -1596,6 +1909,11 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1612,6 +1930,11 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1619,7 +1942,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workerVirtualTaskRunTime
     ).toBe(0)
     // We need to clean up the resources after our test
@@ -1635,7 +1958,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -1645,7 +1969,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1663,8 +1988,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1689,8 +2014,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1717,8 +2042,6 @@ describe('Selection strategies test suite', () => {
           WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
       }
     )
-    // FIXME: shall not be needed
-    await waitPoolEvents(pool, PoolEvents.ready, 1)
     // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
     const promises = new Set()
     const maxMultiplier = 2
@@ -1729,27 +2052,32 @@ describe('Selection strategies test suite', () => {
     for (const workerNode of pool.workerNodes) {
       expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1761,11 +2089,21 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1799,27 +2137,32 @@ describe('Selection strategies test suite', () => {
     for (const workerNode of pool.workerNodes) {
       expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1831,11 +2174,21 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1861,11 +2214,21 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).roundId
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).workerNodeId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1879,14 +2242,24 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1894,7 +2267,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1912,11 +2285,21 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).roundId
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).workerNodeId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1928,11 +2311,26 @@ describe('Selection strategies test suite', () => {
       ).roundWeights
     ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).roundId
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1940,7 +2338,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(