plugins {
    id 'conventions.common'
    id 'conventions.jvm'
    alias libs.plugins.jmh
}

description = 'Conscrypt: JMH on OpenJDK Benchmarks'

evaluationDependsOn(':conscrypt-openjdk')

ext {
    preferredSourceSet = project(':conscrypt-openjdk').preferredSourceSet
    preferredNativeFileDir = project(':conscrypt-openjdk').preferredNativeFileDir

    genDir = "${buildDir}/jmh-generated-classes"
    jmhInclude = System.getProperty('jmh.include')
    jmhParams = System.getProperty('jmh.parameters')
    jmhWarmupIterations = System.getProperty('jmh.wi', '10')
    jmhIterations = System.getProperty('jmh.i', '10')
    jmhFork = System.getProperty('jmh.f', '1')
    jmhJvm = System.getProperty('jmh.jvm')
    jmhJvmArgs = System.getProperty('jmh.jvmArgs', '-server -Xms2g -Xmx2g')
}

jmh {
    jmhVersion = "$jmhVersion"
    if (jmhInclude != null) {
        setInclude(jmhInclude.toString())
    }
    if (jmhParams != null) {
        setBenchmarkParameters(parseParams(jmhParams))
    }
    warmupIterations = "$jmhWarmupIterations".toInteger()
    iterations = "$jmhIterations".toInteger()
    fork = "$jmhFork".toInteger()
    // jvmArgs = jmhJvmArgs
    if (jmhJvm != null) {
        jvm = jmhJvm
    }
    duplicateClassesStrategy = DuplicatesStrategy.WARN
}

configurations {
    // The JMH plugin by defaults depends on all of the generators for an old version of JMH.
    // Need to remove all the generators that we're not explicitly overriding to eliminate the
    // dependency on the old version of JMH.
    jmh.exclude module:'jmh-generator-asm'

    jmhGeneratorAnnprocess
}

sourceSets {
    sourceSets {
        main {
            resources {
                // This shouldn't be needed but seems to help IntelliJ locate
                // META_INF/BenchmarkList.
                srcDirs += genDir

                // This shouldn't be needed but seems to help IntelliJ locate the native artifact.
                srcDirs += preferredNativeFileDir
            }
        }
    }
}

dependencies {
    implementation project(":conscrypt-openjdk"),
            project(path: ":conscrypt-testing", configuration: "runtimeElements"),
            project(':conscrypt-benchmark-base'),
            // Add the preferred native openjdk configuration for this platform.
            //project(':conscrypt-openjdk').sourceSets["$preferredSourceSet"].output,
            libs.junit,
            libs.netty.handler,
            libs.netty.tcnative

    jmhGeneratorAnnprocess libs.jmh.generator.annprocess

    // Override the default JMH dependencies with the new versions.
    jmh libs.jmh.core,
            libs.jmh.generator.reflection,
            libs.jmh.generator.bytecode
}

// Running benchmarks in IntelliJ seems broken without this.
// See https://github.com/melix/jmh-gradle-plugin/issues/39
// TODO(prb): Investigate and fix for Gradle 7+
//idea.module {
//    scopes.PROVIDED.plus += [ configurations.compile, configurations.jmh ]
//}

// Param strings are in the form "param:VAL1,VAL2;param2:VAL3,VAL4"
static def parseParams(s) {
    // It's really easy to type jmh.parameters=foo=bar instead of jmh.parameters=foo:bar,
    // so check for that.
    if (s.contains("=")) {
        throw new IllegalArgumentException("jmh.parameters value shouldn't include '='.  (Did you mean ':'?)")
    }
    return s.split(";").collectEntries { entry ->
        def pair = entry.split(":")
        [ (pair.first().trim()) : pair.last().split(",").collect { it.trim() } ]
    }
}
