/*
 * Adds an 'integTest' source set, which contains the integration tests for the project.
 */
apply plugin: 'java'
rootProject.apply plugin: IntegTestPlugin

configurations {
    integTestCompile {
        extendsFrom testCompile
    }
    integTestRuntime {
        extendsFrom integTestCompile, testRuntime
    }
}

dependencies {
    integTestCompile project(":internalIntegTesting")
}

sourceSets {
    integTest {
        compileClasspath = sourceSets.main.output + sourceSets.test.output + configurations.integTestCompile
        runtimeClasspath = output + compileClasspath + configurations.integTestRuntime
    }
}

plugins.withType(org.gradle.plugins.ide.idea.IdeaPlugin) { // lazy as plugin not applied yet
    idea {
        module {
            testSourceDirs += sourceSets.integTest.groovy.srcDirs
            testSourceDirs += sourceSets.integTest.resources.srcDirs
            scopes.TEST.plus.add(configurations.integTestCompile)
            scopes.TEST.plus.add(configurations.integTestRuntime)
        }
    }
}

plugins.withType(org.gradle.plugins.ide.eclipse.EclipsePlugin) { // lazy as plugin not applied yet
    eclipse {
        classpath {
            plusConfigurations.add(configurations.integTestCompile)
            plusConfigurations.add(configurations.integTestRuntime)
        }
    }
}

integTestTasks = tasks.withType(Test).matching { it.name.toLowerCase().endsWith('integtest') }

integTestTasks.all {
    dependsOn ':intTestImage', project(":docs").tasks.matching { it.name == "samples" } // lazy as doc not eval'd yet
    testClassesDir = sourceSets.integTest.output.classesDir
    classpath = sourceSets.integTest.runtimeClasspath
    testSrcDirs = []
    jvmArgs '-XX:+HeapDumpOnOutOfMemoryError'
    maxParallelForks = guessMaxForks()

    testResultsDir = file("${project.testResultsDir}/$name")

    systemProperties['org.gradle.integtest.versions'] = 'all'

    doFirst {
        testReportDir = file("${project.reportsDir}/$name")
        systemProperties['integTest.gradleHomeDir'] = integTestImageDir.absolutePath
        systemProperties['integTest.gradleUserHomeDir'] = integTestUserDir.absolutePath
        systemProperties['integTest.samplesdir'] = project(":docs").samplesDir.absolutePath
        // TODO - remove this once wharf is behaving itself
        delete fileTree(dir: "$integTestUserDir/worker-1/caches/artifacts-2/", include: "**/*.kryo")
        if (isDevBuild()) {
            systemProperties['org.gradle.integtest.versions'] = 'latest'
        }
    }
}

['embedded', 'forking', 'daemon', 'embeddedDaemon'].each {
    def mode = it
    def taskName = "${it}IntegTest"
    tasks.addRule(taskName) { name ->
        if (name != taskName) { return }
        tasks.add(taskName, Test).configure {
            systemProperties['org.gradle.integtest.executer'] = mode
        }
    }
}

daemonIntegTest {
    doLast {
        if (project.hasProperty("waitForDaemonsToDieMillis")) {
            println "Property 'waitForDaemonsToDieMillis' passed so I'm waiting $project.waitForDaemonsToDieMillis millis so that deamons can die with honor..."
            Thread.sleep(Integer.parseInt(project.waitForDaemonsToDieMillis));
        }
    }
}

task integTest(type: Test) {
    doFirst {
        systemProperties['org.gradle.integtest.executer'] = integTestMode
    }
}

tasks.findByName("check")?.dependsOn(integTest)

class IntegTestPlugin implements Plugin<Project> {
    public void apply(Project project) {
        project.convention.plugins.integTest = new IntegTestConvention(project)
    }
}

class IntegTestConvention {
    private final Project project
    final List integTests = []

    IntegTestConvention(Project project) {
        this.project = project
    }

    String getIntegTestMode() {
        if (!project.tasks.findByName('ciBuild') || !project.gradle.taskGraph.populated) {
            return null
        }
        if (project.isCIBuild()) {
            return 'forking'
        }
        return 'embedded'
    }

    File getIntegTestUserDir() {
        return project.file('intTestHomeDir')
    }

    File getIntegTestImageDir() {
        if (!project.tasks.findByName('intTestImage')) {
            return null
        }
        return project.intTestImage.destinationDir
    }
}
