From 444c3a9260fc348b20004d18b5172f5cb4287a0c Mon Sep 17 00:00:00 2001 From: manami-project <13179375+manami-project@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:29:03 +0200 Subject: [PATCH] Added possibility to configure app --- .gitignore | 3 + tooling/app/README.md | 13 ++ .../manamiproject/modb/extension/Main.kt | 35 +++--- .../modb/extension/config/AppConfig.kt | 42 +++++++ .../modb/extension/config/Config.kt | 35 ++++++ .../score/DefaultScoreDownloadListCreator.kt | 20 +-- .../DefaultSynopsisDownloadListCreator.kt | 19 +-- .../updates/DefaultUpdatableItemsFinder.kt | 15 +-- .../modb/extension/TestingAssets.kt | 24 ++++ .../modb/extension/config/AppConfigTest.kt | 114 ++++++++++++++++++ .../modb/extension/config/ConfigTest.kt | 32 +++++ .../DefaultScoreDownloadListCreatorTest.kt | 58 +++------ .../DefaultSynopsisDownloadListCreatorTest.kt | 58 +++------ .../DefaultUpdatableItemsFinderTest.kt | 61 ++++------ tooling/lib/README.md | 17 ++- 15 files changed, 369 insertions(+), 177 deletions(-) create mode 100644 tooling/app/README.md create mode 100644 tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/AppConfig.kt create mode 100644 tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/Config.kt create mode 100644 tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/AppConfigTest.kt create mode 100644 tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/ConfigTest.kt diff --git a/.gitignore b/.gitignore index 1acabeacd7..ff3cdb88f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# CUSTOM +**/config.toml + # Created by https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+all,intellij+iml,visualstudiocode # Edit at https://www.gitignore.io/?templates=linux,macos,gradle,kotlin,windows,intellij,intellij+all,intellij+iml,visualstudiocode diff --git a/tooling/app/README.md b/tooling/app/README.md new file mode 100644 index 0000000000..6e80feea16 --- /dev/null +++ b/tooling/app/README.md @@ -0,0 +1,13 @@ +# modb-extension app + +This application creates and updates the data that you can find in the `/data` folder of this repository. + +## How to run + +1. Setup config by creating a config file `tooling/app/src/main/resources/config.toml` with content: +```toml +[modb.extension.config] +dataDirectory="" +``` +Set `dataDirectory` to the absolute path of json files on your machine. +2. Run application via `tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/Main.kt` \ No newline at end of file diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/Main.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/Main.kt index faccffe628..5d1d20f474 100644 --- a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/Main.kt +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/Main.kt @@ -1,11 +1,11 @@ package io.github.manamiproject.modb.extension import io.github.manamiproject.modb.core.coroutines.CoroutineManager.runCoroutine -import io.github.manamiproject.modb.core.extensions.Directory -import io.github.manamiproject.modb.core.extensions.directoryExists import io.github.manamiproject.modb.core.extensions.readFile import io.github.manamiproject.modb.core.extractor.JsonDataExtractor import io.github.manamiproject.modb.core.random +import io.github.manamiproject.modb.extension.config.AppConfig +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.extension.score.* import io.github.manamiproject.modb.extension.synopsis.* import io.github.manamiproject.modb.extension.updates.DefaultUpdatableItemsFinder @@ -13,19 +13,18 @@ import io.github.manamiproject.modb.serde.json.AnimeListJsonStringDeserializer import io.github.manamiproject.modb.serde.json.DefaultExternalResourceJsonDeserializer import kotlinx.coroutines.delay import java.net.URI -import kotlin.io.path.Path import kotlin.io.path.forEachDirectoryEntry fun main() = runCoroutine { - val sourcesFromDb = fetchSourcesFromDb() - val dataDirectory = Path(System.getenv("MODB_EXTENSION_DATA_DIR")) - val localFileOrigin = LocalFileOrigin(dataDirectory) - val existingFiles = fetchAllExistingFiles(dataDirectory) - val newDbEntries = DefaultUpdatableItemsFinder(dataDirectory).findNewDbEntries(sourcesFromDb, existingFiles) + val appConfig = AppConfig() + val sourcesFromDb = fetchSourcesFromDb(appConfig) + val localFileOrigin = LocalFileOrigin(appConfig.dataDirectory()) + val existingFiles = fetchAllExistingFiles(appConfig) + val newDbEntries = DefaultUpdatableItemsFinder(appConfig).findNewDbEntries(sourcesFromDb, existingFiles) val scoreCreator = DefaultScoreCreator() val scoreWriter = DefaultScoreWriter(localFileOrigin) - val scoreDownloadListCreator = DefaultScoreDownloadListCreator(dataDirectory) + val scoreDownloadListCreator = DefaultScoreDownloadListCreator(appConfig) val scoreDownloadList = newDbEntries.union(scoreDownloadListCreator.createDownloadList()) scoreDownloadList.forEachIndexed { index, sourcesBlock -> println("Downloading [${index + 1}/${scoreDownloadList.size}]") @@ -38,7 +37,7 @@ fun main() = runCoroutine { val synopsisCreator = DefaultSynopsisCreator() val synopsisWriter = DefaultSynopsisWriter(localFileOrigin) - val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(dataDirectory) + val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(appConfig) val synopsisDownloadList = newDbEntries.union(synopsisDownloadListCreator.createDownloadList()) synopsisDownloadList.forEachIndexed { index, sourcesBlock -> println("Downloading [${index + 1}/${synopsisDownloadList.size}]") @@ -49,20 +48,19 @@ fun main() = runCoroutine { } } - check((fetchAllSourcesInFiles(dataDirectory) - sourcesFromDb).isEmpty()) { "All sources in files must exist in db at this point." } + check((fetchAllSourcesInFiles(appConfig) - sourcesFromDb).isEmpty()) { "All sources in files must exist in db at this point." } println("Done") } -private suspend fun fetchSourcesFromDb(): Set> { +private suspend fun fetchSourcesFromDb(config: Config): Set> { val deserializer = DefaultExternalResourceJsonDeserializer(deserializer = AnimeListJsonStringDeserializer()) - val zipFile = URI("https://raw.githubusercontent.com/manami-project/anime-offline-database/master/anime-offline-database.zip") - return deserializer.deserialize(zipFile.toURL()).data.map { it.sources }.toSet() + return deserializer.deserialize(config.animeDataSet().toURL()).data.map { it.sources }.toSet() } -private suspend fun fetchAllSourcesInFiles(directory: Directory): Set> { +private suspend fun fetchAllSourcesInFiles(config: Config): Set> { val list = mutableSetOf>() - directory.forEachDirectoryEntry("*.json") { file -> + config.dataDirectory().forEachDirectoryEntry("*.json") { file -> val extractionResult = JsonDataExtractor.extract(file.readFile(), mapOf( "sources" to "$.sources" )) @@ -71,10 +69,9 @@ private suspend fun fetchAllSourcesInFiles(directory: Directory): Set> return list } -private fun fetchAllExistingFiles(directory: Directory): Set { - require(directory.directoryExists()) { "Data directory either doesn't exist or is not a directory." } +private fun fetchAllExistingFiles(config: Config): Set { val ret = mutableSetOf() - directory.forEachDirectoryEntry("*.json") { + config.dataDirectory().forEachDirectoryEntry("*.json") { ret.add(it.fileName.toString()) } return ret diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/AppConfig.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/AppConfig.kt new file mode 100644 index 0000000000..a0cb069ff9 --- /dev/null +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/AppConfig.kt @@ -0,0 +1,42 @@ +package io.github.manamiproject.modb.extension.config + +import io.github.manamiproject.modb.core.config.ConfigRegistry +import io.github.manamiproject.modb.core.config.DefaultConfigRegistry +import io.github.manamiproject.modb.core.config.StringPropertyDelegate +import io.github.manamiproject.modb.core.extensions.Directory +import io.github.manamiproject.modb.core.extensions.directoryExists +import java.net.URI +import kotlin.io.path.Path + +/** + * Implementation of [Config] which contains all necessary properties. + * @since 1.0.0 + * @param configRegistry Implementation of [ConfigRegistry] used for populating properties. Uses [DefaultConfigRegistry] by default. + */ +class AppConfig( + configRegistry: ConfigRegistry = DefaultConfigRegistry, +) : Config { + + private val dataDirectory: String by StringPropertyDelegate( + namespace = NAMESPACE, + configRegistry = configRegistry, + ) + + private val animeDataset: String by StringPropertyDelegate( + namespace = NAMESPACE, + configRegistry = configRegistry, + default = "https://raw.githubusercontent.com/manami-project/anime-offline-database/master/anime-offline-database.zip" + ) + + override fun dataDirectory(): Directory { + val path = Path(dataDirectory) + check(path.directoryExists()) { "Given value for dataDirectory [$dataDirectory] doesn't exist or is not a directory." } + return path + } + + override fun animeDataSet(): URI = URI(animeDataset) + + companion object { + private const val NAMESPACE = "modb.extension.config" + } +} \ No newline at end of file diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/Config.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/Config.kt new file mode 100644 index 0000000000..433d0da041 --- /dev/null +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/config/Config.kt @@ -0,0 +1,35 @@ +package io.github.manamiproject.modb.extension.config + +import io.github.manamiproject.modb.core.extensions.Directory +import java.net.URI +import java.time.Clock + +/** + * Contains all configurable and directly derived properties. + * @since 1.0.0 + */ +interface Config { + + /** + * Returns the directory in which the `*.json` files are being saved. + * @since 1.0.0 + * @return Path to the JSON files created by the app. + */ + fun dataDirectory(): Directory + + /** + * Source of the anime data set. + * Expected is the format defined [here](https://github.com/manami-project/anime-offline-database). + * @since 1.0.0 + * @return [URI] pointing to the anime data set. + */ + fun animeDataSet(): URI + + /** + * Clock being used whenever dates and timestamps are created. + * Default is system default zone. + * @since 1.0.0 + * @return Instance of [Clock] as basis for any type of date instances. + */ + fun clock(): Clock = Clock.systemDefaultZone() +} \ No newline at end of file diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreator.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreator.kt index 2c945f4e5b..69ff14f4f3 100644 --- a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreator.kt +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreator.kt @@ -1,40 +1,30 @@ package io.github.manamiproject.modb.extension.score -import io.github.manamiproject.modb.core.extensions.Directory -import io.github.manamiproject.modb.core.extensions.EMPTY -import io.github.manamiproject.modb.core.extensions.directoryExists import io.github.manamiproject.modb.core.extensions.readFile import io.github.manamiproject.modb.core.extractor.DataExtractor import io.github.manamiproject.modb.core.extractor.JsonDataExtractor import io.github.manamiproject.modb.core.json.Json import io.github.manamiproject.modb.extension.ExtensionData -import io.github.manamiproject.modb.extension.filename +import io.github.manamiproject.modb.extension.config.Config import java.net.URI -import java.time.Clock import java.time.LocalDate import java.time.Period import kotlin.io.path.forEachDirectoryEntry /** * @since 1.0.0 - * @property directory - * @property clock + * @property config * @property extractor */ class DefaultScoreDownloadListCreator( - private val directory: Directory, - private val clock: Clock = Clock.systemDefaultZone(), + private val config: Config, private val extractor: DataExtractor = JsonDataExtractor, ): ScoreDownloadListCreator { - init { - require(directory.directoryExists()) { "Data directory either doesn't exist or is not a directory." } - } - override suspend fun createDownloadList(redownloadEntriesOlderThan: Period): Set> { val ret = mutableSetOf>() - directory.forEachDirectoryEntry("*.json") { file -> + config.dataDirectory().forEachDirectoryEntry("*.json") { file -> val fileContent = file.readFile() val extensionData = Json.parseJson(fileContent)!! @@ -64,6 +54,6 @@ class DefaultScoreDownloadListCreator( } private fun isRedownloadNecessary(redownloadEntriesOlderThan: Period, dateToCheck: LocalDate): Boolean { - return LocalDate.now(clock).minus(redownloadEntriesOlderThan).isAfter(dateToCheck) + return LocalDate.now(config.clock()).minus(redownloadEntriesOlderThan).isAfter(dateToCheck) } } \ No newline at end of file diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreator.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreator.kt index 3c92d27d44..c7a161572d 100644 --- a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreator.kt +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreator.kt @@ -1,40 +1,31 @@ package io.github.manamiproject.modb.extension.synopsis -import io.github.manamiproject.modb.core.extensions.Directory -import io.github.manamiproject.modb.core.extensions.EMPTY -import io.github.manamiproject.modb.core.extensions.directoryExists import io.github.manamiproject.modb.core.extensions.readFile import io.github.manamiproject.modb.core.extractor.DataExtractor import io.github.manamiproject.modb.core.extractor.JsonDataExtractor import io.github.manamiproject.modb.core.json.Json import io.github.manamiproject.modb.extension.ExtensionData -import io.github.manamiproject.modb.extension.filename +import io.github.manamiproject.modb.extension.config.Config import java.net.URI -import java.time.Clock import java.time.LocalDate import java.time.Period import kotlin.io.path.forEachDirectoryEntry /** * @since 1.0.0 - * @property directory + * @property config * @property clock * @property extractor */ class DefaultSynopsisDownloadListCreator( - private val directory: Directory, - private val clock: Clock = Clock.systemDefaultZone(), + private val config: Config, private val extractor: DataExtractor = JsonDataExtractor, ): SynopsisDownloadListCreator { - init { - require(directory.directoryExists()) { "Data directory either doesn't exist or is not a directory." } - } - override suspend fun createDownloadList(redownloadEntriesOlderThan: Period): Set> { val ret = mutableSetOf>() - directory.forEachDirectoryEntry("*.json") { file -> + config.dataDirectory().forEachDirectoryEntry("*.json") { file -> val fileContent = file.readFile() val extensionData = Json.parseJson(fileContent)!! when (val synopsis = extensionData.synopsis()) { @@ -63,6 +54,6 @@ class DefaultSynopsisDownloadListCreator( } private fun isRedownloadNecessary(redownloadEntriesOlderThan: Period, dateToCheck: LocalDate): Boolean { - return LocalDate.now(clock).minus(redownloadEntriesOlderThan).isAfter(dateToCheck) + return LocalDate.now(config.clock()).minus(redownloadEntriesOlderThan).isAfter(dateToCheck) } } \ No newline at end of file diff --git a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinder.kt b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinder.kt index 8fa3513cf3..97152ede6a 100644 --- a/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinder.kt +++ b/tooling/app/src/main/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinder.kt @@ -1,20 +1,17 @@ package io.github.manamiproject.modb.extension.updates -import io.github.manamiproject.modb.core.extensions.Directory -import io.github.manamiproject.modb.core.extensions.directoryExists +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.extension.filename import java.net.URI import kotlin.io.path.deleteIfExists /** * @since 1.0.0 - * @property directory + * @property config */ -class DefaultUpdatableItemsFinder(private val directory: Directory): UpdatableItemsFinder { - - init { - require(directory.directoryExists()) { "Data directory either doesn't exist or is not a directory." } - } +class DefaultUpdatableItemsFinder( + private val config: Config +): UpdatableItemsFinder { override suspend fun findNewDbEntries( sourcesFromDb: Set>, @@ -29,7 +26,7 @@ class DefaultUpdatableItemsFinder(private val directory: Directory): UpdatableIt existingFileNames.toMutableSet().apply { removeAll(expectedFilenameToDbSources.keys) }.forEach { - directory.resolve(it).deleteIfExists() + config.dataDirectory().resolve(it).deleteIfExists() } return newOrUpdatedEntriesInDb.values.toSet() diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/TestingAssets.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/TestingAssets.kt index e9909bffb4..0752ceb9e5 100644 --- a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/TestingAssets.kt +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/TestingAssets.kt @@ -1,10 +1,34 @@ package io.github.manamiproject.modb.extension import io.github.manamiproject.modb.core.config.AnimeId +import io.github.manamiproject.modb.core.config.ConfigRegistry import io.github.manamiproject.modb.core.downloader.Downloader +import io.github.manamiproject.modb.core.extensions.Directory +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.test.shouldNotBeInvoked +import java.net.URI +import java.time.Clock +import java.time.LocalDate +import java.time.LocalDateTime internal object TestDownloader: Downloader { override suspend fun download(id: AnimeId, onDeadEntry: suspend (AnimeId) -> Unit): String = shouldNotBeInvoked() } +internal object TestConfigRegistry: ConfigRegistry { + override fun boolean(key: String): Boolean = shouldNotBeInvoked() + override fun double(key: String): Double = shouldNotBeInvoked() + override fun list(key: String): List = shouldNotBeInvoked() + override fun localDate(key: String): LocalDate = shouldNotBeInvoked() + override fun localDateTime(key: String): LocalDateTime = shouldNotBeInvoked() + override fun long(key: String): Long = shouldNotBeInvoked() + override fun map(key: String): Map = shouldNotBeInvoked() + override fun offsetDateTime(key: String) = shouldNotBeInvoked() + override fun string(key: String): String = shouldNotBeInvoked() +} + +internal object TestConfig: Config { + override fun dataDirectory(): Directory = shouldNotBeInvoked() + override fun animeDataSet(): URI = shouldNotBeInvoked() + override fun clock(): Clock = shouldNotBeInvoked() +} diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/AppConfigTest.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/AppConfigTest.kt new file mode 100644 index 0000000000..a86d4c36da --- /dev/null +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/AppConfigTest.kt @@ -0,0 +1,114 @@ +package io.github.manamiproject.modb.extension.config + +import io.github.manamiproject.modb.core.config.ConfigRegistry +import io.github.manamiproject.modb.extension.TestConfigRegistry +import io.github.manamiproject.modb.test.exceptionExpected +import io.github.manamiproject.modb.test.tempDirectory +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import java.net.URI +import kotlin.io.path.createFile + +internal class AppConfigTest { + + @Nested + inner class DataDirectoryTests { + + @Test + fun `throws exception if directory doesn't exist`() { + // given + val testConfigRegistry = object: ConfigRegistry by TestConfigRegistry { + override fun string(key: String): String = "pathNotExists" + } + val appConfig = AppConfig( + configRegistry = testConfigRegistry, + ) + + // when + val result = exceptionExpected { + appConfig.dataDirectory() + } + + // then + assertThat(result).hasMessage("Given value for dataDirectory [pathNotExists] doesn't exist or is not a directory.") + } + + @Test + fun `throws exception if path is not a directory`() { + tempDirectory { + // given + val file = tempDir.resolve("testfile.txt").createFile() + + val testConfigRegistry = object: ConfigRegistry by TestConfigRegistry { + override fun string(key: String): String = file.toAbsolutePath().toString() + } + + val appConfig = AppConfig( + configRegistry = testConfigRegistry, + ) + + // when + val result = exceptionExpected { + appConfig.dataDirectory() + } + + // then + assertThat(result).hasMessageEndingWith("/testfile.txt] doesn't exist or is not a directory.") + } + } + + @Test + fun `use config value`() { + tempDirectory { + // given + val testConfigRegistry = object: ConfigRegistry by TestConfigRegistry { + override fun string(key: String): String = tempDir.toString() + } + + val appConfig = AppConfig( + configRegistry = testConfigRegistry, + ) + + // when + val result = appConfig.dataDirectory() + + // then + assertThat(result).isEqualTo(tempDir) + } + } + } + + @Nested + inner class AnimeDatasetTests { + + @Test + fun `use config value`() { + // given + val testConfigRegistry = object: ConfigRegistry by TestConfigRegistry { + override fun string(key: String): String = "http://localhost:8080/anime-offline-database.zip" + } + val config = AppConfig( + configRegistry = testConfigRegistry, + ) + + // when + val result = config.animeDataSet() + + // then + assertThat(result).isEqualTo(URI("http://localhost:8080/anime-offline-database.zip")) + } + + @Test + fun `default value`() { + // given + val config = AppConfig() + + // when + val result = config.animeDataSet() + + // then + assertThat(result).isEqualTo(URI("https://raw.githubusercontent.com/manami-project/anime-offline-database/master/anime-offline-database.zip")) + } + } +} \ No newline at end of file diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/ConfigTest.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/ConfigTest.kt new file mode 100644 index 0000000000..75aad687f4 --- /dev/null +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/config/ConfigTest.kt @@ -0,0 +1,32 @@ +package io.github.manamiproject.modb.extension.config + +import io.github.manamiproject.modb.core.extensions.Directory +import io.github.manamiproject.modb.test.shouldNotBeInvoked +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import java.net.URI +import java.time.Clock + +internal class ConfigTest { + + @Nested + inner class ClockTests { + + @Test + fun `default value is current system local zone`() { + // given + val systemDefaultZone = Clock.systemDefaultZone() + val config = object : Config { + override fun dataDirectory(): Directory = shouldNotBeInvoked() + override fun animeDataSet(): URI = shouldNotBeInvoked() + } + + // when + val result = config.clock() + + // then + assertThat(result).isEqualTo(systemDefaultZone) + } + } +} \ No newline at end of file diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreatorTest.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreatorTest.kt index e4bba9e181..995808258b 100644 --- a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreatorTest.kt +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/score/DefaultScoreDownloadListCreatorTest.kt @@ -1,9 +1,11 @@ package io.github.manamiproject.modb.extension.score +import io.github.manamiproject.modb.core.extensions.Directory import io.github.manamiproject.modb.core.extensions.writeToFile import io.github.manamiproject.modb.core.json.Json import io.github.manamiproject.modb.extension.ExtensionData -import io.github.manamiproject.modb.test.exceptionExpected +import io.github.manamiproject.modb.extension.TestConfig +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.test.tempDirectory import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Nested @@ -14,43 +16,9 @@ import java.time.Instant import java.time.LocalDate import java.time.ZoneOffset.UTC import java.time.format.DateTimeFormatter.ISO_LOCAL_DATE -import kotlin.io.path.createFile internal class DefaultScoreDownloadListCreatorTest { - @Nested - inner class ConstructorTests { - - @Test - fun `throws exception if directory doesn't exist`() { - tempDirectory { - // when - val result = exceptionExpected { - DefaultScoreDownloadListCreator(tempDir.resolve("unknown")) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - - @Test - fun `throws exception if path is not a directory`() { - tempDirectory { - // given - val path = tempDir.resolve("text.txt").createFile() - - // when - val result = exceptionExpected { - DefaultScoreDownloadListCreator(path) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - } - @Nested inner class CreateDownloadListTests { @@ -58,7 +26,10 @@ internal class DefaultScoreDownloadListCreatorTest { fun `return file without score`() { tempDirectory { // given - val scoreDownloadListCreator = DefaultScoreDownloadListCreator(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val scoreDownloadListCreator = DefaultScoreDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), @@ -84,15 +55,18 @@ internal class DefaultScoreDownloadListCreatorTest { fun `returns file if entry is older than 6 months`() { tempDirectory { // given - val clock = Clock.fixed(Instant.parse("2021-01-31T16:02:42.00Z"), UTC) - val scoreDownloadListCreator = DefaultScoreDownloadListCreator(tempDir, clock) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + override fun clock(): Clock = Clock.fixed(Instant.parse("2021-01-31T16:02:42.00Z"), UTC) + } + val scoreDownloadListCreator = DefaultScoreDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), URI("https://example5.com"), ), score = Score( - lastUpdate = LocalDate.now(clock).minusMonths(6L).minusDays(1L).format(ISO_LOCAL_DATE), + lastUpdate = LocalDate.now(testConfig.clock()).minusMonths(6L).minusDays(1L).format(ISO_LOCAL_DATE), ), ) Json.toJson(extensionData).writeToFile(tempDir.resolve("6f0e12caa76e9514.json")) @@ -114,7 +88,11 @@ internal class DefaultScoreDownloadListCreatorTest { fun `don't return recent and valid entries`() { tempDirectory { // given - val scoreDownloadListCreator = DefaultScoreDownloadListCreator(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + override fun clock(): Clock = Clock.systemDefaultZone() + } + val scoreDownloadListCreator = DefaultScoreDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreatorTest.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreatorTest.kt index 04d0f6e0a1..f3168bda61 100644 --- a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreatorTest.kt +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/synopsis/DefaultSynopsisDownloadListCreatorTest.kt @@ -1,9 +1,11 @@ package io.github.manamiproject.modb.extension.synopsis +import io.github.manamiproject.modb.core.extensions.Directory import io.github.manamiproject.modb.core.extensions.writeToFile import io.github.manamiproject.modb.core.json.Json import io.github.manamiproject.modb.extension.ExtensionData -import io.github.manamiproject.modb.test.exceptionExpected +import io.github.manamiproject.modb.extension.TestConfig +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.test.tempDirectory import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Nested @@ -14,43 +16,9 @@ import java.time.Instant import java.time.LocalDate import java.time.ZoneOffset.UTC import java.time.format.DateTimeFormatter.ISO_LOCAL_DATE -import kotlin.io.path.createFile internal class DefaultSynopsisDownloadListCreatorTest { - @Nested - inner class ConstructorTests { - - @Test - fun `throws exception if directory doesn't exist`() { - tempDirectory { - // when - val result = exceptionExpected { - DefaultSynopsisDownloadListCreator(tempDir.resolve("unknown")) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - - @Test - fun `throws exception if path is not a directory`() { - tempDirectory { - // given - val path = tempDir.resolve("text.txt").createFile() - - // when - val result = exceptionExpected { - DefaultSynopsisDownloadListCreator(path) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - } - @Nested inner class CreateDownloadListTests { @@ -58,7 +26,10 @@ internal class DefaultSynopsisDownloadListCreatorTest { fun `return file without score`() { tempDirectory { // given - val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), @@ -84,8 +55,11 @@ internal class DefaultSynopsisDownloadListCreatorTest { fun `returns file if entry is older than 6 months`() { tempDirectory { // given - val clock = Clock.fixed(Instant.parse("2021-01-31T16:02:42.00Z"), UTC) - val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(tempDir, clock) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + override fun clock(): Clock = Clock.fixed(Instant.parse("2021-01-31T16:02:42.00Z"), UTC) + } + val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), @@ -94,7 +68,7 @@ internal class DefaultSynopsisDownloadListCreatorTest { synopsis = Synopsis( text = "text", author = "me", - lastUpdate = LocalDate.now(clock).minusMonths(6L).minusDays(1L).format(ISO_LOCAL_DATE), + lastUpdate = LocalDate.now(testConfig.clock()).minusMonths(6L).minusDays(1L).format(ISO_LOCAL_DATE), ), ) Json.toJson(extensionData).writeToFile(tempDir.resolve("6f0e12caa76e9514.json")) @@ -116,7 +90,11 @@ internal class DefaultSynopsisDownloadListCreatorTest { fun `don't return recent and valid entries`() { tempDirectory { // given - val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + override fun clock(): Clock = Clock.systemDefaultZone() + } + val synopsisDownloadListCreator = DefaultSynopsisDownloadListCreator(testConfig) val extensionData = ExtensionData( sources = listOf( URI("https://example4.com"), diff --git a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinderTest.kt b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinderTest.kt index 87015590a6..1afb6d7db6 100644 --- a/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinderTest.kt +++ b/tooling/app/src/test/kotlin/io/github/manamiproject/modb/extension/updates/DefaultUpdatableItemsFinderTest.kt @@ -1,6 +1,9 @@ package io.github.manamiproject.modb.extension.updates +import io.github.manamiproject.modb.core.extensions.Directory import io.github.manamiproject.modb.core.extensions.writeToFile +import io.github.manamiproject.modb.extension.TestConfig +import io.github.manamiproject.modb.extension.config.Config import io.github.manamiproject.modb.test.exceptionExpected import io.github.manamiproject.modb.test.tempDirectory import org.assertj.core.api.Assertions.assertThat @@ -11,39 +14,6 @@ import kotlin.io.path.createFile internal class DefaultUpdatableItemsFinderTest { - @Nested - inner class ConstructorTests { - - @Test - fun `throws exception if directory doesn't exist`() { - tempDirectory { - // when - val result = exceptionExpected { - DefaultUpdatableItemsFinder(tempDir.resolve("unknown")) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - - @Test - fun `throws exception if path is not a directory`() { - tempDirectory { - // given - val path = tempDir.resolve("text.txt").createFile() - - // when - val result = exceptionExpected { - DefaultUpdatableItemsFinder(path) - } - - // then - assertThat(result).hasMessage("Data directory either doesn't exist or is not a directory.") - } - } - } - @Nested inner class FindUpdateItems { @@ -51,7 +21,10 @@ internal class DefaultUpdatableItemsFinderTest { fun `correctly returns new db entries`() { tempDirectory { // given - val updateItemsFinder = DefaultUpdatableItemsFinder(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val updateItemsFinder = DefaultUpdatableItemsFinder(testConfig) val testDbContent = setOf( hashSetOf( URI("https://example1.org"), @@ -85,7 +58,10 @@ internal class DefaultUpdatableItemsFinderTest { } """.trimIndent().writeToFile(tempDir.resolve("5bab47db75e97361.json")) - val updateItemsFinder = DefaultUpdatableItemsFinder(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val updateItemsFinder = DefaultUpdatableItemsFinder(testConfig) val testDbContent = setOf( hashSetOf( URI("https://example1.org"), @@ -122,7 +98,10 @@ internal class DefaultUpdatableItemsFinderTest { } """.trimIndent().writeToFile(testFile) - val updateItemsFinder = DefaultUpdatableItemsFinder(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val updateItemsFinder = DefaultUpdatableItemsFinder(testConfig) val testDbContent = emptySet>() // when @@ -148,7 +127,10 @@ internal class DefaultUpdatableItemsFinderTest { } """.trimIndent().writeToFile(testFile) - val updateItemsFinder = DefaultUpdatableItemsFinder(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val updateItemsFinder = DefaultUpdatableItemsFinder(testConfig) val testDbContent = setOf( hashSetOf( URI("https://example1.org"), @@ -180,7 +162,10 @@ internal class DefaultUpdatableItemsFinderTest { } """.trimIndent().writeToFile(testFile) - val updateItemsFinder = DefaultUpdatableItemsFinder(tempDir) + val testConfig = object: Config by TestConfig { + override fun dataDirectory(): Directory = tempDir + } + val updateItemsFinder = DefaultUpdatableItemsFinder(testConfig) val testDbContent = setOf( hashSetOf( URI("https://example1.org"), diff --git a/tooling/lib/README.md b/tooling/lib/README.md index dd4ac76f32..2e117d76e5 100644 --- a/tooling/lib/README.md +++ b/tooling/lib/README.md @@ -57,11 +57,24 @@ suspend fun main() { println(""" ${deathNote.title} ${"-".repeat(deathNote.title.length)} - arithmetic mean: ${score.arithmeticMean} + arithmetic mean: ${score.arithmeticMean} arithmetic geometric mean: ${score.arithmeticGeometricMean} - median: ${score.median} + median: ${score.median} ${synopsis.text} """.trimIndent()) } +``` + +Output: + +``` +Death Note +---------- + + arithmetic mean: 8.655917642188147 +arithmetic geometric mean: 8.65518822146276 + median: 8.617492461145904 + +Light Yagami is a brilliant high school student ... ``` \ No newline at end of file