@Override
    public MigratablePipeline findPipelineToMigrate(LoadImbalance imbalance) {
        Set<? extends MigratablePipeline> candidates = imbalance.getPipelinesOwnedBy(imbalance.srcOwner);
        long migrationThreshold = (long) ((imbalance.maximumLoad - imbalance.minimumLoad)
                * MAXIMUM_NO_OF_EVENTS_AFTER_MIGRATION_COEFFICIENT);
        MigratablePipeline candidate = null;
        long loadInSelectedPipeline = 0;
        for (MigratablePipeline pipeline : candidates) {
            long load = imbalance.getLoad(pipeline);
            if (load > loadInSelectedPipeline) {
                if (load < migrationThreshold) {
                    loadInSelectedPipeline = load;
                    candidate = pipeline;
                }
            }
        }
        return candidate;
    }
@Test
    public void testFindPipelineToMigrate() {
        NioThread srcOwner = mock(NioThread.class);
        NioThread dstOwner = mock(NioThread.class);
        imbalance.srcOwner = srcOwner;
        imbalance.dstOwner = dstOwner;

        imbalance.minimumLoad = 100;
        MigratablePipeline pipeline1 = mock(MigratablePipeline.class);
        loadCounter.set(pipeline1, 100L);
        ownerToPipelines.put(dstOwner, singleton(pipeline1));

        imbalance.maximumLoad = 300;
        MigratablePipeline pipeline2 = mock(MigratablePipeline.class);
        MigratablePipeline pipeline3 = mock(MigratablePipeline.class);
        loadCounter.set(pipeline2, 200L);
        loadCounter.set(pipeline3, 100L);
        ownerToPipelines.put(srcOwner, Set.of(pipeline2, pipeline3));

        MigratablePipeline pipelineToMigrate = strategy.findPipelineToMigrate(imbalance);
        assertEquals(pipeline3, pipelineToMigrate);
    }