diff --git a/README.md b/README.md
index f213237..388ca8e 100644
--- a/README.md
+++ b/README.md
@@ -23,8 +23,7 @@ The engine is designed to be modular, configurable
and extensible while being lightweight and fast.
In this repository you can find the
-[engine's logging system](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/logging),
-[engine core](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/base), official
+[core engine](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/base), official
subsystems, [their documentation](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/docs)
and [some miscellaneous files](https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/dist).
diff --git a/base/README.md b/base/README.md
new file mode 100644
index 0000000..31a7443
--- /dev/null
+++ b/base/README.md
@@ -0,0 +1,2 @@
+# `/base`
+The core engine. The grand piece of code which makes everything work.
diff --git a/base/src/test/kotlin/de/staropensource/engine/base/EngineTest.kt b/base/src/test/kotlin/de/staropensource/engine/base/EngineTest.kt
new file mode 100644
index 0000000..f4df89f
--- /dev/null
+++ b/base/src/test/kotlin/de/staropensource/engine/base/EngineTest.kt
@@ -0,0 +1,46 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.engine.base
+
+import de.staropensource.engine.base.exception.EngineInitializationFailureException
+import de.staropensource.engine.base.implementable.ShutdownHandler
+import de.staropensource.engine.testing.TestBase
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.MethodOrderer
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.TestMethodOrder
+
+@TestMethodOrder(MethodOrderer.MethodName::class)
+class EngineTest : TestBase(autoManage = false) {
+ @Test
+ fun initialize() {
+ try {
+ Engine.initialize()
+ } catch (exception: EngineInitializationFailureException) {
+ fail("Engine failed to initialize", exception)
+ }
+ }
+
+ @Test
+ fun shutdown() {
+ Engine.shutdown()
+ }
+}
diff --git a/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt
new file mode 100644
index 0000000..cfd9d06
--- /dev/null
+++ b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt
@@ -0,0 +1,268 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.engine.base.utility
+
+import de.staropensource.engine.testing.TestBase
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.CsvSource
+import java.io.File
+import kotlin.test.assertNotNull
+
+@Suppress("EmptyFunctionBlock")
+class FileAccessTest : TestBase() {
+ // -----> Tests on non-existent files
+ // These tests are executed on paths which likely do not exist
+ @ParameterizedTest
+ @CsvSource(
+ delimiter = ',',
+ quoteCharacter = '"',
+ textBlock = """
+ "/some/test/file", "/some/test/file"
+ "\very\nice\test\file.txt", "/very/nice/test/file.txt"
+ "/./did/somebody\\/say\\yoga?", "/did/somebody/say/yoga?"
+ "test.txt", "+%test.txt""""
+ )
+ fun toStringTest(supplyValue: String, compareValue: String) {
+ assertEquals(
+ compareValue
+ .replace("+", "${System.getProperty("user.dir")}")
+ .replace("%", File.separator),
+ FileAccess(supplyValue).toString()
+ )
+ }
+
+ @ParameterizedTest
+ @CsvSource(
+ delimiter = ',',
+ quoteCharacter = '"',
+ textBlock = """
+ "/some/test/file", "%some%test%file"
+ "\very\nice\test\file.txt", "%very%nice%test%file.txt"
+ "/./did/somebody\////say\\\yoga?", "%did%somebody%say%yoga?"
+ "test.txt", "+%test.txt""""
+ )
+ fun toStringRaw(supplyValue: String, compareValue: String) {
+ assertEquals(
+ compareValue
+ .replace("+", "${System.getProperty("user.dir")}")
+ .replace("%", File.separator),
+ FileAccess(supplyValue).toStringRaw()
+ )
+ }
+
+ @ParameterizedTest
+ @CsvSource(
+ delimiter = ',',
+ quoteCharacter = '"',
+ textBlock = """
+ "/some/test/file", "file"
+ "\very\nice\test\file.txt", "file.txt"
+ "/./did/somebody\\/say\\yoga?", "yoga?"
+ "test.txt", "test.txt""""
+ )
+ fun getBaseName(supplyValue: String, compareValue: String) {
+ assertEquals(
+ compareValue,
+ FileAccess(supplyValue).getBaseName()
+ )
+ }
+ @ParameterizedTest
+ @CsvSource(
+ delimiter = ',',
+ quoteCharacter = '"',
+ textBlock = """
+ "/some/test/file", "/some/test"
+ "\very\nice\test\file.txt", "/very/nice/test"
+ "/./did/somebody\\/say\\yoga?", "/did/somebody/say"
+ "test.txt", "+"
+ "configs/default.conf", "+%configs""""
+ )
+ fun parent(supplyValue: String, compareValue: String) {
+ assertEquals(
+ compareValue
+ .replace("+", "${System.getProperty("user.dir")}")
+ .replace("%", File.separator),
+ FileAccess(supplyValue).parent().toString()
+ )
+ }
+
+
+ // -----> Tests on default paths
+ // These tests are executed on FileAccess' default paths
+ @Test
+ fun getTemporaryCacheDirectory() {
+ assertNotNull(FileAccess.temporaryCacheDirectory)
+ }
+
+ @Test
+ fun getPersistentCacheDirectory() {
+ assertNotNull(FileAccess.persistentCacheDirectory)
+ }
+
+ @Test
+ fun getHomeDirectory() {
+ assertNotNull(FileAccess.homeDirectory)
+ }
+
+ @Test
+ fun getConfigDirectory() {
+ assertNotNull(FileAccess.configDirectory)
+ }
+
+ @Test
+ fun getDataDirectory() {
+ assertNotNull(FileAccess.dataDirectory)
+ }
+
+ @Test
+ fun exists() {
+
+ }
+
+ @Test
+ fun getType() {
+
+ }
+
+ @Test
+ fun isSymbolicLink() {
+
+ }
+
+ @Test
+ fun isHidden() {
+
+ }
+
+ @Test
+ fun isReadable() {
+
+ }
+
+ @Test
+ fun isWritable() {
+
+ }
+
+ @Test
+ fun isExecutable() {
+
+ }
+
+ @Test
+ fun getPosixPermissions() {
+
+ }
+
+ @Test
+ fun getLinkDestination() {
+ }
+
+ @Test
+ fun getFileSystem() {
+ }
+
+ @Test
+ fun isFilesystemPosixCompliant() {
+ }
+
+ @Test
+ fun getFilesystemRestrictedNames() {
+ }
+
+ @Test
+ fun createFile() {
+ }
+
+ @Test
+ fun createDirectory() {
+ }
+
+ @Test
+ fun createLink() {
+ }
+
+ @Test
+ fun move() {
+ }
+
+ @Test
+ fun copy() {
+ }
+
+ @Test
+ fun delete() {
+ }
+
+ @Test
+ fun deleteOnShutdown() {
+ }
+
+ @Test
+ fun readBytes() {
+ }
+
+ @Test
+ fun readLines() {
+ }
+
+ @Test
+ fun readString() {
+ }
+
+ @Test
+ fun writeBytes() {
+ }
+
+ @Test
+ fun writeLines() {
+ }
+
+ @Test
+ fun writeString() {
+ }
+
+ @Test
+ fun appendBytes() {
+ }
+
+ @Test
+ fun appendLines() {
+ }
+
+ @Test
+ fun appendString() {
+ }
+
+ @Test
+ fun list() {
+ }
+
+ @Test
+ fun listFiles() {
+ }
+
+ @Test
+ fun listDirectories() {
+ }
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 5259ab3..a76d143 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -80,6 +80,16 @@ allprojects {
// OSHI
implementation("${property("dependencyOshiIdentifier") as String}:${property("dependencyOshiVersion") as String}")
+
+ // Unit testing
+ // -> Kotlin
+ testImplementation(kotlin("test"))
+ // -> JUnit
+ testImplementation(platform("${property("testDependencyJUnitBOMIdentifier")}:${property("testDependencyJUnitVersion")}"))
+ testImplementation("${property("testDependencyJUnitJupiterIdentifier")}")
+ testRuntimeOnly("${property("testDependencyJUnitPlatformLauncherIdentifier")}")
+ // -> sos!engine
+ testImplementation(project(":testing"))
}
// Java
@@ -162,4 +172,18 @@ allprojects {
}
}
}
+
+ // Unit testing
+ // -> Configure Gradle to use JUnit
+ tasks.test {
+ useJUnitPlatform()
+ testLogging {
+ events(
+ "passed",
+ "skipped",
+ "failed"
+ )
+ }
+ maxParallelForks = 1
+ }
}
diff --git a/dist/template-subproject/build.gradle.kts b/dist/template-subproject/build.gradle.kts
index bc133dc..6a8a6d9 100644
--- a/dist/template-subproject/build.gradle.kts
+++ b/dist/template-subproject/build.gradle.kts
@@ -24,6 +24,5 @@ dependencies {
kotlin(property("dependencyKotlinStdIdentifier") as String)
// sos!engine
- implementation(project(":logging"))
implementation(project(":base"))
}
diff --git a/gradle.properties b/gradle.properties
index 2a3d851..746923e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -24,6 +24,7 @@ org.gradle.parallel=true
org.gradle.priority=normal
# Versioning
+versionCodename=Sugarcane
versionRelease=1
versionType=alpha
versionTyperelease=10
@@ -44,3 +45,9 @@ dependencyOshiIdentifier=com.github.oshi:oshi-core-java11
dependencyOshiVersion=6.6.5
dependencyJansiIdentifier=org.fusesource:jansi
dependencyJansiVersion=2.4.1
+
+# Test dependencies
+testDependencyJUnitVersion=5.11.3
+testDependencyJUnitBOMIdentifier=org.junit:junit-bom
+testDependencyJUnitJupiterIdentifier=org.junit.jupiter:junit-jupiter
+testDependencyJUnitPlatformLauncherIdentifier=org.junit.platform:junit-platform-launcher
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 41ad465..819f6a5 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -25,3 +25,4 @@ rootProject.name = "sos!engine"
include("") // scan root
include("base")
include("testapp")
+include("testing")
diff --git a/testapp/README.md b/testapp/README.md
index 8792f68..4757e7e 100644
--- a/testapp/README.md
+++ b/testapp/README.md
@@ -1,2 +1,3 @@
-# `/dist/template-subproject`
-This is a template subproject, simply existing to ease the process of creating a new Gradle subproject.
+# `/testapp`
+This is a development playground for the StarOpenSource Engine.
+You can modify this test application to your liking while you are working on the engine.
diff --git a/testing/README.md b/testing/README.md
new file mode 100644
index 0000000..4a1f4bf
--- /dev/null
+++ b/testing/README.md
@@ -0,0 +1,4 @@
+# `/testing`
+This subproject handles all the heavy lifting when it comes to unit testing.
+It heavily simplifies the process of creating unit tests involving the
+StarOpenSource Engine. See the TestBase class for more information.
diff --git a/testing/build.gradle.kts b/testing/build.gradle.kts
new file mode 100644
index 0000000..71bbacd
--- /dev/null
+++ b/testing/build.gradle.kts
@@ -0,0 +1,35 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+// Dependencies
+dependencies {
+ // Kotlin support
+ kotlin(property("dependencyKotlinStdIdentifier") as String)
+
+ // sos!engine
+ implementation(project(":base"))
+
+ // Unit testing
+ // -> Kotlin
+ implementation(kotlin("test"))
+ // -> JUnit
+ implementation(platform("${property("testDependencyJUnitBOMIdentifier")}:${property("testDependencyJUnitVersion")}"))
+ implementation("${property("testDependencyJUnitJupiterIdentifier")}")
+}
diff --git a/testing/src/main/kotlin/de/staropensource/engine/testing/TestBase.kt b/testing/src/main/kotlin/de/staropensource/engine/testing/TestBase.kt
new file mode 100644
index 0000000..7f9a1a4
--- /dev/null
+++ b/testing/src/main/kotlin/de/staropensource/engine/testing/TestBase.kt
@@ -0,0 +1,126 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.engine.testing
+
+import de.staropensource.engine.base.Engine
+import de.staropensource.engine.base.Engine.State
+import de.staropensource.engine.base.EngineConfiguration
+import de.staropensource.engine.base.type.logging.ChannelSettings
+import de.staropensource.engine.testing.implementation.FailureShutdownHandler
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.fail
+
+/**
+ * Base class for implementing tests.
+ *
+ * @param autoManage automatically initializes and shuts the engine down after each test
+ * @param suppressInitAndShutdownLogging if to suppress the engine's log output during engine initialization and shutdown. Only takes effect if [autoManage] is `true`
+ * @param shutdownMarksFailure whether engine shutdowns should mark the test as failed
+ * @since v1-alpha10
+ */
+abstract class TestBase(
+ val autoManage: Boolean = true,
+ val suppressInitAndShutdownLogging: Boolean = true,
+ val shutdownMarksFailure: Boolean = false
+) {
+ init {
+ performConfiguration()
+ }
+
+ /**
+ * Configures the engine before
+ * starting any tests.
+ *
+ * Absolutely mandatory or else tests
+ * may misbehave, which defeats the
+ * purpose of unit tests.
+ *
+ * @since v1-alpha10
+ */
+ private fun performConfiguration() {
+ if (shutdownMarksFailure)
+ EngineConfiguration.shutdownHandler = FailureShutdownHandler.instance
+ else
+ EngineConfiguration.shutdownHandler = FailureShutdownHandler.instance
+
+ //if (Engine.state == State.UNINITIALIZED) {}
+ }
+
+ /**
+ * Initializes the engine before each test.
+ *
+ * @since v1-alpha10
+ */
+ @BeforeEach
+ fun initializeEngine() {
+ when (Engine.state) {
+ State.INITIALIZING, State.SHUTTING_DOWN -> fail("Engine is in invalid state 'Engine.State.${Engine.state.name}'")
+ State.CRASHED -> fail("The StarOpenSource Engine has crashed")
+ else -> {}
+ }
+
+ if (autoManage) {
+ val originalSettings: ChannelSettings = ChannelSettings.global
+
+ // Set 'adapters' to an empty set
+ if (suppressInitAndShutdownLogging)
+ ChannelSettings.global = ChannelSettings.global.copy(adapters = linkedSetOf())
+
+ // Initialize the engine
+ Engine.initialize()
+
+ // Restore channel configuration
+ if (suppressInitAndShutdownLogging)
+ ChannelSettings.global = originalSettings
+ }
+ }
+
+ /**
+ * Shuts the engine down after each test
+ *
+ * @since v1-alpha10
+ */
+ @AfterEach
+ fun shutdownEngine() {
+ when (Engine.state) {
+ State.UNINITIALIZED -> fail("Internal inconsistency detected: Engine configuration was not performed")
+ State.INITIALIZING, State.SHUTTING_DOWN -> fail("Engine is in invalid state 'Engine.State.${Engine.state.name}'")
+ State.CRASHED -> fail("The StarOpenSource Engine has crashed")
+ else -> {}
+ }
+
+ if (autoManage) {
+ val originalSettings: ChannelSettings = ChannelSettings.global
+
+ // Set 'adapters' to an empty set
+ if (suppressInitAndShutdownLogging)
+ ChannelSettings.global = ChannelSettings.global.copy(adapters = linkedSetOf())
+
+ // Shut the engine down
+ Engine.shutdown()
+
+ // Restore channel configuration
+ if (suppressInitAndShutdownLogging)
+ ChannelSettings.global = originalSettings
+ }
+ }
+}
diff --git a/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/FailureShutdownHandler.kt b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/FailureShutdownHandler.kt
new file mode 100644
index 0000000..70c5c59
--- /dev/null
+++ b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/FailureShutdownHandler.kt
@@ -0,0 +1,51 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.engine.testing.implementation
+
+import de.staropensource.engine.base.implementable.ShutdownHandler
+import kotlin.test.fail
+
+/**
+ * [ShutdownHandler] implementation which
+ * causes the test to fail if executed.
+ *
+ * @since v1-alpha10
+ */
+class FailureShutdownHandler private constructor() : ShutdownHandler {
+ /**
+ * Companion object of [FailureShutdownHandler].
+ *
+ * @since v1-alpha10
+ */
+ companion object {
+ /**
+ * Global instance of [FailureShutdownHandler].
+ *
+ * @since v1-alpha10
+ */
+ @JvmStatic
+ val instance: FailureShutdownHandler = FailureShutdownHandler()
+ }
+
+ override fun exit(exitcode: UByte) {
+ fail("The engine was shut down with code ${exitcode}")
+ }
+}
diff --git a/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/NoOperationShutdownHandler.kt b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/NoOperationShutdownHandler.kt
new file mode 100644
index 0000000..f53455e
--- /dev/null
+++ b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/NoOperationShutdownHandler.kt
@@ -0,0 +1,49 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.staropensource.engine.testing.implementation
+
+import de.staropensource.engine.base.implementable.ShutdownHandler
+import kotlin.test.fail
+
+/**
+ * [ShutdownHandler] implementation which
+ * causes the test to fail if executed.
+ *
+ * @since v1-alpha10
+ */
+class NoOperationShutdownHandler private constructor() : ShutdownHandler {
+ /**
+ * Companion object of [NoOperationShutdownHandler].
+ *
+ * @since v1-alpha10
+ */
+ companion object {
+ /**
+ * Global instance of [NoOperationShutdownHandler].
+ *
+ * @since v1-alpha10
+ */
+ @JvmStatic
+ val instance: NoOperationShutdownHandler = NoOperationShutdownHandler()
+ }
+
+ override fun exit(exitcode: UByte) = Unit
+}
diff --git a/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/package-info.kt b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/package-info.kt
new file mode 100644
index 0000000..ef6d54d
--- /dev/null
+++ b/testing/src/main/kotlin/de/staropensource/engine/testing/implementation/package-info.kt
@@ -0,0 +1,27 @@
+/*
+ * STAROPENSOURCE ENGINE SOURCE FILE
+ * Copyright (c) 2024 The StarOpenSource Engine Authors
+ * Licensed under the GNU Affero General Public License v3
+ * with an exception allowing classpath linking.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * Implementations of various
+ * interfaces and abstract classes.
+ *
+ * @since v1-alpha10
+ */
+package de.staropensource.engine.testing.implementation