summaryrefslogtreecommitdiff
path: root/support/arara/source/src/test/kotlin/org
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-03-05 03:00:59 +0000
committerNorbert Preining <norbert@preining.info>2020-03-05 03:00:59 +0000
commit898048513951b471a492afa23e46112d14bcb236 (patch)
tree8596afc705f55d2d07b324a756f7283ac0e2d21b /support/arara/source/src/test/kotlin/org
parent19d25b8009801aa98ea2f46b45c37c257f990491 (diff)
CTAN sync 202003050300
Diffstat (limited to 'support/arara/source/src/test/kotlin/org')
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileHandlingUtilsTest.kt62
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileSearchingUtilsTest.kt58
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageCoverageTest.kt102
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageReport.kt143
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageTest.kt20
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/model/SessionTest.kt76
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/CommonUtilsTest.kt33
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExecutionTest.kt139
-rw-r--r--support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExtensionTest.kt23
9 files changed, 656 insertions, 0 deletions
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileHandlingUtilsTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileHandlingUtilsTest.kt
new file mode 100644
index 0000000000..55b13a8fe5
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileHandlingUtilsTest.kt
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.filehandling
+
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+import java.io.File
+import java.nio.file.Files
+import org.islandoftex.arara.Arara
+import org.islandoftex.arara.configuration.AraraSpec
+import org.islandoftex.arara.model.AraraException
+
+class FileHandlingUtilsTest : ShouldSpec({
+ should("fail generating CRC sums on inexistent files") {
+ shouldThrow<AraraException> {
+ FileHandlingUtils.calculateHash(File("QUACK"))
+ }
+ }
+ should("generate correct CRC sums") {
+ FileHandlingUtils.calculateHash(File("../LICENSE")) shouldBe "2396b4e2"
+ FileHandlingUtils.calculateHash(File("../CODE_OF_CONDUCT.md")) shouldBe "536c426f"
+ }
+
+ should("find correct extension") {
+ FileHandlingUtils.getFileExtension(File("QUACK")) shouldBe ""
+ FileHandlingUtils.getFileExtension(File("a.tex")) shouldBe "tex"
+ FileHandlingUtils.getFileExtension(File(".tex")) shouldBe "tex"
+ }
+ should("find correct basename") {
+ FileHandlingUtils.getBasename(File("QUACK")) shouldBe "QUACK"
+ FileHandlingUtils.getBasename(File("a.tex")) shouldBe "a"
+ FileHandlingUtils.getBasename(File(".tex")) shouldBe ""
+ }
+
+ should("get subdirecotry relationship right") {
+ FileHandlingUtils.isSubDirectory(File("../docs"), File("..")) shouldBe true
+ FileHandlingUtils.isSubDirectory(File(".."), File("../docs")) shouldBe false
+ shouldThrow<AraraException> {
+ FileHandlingUtils.isSubDirectory(File("../LICENSE"), File(".."))
+ }
+ shouldThrow<AraraException> {
+ FileHandlingUtils.isSubDirectory(File(".."), File("../LICENSE"))
+ }
+ }
+
+ should("detect changes on file") {
+ val file = Files.createTempFile(null, null).toFile()
+ val referenceBackup = Arara.config[AraraSpec.Execution.reference]
+ Arara.config[AraraSpec.Execution.reference] = file.parentFile.resolve("reference")
+ FileHandlingUtils.hasChanged(file) shouldBe true
+ FileHandlingUtils.hasChanged(file) shouldBe false
+ file.writeText("QUACK")
+ FileHandlingUtils.hasChanged(file) shouldBe true
+ FileHandlingUtils.hasChanged(file) shouldBe false
+ file.writeText("QUACK2")
+ FileHandlingUtils.hasChanged(file) shouldBe true
+ file.delete()
+ FileHandlingUtils.hasChanged(file) shouldBe true
+ FileHandlingUtils.hasChanged(file) shouldBe false
+ Arara.config[AraraSpec.Execution.reference] = referenceBackup
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileSearchingUtilsTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileSearchingUtilsTest.kt
new file mode 100644
index 0000000000..47f9916c43
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/filehandling/FileSearchingUtilsTest.kt
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.filehandling
+
+import io.kotlintest.shouldBe
+import io.kotlintest.specs.ShouldSpec
+import java.nio.file.Files
+import java.nio.file.Path
+import kotlin.reflect.full.declaredMemberFunctions
+import kotlin.reflect.jvm.isAccessible
+
+class FileSearchingUtilsTest : ShouldSpec({
+ // TODO: test implicit extensions
+
+ fun prepareFileSystem(): Path {
+ val tempDir = Files.createTempDirectory(System.nanoTime().toString())
+ tempDir.resolve("quack/quack").toFile().mkdirs()
+ listOf("quack", "quack/quack", "quack/quack/quack").forEach {
+ tempDir.resolve("$it.tex").toFile().writeText(" ")
+ tempDir.resolve("$it.txt").toFile().writeText(" ")
+ }
+ return tempDir
+ }
+
+ should("fail looking up inexistent file") {
+ val lookupFile = FileSearchingUtils::class.declaredMemberFunctions
+ .first { it.name == "lookupFile" }
+ lookupFile.isAccessible = true
+ lookupFile.call(FileSearchingUtils, "QUACK") shouldBe null
+ }
+
+ should("fail on existing directory") {
+ val lookupFile = FileSearchingUtils::class.declaredMemberFunctions
+ .first { it.name == "lookupFile" }
+ lookupFile.isAccessible = true
+ lookupFile.call(FileSearchingUtils, "../buildSrc") shouldBe null
+ }
+
+ should("find file by extension") {
+ val tempDir = prepareFileSystem()
+ FileSearchingUtils.listFilesByExtensions(tempDir.toFile(),
+ listOf("tex"), false).toSet() shouldBe
+ setOf(tempDir.resolve("quack.tex").toFile())
+ FileSearchingUtils.listFilesByExtensions(tempDir.toFile(),
+ listOf("tex"), true).toSet() shouldBe
+ listOf("quack", "quack/quack", "quack/quack/quack")
+ .map { tempDir.resolve("$it.tex").toFile() }.toSet()
+ }
+ should("find file by pattern") {
+ val tempDir = prepareFileSystem()
+ FileSearchingUtils.listFilesByPatterns(tempDir.toFile(),
+ listOf("*q*.txt"), false).toSet() shouldBe
+ setOf(tempDir.resolve("quack.txt").toFile())
+ FileSearchingUtils.listFilesByPatterns(tempDir.toFile(),
+ listOf("q*.txt"), true).toSet() shouldBe
+ listOf("quack", "quack/quack", "quack/quack/quack")
+ .map { tempDir.resolve("$it.txt").toFile() }.toSet()
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageCoverageTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageCoverageTest.kt
new file mode 100644
index 0000000000..704d3e319d
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageCoverageTest.kt
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.localization
+
+import ch.qos.cal10n.verifier.MessageKeyVerifier
+import io.kotlintest.inspectors.forAll
+import io.kotlintest.matchers.collections.shouldNotBeEmpty
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+import java.io.File
+import java.io.IOException
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.Locale
+import java.util.stream.Collectors
+import org.islandoftex.arara.model.AraraException
+
+class LanguageCoverageTest : ShouldSpec({
+ "locale definitions" {
+ /**
+ * Helper method, checks the provided locale (all keys set?).
+ *
+ * @param locale The locale.
+ * @return The size of the error list.
+ */
+ fun check(locale: Locale): Int {
+ val errors = MessageKeyVerifier(Messages::class.java).verify(locale)
+ errors.forEach(System.err::println)
+ return errors.size
+ }
+
+ should("succeed instantiating known locale") {
+ Language("en").locale.language shouldBe "en"
+ }
+ should("throw on unknown locale instantiation") {
+ shouldThrow<AraraException> {
+ Language("quack")
+ }
+ }
+
+ should("not error on known localizations") {
+ listOf("en", "de", "nl", "it").forAll {
+ check(Locale(it)) shouldBe 0
+ }
+ check(Locale("en", "QN")) shouldBe 0
+ check(Locale("pt", "BR")) shouldBe 0
+ }
+ }
+ "language coverage" {
+ /*
+ * Tests the localized messages, checking if all messages are properly
+ * quoted (but not necessarily whether they are loadable).
+ */
+ should("get all strings from every language") {
+ // get all files
+ val files = Files.list(
+ Paths.get("src/main/resources/org/islandoftex/arara/localization"))
+ .map { p: Path ->
+ val f = p.toFile()
+ if (f.name.endsWith("properties") && !f.isDirectory) f
+ else null
+ }
+ .collect(Collectors.toList())
+ .toList()
+ .filterNotNull()
+ files.shouldNotBeEmpty()
+
+ // for each report, print
+ // the corresponding entry
+ files.map { file: File ->
+ try {
+ LanguageReport.analyze(file)
+ } catch (exception: IOException) {
+ throw AssertionError(
+ "Fatal exception: an error was raised while " +
+ "trying to read one of the languages. Please " +
+ "make sure all languages in the provided " +
+ "directory have read permission.")
+ }
+ }.forEach { report ->
+ // debug output
+ println(report.reference.name +
+ "\t" + String.format(" %2.2f%%", report.coverage))
+
+ // if there are problematic lines,
+ // add the current language report
+ if (report.lines.isNotEmpty()) {
+ // legend: S = Simple message, single quotes should not be doubled
+ // P = Parametrized message, single quotes must be doubled
+
+ // build the beginning of the line
+ println(report.reference.name)
+ // print error lines
+ println(report.lines)
+ }
+
+ report.coverage shouldBe 100.0f
+ }
+ }
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageReport.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageReport.kt
new file mode 100644
index 0000000000..addcd0262c
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageReport.kt
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.localization
+
+import java.io.File
+
+/**
+ * Implements the language report model.
+ *
+ * @author Island of TeX
+ * @version 5.0
+ * @since 5.0
+ */
+data class LanguageReport(
+ /**
+ * The file reference.
+ */
+ val reference: File,
+ /**
+ * Total of checked lines.
+ */
+ val total: Int,
+ /**
+ * List of problematic lines and their corresponding error types.
+ */
+ val lines: Map<Int, Char>
+) {
+ /**
+ * Language coverage of the file.
+ */
+ val coverage: Float
+ get() = if (lines.isEmpty()) {
+ 100f
+ } else {
+ (1f - lines.size.toFloat() / total) * 100f
+ }
+
+ companion object {
+ /**
+ * Analyzes the list of lines.
+ *
+ * @param file The file to read.
+ * @return The language report.
+ */
+ internal fun analyze(file: File): LanguageReport {
+ // holds the current line number
+ var number = 1
+ // holds the number of checked lines
+ var checked = 0
+
+ // flag that holds the
+ // current analysis
+ var check: Int
+
+ val reportLines = mutableMapOf<Int, Char>()
+
+ // check every line of the language file
+ file.forEachLine { line ->
+ // let's only analyze lines
+ // that are not comments
+ if (!line.trim().startsWith("#")) {
+ // increment the checked
+ // line counter
+ checked++
+
+ // line is a parametrized message
+ check = if (line.contains("{0}")) {
+ // check the corresponding pattern
+ checkParametrizedMessage(line)
+ } else {
+ // check the corresponding pattern
+ checkMessage(line)
+ }
+
+ // we found an error,
+ // report it
+ if (check != 0) {
+ // add line and error type to the report
+ reportLines[number] = if (check == 1) 'P' else 'S'
+ }
+ }
+
+ // let's move to the next line
+ number++
+ }
+
+ // return the language report
+ return LanguageReport(
+ reference = file,
+ total = checked,
+ lines = reportLines)
+ }
+
+ /**
+ * Checks if the provided message follows the simple format.
+ *
+ * @param text Message.
+ * @return An integer value.
+ */
+ private fun checkMessage(text: String): Int {
+ var i = 0
+ var c: Char
+ for (element in text) {
+ c = element
+ i = if (c == '\'') {
+ if (i == 1) {
+ return 2
+ } else {
+ 1
+ }
+ } else {
+ 0
+ }
+ }
+ return 0
+ }
+
+ /**
+ * Checks if the provided message follows the parametrized format.
+ *
+ * @param text Message.
+ * @return An integer value.
+ */
+ private fun checkParametrizedMessage(text: String): Int {
+ var i = 0
+ var c: Char
+ for (element in text) {
+ c = element
+ if (c == '\'') {
+ i += 1
+ } else {
+ if (i != 0) {
+ if (i != 2) {
+ return 1
+ } else {
+ i = 0
+ }
+ }
+ }
+ }
+ return 0
+ }
+ }
+}
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageTest.kt
new file mode 100644
index 0000000000..92d38ebc9b
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/localization/LanguageTest.kt
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.localization
+
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+import java.util.Locale
+import org.islandoftex.arara.model.AraraException
+
+class LanguageTest : ShouldSpec({
+ should("instantiate with known code") {
+ Language("en").locale shouldBe Locale.ENGLISH
+ }
+
+ should("throw on unknown language") {
+ shouldThrow<AraraException> {
+ Language("quack")
+ }
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/model/SessionTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/model/SessionTest.kt
new file mode 100644
index 0000000000..7580d8c81e
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/model/SessionTest.kt
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.model
+
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldNotThrow
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+
+class SessionTest : ShouldSpec({
+ should("include all environment variables") {
+ Session.clear()
+ Session.updateEnvironmentVariables()
+ Session.contains("environment:PATH") shouldBe true
+ }
+
+ should("properly check existence") {
+ Session.clear()
+ Session.put("A", "B")
+ Session.contains("A") shouldBe true
+ Session.contains("C") shouldBe false
+ }
+
+ should("support insertion") {
+ Session.clear()
+ Session.put("A", "B")
+ Session.contains("A") shouldBe true
+ }
+
+ should("support get") {
+ Session.clear()
+ Session.put("A", "B")
+ Session["A"] shouldBe "B"
+ }
+
+ should("support removal") {
+ Session.clear()
+ Session.put("A", "B")
+ Session.put("C", "D")
+ Session.contains("A") shouldBe true
+ Session.contains("C") shouldBe true
+ Session.remove("A")
+ Session.contains("A") shouldBe false
+ Session.contains("C") shouldBe true
+ }
+
+ should("clear itself") {
+ Session.clear()
+ Session.put("A", "B")
+ Session.put("C", "D")
+ Session.contains("A") shouldBe true
+ Session.contains("C") shouldBe true
+ Session.clear()
+ Session.contains("A") shouldBe false
+ Session.contains("C") shouldBe false
+ }
+
+ should("throw on unknown removal") {
+ Session.clear()
+ Session.put("A", "B")
+ shouldNotThrow<AraraException> {
+ Session.remove("A")
+ }
+ shouldThrow<AraraException> {
+ Session.remove("C")
+ }
+ }
+
+ should("throw on unknown getter") {
+ Session.clear()
+ Session.put("A", "B")
+ Session["A"] shouldBe "B"
+ shouldThrow<AraraException> {
+ Session["C"]
+ }
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/CommonUtilsTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/CommonUtilsTest.kt
new file mode 100644
index 0000000000..b77b901ef6
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/CommonUtilsTest.kt
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.utils
+
+import io.kotlintest.shouldBe
+import io.kotlintest.specs.ShouldSpec
+import org.islandoftex.arara.Arara
+import org.islandoftex.arara.configuration.AraraSpec
+import org.islandoftex.arara.localization.Language
+
+class CommonUtilsTest : ShouldSpec({
+ should("format bytes correctly") {
+ Arara.config[AraraSpec.Execution.language] = Language("en")
+ mapOf(800 to "800 B",
+ 1000 to "1.0 kB",
+ 1024 to "1.0 kB",
+ 1000000 to "1.0 MB").forEach { (key, value) ->
+ CommonUtils.byteSizeToString(key.toLong()) shouldBe value
+ }
+ }
+
+ should("find system utils") {
+ CommonUtils.isOnPath("echo") shouldBe true
+ }
+ should("not find utils with fantasy name") {
+ // hopefully no one will have such a command in the path…
+ CommonUtils.isOnPath("echoQuackForArara") shouldBe false
+ }
+
+ should("flatten lists correctly") {
+ CommonUtils.flatten(listOf(1, 2, listOf(3, 4, listOf(5, 6))))
+ .toSet() shouldBe (setOf(1, 2, 3, 4, 5, 6) as Set<Any>)
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExecutionTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExecutionTest.kt
new file mode 100644
index 0000000000..a0cc52145a
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExecutionTest.kt
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.utils
+
+import io.kotlintest.DoNotParallelize
+import io.kotlintest.matchers.string.shouldContain
+import io.kotlintest.matchers.string.shouldNotContain
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldNotBe
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.PrintStream
+import java.nio.file.Paths
+import kotlin.time.ExperimentalTime
+import org.islandoftex.arara.Arara
+import org.islandoftex.arara.configuration.AraraSpec
+import org.islandoftex.arara.configuration.Configuration
+import org.islandoftex.arara.filehandling.FileSearchingUtils
+import org.islandoftex.arara.model.AraraException
+import org.islandoftex.arara.model.Extractor
+import org.islandoftex.arara.model.Interpreter
+import org.islandoftex.arara.ruleset.DirectiveUtils
+
+@ExperimentalTime
+@DoNotParallelize
+class ExecutionTest : ShouldSpec({
+ fun getPathForTest(name: String): String = "src/test/resources/executiontests/$name"
+ fun outputForTest(testName: String, fileName: String = "$testName.tex"):
+ String {
+ val sysout = System.out
+ val output = ByteArrayOutputStream()
+ try {
+ System.setOut(PrintStream(output))
+ Arara.config[AraraSpec.Execution.workingDirectory] =
+ Paths.get(getPathForTest(testName))
+ Configuration.load()
+ Arara.config[AraraSpec.Execution.verbose] = true
+ FileSearchingUtils.discoverFile(fileName)
+ val directives = DirectiveUtils.process(Extractor.extract(
+ File("${getPathForTest(testName)}/$fileName")))
+ Interpreter(directives).execute()
+ return output.toByteArray().toString(Charsets.UTF_8)
+ } catch (ex: Exception) {
+ throw ex
+ } finally {
+ System.setOut(sysout)
+ output.close()
+ }
+ }
+
+ should("be able to store variables sessions") {
+ outputForTest("sessions") shouldContain "MeowQuack"
+ }
+
+ should("honor falsy existence test") {
+ val file = File(getPathForTest("conditionals") + "/conditionals.quack")
+ if (file.exists()) file.delete()
+ val output = outputForTest("conditionals")
+ output shouldContain "QuackOne"
+ output shouldContain "QuackFour"
+ output shouldNotContain "QuackTwo"
+ output shouldNotContain "QuackThree"
+ }
+ should("honor truthy existence (falsy contains) test") {
+ val file = File(getPathForTest("conditionals") + "/conditionals.quack")
+ file.writeText("Meow")
+ val output = outputForTest("conditionals")
+ file.delete()
+ output shouldContain "QuackOne"
+ output shouldContain "QuackFour"
+ output shouldContain "QuackTwo"
+ output shouldNotContain "QuackThree"
+ }
+ should("honor truthy contains test") {
+ val file = File(getPathForTest("conditionals") + "/conditionals.quack")
+ file.writeText("Duck")
+ val output = outputForTest("conditionals")
+ file.delete()
+ output shouldContain "QuackOne"
+ output shouldContain "QuackFour"
+ output shouldContain "QuackTwo"
+ output shouldContain "QuackThree"
+ }
+
+ should("track changes") {
+ val file = File(getPathForTest("changes") + "/arara.yaml")
+ if (file.exists()) file.delete()
+ outputForTest("changes") shouldContain "QuackOne"
+ outputForTest("changes") shouldNotContain "QuackOne"
+ }
+
+ should("gracefully halt on halt rule") {
+ val output = outputForTest("halt")
+ output shouldContain "QuackOne"
+ output shouldNotContain "QuackTwo"
+ CommonUtils.exitStatus shouldBe 0
+ }
+ should("forcefully halt on halt error rule") {
+ val output = outputForTest("halt-error")
+ output shouldContain "QuackOne"
+ output shouldNotContain "QuackTwo"
+ CommonUtils.exitStatus shouldNotBe 0
+ }
+
+ should("fail on invalid config") {
+ val exception = shouldThrow<AraraException> {
+ outputForTest("invalid-config")
+ }
+ exception.message shouldContain "could not parse the configuration"
+ }
+
+ should("read foreign extension") {
+ val output = outputForTest("foreign-extension", "foreign-extension.my")
+ output shouldContain "QuackOne"
+ }
+ should("fail on unknown extension") {
+ shouldThrow<AraraException> {
+ outputForTest("foreign-extension", "foreign-extension.xy")
+ }
+ }
+ should("accept empty pattern on known extension") {
+ val output = outputForTest("known-extension")
+ output shouldContain "QuackOne"
+ }
+
+ should("execute option-less directives") {
+ val output = outputForTest("simple-directive")
+ output shouldContain "The echoer"
+ output shouldContain "SUCCESS"
+ }
+ should("execute directive with options") {
+ val output = outputForTest("directive-with-options")
+ output shouldContain "The echoer"
+ output shouldContain "batchmode"
+ output shouldContain "SUCCESS"
+ output shouldNotContain "FAILURE"
+ }
+})
diff --git a/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExtensionTest.kt b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExtensionTest.kt
new file mode 100644
index 0000000000..cd41545ee9
--- /dev/null
+++ b/support/arara/source/src/test/kotlin/org/islandoftex/arara/utils/ExtensionTest.kt
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package org.islandoftex.arara.utils
+
+import io.kotlintest.shouldBe
+import io.kotlintest.shouldThrow
+import io.kotlintest.specs.ShouldSpec
+
+class ExtensionTest : ShouldSpec({
+ should("abbreviate strings correctly") {
+ "Quack quack".abbreviate(6) shouldBe "Quack…"
+ "Quack Quack".abbreviate(80) shouldBe "Quack Quack"
+ shouldThrow<IllegalArgumentException> { "Quack".abbreviate(1) }
+ }
+
+ should("center strings correctly") {
+ "Quack".center(3, '-') shouldBe "Quack"
+ "Quack".center(9, '-') shouldBe "--Quack--"
+ }
+
+ should("wrap strings correctly") {
+ "This text should be wrapped".wrap(10) shouldBe "This text\nshould be\nwrapped"
+ }
+})