private void testClientConnectionHandler(boolean local, boolean global) throws Exception { server.requestHandler(req -> { req.response().end(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); AtomicInteger status = new AtomicInteger(); Handler<HttpConnection> handler = conn -> status.getAndIncrement(); if (global) { client.connectionHandler(handler); } HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { assertEquals((local ? 1 : 0) + (global ? 1 : 0), status.getAndIncrement()); testComplete(); }); if (local) { req.connectionHandler(handler); } req.end(); await(); }
@Test public void testClientConnectionExceptionHandler() throws Exception { server.requestHandler(req -> { NetSocket so = req.netSocket(); so.write(Buffer.buffer(TestUtils.randomAlphaString(40) + "\r\n")); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { }); req.connectionHandler(conn -> { conn.exceptionHandler(err -> { testComplete(); }); }); req.sendHead(); await(); }
@Test public void testServerConnectionClose() throws Exception { // Test server connection close + client close handler server.requestHandler(req -> { req.connection().close(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onFailure(err -> { })) .connectionHandler(conn -> { conn.closeHandler(v -> { testComplete(); }); }).sendHead(); await(); }
@Test public void testIncorrectHttpVersion() throws Exception { server.requestHandler(req -> { NetSocket so = req.netSocket(); so.write(Buffer.buffer("HTTP/1.2 200 OK\r\nContent-Length:5\r\n\r\nHELLO")); so.close(); }); startServer(); AtomicBoolean a = new AtomicBoolean(); HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(err -> { if (a.compareAndSet(false, true)) { assertTrue("message " + err.getMessage() + " should contain HTTP/1.2", err.getMessage().contains("HTTP/1.2")); } })); req.exceptionHandler(err -> { fail("Should not be called"); }).putHeader("connection", "close") .connectionHandler(conn -> conn.closeHandler(v -> testComplete())) .end(); await(); }
startServer(); HttpClientRequest req = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onFailure(resp -> {})); req.connectionHandler(conn -> { AtomicInteger gaCount = new AtomicInteger(); conn.goAwayHandler(ga -> {
@Test public void testInvalidServerResponse() throws Exception { ServerBootstrap bootstrap = createH2Server((dec, enc) -> new Http2EventAdapter() { @Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception { enc.writeHeaders(ctx, streamId, new DefaultHttp2Headers().status("xyz"), 0, false, ctx.newPromise()); ctx.flush(); } }); ChannelFuture s = bootstrap.bind(DEFAULT_HTTPS_HOST, DEFAULT_HTTPS_PORT).sync(); try { Context ctx = vertx.getOrCreateContext(); ctx.runOnContext(v -> { client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onFailure(err -> { assertOnIOContext(ctx); if (err instanceof NumberFormatException) { testComplete(); } })) .connectionHandler(conn -> conn.exceptionHandler(err -> fail())) .end(); }); await(); } finally { s.channel().close().sync(); } }
@Test public void testDiscardConnectionWhenChannelBecomesInactive() throws Exception { AtomicInteger count = new AtomicInteger(); server.requestHandler(req -> { if (count.getAndIncrement() == 0) { Http2ServerConnection a = (Http2ServerConnection) req.connection(); SocketChannel channel = (SocketChannel) a.channel(); channel.shutdown(); } else { req.response().end(); } }); startServer(); AtomicBoolean closed = new AtomicBoolean(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(err -> {})) .connectionHandler(conn -> conn.closeHandler(v -> closed.set(true))) .end(); AsyncTestBase.assertWaitUntil(closed::get); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> { testComplete(); }).exceptionHandler(err -> { fail(); }).end(); await(); }
@Test public void testConnectionHandler() throws Exception { waitFor(2); server.requestHandler(req -> { req.response().end(); }); startServer(); AtomicReference<HttpConnection> connection = new AtomicReference<>(); HttpClientRequest req1 = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onSuccess(resp -> { assertSame(connection.get(), resp.request().connection()); complete(); })); req1.connectionHandler(conn -> { Context ctx = Vertx.currentContext(); assertOnIOContext(ctx); assertTrue(connection.compareAndSet(null, conn)); }); HttpClientRequest req2 = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onSuccess(resp -> { assertSame(connection.get(), resp.request().connection()); complete(); })); req2.connectionHandler(conn -> { fail(); }); req1.end(); req2.end(); await(); }
@Test public void testServerShutdownConnection() throws Exception { waitFor(2); server.connectionHandler(HttpConnection::shutdown); server.requestHandler(req -> fail()); startServer(); AtomicInteger count = new AtomicInteger(); HttpClientRequest req1 = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onFailure(err -> { if (count.getAndIncrement() == 0) { complete(); } })); req1.connectionHandler(conn -> { Context ctx = Vertx.currentContext(); conn.goAwayHandler(ga -> { assertOnIOContext(ctx); complete(); }); }); req1.end(); await(); }
@Test public void testUpdateConnectionWindowSize() throws Exception { ServerBootstrap bootstrap = createH2Server((decoder, encoder) -> new Http2EventAdapter() { @Override public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement) throws Http2Exception { vertx.runOnContext(v -> { assertEquals(65535, windowSizeIncrement); testComplete(); }); } }); ChannelFuture s = bootstrap.bind(DEFAULT_HTTPS_HOST, DEFAULT_HTTPS_PORT).sync(); client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { }).connectionHandler(conn -> { assertEquals(65535, conn.getWindowSize()); conn.setWindowSize(65535 + 10000); assertEquals(65535 + 10000, conn.getWindowSize()); conn.setWindowSize(65535 + 65535); assertEquals(65535 + 65535, conn.getWindowSize()); }).end(); await(); }
fail(); }); req.connectionHandler(conn -> { conn.closeHandler(v -> { assertTrue(System.currentTimeMillis() - time.get() > 1000);
@Test public void testSendPing() throws Exception { waitFor(2); Buffer expected = TestUtils.randomBuffer(8); Context ctx = vertx.getOrCreateContext(); server.close(); server.connectionHandler(conn -> { conn.pingHandler(data -> { assertEquals(expected, data); complete(); }); }); server.requestHandler(req -> {}); startServer(ctx); HttpClientRequest req = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { }); req.connectionHandler(conn -> { conn.ping(expected, ar -> { assertTrue(ar.succeeded()); Buffer buff = ar.result(); assertEquals(expected, buff); complete(); }); }); req.end(); await(); }
})).connectionHandler(conn -> { conn.exceptionHandler(err -> { assertSame(ctx, Vertx.currentContext());
@Repeat(times = 10) @Test public void testCloseServerConnectionWithPendingMessages() throws Exception { int n = 5; server.requestHandler(req -> { vertx.setTimer(100, id -> { req.response().close(); }); }); startServer(); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(n).setPipelining(true)); AtomicBoolean completed = new AtomicBoolean(); for (int i = 0; i < n * 2; i++) { client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(resp -> { })) .connectionHandler(conn -> { conn.closeHandler(v -> { if (completed.compareAndSet(false, true)) { testComplete(); } }); }).end(); } await(); }
@Test public void testReceivePing() throws Exception { Buffer expected = TestUtils.randomBuffer(8); Context ctx = vertx.getOrCreateContext(); server.close(); server.connectionHandler(conn -> { conn.ping(expected, ar -> { }); }); server.requestHandler(req -> {}); startServer(ctx); HttpClientRequest req = client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { }); req.connectionHandler(conn -> { conn.pingHandler(data -> { assertEquals(expected, data); complete(); }); }); req.end(); await(); }
})).connectionHandler(conn -> { conn.closeHandler(v -> { complete();
CountDownLatch latch = new CountDownLatch(1); client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { }).connectionHandler(conn -> { assertEquals(max == null ? 0xFFFFFFFFL : max, conn.remoteSettings().getMaxConcurrentStreams()); latch.countDown();
@Test public void testInitialMaxConcurrentStreamZero() throws Exception { server.close(); server = vertx.createHttpServer(createBaseServerOptions().setInitialSettings(new Http2Settings().setMaxConcurrentStreams(0))); server.requestHandler(req -> { req.response().end(); }); server.connectionHandler(conn -> { vertx.setTimer(500, id -> { conn.updateSettings(new Http2Settings().setMaxConcurrentStreams(10)); }); }); startServer(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> { testComplete(); }).connectionHandler(conn -> { assertEquals(10, conn.remoteSettings().getMaxConcurrentStreams()); }).setTimeout(10000).exceptionHandler(this::fail).end(); await(); }
startServer(); AtomicInteger count = new AtomicInteger(); client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onFailure(resp -> {})).connectionHandler(conn -> { conn.remoteSettingsHandler(settings -> { switch (count.getAndIncrement()) {
complete(); }); req.connectionHandler(conn -> { conn.closeHandler(v2 -> { assertSame(ctx, Vertx.currentContext());