[Native][tests] Extract GTest report verification logic
This commit is contained in:
+9
-41
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.konan.blackboxtest.support.runner
|
|||||||
|
|
||||||
import com.intellij.openapi.util.text.StringUtilRt.convertLineSeparators
|
import com.intellij.openapi.util.text.StringUtilRt.convertLineSeparators
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.parseGTestReport
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
@@ -55,46 +56,22 @@ internal class LocalTestRunner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyTestWithGTestRunner() {
|
private fun verifyTestWithGTestRunner() {
|
||||||
val testStatuses = hashMapOf<TestStatus, MutableSet<TestName>>()
|
val testReport = parseGTestReport(runResult.output.stdOut)
|
||||||
val cleanStdOut = StringBuilder()
|
|
||||||
|
|
||||||
var expectStatusLine = false
|
verifyExpectation(!testReport.isEmpty()) { "No tests have been executed." }
|
||||||
runResult.output.stdOut.lines().forEach { line ->
|
|
||||||
when {
|
|
||||||
expectStatusLine -> {
|
|
||||||
val matcher = GTEST_STATUS_LINE_REGEX.matchEntire(line)
|
|
||||||
if (matcher != null) {
|
|
||||||
// Read the line with test status.
|
|
||||||
val testStatus = matcher.groupValues[1]
|
|
||||||
val testName = matcher.groupValues[2]
|
|
||||||
testStatuses.getOrPut(testStatus) { hashSetOf() } += testName
|
|
||||||
expectStatusLine = false
|
|
||||||
} else {
|
|
||||||
// If current line is not a status line then it could be only the line with the process' output.
|
|
||||||
cleanStdOut.appendLine(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line.startsWith(GTEST_RUN_LINE_PREFIX) -> {
|
|
||||||
expectStatusLine = true // Next line contains either test status.
|
|
||||||
}
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyExpectation(testStatuses.isNotEmpty()) { "No tests have been executed." }
|
val passedTests = testReport.getPassedTests()
|
||||||
|
verifyExpectation(passedTests.isNotEmpty()) { "No passed tests." }
|
||||||
val passedTests = testStatuses[GTEST_STATUS_OK]?.size ?: 0
|
|
||||||
verifyExpectation(passedTests > 0) { "No passed tests." }
|
|
||||||
|
|
||||||
testRun.runParameters.get<TestRunParameter.WithFilter> {
|
testRun.runParameters.get<TestRunParameter.WithFilter> {
|
||||||
val excessiveTests = testStatuses.getValue(GTEST_STATUS_OK).filter { testName -> !testMatches(testName) }
|
val excessiveTests = passedTests.filter { testName -> !testMatches(testName) }
|
||||||
verifyExpectation(excessiveTests.isEmpty()) { "Excessive tests have been executed: $excessiveTests." }
|
verifyExpectation(excessiveTests.isEmpty()) { "Excessive tests have been executed: $excessiveTests." }
|
||||||
}
|
}
|
||||||
|
|
||||||
val failedTests = (testStatuses - GTEST_STATUS_OK).values.sumOf { it.size }
|
val failedTests = testReport.getFailedTests().size
|
||||||
verifyExpectation(0, failedTests) { "There are failed tests." }
|
verifyExpectation(0, failedTests) { "There are $failedTests failed tests." }
|
||||||
|
|
||||||
verifyOutputData(mergedOutput = cleanStdOut.toString() + runResult.output.stdErr)
|
verifyOutputData(mergedOutput = testReport.cleanStdOut + runResult.output.stdErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyPlainTest() = verifyOutputData(mergedOutput = runResult.output.stdOut + runResult.output.stdErr)
|
private fun verifyPlainTest() = verifyOutputData(mergedOutput = runResult.output.stdOut + runResult.output.stdErr)
|
||||||
@@ -107,13 +84,4 @@ internal class LocalTestRunner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val GTEST_RUN_LINE_PREFIX = "[ RUN ]"
|
|
||||||
private val GTEST_STATUS_LINE_REGEX = Regex("^\\[\\s+([A-Z]+)\\s+]\\s+(\\S+)\\s+.*")
|
|
||||||
private const val GTEST_STATUS_OK = "OK"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private typealias TestStatus = String
|
|
||||||
private typealias TestName = String
|
|
||||||
|
|||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.konan.blackboxtest.support.util
|
||||||
|
|
||||||
|
internal typealias TestName = String
|
||||||
|
internal typealias TestStatus = String
|
||||||
|
|
||||||
|
internal class GTestReport(
|
||||||
|
private val testStatuses: Map<TestStatus, Collection<TestName>>,
|
||||||
|
val cleanStdOut: String
|
||||||
|
) {
|
||||||
|
fun getPassedTests(): Collection<TestName> = testStatuses[STATUS_OK].orEmpty()
|
||||||
|
fun getFailedTests(): Collection<TestName> = (testStatuses - STATUS_OK).flatMap { it.value }
|
||||||
|
|
||||||
|
fun isEmpty(): Boolean = testStatuses.isEmpty()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val STATUS_OK = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses GTest reports like this:
|
||||||
|
*
|
||||||
|
* [==========] Running 2 tests from 1 test cases.
|
||||||
|
* [----------] Global test environment set-up.
|
||||||
|
* [----------] 2 tests from sample.test.SampleTestKt
|
||||||
|
* [ RUN ] sample.test.SampleTestKt.one
|
||||||
|
* [ OK ] sample.test.SampleTestKt.one (0 ms)
|
||||||
|
* [ RUN ] sample.test.SampleTestKt.two
|
||||||
|
* [ OK ] sample.test.SampleTestKt.two (0 ms)
|
||||||
|
* [----------] 2 tests from sample.test.SampleTestKt (0 ms total)
|
||||||
|
*
|
||||||
|
* [----------] Global test environment tear-down
|
||||||
|
* [==========] 2 tests from 1 test cases ran. (0 ms total)
|
||||||
|
* [ PASSED ] 2 tests.
|
||||||
|
*/
|
||||||
|
internal fun parseGTestReport(stdOut: String): GTestReport {
|
||||||
|
val testStatuses = hashMapOf<TestStatus, MutableSet<TestName>>()
|
||||||
|
val cleanStdOut = StringBuilder()
|
||||||
|
|
||||||
|
var expectStatusLine = false
|
||||||
|
stdOut.lineSequence().forEach { line ->
|
||||||
|
when {
|
||||||
|
expectStatusLine -> {
|
||||||
|
val matcher = STATUS_LINE_REGEX.matchEntire(line)
|
||||||
|
if (matcher != null) {
|
||||||
|
// Read the line with test status.
|
||||||
|
val testStatus = matcher.groupValues[1]
|
||||||
|
val testName = matcher.groupValues[2]
|
||||||
|
testStatuses.getOrPut(testStatus) { hashSetOf() } += testName
|
||||||
|
expectStatusLine = false
|
||||||
|
} else {
|
||||||
|
// If current line is not a status line then it could be only the line with the process' output.
|
||||||
|
cleanStdOut.appendLine(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line.matches(RUN_LINE_REGEX) -> {
|
||||||
|
expectStatusLine = true // Next line contains either test status.
|
||||||
|
}
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GTestReport(testStatuses, cleanStdOut.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private val RUN_LINE_REGEX = Regex("""^\[\s+RUN\s+]\s+.*""")
|
||||||
|
private val STATUS_LINE_REGEX = Regex("""^\[\s+([A-Z]+)\s+]\s+(\S+)\s+.*""")
|
||||||
Reference in New Issue
Block a user