Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix crash on parse some control chars
  • Loading branch information
adamfilipow92 committed May 7, 2020
1 parent 3fa5b8b commit b36c3b5
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 14 deletions.
2 changes: 2 additions & 0 deletions test_runner/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ dependencies {
implementation(Libs.SYSTEM_RULES)
testImplementation(Libs.TRUTH)
testImplementation(Libs.MOCKK)

implementation(Libs.COMMON_TEXT)
}

// Fix Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.hash.Hashing.crc32c()Lcom/google/common/hash/HashFunction;
Expand Down
4 changes: 4 additions & 0 deletions test_runner/buildSrc/src/main/kotlin/Deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ object Versions {

// https://github.com/mockk/mockk
const val MOCKK = "1.9.3"

const val COMMON_TEXT = "1.7"
}

object Libs {
Expand Down Expand Up @@ -123,4 +125,6 @@ object Libs {
const val TRUTH = "com.google.truth:truth:${Versions.TRUTH}"
const val MOCKK = "io.mockk:mockk:${Versions.MOCKK}"
//endregion

const val COMMON_TEXT = "org.apache.commons:commons-text:${Versions.COMMON_TEXT}"
}
28 changes: 17 additions & 11 deletions test_runner/src/main/kotlin/ftl/reports/xml/JUnitXml.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,52 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
import ftl.reports.xml.model.JUnitTestResult
import ftl.reports.xml.model.JUnitTestSuite
import ftl.reports.xml.preprocesor.fixHtmlCodes
import java.io.File
import java.nio.file.Files
import java.nio.file.Path

private val xmlModule = JacksonXmlModule().apply { setDefaultUseWrapper(false) }

private val xmlMapper = XmlMapper(xmlModule)
.registerModules(KotlinModule())
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)

internal val xmlPrettyWriter = xmlMapper.writerWithDefaultPrettyPrinter()

private fun xmlText(path: Path): String {
if (!path.toFile().exists()) throw RuntimeException("$path doesn't exist!")
return String(Files.readAllBytes(path))
}

fun JUnitTestResult?.xmlToString(): String {
if (this == null) return ""
val prefix = "<?xml version='1.0' encoding='UTF-8' ?>\n"
return prefix + xmlPrettyWriter.writeValueAsString(this)
}

fun parseOneSuiteXml(path: Path): JUnitTestResult {
return parseOneSuiteXml(path.toFile())
return parseOneSuiteXml(xmlText(path))
}

