commit 2284014bba3b548f4ecbdcb4f0a5561cb922421a equwal <truex@equwal.com> 2026-09-22 14:05:13 -0700 Test the panel with the text of five languages The overlay shows the lines of a subtitle file and cuts a word out of a line. Both steps are sensitive to the script. Only English and Japanese had a test, so a defect in another language was not found by a test. Add a property test that writes and reads a subtitle file with lines of English, Portuguese, Spanish, Russian and Japanese. The line must come back byte for byte: the accents, the inverted marks, the guillemets and the ideographic space. Add cases to the word cutter test on the device for Portuguese, Spanish and Russian. A word with an accent, and a word after an inverted mark or a guillemet, must be one word.
.../kotlin/space/subread/overlay/OverlayTest.kt | 15 ++++++++++++ .../kotlin/space/subread/overlay/core/CoreTest.kt | 27 ++++++++++++++++++++++ 2 files changed, 42 insertions(+)
diff --git a/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt b/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt index d62659d..27bfb31 100644 --- a/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt +++ b/app/src/androidTest/kotlin/space/subread/overlay/OverlayTest.kt @@ -36,6 +36,21 @@ class WordsTest { assertNull(word("", 0)) } + @Test + fun aWordWithAccentsOrInvertedMarks() { + val pt = "— Não me parece bonito — disse ela, à porta." + assertEquals("Não", word(pt, pt.indexOf("Não"))) + assertEquals("à", word(pt, pt.indexOf("à"))) + assertNull("a dash", word(pt, 0)) + val es = "¿Qué es esto? ¡Ñandú, señor!" + assertEquals("Qué", word(es, es.indexOf("Qué"))) + assertEquals("Ñandú", word(es, es.indexOf("Ñandú"))) + assertNull("the inverted mark", word(es, 0)) + val ru = "«Ёлка, — сказал он, — и её огни»." + assertEquals("Ёлка", word(ru, ru.indexOf("Ёлка"))) + assertEquals("её", word(ru, ru.indexOf("её"))) + } + @Test fun aWordOfJapaneseThatHasNoSpaces() { val text = "女のいない男たちは、東京で暮らしている。" diff --git a/core/src/test/kotlin/space/subread/overlay/core/CoreTest.kt b/core/src/test/kotlin/space/subread/overlay/core/CoreTest.kt index ef1d200..09611eb 100644 --- a/core/src/test/kotlin/space/subread/overlay/core/CoreTest.kt +++ b/core/src/test/kotlin/space/subread/overlay/core/CoreTest.kt @@ -2,11 +2,13 @@ package space.subread.overlay.core import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean +import io.kotest.property.arbitrary.element import io.kotest.property.arbitrary.float import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.stringPattern import io.kotest.property.checkAll import kotlinx.coroutines.runBlocking @@ -44,6 +46,31 @@ class SrtTest { } } + /** Lines of the languages the overlay is checked against, with the marks their books use. */ + private val lines = Arb.element( + "It was a dark night; the rain fell.", // en + "— Não me parece bonito — disse ela, à porta.", // pt + "¿Qué es esto? ¡Ñandú, señor Quijote!", // es + "«Ёлка, — сказал он, — и её огни».", // ru + "吾輩は猫である。名前はまだ無い。", // ja + "「女のいない男たち」 東京で暮らしている", // ja, ideographic space and brackets + ) + + private val multilingualCues = Arb.list(Arb.pair(Arb.int(1..20_000).map { it.toLong() }, lines), 1..30).map { list -> + var at = 0L + list.map { (gap, text) -> + at += gap + Cue(at, at + 1 + gap, text) + } + } + + @Test + fun aLineOfAnyScriptIsReadBackUnchanged(): Unit = runBlocking { + checkAll(multilingualCues) { list -> + assertEquals(list, Srt.parse(write(list))) + } + } + @Test fun noTextMakesTheReaderFail(): Unit = runBlocking { checkAll(Arb.stringPattern("[0-9a-z:>,\\- \n]{0,200}")) { junk -> Srt.parse(junk) }