@Test
    void exceededMaxStreamsPropagatesFailureCorrectly() throws Exception {
        final Queue<ClientConnectionTimings> connectionTimings = new ConcurrentLinkedQueue<>();
        final WebClient client = WebClient.builder(server.uri(SessionProtocol.H2C))
                                          .factory(clientFactory)
                                          .decorator(connectionTimingsAccumulatingDecorator(connectionTimings))
                                          .build();
        final AtomicInteger opens = new AtomicInteger();
        connectionPoolListener = newConnectionPoolListener(opens::incrementAndGet, () -> {});
        final List<CompletableFuture<AggregatedHttpResponse>> receivedResponses = new ArrayList<>();

        final int numExpectedConnections = MAX_NUM_CONNECTIONS;
        final int numRequests = MAX_CONCURRENT_STREAMS * numExpectedConnections;
        final int numFailedRequests = MAX_CONCURRENT_STREAMS - 1;

        runInsideEventLoop(clientFactory.eventLoopGroup(), () -> {
            for (int i = 0; i < numRequests + numFailedRequests; i++) {
                receivedResponses.add(client.get(PATH).aggregate());
            }
        });

        await().untilAsserted(() -> assertThat(responses).hasSize(numRequests));
        await().until(() -> receivedResponses.stream().filter(CompletableFuture::isCompletedExceptionally)
                                             .count() == numFailedRequests);
        assertThat(opens).hasValue(numExpectedConnections);
        assertThat(connectionTimings.stream().filter(
                timings -> timings.pendingAcquisitionDurationNanos() > 0))
                .hasSize(numRequests + numFailedRequests - 1);

        // Check exception thrown by responses
        await().untilAsserted(() -> assertThat(receivedResponses.stream().filter(
                CompletableFuture::isCompletedExceptionally)).hasSize(2));

        receivedResponses
                .stream().filter(CompletableFuture::isCompletedExceptionally)
                .forEach(responseFuture -> {
                    final Throwable throwable = catchThrowable(responseFuture::join);
                    assertThat(throwable).isInstanceOf(CompletionException.class)
                                         .hasCauseInstanceOf(UnprocessedRequestException.class);
                    assertThat(throwable.getCause().getCause()).satisfiesAnyOf(
                            e -> assertThat(e).isInstanceOf(ClosedSessionException.class),
                            e -> assertThat(e).isInstanceOf(ConnectException.class)
                                              .hasMessageContaining("reset by peer"),
                            e -> assertThat(e).isInstanceOf(SocketException.class)
                                              .hasMessageContaining("reset by peer"));
                });
    }
Makes sure Armeria HTTP client respects {@code MAX_CONCURRENT_STREAMS} HTTP/2 setting.
core/src/test/java/com/linecorp/armeria/client/HttpClientMaxConcurrentStreamTest.java