You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by ew...@apache.org on 2019/02/15 18:50:25 UTC
[kafka] branch trunk updated: MINOR: Save failed test output to
build output directory
This is an automated email from the ASF dual-hosted git repository.
ewencp pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new ed30712 MINOR: Save failed test output to build output directory
ed30712 is described below
commit ed3071231aee1ba8a5c2c496112dd6034f9bf942
Author: Ewen Cheslack-Postava <me...@ewencp.org>
AuthorDate: Fri Feb 15 10:50:08 2019 -0800
MINOR: Save failed test output to build output directory
Author: Ewen Cheslack-Postava <me...@ewencp.org>
Reviewers: Colin Patrick McCabe <co...@cmccabe.xyz>
Closes #6234 from ewencp/test-logs
---
build.gradle | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
diff --git a/build.gradle b/build.gradle
index 420edf7..ff316c8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -15,6 +15,8 @@
import org.ajoberstar.grgit.Grgit
+import java.nio.charset.StandardCharsets
+
buildscript {
repositories {
mavenCentral()
@@ -139,6 +141,7 @@ if (file('.git').exists()) {
}
}
+
subprojects {
apply plugin: 'java'
// apply the eclipse plugin only to subprojects that hold code. 'connect' is just a folder.
@@ -204,6 +207,65 @@ subprojects {
def testLoggingEvents = ["passed", "skipped", "failed"]
def testShowStandardStreams = false
def testExceptionFormat = 'full'
+ // Gradle built-in logging only supports sending test output to stdout, which generates a lot
+ // of noise, especially for passing tests. We really only want output for failed tests. This
+ // hooks into the output and logs it (so we don't have to buffer it all in memory) and only
+ // saves the output for failing tests. Directory and filenames are such that you can, e.g.,
+ // create a Jenkins rule to collect failed test output.
+ def logTestStdout = {
+ def testId = { TestDescriptor descriptor ->
+ "${descriptor.className}.${descriptor.name}".toString()
+ }
+
+ def logFiles = new HashMap<String, File>()
+ def logStreams = new HashMap<String, FileOutputStream>()
+ beforeTest { TestDescriptor td ->
+ def tid = testId(td)
+ def logFile = new File(
+ "${projectDir}/build/reports/testOutput/${tid}.test.stdout")
+ logFile.parentFile.mkdirs()
+ logFiles.put(tid, logFile)
+ logStreams.put(tid, new FileOutputStream(logFile))
+ }
+ onOutput { TestDescriptor td, TestOutputEvent toe ->
+ def tid = testId(td)
+ // Some output can happen outside the context of a specific test (e.g. at the class level)
+ // and beforeTest/afterTest seems to not be invoked for these cases (and similarly, there's
+ // a TestDescriptor hierarchy that includes the thread executing the test, Gradle tasks,
+ // etc). We see some of these in practice and it seems like something buggy in the Gradle
+ // test runner since we see it *before* any tests and it is frequently not related to any
+ // code in the test (best guess is that it is tail output from last test). We won't have
+ // an output file for these, so simply ignore them. If they become critical for debugging,
+ // they can be seen with showStandardStreams.
+ if (td.name == td.className) {
+ return
+ }
+ try {
+ logStreams.get(tid).write(toe.message.getBytes(StandardCharsets.UTF_8))
+ } catch (Exception e) {
+ println "ERROR: Failed to write output for test ${tid}"
+ e.printStackTrace()
+ }
+ }
+ afterTest { TestDescriptor td, TestResult tr ->
+ def tid = testId(td)
+ try {
+ logStreams.get(tid).close()
+ if (tr.resultType != TestResult.ResultType.FAILURE) {
+ logFiles.get(tid).delete()
+ } else {
+ def file = logFiles.get(tid)
+ println "${tid} failed, log available in ${file}"
+ }
+ } catch (Exception e) {
+ println "ERROR: Failed to close stdout file for ${tid}"
+ e.printStackTrace()
+ } finally {
+ logFiles.remove(tid)
+ logStreams.remove(tid)
+ }
+ }
+ }
test {
maxParallelForks = userMaxForks ?: Runtime.runtime.availableProcessors()
@@ -216,7 +278,7 @@ subprojects {
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
}
-
+ logTestStdout.rehydrate(delegate, owner, this)()
}
task integrationTest(type: Test, dependsOn: compileJava) {
@@ -230,6 +292,7 @@ subprojects {
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
}
+ logTestStdout.rehydrate(delegate, owner, this)()
useJUnit {
includeCategories 'org.apache.kafka.test.IntegrationTest'
@@ -248,6 +311,7 @@ subprojects {
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
}
+ logTestStdout.rehydrate(delegate, owner, this)()
if (it.project.name != 'generator') {
useJUnit {