private Summary run(long operations, int workPerSuccess, int numberOfWorkers, int maximumTasksPerWorker,
                        int workerParallelism, ManualTimer timer, DynamicThrottlePolicy... policies) {
        System.err.printf("\n### Running %d operations of %d ticks each against %d workers with parallelism %d and queue size %d\n",
                          operations, workPerSuccess, numberOfWorkers, workerParallelism, maximumTasksPerWorker);

        List<Integer> order = IntStream.range(0, policies.length).boxed().collect(Collectors.toCollection(ArrayList::new));
        MockServer resource = new MockServer(workPerSuccess, numberOfWorkers, maximumTasksPerWorker, workerParallelism);
        AtomicLong outstanding = new AtomicLong(operations);
        AtomicLong errors = new AtomicLong(0);
        long ticks = 0;
        long totalPending = 0;
        double[] windows = new double[policies.length];
        int[] pending = new int[policies.length];
        while (outstanding.get() + resource.pending() > 0) {
            Collections.shuffle(order);
            for (int j = 0; j < policies.length; j++) {
                int i = order.get(j);
                DynamicThrottlePolicy policy = policies[i];
                windows[i] += policy.getWindowSize();
                while (policy.canSend(message, pending[i])) {
                    outstanding.decrementAndGet();
                    policy.processMessage(message);
                    ++pending[i];
                    resource.send(successful -> {
                        --pending[i];
                        if (successful)
                            policy.processReply(success);
                        else {
                            errors.incrementAndGet();
                            outstanding.incrementAndGet();
                            policy.processReply(error);
                        }
                    });
                }
            }
            ++ticks;
            totalPending += resource.pending();
            resource.tick();
            timer.advance(1);
        }

        for (int i = 0; i < windows.length; i++)
            windows[i] /= ticks;

        return new Summary(timer.milliTime() / (workPerSuccess * operations / (double) numberOfWorkers) * workerParallelism,
                           errors.get() / (double) operations,
                           totalPending / (double) ticks,
                           windows);
    }
A more realistic test, where throughput gradually flattens with increasing window size, and with more variance in throughput.
messagebus/src/test/java/com/yahoo/messagebus/DynamicThrottlePolicyTest.java