/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF 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
 *
 *    http://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.
 */
allprojects {
    tasks.withType(Test) {
        def jdk8 = ['-XX:+UseConcMarkSweepGC']
        def jdk9 = ['-Djava.locale.providers=COMPAT,SPI'/*, '--illegal-access=debug'*/]
        def common = ['-ea', '-Duser.language=en', "-Xms${groovyJUnit_ms}", "-Xmx${groovyJUnit_mx}"]
        if (JavaVersion.current().isJava9Compatible()) {
            jvmArgs (*common, *jdk9)
            systemProperty 'groovy.force.illegal.access', findProperty('groovy.force.illegal.access')
        } else {
            jvmArgs (*common, *jdk8)
        }
        def headless = System.properties['java.awt.headless']
        if (headless == 'true') {
            systemProperties 'java.awt.headless': 'true'
        }
        systemProperties 'apple.awt.UIElement': 'true', 'javadocAssertion.src.dir': './src/main'
        if (rootProject.hasProperty('target.java.home')) {
            String targetJavaHome = rootProject.property('target.java.home')
            if (targetJavaHome?.trim()) {
                executable = "${targetJavaHome}/bin/java"
            }
        }

        forkEvery = 50
        maxParallelForks = isRunningOnCI() ? 1 : Runtime.runtime.availableProcessors()
        scanForTestClasses = true
        ignoreFailures = false
        testLogging {
            exceptionFormat = 'full'
            // uncomment the following line if you need more logging
            // events "failed", "started"
        }
    }

    // create an Indy test suite
    if (rootProject.indyCapable()) {
        def dependencies = configurations.testRuntimeOnly.incoming.dependencies.findResults {
            if (it.name.startsWith('groovy')) return it.name
        }
        task testWithIndy(type: Test) {
            systemProperties 'groovy.target.indy': true
            dependsOn 'jarWithIndy'
            dependencies.each { dependsOn "${it}:jarWithIndy" }
            classpath = classpath - files(jar.archivePath, *dependencies.collect { project(it).jar }) +
                    files({ [jarWithIndy.archivePath, *dependencies.collect { project(it).jarWithIndy }] })
        }
        task testAll {
            description = "Runs both the normal and indy test suites"
            dependsOn test, testWithIndy
        }
        check.dependsOn testWithIndy
    }

    sourceSets {
        test {
            groovy {
                srcDirs += 'src/spec/test'
            }
            resources {
                srcDirs += 'src/spec/test-resources'
            }
        }
    }
}

tasks.withType(Test) {
    def testdb = System.properties['groovy.testdb.props']
    if (testdb) {
        systemProperties 'groovy.testdb.props': testdb
    }
    systemProperties 'gradle.home': gradle.gradleHomeDir // this is needed by the security.policy

    classpath = files('src/test') + classpath
    exclude buildExcludeFilter(it.name == 'test')
    ext.resultText = ''
    doLast {
        ant.delete {
            fileset(dir: '.', includes: '*.class')
        }
    }
}

boolean isRunningOnCI() {
    // home/runner/work is path for Github actions
    new File('.').absolutePath =~ $/teamcity|jenkins|hudson|travis|/home/runner/work/$
}

logger.lifecycle "Detected ${isRunningOnCI() ? 'Continuous Integration environment' : 'development environment'}"

tasks.addRule('Pattern: testSingle<Name> will test **/<Name>.class') { String taskName ->
    if (taskName.startsWith('testSingle')) {
        tasks.create(taskName).dependsOn(test)
        test.includes = ['**/' + taskName.substring(10) + '.class']
        test.outputs.upToDateWhen { false }
    }
}

def buildExcludeFilter(boolean legacyTestSuite) {
    def excludes = []

    // if no network available, disable Grapes
    if (!System.properties['junit.network']) {
        excludes << 'groovy/grape/'
    }

    if (legacyTestSuite) {
        // indy tests will only be executed in indy test suite
        excludes += ['indy', 'Indy']
    } else {
        // tests not passing with indy : investigation required!
        excludes += ['Log4j2Test', 'ASTTransformationCustomizerTest']
    }

    return { f ->
        excludes.any { f.file =~ it }
    }
}

// some tests require Jars, but those are not allowed in the source directory
// by the Apache policy, so we need to build them and add them to the test
// resources classpath

ext.extModuleFixtureDir = file("$projectDir/src/test-fixtures/extmodule")
ext.extModuleOutputDir = file("$buildDir/testFixtures/extmodule")
ext.extModuleRepoDir = file("$extModuleOutputDir/repo")

task compileTestExtensionModule(type: JavaCompile) {
    classpath = files(jar)
    source fileTree("$extModuleFixtureDir/src/main/java")
    destinationDir = file("$extModuleOutputDir/classes")
    sourceCompatibility = 1.7
    targetCompatibility = 1.7
}

task testExtensionModuleJar(type: Jar) {
    description = 'Builds a sample extension module used in tests'
    dependsOn compileTestExtensionModule
    baseName = 'module-test'
    version = '1.4'
    from { compileTestExtensionModule.destinationDir }
    from files("$extModuleFixtureDir/src/main/resources")
    // emulate Maven repo format for output
    destinationDir = file("$extModuleRepoDir/jars/module-test/module-test/${version}")
}

tasks.withType(Test) {
    dependsOn(testExtensionModuleJar)
    classpath += files(extModuleRepoDir)
}