/*
 * Copyright 2017 LINE Corporation
 *
 * LINE Corporation licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.linecorp.armeria.core;

import java.time.Duration;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.infra.Blackhole;

import com.linecorp.armeria.client.Clients;
import com.linecorp.armeria.client.WebClient;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
import com.linecorp.armeria.common.SessionProtocol;
import com.linecorp.armeria.common.metric.NoopMeterRegistry;
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerPort;
import com.linecorp.armeria.shared.AsyncCounters;

/**
 * Microbenchmarks of a {@link Server}.
 */
@State(Scope.Benchmark)
public class HttpServerBenchmark {

    // JMH bug prevents it from using enums that override toString() (it should use name() instead...).
    public enum Protocol {
        H2C(SessionProtocol.H2C),
        H1C(SessionProtocol.H1C);

        private final SessionProtocol sessionProtocol;

        Protocol(SessionProtocol sessionProtocol) {
            this.sessionProtocol = sessionProtocol;
        }

        String uriText() {
            return sessionProtocol.uriText();
        }
    }

    private Server server;
    private WebClient webClient;

    @Param
    private Protocol protocol;

    @Setup
    public void startServer() throws Exception {
        server = Server.builder()
                       .service("/empty", (ctx, req) -> HttpResponse.of(HttpStatus.OK))
                       .requestTimeout(Duration.ZERO)
                       .meterRegistry(NoopMeterRegistry.get())
                       .build();
        server.start().join();
        final ServerPort httpPort = server.activePorts().values().stream()
                                          .filter(ServerPort::hasHttp).findAny()
                                          .get();
        webClient = Clients.newClient("none+" + protocol.uriText() + "://127.0.0.1:" +
                                      httpPort.localAddress().getPort() + '/',
                                      WebClient.class);
    }

    @TearDown
    public void stopServer() throws Exception {
        server.stop().join();
    }

    @Benchmark
    public void empty(Blackhole bh, AsyncCounters counters) throws Exception {
        counters.incrementCurrentRequests();
        bh.consume(
                webClient.get("/empty")
                         .aggregate()
                         .handle((msg, t) -> {
                             counters.decrementCurrentRequests();
                             if (t != null) {
                                 counters.incrementNumFailures();
                             } else {
                                 counters.incrementNumSuccesses();
                             }
                             return null;
                         }));
    }
}

@@ -660,24 +660,66 @@
 eria.core;%0A%0A
+import java.nio.charset.StandardCharsets;%0A
 import java.
@@ -733,16 +733,16 @@
 ration;%0A
-
 %0Aimport 
@@ -993,16 +993,60 @@
 arDown;%0A
+import org.openjdk.jmh.annotations.Threads;%0A
 import o
@@ -1264,16 +1264,62 @@
 Status;%0A
+import com.linecorp.armeria.common.MediaType;%0A
 import c
@@ -2289,32 +2289,115 @@
 ows Exception %7B%0A
+        final byte%5B%5D PLAINTEXT = %22Hello, World!%22.getBytes(StandardCharsets.UTF_8);%0A
         server =
@@ -2502,16 +2502,179 @@
 us.OK))%0A
+                       .service(%22/plaintext%22, (ctx, req) -%3E HttpResponse%0A                               .of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, PLAINTEXT))%0A
         
@@ -4020,16 +4020,16 @@
 n null;%0A
-
         
@@ -4055,11 +4055,640 @@
 );%0A    %7D
+%0A%0A    /**%0A     * A benchmark for a test designed to demonstrate the capacity about %7B@code MediaType.PLAIN_TEXT_UTF_8%7D.%0A     *%0A     * @see %3Ca href=%22https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#plaintext%22%3EPlaintext test%3C/a%3E%0A     * @see %3Ca href=%22https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Java/armeria/src/main/java/hello/services/HelloService.java%22%3EReference%3C/a%3E%0A     */%0A    @Threads(Threads.MAX)%0A    @Benchmark%0A    public void plainText(Blackhole bh) throws Exception %7B%0A        bh.consume(webClient.get(%22/plaintext%22).aggregate().join());%0A    %7D
 %0A%7D%0A

Add a benchmark for plaintext (#3444)