Version + more tests
This commit is contained in:
parent
6bc2ade681
commit
295349e78b
@ -39,7 +39,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
||||||
implementation("no.iktdev.library:subtitle:1.8.1-SNAPSHOT")
|
implementation("no.iktdev.library:subtitle:1.8.1-SNAPSHOT")
|
||||||
implementation("no.iktdev:eventi:1.0-rc15")
|
implementation("no.iktdev:eventi:1.0-rc17")
|
||||||
|
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
@ -53,6 +53,7 @@ dependencies {
|
|||||||
testImplementation("io.mockk:mockk:1.12.0")
|
testImplementation("io.mockk:mockk:1.12.0")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
testImplementation(project(":shared:common", configuration = "testArtifacts"))
|
testImplementation(project(":shared:common", configuration = "testArtifacts"))
|
||||||
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter
|
||||||
|
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface ConverterEnvironment {
|
||||||
|
fun canRead(file: File): Boolean
|
||||||
|
fun getReader(file: File): BaseReader?
|
||||||
|
fun createExporter(input: File, outputDir: File, name: String): Exporter
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter
|
||||||
|
|
||||||
|
import no.iktdev.library.subtitle.classes.Dialog
|
||||||
|
import no.iktdev.library.subtitle.export.Export
|
||||||
|
|
||||||
|
class ExportAdapter(
|
||||||
|
private val export: Export
|
||||||
|
) : Exporter {
|
||||||
|
|
||||||
|
override fun write(dialogs: List<Dialog>) = export.write(dialogs)
|
||||||
|
override fun writeSrt(dialogs: List<Dialog>) = export.writeSrt(dialogs)
|
||||||
|
override fun writeSmi(dialogs: List<Dialog>) = export.writeSmi(dialogs)
|
||||||
|
override fun writeVtt(dialogs: List<Dialog>) = export.writeVtt(dialogs)
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter
|
||||||
|
|
||||||
|
import no.iktdev.library.subtitle.classes.Dialog
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface Exporter {
|
||||||
|
fun write(dialogs: List<Dialog>): MutableList<File>
|
||||||
|
fun writeSrt(dialogs: List<Dialog>): File
|
||||||
|
fun writeSmi(dialogs: List<Dialog>): File
|
||||||
|
fun writeVtt(dialogs: List<Dialog>): File
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter.convert
|
||||||
|
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import no.iktdev.mediaprocessing.converter.ConverterEnvironment
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class Converter(val env: ConverterEnvironment, val listener: ConvertListener) {
|
||||||
|
var writtenUris: List<String>? = null
|
||||||
|
|
||||||
|
abstract fun getSubtitleReader(useFile: File): BaseReader?
|
||||||
|
abstract suspend fun convert(data: ConvertTask.Data)
|
||||||
|
|
||||||
|
class FileIsNullOrEmpty(override val message: String? = "File read is null or empty"): RuntimeException()
|
||||||
|
class FileUnavailableException(override val message: String): RuntimeException()
|
||||||
|
|
||||||
|
abstract fun getResult(): List<String>
|
||||||
|
}
|
||||||
@ -4,51 +4,43 @@ import no.iktdev.library.subtitle.Configuration
|
|||||||
import no.iktdev.library.subtitle.Syncro
|
import no.iktdev.library.subtitle.Syncro
|
||||||
import no.iktdev.library.subtitle.classes.Dialog
|
import no.iktdev.library.subtitle.classes.Dialog
|
||||||
import no.iktdev.library.subtitle.classes.DialogType
|
import no.iktdev.library.subtitle.classes.DialogType
|
||||||
import no.iktdev.library.subtitle.export.Export
|
|
||||||
import no.iktdev.library.subtitle.reader.BaseReader
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
import no.iktdev.library.subtitle.reader.Reader
|
|
||||||
import no.iktdev.mediaprocessing.converter.ConverterEnv
|
import no.iktdev.mediaprocessing.converter.ConverterEnv
|
||||||
|
import no.iktdev.mediaprocessing.converter.ConverterEnvironment
|
||||||
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
import no.iktdev.mediaprocessing.shared.common.model.SubtitleFormat
|
import no.iktdev.mediaprocessing.shared.common.model.SubtitleFormat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Converter2(val data: ConvertTask.Data,
|
class Converter2(
|
||||||
private val listener: ConvertListener) {
|
env: ConverterEnvironment,
|
||||||
|
listener: ConvertListener
|
||||||
|
): Converter(env = env, listener = listener) {
|
||||||
|
|
||||||
@Throws(FileUnavailableException::class)
|
@Throws(FileUnavailableException::class)
|
||||||
private fun getReader(): BaseReader? {
|
override fun getSubtitleReader(useFile: File): BaseReader? {
|
||||||
val file = File(data.inputFile)
|
if (!env.canRead(useFile)) {
|
||||||
if (!file.canRead())
|
|
||||||
throw FileUnavailableException("Can't open file for reading..")
|
throw FileUnavailableException("Can't open file for reading..")
|
||||||
return Reader(file).getSubtitleReader()
|
}
|
||||||
|
return env.getReader(useFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncDialogs(input: List<Dialog>): List<Dialog> {
|
private fun syncDialogs(input: List<Dialog>): List<Dialog> {
|
||||||
return if (ConverterEnv.syncDialogs) Syncro().sync(input) else input
|
return if (ConverterEnv.syncDialogs) Syncro().sync(input) else input
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canRead(): Boolean {
|
|
||||||
try {
|
|
||||||
val reader = getReader()
|
|
||||||
return reader != null
|
|
||||||
} catch (e: FileUnavailableException) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(FileUnavailableException::class, FileIsNullOrEmpty::class)
|
@Throws(FileUnavailableException::class, FileIsNullOrEmpty::class)
|
||||||
fun execute() {
|
override suspend fun convert(data: ConvertTask.Data) {
|
||||||
val file = File(data.inputFile)
|
val file = File(data.inputFile)
|
||||||
listener.onStarted(file.absolutePath)
|
listener.onStarted(file.absolutePath)
|
||||||
try {
|
try {
|
||||||
Configuration.exportJson = true
|
Configuration.exportJson = true
|
||||||
val read = getReader()?.read() ?: throw FileIsNullOrEmpty()
|
val read = getSubtitleReader(file)?.read() ?: throw FileIsNullOrEmpty()
|
||||||
if (read.isEmpty())
|
if (read.isEmpty())
|
||||||
throw FileIsNullOrEmpty()
|
throw FileIsNullOrEmpty()
|
||||||
val filtered = read.filter { !it.ignore && it.type !in listOf(DialogType.SIGN_SONG, DialogType.CAPTION) }
|
val filtered = read.filter { !it.ignore && it.type !in listOf(DialogType.SIGN_SONG, DialogType.CAPTION) }
|
||||||
val syncOrNotSync = syncDialogs(filtered)
|
val syncOrNotSync = syncDialogs(filtered)
|
||||||
|
|
||||||
val exporter = Export(file, File(data.outputDirectory), data.outputFileName)
|
val exporter = env.createExporter(file, File(data.outputDirectory), data.outputFileName)
|
||||||
|
|
||||||
val outFiles = if (data.formats.isEmpty()) {
|
val outFiles = if (data.formats.isEmpty()) {
|
||||||
exporter.write(syncOrNotSync)
|
exporter.write(syncOrNotSync)
|
||||||
@ -65,22 +57,17 @@ class Converter2(val data: ConvertTask.Data,
|
|||||||
}
|
}
|
||||||
exported
|
exported
|
||||||
}
|
}
|
||||||
result = outFiles.map { it.absolutePath }
|
writtenUris = outFiles.map { it.absolutePath }
|
||||||
listener.onCompleted(file.absolutePath, result!!)
|
listener.onCompleted(file.absolutePath, writtenUris!!)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
listener.onError(file.absolutePath, e.message ?: e.localizedMessage)
|
listener.onError(file.absolutePath, e.message ?: e.localizedMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var result: List<String>? = null
|
override fun getResult(): List<String> {
|
||||||
fun getResult(): List<String> {
|
if (writtenUris == null) {
|
||||||
if (result == null) {
|
|
||||||
throw IllegalStateException("Execute must be called before getting result")
|
throw IllegalStateException("Execute must be called before getting result")
|
||||||
}
|
}
|
||||||
return result!!
|
return writtenUris!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FileIsNullOrEmpty(override val message: String? = "File read is null or empty"): RuntimeException()
|
|
||||||
class FileUnavailableException(override val message: String): RuntimeException()
|
|
||||||
}
|
}
|
||||||
@ -1,19 +1,29 @@
|
|||||||
package no.iktdev.mediaprocessing.converter.listeners
|
package no.iktdev.mediaprocessing.converter.listeners
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import no.iktdev.eventi.models.Event
|
import no.iktdev.eventi.models.Event
|
||||||
import no.iktdev.eventi.models.Task
|
import no.iktdev.eventi.models.Task
|
||||||
import no.iktdev.eventi.models.store.TaskStatus
|
import no.iktdev.eventi.models.store.TaskStatus
|
||||||
import no.iktdev.eventi.tasks.TaskListener
|
import no.iktdev.eventi.tasks.TaskListener
|
||||||
import no.iktdev.eventi.tasks.TaskType
|
import no.iktdev.eventi.tasks.TaskType
|
||||||
|
import no.iktdev.library.subtitle.export.Export
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import no.iktdev.library.subtitle.reader.Reader
|
||||||
|
import no.iktdev.mediaprocessing.converter.ConverterEnvironment
|
||||||
|
import no.iktdev.mediaprocessing.converter.ExportAdapter
|
||||||
|
import no.iktdev.mediaprocessing.converter.Exporter
|
||||||
import no.iktdev.mediaprocessing.converter.convert.ConvertListener
|
import no.iktdev.mediaprocessing.converter.convert.ConvertListener
|
||||||
|
import no.iktdev.mediaprocessing.converter.convert.Converter
|
||||||
import no.iktdev.mediaprocessing.converter.convert.Converter2
|
import no.iktdev.mediaprocessing.converter.convert.Converter2
|
||||||
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ConvertTaskResultEvent
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ConvertTaskResultEvent
|
||||||
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class ConvertTaskListener: TaskListener(TaskType.CPU_INTENSIVE) {
|
open class ConvertTaskListener(): TaskListener(TaskType.CPU_INTENSIVE) {
|
||||||
|
|
||||||
override fun getWorkerId(): String {
|
override fun getWorkerId(): String {
|
||||||
return "${this::class.java.simpleName}-${TaskType.CPU_INTENSIVE}-${UUID.randomUUID()}"
|
return "${this::class.java.simpleName}-${TaskType.CPU_INTENSIVE}-${UUID.randomUUID()}"
|
||||||
@ -27,18 +37,15 @@ class ConvertTaskListener: TaskListener(TaskType.CPU_INTENSIVE) {
|
|||||||
if (task !is ConvertTask) {
|
if (task !is ConvertTask) {
|
||||||
throw IllegalArgumentException("Invalid task type: ${task::class.java.name}")
|
throw IllegalArgumentException("Invalid task type: ${task::class.java.name}")
|
||||||
}
|
}
|
||||||
val converter = Converter2(task.data, object: ConvertListener {
|
val converter = getConverter()
|
||||||
override fun onStarted(inputFile: String) {
|
|
||||||
}
|
|
||||||
override fun onCompleted(inputFile: String, outputFiles: List<String>) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
withHeartbeatRunner {
|
withHeartbeatRunner {
|
||||||
reporter?.updateLastSeen(task.taskId)
|
reporter?.updateLastSeen(task.taskId)
|
||||||
}
|
}
|
||||||
|
|
||||||
converter.execute()
|
withContext(Dispatchers.Unconfined) {
|
||||||
|
converter.convert(task.data)
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val result = converter.getResult()
|
val result = converter.getResult()
|
||||||
@ -59,9 +66,38 @@ class ConvertTaskListener: TaskListener(TaskType.CPU_INTENSIVE) {
|
|||||||
).producedFrom(task)
|
).producedFrom(task)
|
||||||
newEvent
|
newEvent
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getConverter(): Converter {
|
||||||
|
return Converter2(getConverterEnvironment(), getListener())
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getListener(): ConvertListener {
|
||||||
|
return DefaultConvertListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultConvertListener: ConvertListener {
|
||||||
|
override fun onStarted(inputFile: String) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCompleted(inputFile: String, outputFiles: List<String>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getConverterEnvironment(): ConverterEnvironment {
|
||||||
|
return DefaultConverterEnvironment()
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultConverterEnvironment : ConverterEnvironment {
|
||||||
|
override fun canRead(file: File) = file.canRead()
|
||||||
|
|
||||||
|
override fun getReader(file: File): BaseReader? =
|
||||||
|
Reader(file).getSubtitleReader()
|
||||||
|
|
||||||
|
override fun createExporter(input: File, outputDir: File, name: String): Exporter {
|
||||||
|
return ExportAdapter(Export(input, outputDir, name))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter
|
||||||
|
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import no.iktdev.eventi.models.store.TaskStatus
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import no.iktdev.mediaprocessing.converter.convert.ConvertListener
|
||||||
|
import no.iktdev.mediaprocessing.converter.convert.Converter
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class MockConverter(
|
||||||
|
val delayMillis: Long = 0,
|
||||||
|
private val simulatedResult: List<String>? = null,
|
||||||
|
private val taskResultStatus: TaskStatus = TaskStatus.Completed,
|
||||||
|
private val throwException: Boolean = false,
|
||||||
|
val mockEnv: ConverterEnvironment = MockConverterEnvironment(),
|
||||||
|
listener: ConvertListener
|
||||||
|
) : Converter(env = mockEnv, listener = listener) {
|
||||||
|
|
||||||
|
override fun getSubtitleReader(useFile: File): BaseReader? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun convert(data: ConvertTask.Data) {
|
||||||
|
if (delayMillis > 0) delay(delayMillis)
|
||||||
|
if (throwException) throw RuntimeException("Simulated convert failure")
|
||||||
|
|
||||||
|
if (taskResultStatus == TaskStatus.Failed) {
|
||||||
|
listener.onError(data.inputFile, "Failed state desired")
|
||||||
|
} else {
|
||||||
|
listener.onCompleted(data.inputFile, simulatedResult!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResult(): List<String> {
|
||||||
|
return simulatedResult!!
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter
|
||||||
|
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class MockConverterEnvironment(
|
||||||
|
var canReadValue: Boolean = true,
|
||||||
|
var reader: BaseReader? = null,
|
||||||
|
var exporter: Exporter? = null
|
||||||
|
) : ConverterEnvironment {
|
||||||
|
|
||||||
|
override fun canRead(file: File): Boolean = canReadValue
|
||||||
|
|
||||||
|
override fun getReader(file: File): BaseReader? = reader
|
||||||
|
|
||||||
|
override fun createExporter(input: File, outputDir: File, name: String): Exporter {
|
||||||
|
return exporter ?: error("FakeEnv.exporter must be set before calling createExporter")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,249 @@
|
|||||||
|
package no.iktdev.mediaprocessing.converter.convert
|
||||||
|
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import no.iktdev.library.subtitle.classes.Dialog
|
||||||
|
import no.iktdev.library.subtitle.classes.DialogType
|
||||||
|
import no.iktdev.library.subtitle.classes.Time
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import no.iktdev.mediaprocessing.converter.ConverterEnvironment
|
||||||
|
import no.iktdev.mediaprocessing.converter.Exporter
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.model.SubtitleFormat
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class Converter2Test {
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Fake implementations
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FakeReader(
|
||||||
|
private val dialogs: List<Dialog>,
|
||||||
|
private val shouldThrow: Boolean = false
|
||||||
|
) : BaseReader() {
|
||||||
|
override fun read(): List<Dialog> {
|
||||||
|
if (shouldThrow) throw RuntimeException("reader failed")
|
||||||
|
return dialogs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeExporter(
|
||||||
|
private val srtFile: File? = null,
|
||||||
|
private val smiFile: File? = null,
|
||||||
|
private val vttFile: File? = null,
|
||||||
|
private val filesForWrite: List<File> = emptyList(),
|
||||||
|
private val shouldThrow: Boolean = false
|
||||||
|
) : Exporter {
|
||||||
|
|
||||||
|
override fun write(dialogs: List<Dialog>): MutableList<File> {
|
||||||
|
if (shouldThrow) throw RuntimeException("export failed")
|
||||||
|
return filesForWrite.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeSrt(dialogs: List<Dialog>): File =
|
||||||
|
srtFile ?: error("srtFile not set in FakeExporter")
|
||||||
|
|
||||||
|
override fun writeSmi(dialogs: List<Dialog>): File =
|
||||||
|
smiFile ?: error("smiFile not set in FakeExporter")
|
||||||
|
|
||||||
|
override fun writeVtt(dialogs: List<Dialog>): File =
|
||||||
|
vttFile ?: error("vttFile not set in FakeExporter")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FakeListener : ConvertListener {
|
||||||
|
var started = 0
|
||||||
|
var completed = 0
|
||||||
|
var errors = 0
|
||||||
|
var lastError: String? = null
|
||||||
|
|
||||||
|
override fun onStarted(inputFile: String) {
|
||||||
|
started++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCompleted(inputFile: String, outputFiles: List<String>) {
|
||||||
|
completed++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(inputFile: String, message: String) {
|
||||||
|
errors++
|
||||||
|
lastError = message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeEnv(
|
||||||
|
var canReadValue: Boolean = true,
|
||||||
|
var reader: BaseReader? = null,
|
||||||
|
var exporter: Exporter? = null
|
||||||
|
) : ConverterEnvironment {
|
||||||
|
|
||||||
|
override fun canRead(file: File): Boolean = canReadValue
|
||||||
|
|
||||||
|
override fun getReader(file: File): BaseReader? = reader
|
||||||
|
|
||||||
|
override fun createExporter(input: File, outputDir: File, name: String): Exporter {
|
||||||
|
return exporter ?: error("FakeEnv.exporter must be set before calling createExporter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private fun makeTaskData(
|
||||||
|
input: String = "input.srt",
|
||||||
|
language: String = "no",
|
||||||
|
outDir: String = "out",
|
||||||
|
outName: String = "name",
|
||||||
|
formats: List<SubtitleFormat> = emptyList(),
|
||||||
|
allowOverwrite: Boolean = true
|
||||||
|
) = ConvertTask.Data(
|
||||||
|
inputFile = input,
|
||||||
|
language = language,
|
||||||
|
outputDirectory = outDir,
|
||||||
|
outputFileName = outName,
|
||||||
|
formats = formats,
|
||||||
|
allowOverwrite = allowOverwrite
|
||||||
|
)
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Tests
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når execute() kjøres
|
||||||
|
Hvis reader returnerer tom liste
|
||||||
|
Så kalles onError
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun execute_emptyFile() = runTest {
|
||||||
|
val env = FakeEnv(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(emptyList())
|
||||||
|
)
|
||||||
|
val listener = FakeListener()
|
||||||
|
|
||||||
|
val converter = Converter2(
|
||||||
|
env = env,
|
||||||
|
listener = listener
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.convert(makeTaskData())
|
||||||
|
|
||||||
|
assertEquals(1, listener.errors)
|
||||||
|
assertEquals(0, listener.completed)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når execute() kjøres
|
||||||
|
Hvis reader returnerer dialoger
|
||||||
|
Og exporter.write lykkes
|
||||||
|
Så kalles onCompleted
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun execute_success() = runTest {
|
||||||
|
val dialogs = listOf(
|
||||||
|
Dialog("0", Time(0, 0, 0, 0), Time(0, 0, 1000, 0), "Hello", DialogType.DIALOG_NORMAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
val env = FakeEnv(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(dialogs),
|
||||||
|
exporter = FakeExporter(srtFile = File("/fake/out.srt"))
|
||||||
|
)
|
||||||
|
|
||||||
|
val listener = FakeListener()
|
||||||
|
|
||||||
|
val converter = Converter2(
|
||||||
|
env = env,
|
||||||
|
listener = listener
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.convert(
|
||||||
|
makeTaskData(
|
||||||
|
formats = listOf(SubtitleFormat.SRT)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(1, listener.completed)
|
||||||
|
assertEquals(listOf("/fake/out.srt"), converter.getResult())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når execute() kjøres
|
||||||
|
Hvis exporter.write kaster exception
|
||||||
|
Så kalles onError
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun execute_exportFails() = runTest {
|
||||||
|
val dialogs = listOf(
|
||||||
|
Dialog("0", Time(0, 0, 0, 0), Time(0, 0, 1000, 0), "Hello", DialogType.DIALOG_NORMAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
val env = FakeEnv(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(dialogs),
|
||||||
|
exporter = FakeExporter(srtFile = File("/fake/out.srt"), shouldThrow = true)
|
||||||
|
)
|
||||||
|
|
||||||
|
val listener = FakeListener()
|
||||||
|
|
||||||
|
val converter = Converter2(
|
||||||
|
env = env,
|
||||||
|
listener = listener
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.convert(makeTaskData())
|
||||||
|
|
||||||
|
assertEquals(1, listener.errors)
|
||||||
|
assertEquals(0, listener.completed)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når execute() kjøres
|
||||||
|
Hvis formats inneholder SRT og VTT
|
||||||
|
Så brukes writeSrt og writeVtt
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun execute_multipleFormats() = runTest {
|
||||||
|
val dialogs = listOf(
|
||||||
|
Dialog("0", Time(0, 0, 0, 0), Time(0, 0, 1000, 0), "Hello", DialogType.DIALOG_NORMAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val env = FakeEnv(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(dialogs),
|
||||||
|
exporter = FakeExporter(srtFile = File("/fake/out.srt"), vttFile = File("/fake/out.vtt"))
|
||||||
|
)
|
||||||
|
|
||||||
|
val listener = FakeListener()
|
||||||
|
|
||||||
|
val converter = Converter2(
|
||||||
|
env = env,
|
||||||
|
listener = listener
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.convert(
|
||||||
|
makeTaskData(
|
||||||
|
formats = listOf(SubtitleFormat.SRT, SubtitleFormat.VTT)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(1, listener.completed)
|
||||||
|
assertEquals(listOf("/fake/out.srt", "/fake/out.vtt"), converter.getResult())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,7 +1,245 @@
|
|||||||
package no.iktdev.mediaprocessing.converter.listeners
|
package no.iktdev.mediaprocessing.converter.listeners
|
||||||
|
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import no.iktdev.eventi.models.Event
|
||||||
|
import no.iktdev.eventi.models.Task
|
||||||
|
import no.iktdev.eventi.models.store.TaskStatus
|
||||||
|
import no.iktdev.eventi.tasks.TaskReporter
|
||||||
|
import no.iktdev.library.subtitle.classes.Dialog
|
||||||
|
import no.iktdev.library.subtitle.classes.DialogType
|
||||||
|
import no.iktdev.library.subtitle.classes.Time
|
||||||
|
import no.iktdev.library.subtitle.reader.BaseReader
|
||||||
|
import no.iktdev.mediaprocessing.converter.ConverterEnvironment
|
||||||
|
import no.iktdev.mediaprocessing.converter.Exporter
|
||||||
|
import no.iktdev.mediaprocessing.converter.MockConverter
|
||||||
|
import no.iktdev.mediaprocessing.converter.MockConverterEnvironment
|
||||||
|
import no.iktdev.mediaprocessing.converter.convert.ConvertListener
|
||||||
|
import no.iktdev.mediaprocessing.converter.convert.Converter
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ConvertTaskResultEvent
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ConvertTask
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.model.SubtitleFormat
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
class ConvertTaskListenerTest {
|
class ConvertTaskListenerTest {
|
||||||
|
|
||||||
|
class ConvertTaskListenerTestImplementation : ConvertTaskListener() {
|
||||||
|
fun getJob() = currentJob
|
||||||
|
|
||||||
|
|
||||||
}
|
var overrideEnv: ConverterEnvironment = DefaultConverterEnvironment()
|
||||||
|
override fun getConverterEnvironment(): ConverterEnvironment {
|
||||||
|
return overrideEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
var overrideListener: ConvertListener? = null
|
||||||
|
override fun getListener(): ConvertListener {
|
||||||
|
if (overrideListener != null)
|
||||||
|
return overrideListener!!
|
||||||
|
else
|
||||||
|
return super.getListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
var overrideConverter: Converter? = null
|
||||||
|
override fun getConverter(): Converter {
|
||||||
|
return if (overrideConverter != null)
|
||||||
|
overrideConverter!!
|
||||||
|
else
|
||||||
|
super.getConverter()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val listener = ConvertTaskListenerTestImplementation()
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Fake environment + fake converter
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FakeListener : ConvertListener {
|
||||||
|
var started = 0
|
||||||
|
var completed = 0
|
||||||
|
var errors = 0
|
||||||
|
|
||||||
|
override fun onStarted(inputFile: String) {
|
||||||
|
started++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCompleted(inputFile: String, outputFiles: List<String>) {
|
||||||
|
completed++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(inputFile: String, message: String) {
|
||||||
|
errors++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeExporter(
|
||||||
|
private val files: List<File>,
|
||||||
|
private val shouldThrow: Boolean = false
|
||||||
|
) : Exporter {
|
||||||
|
|
||||||
|
override fun write(dialogs: List<Dialog>): MutableList<File> {
|
||||||
|
if (shouldThrow) throw RuntimeException("export failed")
|
||||||
|
return files.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeSrt(dialogs: List<Dialog>) = files[0]
|
||||||
|
override fun writeSmi(dialogs: List<Dialog>) = files[0]
|
||||||
|
override fun writeVtt(dialogs: List<Dialog>) = files[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeReader(
|
||||||
|
private val dialogs: List<Dialog>,
|
||||||
|
private val shouldThrow: Boolean = false
|
||||||
|
) : BaseReader() {
|
||||||
|
override fun read(): List<Dialog> {
|
||||||
|
if (shouldThrow) throw RuntimeException("reader failed")
|
||||||
|
return dialogs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val overrideReporter = object : TaskReporter {
|
||||||
|
override fun markClaimed(taskId: UUID, workerId: String) {}
|
||||||
|
override fun updateLastSeen(taskId: UUID) {}
|
||||||
|
override fun markConsumed(taskId: UUID) {}
|
||||||
|
override fun updateProgress(taskId: UUID, progress: Int) {}
|
||||||
|
override fun log(taskId: UUID, message: String) {}
|
||||||
|
override fun publishEvent(event: Event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
private fun makeTask(
|
||||||
|
formats: List<SubtitleFormat> = emptyList()
|
||||||
|
): ConvertTask {
|
||||||
|
return ConvertTask(
|
||||||
|
ConvertTask.Data(
|
||||||
|
inputFile = "input.srt",
|
||||||
|
language = "no",
|
||||||
|
outputDirectory = "out",
|
||||||
|
outputFileName = "name",
|
||||||
|
formats = formats,
|
||||||
|
allowOverwrite = true
|
||||||
|
)
|
||||||
|
).apply { newReferenceId() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Tests
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("""
|
||||||
|
Når onTask kjøres og converterer
|
||||||
|
Hvis den bruker lengre tid
|
||||||
|
Så:
|
||||||
|
Skal koden vente til den er ferdig
|
||||||
|
""")
|
||||||
|
fun onTask_validate_delay() = runTest {
|
||||||
|
val delay = 1000L
|
||||||
|
val converter = MockConverter(
|
||||||
|
delay,
|
||||||
|
listOf("file:///potato.srt"),
|
||||||
|
listener = FakeListener()
|
||||||
|
)
|
||||||
|
listener.apply {
|
||||||
|
overrideConverter = converter
|
||||||
|
}
|
||||||
|
val task = makeTask()
|
||||||
|
val event = listener.onTask(task)
|
||||||
|
|
||||||
|
val time = measureTimeMillis {
|
||||||
|
val accepted = listener.accept(task, overrideReporter)
|
||||||
|
assertTrue(accepted, "Task listener did not accept the task.")
|
||||||
|
listener.getJob()?.join()
|
||||||
|
assertTrue(event is ConvertTaskResultEvent)
|
||||||
|
assertEquals(TaskStatus.Completed, (event as ConvertTaskResultEvent).status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når onTask kjøres
|
||||||
|
Hvis converter lykkes
|
||||||
|
Så returneres Completed-event
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun onTask_success() = runTest {
|
||||||
|
val dialogs = listOf(
|
||||||
|
Dialog("0", Time(0, 0, 0, 0), Time(0, 0, 1000, 0), "Hello", DialogType.DIALOG_NORMAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
val env = MockConverterEnvironment(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(dialogs),
|
||||||
|
exporter = FakeExporter(listOf(File("/fake/out.srt")))
|
||||||
|
)
|
||||||
|
|
||||||
|
listener.apply {
|
||||||
|
overrideListener = FakeListener()
|
||||||
|
overrideEnv = env
|
||||||
|
}
|
||||||
|
|
||||||
|
val task = makeTask()
|
||||||
|
|
||||||
|
val event = listener.onTask(task) as ConvertTaskResultEvent
|
||||||
|
|
||||||
|
assertEquals(TaskStatus.Completed, event.status)
|
||||||
|
assertEquals(listOf("/fake/out.srt"), event.data!!.outputFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når onTask kjøres
|
||||||
|
Hvis converter feiler
|
||||||
|
Så returneres Failed-event
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun onTask_failure() = runTest {
|
||||||
|
val env = MockConverterEnvironment(
|
||||||
|
canReadValue = true,
|
||||||
|
reader = FakeReader(emptyList()) // triggers FileIsNullOrEmpty
|
||||||
|
)
|
||||||
|
|
||||||
|
listener.apply {
|
||||||
|
overrideListener = FakeListener()
|
||||||
|
overrideEnv = env
|
||||||
|
}
|
||||||
|
|
||||||
|
val task = makeTask()
|
||||||
|
|
||||||
|
val event = listener.onTask(task) as ConvertTaskResultEvent
|
||||||
|
|
||||||
|
assertEquals(TaskStatus.Failed, event.status)
|
||||||
|
assertNull(event.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når supports() kalles
|
||||||
|
Så returnerer den true for ConvertTask og false for andre typer
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun supports_test() {
|
||||||
|
val listener = ConvertTaskListener()
|
||||||
|
|
||||||
|
assertTrue(listener.supports(makeTask()))
|
||||||
|
assertFalse(listener.supports(DummyTask()))
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyTask : Task()
|
||||||
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
||||||
implementation("no.iktdev.streamit.library:streamit-library-db:1.0.0-alpha14")
|
implementation("no.iktdev.streamit.library:streamit-library-db:1.0.0-alpha14")
|
||||||
implementation("no.iktdev:eventi:1.0-rc16")
|
implementation("no.iktdev:eventi:1.0-rc17")
|
||||||
|
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import no.iktdev.mediaprocessing.coordinator.util.FileSystemService
|
|||||||
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MigrateContentToStoreTaskResultEvent
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MigrateContentToStoreTaskResultEvent
|
||||||
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.MigrateToContentStoreTask
|
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.MigrateToContentStoreTask
|
||||||
import no.iktdev.mediaprocessing.shared.common.model.MigrateStatus
|
import no.iktdev.mediaprocessing.shared.common.model.MigrateStatus
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.silentTry
|
||||||
import org.jetbrains.annotations.VisibleForTesting
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -40,13 +41,13 @@ class MigrateContentToStoreTaskListener: TaskListener(TaskType.IO_INTENSIVE) {
|
|||||||
coverStatus.none { it.status == MigrateStatus.Failed })
|
coverStatus.none { it.status == MigrateStatus.Failed })
|
||||||
{
|
{
|
||||||
pickedTask.data.videoContent?.cachedUri?.let { File(it) }?.let {
|
pickedTask.data.videoContent?.cachedUri?.let { File(it) }?.let {
|
||||||
fs.delete(it)
|
silentTry { fs.delete(it) }
|
||||||
}
|
}
|
||||||
pickedTask.data.subtitleContent?.map { File(it.cachedUri) }?.forEach {
|
pickedTask.data.subtitleContent?.map { File(it.cachedUri) }?.forEach {
|
||||||
fs.delete(it)
|
silentTry { fs.delete(it) }
|
||||||
}
|
}
|
||||||
pickedTask.data.coverContent?.map { File(it.cachedUri) }?.forEach {
|
pickedTask.data.coverContent?.map { File(it.cachedUri) }?.forEach {
|
||||||
fs.delete(it)
|
silentTry { fs.delete(it) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = TaskStatus.Failed
|
status = TaskStatus.Failed
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import java.io.File
|
|||||||
|
|
||||||
class MockFileSystemService : FileSystemService {
|
class MockFileSystemService : FileSystemService {
|
||||||
var copyShouldFail = false
|
var copyShouldFail = false
|
||||||
|
var deleteShouldFail = false
|
||||||
|
|
||||||
var identical = true
|
var identical = true
|
||||||
val copied = mutableListOf<Pair<File, File>>()
|
val copied = mutableListOf<Pair<File, File>>()
|
||||||
val deleted = mutableListOf<File>()
|
val deleted = mutableListOf<File>()
|
||||||
@ -19,6 +21,7 @@ class MockFileSystemService : FileSystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun delete(file: File) {
|
override fun delete(file: File) {
|
||||||
|
if (deleteShouldFail) throw RuntimeException("delete failed")
|
||||||
deleted += file
|
deleted += file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,6 +102,25 @@ class MigrateContentToStoreTaskListenerTest {
|
|||||||
assertEquals(MigrateStatus.Failed, result.status)
|
assertEquals(MigrateStatus.Failed, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når migrateVideo kjøres
|
||||||
|
Hvis content er null
|
||||||
|
Så:
|
||||||
|
returneres NotPresent
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun migrateVideo_null() {
|
||||||
|
val fs = MockFileSystemService().also {
|
||||||
|
listener.fs = it
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = listener.migrateVideo(fs, null)
|
||||||
|
|
||||||
|
assertEquals(MigrateStatus.NotPresent, result.status)
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// migrateSubtitle
|
// migrateSubtitle
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@ -151,6 +170,36 @@ class MigrateContentToStoreTaskListenerTest {
|
|||||||
assertEquals(MigrateStatus.Completed, result.first().status)
|
assertEquals(MigrateStatus.Completed, result.first().status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når migrateSubtitle kjøres
|
||||||
|
Hvis én lykkes og én feiler
|
||||||
|
Så:
|
||||||
|
returneres både Completed og Failed
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun migrateSubtitle_mixed() {
|
||||||
|
val fs = MockFileSystemService().apply {
|
||||||
|
// first OK, second fails
|
||||||
|
copyShouldFail = false
|
||||||
|
}.also { listener.fs = it }
|
||||||
|
|
||||||
|
val subs = listOf(
|
||||||
|
MigrateToContentStoreTask.Data.SingleSubtitle("en", "/tmp/a", "/tmp/b"),
|
||||||
|
MigrateToContentStoreTask.Data.SingleSubtitle("no", "/tmp/c", "/tmp/d")
|
||||||
|
)
|
||||||
|
|
||||||
|
// simulate second failing
|
||||||
|
fs.copyShouldFail = false
|
||||||
|
val result1 = listener.migrateSubtitle(fs, listOf(subs[0]))
|
||||||
|
fs.copyShouldFail = true
|
||||||
|
val result2 = listener.migrateSubtitle(fs, listOf(subs[1]))
|
||||||
|
|
||||||
|
assertEquals(MigrateStatus.Completed, result1.first().status)
|
||||||
|
assertEquals(MigrateStatus.Failed, result2.first().status)
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// migrateCover
|
// migrateCover
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@ -179,6 +228,34 @@ class MigrateContentToStoreTaskListenerTest {
|
|||||||
assertEquals(MigrateStatus.Completed, result.first().status)
|
assertEquals(MigrateStatus.Completed, result.first().status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når migrateCover kjøres
|
||||||
|
Hvis flere covers og én feiler
|
||||||
|
Så:
|
||||||
|
returneres både Completed og Failed
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun migrateCover_mixed() {
|
||||||
|
val fs = MockFileSystemService().also { listener.fs = it }
|
||||||
|
|
||||||
|
val covers = listOf(
|
||||||
|
MigrateToContentStoreTask.Data.SingleContent("/tmp/a", "/tmp/b"),
|
||||||
|
MigrateToContentStoreTask.Data.SingleContent("/tmp/c", "/tmp/d")
|
||||||
|
)
|
||||||
|
|
||||||
|
// first OK, second mismatch
|
||||||
|
fs.identical = true
|
||||||
|
val ok = listener.migrateCover(fs, listOf(covers[0]))
|
||||||
|
|
||||||
|
fs.identical = false
|
||||||
|
val fail = listener.migrateCover(fs, listOf(covers[1]))
|
||||||
|
|
||||||
|
assertEquals(MigrateStatus.Completed, ok.first().status)
|
||||||
|
assertEquals(MigrateStatus.Failed, fail.first().status)
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// onTask
|
// onTask
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@ -244,4 +321,61 @@ class MigrateContentToStoreTaskListenerTest {
|
|||||||
assertEquals(TaskStatus.Failed, event.status)
|
assertEquals(TaskStatus.Failed, event.status)
|
||||||
assertEquals(0, fs.deleted.size)
|
assertEquals(0, fs.deleted.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når onTask kjøres
|
||||||
|
Hvis video feiler
|
||||||
|
Så:
|
||||||
|
returneres Failed og ingenting slettes
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun onTask_videoFails() = runTest {
|
||||||
|
val fs = MockFileSystemService().apply { copyShouldFail = true }
|
||||||
|
.also { listener.fs = it }
|
||||||
|
|
||||||
|
val task = MigrateToContentStoreTask(
|
||||||
|
MigrateToContentStoreTask.Data(
|
||||||
|
collection = "col",
|
||||||
|
videoContent = MigrateToContentStoreTask.Data.SingleContent("/tmp/v", "/tmp/v2"),
|
||||||
|
subtitleContent = emptyList(),
|
||||||
|
coverContent = emptyList()
|
||||||
|
)
|
||||||
|
).newReferenceId()
|
||||||
|
|
||||||
|
val event = listener.onTask(task) as MigrateContentToStoreTaskResultEvent
|
||||||
|
|
||||||
|
assertEquals(TaskStatus.Failed, event.status)
|
||||||
|
assertEquals(0, fs.deleted.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"""
|
||||||
|
Når onTask kjøres
|
||||||
|
Hvis sletting feiler
|
||||||
|
Så:
|
||||||
|
returneres fortsatt Completed
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun onTask_deleteFails() = runTest {
|
||||||
|
val fs = MockFileSystemService().apply { deleteShouldFail = true }
|
||||||
|
.also { listener.fs = it }
|
||||||
|
|
||||||
|
|
||||||
|
val task = MigrateToContentStoreTask(
|
||||||
|
MigrateToContentStoreTask.Data(
|
||||||
|
collection = "col",
|
||||||
|
videoContent = MigrateToContentStoreTask.Data.SingleContent("/tmp/v", "/tmp/v2"),
|
||||||
|
subtitleContent = emptyList(),
|
||||||
|
coverContent = emptyList()
|
||||||
|
)
|
||||||
|
).newReferenceId()
|
||||||
|
|
||||||
|
val event = listener.onTask(task) as MigrateContentToStoreTaskResultEvent
|
||||||
|
|
||||||
|
assertEquals(TaskStatus.Completed, event.status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dependencies {
|
|||||||
implementation("org.json:json:20210307")
|
implementation("org.json:json:20210307")
|
||||||
|
|
||||||
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
implementation("no.iktdev:exfl:0.0.16-SNAPSHOT")
|
||||||
implementation("no.iktdev:eventi:1.0-rc15")
|
implementation("no.iktdev:eventi:1.0-rc17")
|
||||||
|
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
|
|||||||
@ -61,7 +61,7 @@ dependencies {
|
|||||||
implementation("com.zaxxer:HikariCP:7.0.2")
|
implementation("com.zaxxer:HikariCP:7.0.2")
|
||||||
|
|
||||||
implementation(project(":shared:ffmpeg"))
|
implementation(project(":shared:ffmpeg"))
|
||||||
implementation("no.iktdev:eventi:1.0-rc16")
|
implementation("no.iktdev:eventi:1.0-rc17")
|
||||||
|
|
||||||
testImplementation(kotlin("test"))
|
testImplementation(kotlin("test"))
|
||||||
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user