@Test
    public void shouldTriggerDrainHandler(TestContext context) throws Exception {
        Async asyncDrain = context.async(2);
        Async asyncServer = context.async();
        Async waitForServer = context.async();
        Async receivedResponse = context.async();

        HttpServer server = Vertx.vertx().createHttpServer()
                .connectionHandler(connection -> {
                    System.out.println("Connection");
                })
                .requestHandler(requestToPause -> {
                    System.out.println("Test server: pausing inbound request!");
                    requestToPause.pause();
                    pausedRequest = requestToPause;
                    requestToPause
                            .handler(ignored -> {})
                            .endHandler(isEnded -> {
                                requestToPause.response().end("bye!");
                            });
                    asyncServer.complete();
                }).listen(7297, result -> waitForServer.complete());

        waitForServer.await();

        Vertx vertx = Vertx.vertx();
        httpConnector = new HttpConnector(vertx,
                vertx.createHttpClient(),
                request,
                api,
                new ApimanHttpConnectorOptions()
                    .setHasDataPolicy(true)
                    .setUri(URI.create(api.getEndpoint())),
                new VertxConnectorConfig(),
                ignored -> {
                    // Immediately allow the dummy response to come back.
                    if (ignored.isError())
                        throw (RuntimeException) ignored.getError();
                    // Give permission to resume any response immediately.
                    httpConnector.transmit();
                });

        // Should be fired when write queue reduces to acceptable size.
        httpConnector.drainHandler(drain -> {
            System.err.println("Drain handler has been called! Yay.");
            asyncDrain.countDown();
        });

        httpConnector.bodyHandler(ignored -> {});

        httpConnector.endHandler(end -> {
            System.out.println("Called end on client. Should no longer be full!");
            receivedResponse.complete();
        });

        httpConnector.connect();

        writeUntilFull(httpConnector);

        Assert.assertTrue("Connection should be full", httpConnector.isFull());

        System.out.println("Waiting for server...");
        asyncServer.await();

        // Try to write some more as there *could* be some buffer flushed before the remote
        // server hit #pause.
        writeUntilFull(httpConnector);

        Assert.assertTrue("Connection should still be full", httpConnector.isFull());

        System.out.println("Resuming #pause()d server request; waiting packets should be consumed by the server.");
        pausedRequest.resume();

        System.out.println("Waiting for drain to be called (at least once)...");
        asyncDrain.await();

        Assert.assertFalse("Connector should no longer be full", httpConnector.isFull());

        System.out.println("Ending outbound connection");
        httpConnector.end();

        System.out.println("Waiting for response from server");
        receivedResponse.awaitSuccess();
    }
<p>
Test to ensure drain handler fires as expected; when the write queue has been exceeded, and
thus advertises itself as full {@link ISignalWriteStream#isFull}. This enables a simple
back-pressure mechanism which enables the corresponding ingress point to be paused (thus
backing off) until load has decreased.
</p>
<p>
The server then calls {@link HttpServerRequest#resume()}, allowing the queued data to flow
through, simulating a scenario in which the backlog has been cleared. Once the queue has
sufficiently diminished, {@link ISignalWriteStream#drainHandler(IAsyncHandler)} will be
called to indicate that the client can begin sending again.
</p>
<p>
Order of operations:
<ul>
<li>HTTP server initiated which immediately {@link HttpServerRequest#pause()}es any received
requests.</li>
<li>Invoke {@link HttpConnector#write(IApimanBuffer)} on connector until it indicates the
queue {@link HttpConnector#isFull()}.</li>
<li>{@link HttpServerRequest#resume} HTTP server to consume (and thus reduce) incoming
queue.</li>
<li>{@link ISignalWriteStream#drainHandler(IAsyncHandler)} is invoked once queue is
sufficiently small (as determined by impl which at time of writing is maxSize/2).</li>
</ul>

<p>
The drain handler is sometimes called multiple times, I think it's okay though.
</p>

@author Marc Savy {@literal <msavy@redhat.com>}
gateway/platforms/vertx3/vertx3/src/test/java/io/apiman/gateway/platforms/vertx3/connector/HttpConnectorDrainTest.java