Overflowed teamcity messages should failed build

^KT-41133 fixed
This commit is contained in:
Ilya Goncharov
2020-08-19 14:11:18 +03:00
parent e7b12b9bb1
commit 621c87ee84
4 changed files with 46 additions and 6 deletions
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.gradle.internal.testing
import jetbrains.buildServer.messages.serviceMessages.ServiceMessage import jetbrains.buildServer.messages.serviceMessages.ServiceMessage
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageParserCallback import jetbrains.buildServer.messages.serviceMessages.ServiceMessageParserCallback
import jetbrains.buildServer.messages.serviceMessages.TestFailed
import org.gradle.api.GradleException
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.Companion.MESSAGE_LIMIT_BYTES import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.Companion.MESSAGE_LIMIT_BYTES
import org.slf4j.Logger import org.slf4j.Logger
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@@ -24,6 +26,7 @@ internal class TCServiceMessageOutputStreamHandler(
private val client: ServiceMessageParserCallback, private val client: ServiceMessageParserCallback,
private val onException: () -> Unit, private val onException: () -> Unit,
private val logger: Logger, private val logger: Logger,
private val ignoreTcsmOverflow: Boolean = false,
private val messageLimitBytes: Int = MESSAGE_LIMIT_BYTES // for test only private val messageLimitBytes: Int = MESSAGE_LIMIT_BYTES // for test only
) : OutputStream() { ) : OutputStream() {
private var closed: Boolean = false private var closed: Boolean = false
@@ -40,7 +43,10 @@ internal class TCServiceMessageOutputStreamHandler(
if (closed) throw IOException("The stream has been closed.") if (closed) throw IOException("The stream has been closed.")
var i = off var i = off
var last = off var last = off
fun bytesToAppend() = i - last
fun bytesToAppend() =
i - last
val end = off + len val end = off + len
fun append(len: Int = bytesToAppend()) { fun append(len: Int = bytesToAppend()) {
@@ -82,8 +88,21 @@ internal class TCServiceMessageOutputStreamHandler(
// support messageLimitBytes inside "##teamcity[...]" (including "##teamcity[]"). // support messageLimitBytes inside "##teamcity[...]" (including "##teamcity[]").
val i = if (overflowInsideMessage) { val i = if (overflowInsideMessage) {
if (!text.endsWith("]")) { if (!ignoreTcsmOverflow && !text.endsWith("]")) {
logger.warn("Cannot process process output: too long teamcity service message (more then 1Mb). Event was lost. See stdout for more details.") logger.warn(text)
overflowInsideMessage = false
buffer.reset()
client.serviceMessage(
TestFailed(
"overflow-message",
GradleException(
"""
Cannot process output: too long teamcity service message (more than ${MESSAGE_LIMIT_BYTES / 1024 / 1024}Mb). Event was lost.
Build failed to prevent inconsistent behaviour. To ignore it use Gradle property '$IGNORE_TCSM_OVERFLOW=true'
""".trimIndent()
)
)
)
} }
-1 -1
} else text.indexOf("##teamcity[") } else text.indexOf("##teamcity[")
@@ -110,6 +129,7 @@ internal class TCServiceMessageOutputStreamHandler(
} }
companion object { companion object {
private const val MESSAGE_LIMIT_BYTES = 0x100000 // 1Mb private const val MESSAGE_LIMIT_BYTES = 1024 * 1024 // 1Mb
const val IGNORE_TCSM_OVERFLOW = "kotlin.ignore.tcsm.overflow"
} }
} }
@@ -35,6 +35,7 @@ class TCServiceMessagesTestExecutor(
val execHandleFactory: ExecHandleFactory, val execHandleFactory: ExecHandleFactory,
val buildOperationExecutor: BuildOperationExecutor, val buildOperationExecutor: BuildOperationExecutor,
val runListeners: MutableList<KotlinTestRunnerListener>, val runListeners: MutableList<KotlinTestRunnerListener>,
val ignoreTcsmOverflow: Boolean,
val ignoreRunFailures: Boolean val ignoreRunFailures: Boolean
) : TestExecuter<TCServiceMessagesTestExecutionSpec> { ) : TestExecuter<TCServiceMessagesTestExecutionSpec> {
private lateinit var execHandle: ExecHandle private lateinit var execHandle: ExecHandle
@@ -51,8 +52,18 @@ class TCServiceMessagesTestExecutor(
val exec = execHandleFactory.newExec() val exec = execHandleFactory.newExec()
spec.forkOptions.copyTo(exec) spec.forkOptions.copyTo(exec)
exec.args = spec.args exec.args = spec.args
exec.standardOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) exec.standardOutput = TCServiceMessageOutputStreamHandler(
exec.errorOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) client,
{ spec.showSuppressedOutput() },
log,
ignoreTcsmOverflow
)
exec.errorOutput = TCServiceMessageOutputStreamHandler(
client,
{ spec.showSuppressedOutput() },
log,
ignoreTcsmOverflow
)
execHandle = exec.build() execHandle = exec.build()
lateinit var result: ExecResult lateinit var result: ExecResult
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.Coroutines import org.jetbrains.kotlin.gradle.dsl.Coroutines
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.Companion.IGNORE_TCSM_OVERFLOW
import org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPlugin.Companion.NOWARN_2JS_FLAG import org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPlugin.Companion.NOWARN_2JS_FLAG
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
@@ -189,6 +190,12 @@ internal class PropertiesProvider private constructor(private val project: Proje
val nativeCacheKind: NativeCacheKind val nativeCacheKind: NativeCacheKind
get() = property("kotlin.native.cacheKind")?.let { NativeCacheKind.byCompilerArgument(it) } ?: CacheBuilder.DEFAULT_CACHE_KIND get() = property("kotlin.native.cacheKind")?.let { NativeCacheKind.byCompilerArgument(it) } ?: CacheBuilder.DEFAULT_CACHE_KIND
/**
* Ignore overflow in [org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler]
*/
val ignoreTcsmOverflow: Boolean
get() = booleanProperty(IGNORE_TCSM_OVERFLOW) ?: false
/** /**
* Generate kotlin/js external declarations from all .d.ts files found in npm modules * Generate kotlin/js external declarations from all .d.ts files found in npm modules
*/ */
@@ -14,6 +14,7 @@ import org.gradle.api.tasks.testing.AbstractTestTask
import org.gradle.process.internal.ExecHandleFactory import org.gradle.process.internal.ExecHandleFactory
import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.utils.injected import org.jetbrains.kotlin.gradle.utils.injected
import javax.inject.Inject import javax.inject.Inject
@@ -61,6 +62,7 @@ abstract class KotlinTest : AbstractTestTask() {
execHandleFactory, execHandleFactory,
buildOperationExecutor, buildOperationExecutor,
runListeners, runListeners,
PropertiesProvider(project).ignoreTcsmOverflow,
ignoreRunFailures ignoreRunFailures
) )
} }