/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.benchmark;

import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.openjdk.jmh.results.RunResult;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import software.amazon.awssdk.benchmark.apicall.MetricsEnabledBenchmark;
import software.amazon.awssdk.benchmark.apicall.httpclient.async.NettyClientH1NonTlsBenchmark;
import software.amazon.awssdk.benchmark.apicall.httpclient.async.NettyHttpClientH1Benchmark;
import software.amazon.awssdk.benchmark.apicall.httpclient.async.NettyHttpClientH2Benchmark;
import software.amazon.awssdk.benchmark.apicall.httpclient.sync.ApacheHttpClientBenchmark;
import software.amazon.awssdk.benchmark.apicall.httpclient.sync.UrlConnectionHttpClientBenchmark;
import software.amazon.awssdk.benchmark.apicall.protocol.Ec2ProtocolBenchmark;
import software.amazon.awssdk.benchmark.apicall.protocol.JsonProtocolBenchmark;
import software.amazon.awssdk.benchmark.apicall.protocol.QueryProtocolBenchmark;
import software.amazon.awssdk.benchmark.apicall.protocol.XmlProtocolBenchmark;
import software.amazon.awssdk.benchmark.coldstart.V2DefaultClientCreationBenchmark;
import software.amazon.awssdk.benchmark.coldstart.V2OptimizedClientCreationBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientDeleteV1MapperComparisonBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientGetOverheadBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientGetV1MapperComparisonBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientPutOverheadBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientPutV1MapperComparisonBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientQueryV1MapperComparisonBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientScanV1MapperComparisonBenchmark;
import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientUpdateV1MapperComparisonBenchmark;
import software.amazon.awssdk.utils.Logger;


public class BenchmarkRunner {

    private static final List<String> PROTOCOL_BENCHMARKS = Arrays.asList(
        Ec2ProtocolBenchmark.class.getSimpleName(), JsonProtocolBenchmark.class.getSimpleName(),
        QueryProtocolBenchmark.class.getSimpleName(), XmlProtocolBenchmark.class.getSimpleName());

    private static final List<String> ASYNC_BENCHMARKS = Arrays.asList(
        NettyHttpClientH2Benchmark.class.getSimpleName(),
        NettyHttpClientH1Benchmark.class.getSimpleName(),
        NettyClientH1NonTlsBenchmark.class.getSimpleName());

    private static final List<String> SYNC_BENCHMARKS = Arrays.asList(
        ApacheHttpClientBenchmark.class.getSimpleName(),
        UrlConnectionHttpClientBenchmark.class.getSimpleName());

    private static final List<String> COLD_START_BENCHMARKS = Arrays.asList(
        V2OptimizedClientCreationBenchmark.class.getSimpleName(),
        V2DefaultClientCreationBenchmark.class.getSimpleName());

    private static final List<String> MAPPER_BENCHMARKS = Arrays.asList(
            EnhancedClientGetOverheadBenchmark.class.getSimpleName(),
            EnhancedClientPutOverheadBenchmark.class.getSimpleName(),
            EnhancedClientGetV1MapperComparisonBenchmark.class.getSimpleName(),
            EnhancedClientPutV1MapperComparisonBenchmark.class.getSimpleName(),
            EnhancedClientUpdateV1MapperComparisonBenchmark.class.getSimpleName(),
            EnhancedClientDeleteV1MapperComparisonBenchmark.class.getSimpleName(),
            EnhancedClientScanV1MapperComparisonBenchmark.class.getSimpleName(),
            EnhancedClientQueryV1MapperComparisonBenchmark.class.getSimpleName()
    );

    private static final List<String> METRIC_BENCHMARKS = Arrays.asList(MetricsEnabledBenchmark.class.getSimpleName());

    private static final Logger log = Logger.loggerFor(BenchmarkRunner.class);

    private final List<String> benchmarksToRun;
    private final BenchmarkResultProcessor resultProcessor;

    private BenchmarkRunner(List<String> benchmarksToRun) {
        this.benchmarksToRun = benchmarksToRun;
        this.resultProcessor = new BenchmarkResultProcessor();
    }

    public static void main(String... args) throws RunnerException, JsonProcessingException {
        List<String> benchmarksToRun = new ArrayList<>();
        benchmarksToRun.addAll(SYNC_BENCHMARKS);
        benchmarksToRun.addAll(ASYNC_BENCHMARKS);
        benchmarksToRun.addAll(PROTOCOL_BENCHMARKS);
        benchmarksToRun.addAll(COLD_START_BENCHMARKS);
        benchmarksToRun.addAll(MAPPER_BENCHMARKS);
        benchmarksToRun.addAll(METRIC_BENCHMARKS);

        BenchmarkRunner runner = new BenchmarkRunner(benchmarksToRun);

        runner.runBenchmark();
    }

    private void runBenchmark() throws RunnerException {
        ChainedOptionsBuilder optionsBuilder = new OptionsBuilder();

        benchmarksToRun.forEach(optionsBuilder::include);

        log.info(() -> "Starting to run: " + benchmarksToRun);

        Collection<RunResult> results = new Runner(optionsBuilder.build()).run();

        List<String> failedResult = resultProcessor.processBenchmarkResult(results);

        if (!failedResult.isEmpty()) {
            log.info(() -> "Failed perf regression tests: " + failedResult);
            throw new RuntimeException("Perf regression tests failed: " + failedResult);
        }
    }
}

@@ -5426,32 +5426,33 @@
 ENCHMARKS);%0A
+%0A
         
 benchmarksTo
@@ -5443,82 +5443,100 @@
     
-benchmarksToRun.addAll(MAPPER_BENCHMARKS);%0A        benchmarksToRun.addAll(
+log.info(() -%3E %22Skipping tests, to reduce benchmark times: %5Cn%22 + MAPPER_BENCHMARKS + %22%5Cn%22 + 
 METR
@@ -5544,32 +5544,33 @@
 C_BENCHMARKS);%0A%0A
+%0A
         Benchmar

Remove DynamoDB and Metrics tests from the benchmark test suite, by default. This should make running benchmarks much more timely.