fun parseOneSuiteXml(file: File): JUnitTestResult {
if (!file.exists()) throw RuntimeException("$file doesn't exist!")
return JUnitTestResult(mutableListOf(xmlMapper.readValue(file, JUnitTestSuite::class.java)))
fun parseOneSuiteXml(path: File): JUnitTestResult {
return parseOneSuiteXml(xmlText(path.toPath()))
}

fun parseOneSuiteXml(data: String): JUnitTestResult {
return JUnitTestResult(mutableListOf(xmlMapper.readValue(data, JUnitTestSuite::class.java)))
return JUnitTestResult(mutableListOf(xmlMapper.readValue(fixHtmlCodes(data), JUnitTestSuite::class.java)))
}

// --

fun parseAllSuitesXml(path: Path): JUnitTestResult {
return parseAllSuitesXml(path.toFile())
return parseAllSuitesXml(xmlText(path))
}

fun parseAllSuitesXml(file: File): JUnitTestResult {
if (!file.exists()) throw RuntimeException("$file doesn't exist!")
return xmlMapper.readValue(file, JUnitTestResult::class.java)
fun parseAllSuitesXml(path: File): JUnitTestResult {
return parseAllSuitesXml(path.toPath())
}

fun parseAllSuitesXml(data: String): JUnitTestResult {
return xmlMapper.readValue(data, JUnitTestResult::class.java)
}
return xmlMapper.readValue(fixHtmlCodes(data), JUnitTestResult::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ftl.reports.xml.preprocesor

import org.apache.commons.text.StringEscapeUtils

fun fixHtmlCodes(data: String): String {
val isoHtmlCodesToReplace = listOf(0x00..0x1F).union(listOf(0x7F..0x9F)).flatten()
.map { StringEscapeUtils.escapeXml11(it.toChar().toString()) }.filter { it.startsWith("&#") }

var fixedStr = data
for (isoControlCode in isoHtmlCodesToReplace) {
fixedStr = fixedStr.replace(isoControlCode, "")
}
return fixedStr
}
43 changes: 40 additions & 3 deletions test_runner/src/test/kotlin/ftl/reports/xml/JUnitXmlTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ftl.test.util.TestHelper.normalizeLineEnding
import java.nio.file.Paths
import org.junit.Test


class JUnitXmlTest {

companion object {
Expand Down Expand Up @@ -73,7 +74,8 @@ junit.framework.Assert.fail(Assert.java:50)</failure>

@Test
fun `merge ios`() {
val merged = parseAllSuitesXml(iosPassXml).merge(parseAllSuitesXml(iosFailXml)).xmlToString().normalizeLineEnding()
val merged =
parseAllSuitesXml(iosPassXml).merge(parseAllSuitesXml(iosFailXml)).xmlToString().normalizeLineEnding()
val expected = """
<?xml version='1.0' encoding='UTF-8' ?>
<testsuites>
Expand All @@ -94,7 +96,8 @@ junit.framework.Assert.fail(Assert.java:50)</failure>

@Test
fun `Merge iOS large time`() {
val merged = parseAllSuitesXml(iosLargeNum).merge(parseAllSuitesXml(iosLargeNum)).xmlToString().normalizeLineEnding()
val merged =
parseAllSuitesXml(iosLargeNum).merge(parseAllSuitesXml(iosLargeNum)).xmlToString().normalizeLineEnding()

val expected = """
<?xml version='1.0' encoding='UTF-8' ?>
Expand Down Expand Up @@ -423,7 +426,8 @@ junit.framework.Assert.fail(Assert.java:50)</failure>
// * c() failed in newRun and passed in oldRun. timing info copied over from oldRun
// * d() was skipped in newRun and successful in oldRun. d() is excluded from the merged result

val merged = parseAllSuitesXml(newRun).mergeTestTimes(parseAllSuitesXml(oldRun)).xmlToString().normalizeLineEnding()
val merged =
parseAllSuitesXml(newRun).mergeTestTimes(parseAllSuitesXml(oldRun)).xmlToString().normalizeLineEnding()
val expected = """
<?xml version='1.0' encoding='UTF-8' ?>
<testsuites>
Expand All @@ -437,4 +441,37 @@ junit.framework.Assert.fail(Assert.java:50)</failure>
""".trimIndent()
assertThat(merged).isEqualTo(expected)
}


@Test
fun `parse ftl quirks`() {
val crashingAllSuitesMessage = """
<?xml version='1.0' encoding='UTF-8' ?>
<testsuites>
<testsuite name="EarlGreyExampleSwiftTests" tests="3" failures="0" errors="0" skipped="0" time="10.0" hostname="localhost">
<testcase name="a()" classname="a" time="1.0">
<failure> java.net.ConnectException: Failed to connect to ... at &#8;&#8;&#8;(Coroutine boundary.&#8;(&#8;)</failure>
</testcase>
<testcase name="b()" classname="b" time="2.0"/>
<testcase name="c()" classname="c" time="7.0"/>
</testsuite>
</testsuites>
""".trimIndent()
val crashingOneSuiteMessage = """
<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="EarlGreyExampleSwiftTests" tests="3" failures="0" errors="0" skipped="0" time="10.0" hostname="localhost">
<testcase name="a()" classname="a" time="1.0">
<failure> java.net.ConnectException: Failed to connect to ... at &#8;&#8;&#8;(Coroutine boundary.&#8;(&#8;)</failure>
</testcase>
<testcase name="b()" classname="b" time="2.0"/>
<testcase name="c()" classname="c" time="7.0"/>
</testsuite>
""".trimIndent()

parseAllSuitesXml(crashingAllSuitesMessage)
parseOneSuiteXml(crashingOneSuiteMessage)

}

}

0 comments on commit b36c3b5

Please sign in to comment.