From 621c87ee84ba063a34a7eac9e813064cf35c4eae Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 19 Aug 2020 14:11:18 +0300 Subject: [PATCH] Overflowed teamcity messages should failed build ^KT-41133 fixed --- .../TCServiceMessageOutputStreamHandler.kt | 28 ++++++++++++++++--- .../testing/TCServiceMessagesTestExecutor.kt | 15 ++++++++-- .../kotlin/gradle/plugin/KotlinProperties.kt | 7 +++++ .../kotlin/gradle/tasks/KotlinTest.kt | 2 ++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessageOutputStreamHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessageOutputStreamHandler.kt index 0684732ba8f..ddb54d49d19 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessageOutputStreamHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessageOutputStreamHandler.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.gradle.internal.testing import jetbrains.buildServer.messages.serviceMessages.ServiceMessage 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.slf4j.Logger import java.io.ByteArrayOutputStream @@ -24,6 +26,7 @@ internal class TCServiceMessageOutputStreamHandler( private val client: ServiceMessageParserCallback, private val onException: () -> Unit, private val logger: Logger, + private val ignoreTcsmOverflow: Boolean = false, private val messageLimitBytes: Int = MESSAGE_LIMIT_BYTES // for test only ) : OutputStream() { private var closed: Boolean = false @@ -40,7 +43,10 @@ internal class TCServiceMessageOutputStreamHandler( if (closed) throw IOException("The stream has been closed.") var i = off var last = off - fun bytesToAppend() = i - last + + fun bytesToAppend() = + i - last + val end = off + len fun append(len: Int = bytesToAppend()) { @@ -82,8 +88,21 @@ internal class TCServiceMessageOutputStreamHandler( // support messageLimitBytes inside "##teamcity[...]" (including "##teamcity[]"). val i = if (overflowInsideMessage) { - if (!text.endsWith("]")) { - logger.warn("Cannot process process output: too long teamcity service message (more then 1Mb). Event was lost. See stdout for more details.") + if (!ignoreTcsmOverflow && !text.endsWith("]")) { + 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 } else text.indexOf("##teamcity[") @@ -110,6 +129,7 @@ internal class TCServiceMessageOutputStreamHandler( } 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" } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt index 1da2b8944ce..fb005a80e4c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt @@ -35,6 +35,7 @@ class TCServiceMessagesTestExecutor( val execHandleFactory: ExecHandleFactory, val buildOperationExecutor: BuildOperationExecutor, val runListeners: MutableList, + val ignoreTcsmOverflow: Boolean, val ignoreRunFailures: Boolean ) : TestExecuter { private lateinit var execHandle: ExecHandle @@ -51,8 +52,18 @@ class TCServiceMessagesTestExecutor( val exec = execHandleFactory.newExec() spec.forkOptions.copyTo(exec) exec.args = spec.args - exec.standardOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) - exec.errorOutput = TCServiceMessageOutputStreamHandler(client, { spec.showSuppressedOutput() }, log) + exec.standardOutput = TCServiceMessageOutputStreamHandler( + client, + { spec.showSuppressedOutput() }, + log, + ignoreTcsmOverflow + ) + exec.errorOutput = TCServiceMessageOutputStreamHandler( + client, + { spec.showSuppressedOutput() }, + log, + ignoreTcsmOverflow + ) execHandle = exec.build() lateinit var result: ExecResult diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt index c412a651f74..506d6b651c5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.Project import org.jetbrains.kotlin.gradle.dsl.Coroutines 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.KotlinJsCompilerType.Companion.jsCompilerProperty import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin @@ -189,6 +190,12 @@ internal class PropertiesProvider private constructor(private val project: Proje val nativeCacheKind: NativeCacheKind 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 */ diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt index 63b19024656..6c11c5f9aaa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt @@ -14,6 +14,7 @@ import org.gradle.api.tasks.testing.AbstractTestTask import org.gradle.process.internal.ExecHandleFactory import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.utils.injected import javax.inject.Inject @@ -61,6 +62,7 @@ abstract class KotlinTest : AbstractTestTask() { execHandleFactory, buildOperationExecutor, runListeners, + PropertiesProvider(project).ignoreTcsmOverflow, ignoreRunFailures ) }