All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.gradle.internal.testing

import org.gradle.api.internal.tasks.testing.TestExecuter
import org.gradle.api.internal.tasks.testing.TestExecutionSpec
import org.gradle.api.internal.tasks.testing.TestResultProcessor
import org.gradle.internal.operations.BuildOperationExecutor
import org.gradle.process.ExecResult
import org.gradle.process.ProcessForkOptions
import org.gradle.process.internal.ExecHandle
import org.gradle.process.internal.ExecHandleFactory
import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.OutputStream

open class TCServiceMessagesTestExecutionSpec(
    val forkOptions: ProcessForkOptions,
    val args: List,
    val checkExitCode: Boolean,
    val clientSettings: TCServiceMessagesClientSettings,
    val dryRunArgs: List? = null,
) : TestExecutionSpec {
    internal open fun createClient(
        testResultProcessor: TestResultProcessor,
        log: Logger,
        testReporter: MppTestReportHelper,
    ): TCServiceMessagesClient =
        TCServiceMessagesClient(testResultProcessor, clientSettings, log, testReporter)

    internal open fun wrapExecute(body: () -> Unit) = body()
    internal open fun showSuppressedOutput() = Unit
}

private val log = LoggerFactory.getLogger("org.jetbrains.kotlin.gradle.tasks.testing")

class TCServiceMessagesTestExecutor(
    val execHandleFactory: ExecHandleFactory,
    val buildOperationExecutor: BuildOperationExecutor,
    val runListeners: MutableList,
    val ignoreTcsmOverflow: Boolean,
    val ignoreRunFailures: Boolean,
    val testReporter: MppTestReportHelper,
) : TestExecuter {
    private lateinit var execHandle: ExecHandle
    var outputReaderThread: Thread? = null
    var shouldStop = false

    override fun execute(spec: TCServiceMessagesTestExecutionSpec, testResultProcessor: TestResultProcessor) {
        spec.wrapExecute {
            val rootOperation = buildOperationExecutor.currentOperation.parentId!!

            val client = spec.createClient(testResultProcessor, log, testReporter)

            if (spec.dryRunArgs != null) {
                val exec = execHandleFactory.newExec()
                spec.forkOptions.copyTo(exec)
                exec.args = spec.dryRunArgs
                // We do not need output by dry run of tests
                exec.standardOutput = object : OutputStream() {
                    override fun write(b: Int) {
                        // do nothing
                    }
                }
                exec.errorOutput = object : OutputStream() {
                    override fun write(b: Int) {
                        // do nothing
                    }
                }
                execHandle = exec.build()

                execHandle.start()
                val result: ExecResult = execHandle.waitForFinish()
                if (result.exitValue != 0) {
                    error(client.testFailedMessage(execHandle, result.exitValue))
                }
            }

            try {
                val exec = execHandleFactory.newExec()
                spec.forkOptions.copyTo(exec)
                exec.args = spec.args
                exec.standardOutput = TCServiceMessageOutputStreamHandler(
                    client,
                    { spec.showSuppressedOutput() },
                    log,
                    ignoreTcsmOverflow
                )
                exec.errorOutput = TCServiceMessageOutputStreamHandler(
                    client,
                    { spec.showSuppressedOutput() },
                    log,
                    ignoreTcsmOverflow
                )
                execHandle = exec.build()

                lateinit var result: ExecResult
                client.root(rootOperation) {
                    execHandle.start()
                    result = execHandle.waitForFinish()
                }

                if (spec.checkExitCode && result.exitValue != 0) {
                    error(client.testFailedMessage(execHandle, result.exitValue))
                }
            } catch (e: Throwable) {
                spec.showSuppressedOutput()

                val wrappedError = client.ensureNodesClosed(null, e, false) ?: if (e is Error) e else Error(e)

                runListeners.forEach {
                    it.runningFailure(wrappedError)
                }

                if (ignoreRunFailures) {
                    log.error(wrappedError.message)
                } else {
                    throw e
                }
            }
        }
    }

    override fun stopNow() {
        shouldStop = true
        if (::execHandle.isInitialized) {
            execHandle.abort()
        }
        outputReaderThread?.join()
    }

    companion object {
        const val TC_PROJECT_PROPERTY = "teamcity"
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy