This commit is contained in:
Brage Skjønborg 2026-02-01 20:06:45 +01:00
parent e69f8b7ff8
commit 2c7af614d6
18 changed files with 239 additions and 73 deletions

View File

@ -31,6 +31,7 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("org.springframework.boot:spring-boot-starter-websocket")
implementation("org.springframework:spring-tx") implementation("org.springframework:spring-tx")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("io.github.microutils:kotlin-logging-jvm:2.0.11") implementation("io.github.microutils:kotlin-logging-jvm:2.0.11")

View File

@ -49,8 +49,7 @@ open class TestBase {
operation = setOf(OperationType.Encode, OperationType.ExtractSubtitles, OperationType.ConvertSubtitles, OperationType.Metadata), operation = setOf(OperationType.Encode, OperationType.ExtractSubtitles, OperationType.ConvertSubtitles, OperationType.Metadata),
fileUri = "file:///unit/${UUID.randomUUID()}.mkv" fileUri = "file:///unit/${UUID.randomUUID()}.mkv"
) )
) ).apply { newReferenceId() }
start.newReferenceId()
return start return start
} }

View File

@ -84,7 +84,7 @@ class CollectEventsListenerTest : TestBase() {
) )
) )
) )
} }.newReferenceId()
val parsed = mediaParsedEvent( val parsed = mediaParsedEvent(
collection = "MyCollection", collection = "MyCollection",
@ -128,7 +128,7 @@ class CollectEventsListenerTest : TestBase() {
) )
) )
) )
} }.newReferenceId()
val parsed = mediaParsedEvent( val parsed = mediaParsedEvent(
collection = "MyCollection", collection = "MyCollection",
@ -279,7 +279,7 @@ class CollectEventsListenerTest : TestBase() {
fun failure4() { fun failure4() {
val started = defaultStartEvent().let { ev -> val started = defaultStartEvent().let { ev ->
ev.copy(data = ev.data.copy(operation = setOf(OperationType.Encode))) ev.copy(data = ev.data.copy(operation = setOf(OperationType.Encode)))
} }.newReferenceId()
val parsed = mediaParsedEvent( val parsed = mediaParsedEvent(
collection = "MyCollection", collection = "MyCollection",

View File

@ -1,25 +1,18 @@
package no.iktdev.mediaprocessing.coordinator.listeners.events package no.iktdev.mediaprocessing.coordinator.listeners.events
import io.mockk.verify
import no.iktdev.eventi.models.Event
import no.iktdev.eventi.models.store.TaskStatus import no.iktdev.eventi.models.store.TaskStatus
import no.iktdev.mediaprocessing.TestBase import no.iktdev.mediaprocessing.TestBase
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ConvertTaskCreatedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.*
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.OperationType
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserExtractResultEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.StartData
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.StartProcessingEvent
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.io.File
import io.mockk.*
import no.iktdev.eventi.models.Event
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.database.stores.TaskStore import no.iktdev.mediaprocessing.shared.database.stores.TaskStore
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mockStatic import org.mockito.Mockito.mockStatic
import org.mockito.kotlin.any import org.mockito.kotlin.any
import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
@ -43,14 +36,14 @@ class MediaCreateConvertTaskListenerTest : TestBase() {
fileUri = tempFile.absolutePath, fileUri = tempFile.absolutePath,
operation = setOf(OperationType.ConvertSubtitles) operation = setOf(OperationType.ConvertSubtitles)
) )
) ).newReferenceId()
val extractEvent = ProcesserExtractResultEvent( val extractEvent = ProcesserExtractResultEvent(
status = TaskStatus.Completed, status = TaskStatus.Completed,
data = ProcesserExtractResultEvent.ExtractResult( data = ProcesserExtractResultEvent.ExtractResult(
cachedOutputFile = tempFile.absolutePath, cachedOutputFile = tempFile.absolutePath,
language = "en" language = "en"
) )
) ).derivedOf(startEvent)
val history = listOf(startEvent) val history = listOf(startEvent)
val result = listener.onEvent(extractEvent, history) val result = listener.onEvent(extractEvent, history)
@ -221,7 +214,7 @@ class MediaCreateConvertTaskListenerTest : TestBase() {
fileUri = "/tmp/video.srt", fileUri = "/tmp/video.srt",
operation = setOf(OperationType.ConvertSubtitles) operation = setOf(OperationType.ConvertSubtitles)
) )
) ).newReferenceId()
val extractEvent = ProcesserExtractResultEvent( val extractEvent = ProcesserExtractResultEvent(
status = TaskStatus.Completed, status = TaskStatus.Completed,
@ -229,7 +222,7 @@ class MediaCreateConvertTaskListenerTest : TestBase() {
cachedOutputFile = "/tmp/video.srt", cachedOutputFile = "/tmp/video.srt",
language = "en" language = "en"
) )
) ).derivedOf(startEvent)
val history = listOf(startEvent) val history = listOf(startEvent)
val result = listener.onEvent(extractEvent, history) val result = listener.onEvent(extractEvent, history)

View File

@ -45,17 +45,17 @@ class MediaCreateEncodeTaskListenerTest: TestBase() {
fun testOnEventWithSingleAudioTrack() { fun testOnEventWithSingleAudioTrack() {
val startEvent = StartProcessingEvent( val startEvent = StartProcessingEvent(
StartData(setOf(OperationType.Encode), fileUri = "/tmp/movie.mkv") StartData(setOf(OperationType.Encode), fileUri = "/tmp/movie.mkv")
) ).newReferenceId()
val parsedEvent = MediaStreamParsedEvent( val parsedEvent = MediaStreamParsedEvent(
data = ParsedMediaStreams( data = ParsedMediaStreams(
videoStream = listOf(mockVideoStream(index = 0, codec = "h264", disposition = mockDisposition(), tags = mockTags())), videoStream = listOf(mockVideoStream(index = 0, codec = "h264", disposition = mockDisposition(), tags = mockTags())),
audioStream = listOf(mockAudioStream(index = 1, codec = "aac", disposition = mockDisposition(), tags = mockTags())) audioStream = listOf(mockAudioStream(index = 1, codec = "aac", disposition = mockDisposition(), tags = mockTags()))
) )
) ).derivedOf(startEvent)
val selectedEvent = MediaTracksEncodeSelectedEvent( val selectedEvent = MediaTracksEncodeSelectedEvent(
selectedVideoTrack = 0, selectedVideoTrack = 0,
selectedAudioTrack = 0 selectedAudioTrack = 0
) ).derivedOf(parsedEvent)
val history = listOf(startEvent, parsedEvent) val history = listOf(startEvent, parsedEvent)
@ -85,7 +85,8 @@ class MediaCreateEncodeTaskListenerTest: TestBase() {
fun testOnEventWithExtendedAudioTrack() { fun testOnEventWithExtendedAudioTrack() {
val startEvent = StartProcessingEvent( val startEvent = StartProcessingEvent(
StartData(setOf(OperationType.Encode), fileUri = "/tmp/movie.mkv") StartData(setOf(OperationType.Encode), fileUri = "/tmp/movie.mkv")
) ).newReferenceId()
val parsedEvent = MediaStreamParsedEvent( val parsedEvent = MediaStreamParsedEvent(
data = ParsedMediaStreams( data = ParsedMediaStreams(
videoStream = listOf(mockVideoStream(index = 0, codec = "h264", disposition = mockDisposition(), tags = mockTags())), videoStream = listOf(mockVideoStream(index = 0, codec = "h264", disposition = mockDisposition(), tags = mockTags())),
@ -94,12 +95,12 @@ class MediaCreateEncodeTaskListenerTest: TestBase() {
mockAudioStream(index = 2, codec = "aac", disposition = mockDisposition(), tags = mockTags()) mockAudioStream(index = 2, codec = "aac", disposition = mockDisposition(), tags = mockTags())
) )
) )
) ).derivedOf(startEvent)
val selectedEvent = MediaTracksEncodeSelectedEvent( val selectedEvent = MediaTracksEncodeSelectedEvent(
selectedVideoTrack = 0, selectedVideoTrack = 0,
selectedAudioTrack = 0, selectedAudioTrack = 0,
selectedAudioExtendedTrack = 1 selectedAudioExtendedTrack = 1
) ).derivedOf(parsedEvent)
val history = listOf(startEvent, parsedEvent) val history = listOf(startEvent, parsedEvent)

View File

@ -1,11 +1,7 @@
package no.iktdev.mediaprocessing.coordinator.listeners.events package no.iktdev.mediaprocessing.coordinator.listeners.events
import io.mockk.Runs import io.mockk.*
import io.mockk.every
import io.mockk.just
import io.mockk.mockkObject
import io.mockk.verify
import no.iktdev.eventi.models.Task import no.iktdev.eventi.models.Task
import no.iktdev.eventi.models.store.PersistedTask import no.iktdev.eventi.models.store.PersistedTask
import no.iktdev.eventi.models.store.TaskStatus import no.iktdev.eventi.models.store.TaskStatus
@ -13,22 +9,16 @@ import no.iktdev.mediaprocessing.ffmpeg.data.ParsedMediaStreams
import no.iktdev.mediaprocessing.ffmpeg.data.SubtitleStream import no.iktdev.mediaprocessing.ffmpeg.data.SubtitleStream
import no.iktdev.mediaprocessing.ffmpeg.data.SubtitleTags import no.iktdev.mediaprocessing.ffmpeg.data.SubtitleTags
import no.iktdev.mediaprocessing.ffmpeg.data.Tags import no.iktdev.mediaprocessing.ffmpeg.data.Tags
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaStreamParsedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.*
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksExtractSelectedEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.OperationType
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserExtractTaskCreatedEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.StartData
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.StartProcessingEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleTask import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleTask
import no.iktdev.mediaprocessing.shared.database.stores.TaskStore import no.iktdev.mediaprocessing.shared.database.stores.TaskStore
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import java.io.File import java.io.File
import java.time.Duration import java.time.Duration
import java.util.UUID import java.util.*
class MediaCreateExtractTaskListenerTest { class MediaCreateExtractTaskListenerTest {
@ -184,11 +174,12 @@ class MediaCreateExtractTaskListenerTest {
fun testOnEventCreatesTasks() { fun testOnEventCreatesTasks() {
val startEvent = StartProcessingEvent( val startEvent = StartProcessingEvent(
StartData(setOf(OperationType.ExtractSubtitles), fileUri = "/tmp/movie.mkv") StartData(setOf(OperationType.ExtractSubtitles), fileUri = "/tmp/movie.mkv")
) ).newReferenceId()
val parsedEvent = MediaStreamParsedEvent( val parsedEvent = MediaStreamParsedEvent(
data = ParsedMediaStreams(subtitleStream = listOf(dummyStream(0, "subrip", "eng"))) data = ParsedMediaStreams(subtitleStream = listOf(dummyStream(0, "subrip", "eng")))
) ).derivedOf(startEvent)
val selectedEvent = MediaTracksExtractSelectedEvent(selectedSubtitleTracks = listOf(0)) val selectedEvent = MediaTracksExtractSelectedEvent(selectedSubtitleTracks = listOf(0))
.derivedOf(parsedEvent)
val history = listOf(startEvent, parsedEvent) val history = listOf(startEvent, parsedEvent)
@ -222,7 +213,7 @@ class MediaCreateExtractTaskListenerTest {
// Hvis: vi har en StartProcessingEvent og to subtitle streams // Hvis: vi har en StartProcessingEvent og to subtitle streams
val startEvent = StartProcessingEvent( val startEvent = StartProcessingEvent(
StartData(setOf(OperationType.ExtractSubtitles), fileUri = "/tmp/movie.mkv") StartData(setOf(OperationType.ExtractSubtitles), fileUri = "/tmp/movie.mkv")
) ).newReferenceId()
val parsedEvent = MediaStreamParsedEvent( val parsedEvent = MediaStreamParsedEvent(
data = ParsedMediaStreams( data = ParsedMediaStreams(
subtitleStream = listOf( subtitleStream = listOf(
@ -230,8 +221,9 @@ class MediaCreateExtractTaskListenerTest {
dummyStream(1, "ass", "jpn") dummyStream(1, "ass", "jpn")
) )
) )
) ).derivedOf(startEvent)
val selectedEvent = MediaTracksExtractSelectedEvent(selectedSubtitleTracks = listOf(0, 1)) val selectedEvent = MediaTracksExtractSelectedEvent(selectedSubtitleTracks = listOf(0, 1))
.derivedOf(parsedEvent)
val history = listOf(startEvent, parsedEvent) val history = listOf(startEvent, parsedEvent)

View File

@ -9,12 +9,10 @@ import no.iktdev.mediaprocessing.ffmpeg.data.Tags
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaStreamParsedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaStreamParsedEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksDetermineSubtitleTypeEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksDetermineSubtitleTypeEvent
import no.iktdev.mediaprocessing.shared.common.model.SubtitleType import no.iktdev.mediaprocessing.shared.common.model.SubtitleType
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Named import org.junit.jupiter.api.Named
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream import java.util.stream.Stream
@ -163,7 +161,7 @@ class MediaDetermineSubtitleTrackTypeListenerTest {
fun testSubtitleCases(testCase: SubtitleTestCase) { fun testSubtitleCases(testCase: SubtitleTestCase) {
val event = MediaStreamParsedEvent( val event = MediaStreamParsedEvent(
ParsedMediaStreams(subtitleStream = listOf(testCase.stream)) ParsedMediaStreams(subtitleStream = listOf(testCase.stream))
) ).newReferenceId()
val result = listener.onEvent(event, emptyList()) as MediaTracksDetermineSubtitleTypeEvent val result = listener.onEvent(event, emptyList()) as MediaTracksDetermineSubtitleTypeEvent
if (testCase.expectedKept) { if (testCase.expectedKept) {

View File

@ -54,6 +54,8 @@ class MediaReadStreamsTaskCreatedListenerTest: TestBase() {
Returneres CoordinatorReadStreamsTaskCreatedEvent med riktig taskId Returneres CoordinatorReadStreamsTaskCreatedEvent med riktig taskId
""") """)
fun testOnEventParsedInfoEventWithStartProcessing() { fun testOnEventParsedInfoEventWithStartProcessing() {
val startEvent = StartProcessingEvent(StartData(fileUri = "file://test.mkv", operation = emptySet()))
.newReferenceId()
val parsedEvent = MediaParsedInfoEvent( val parsedEvent = MediaParsedInfoEvent(
MediaParsedInfoEvent.ParsedData( MediaParsedInfoEvent.ParsedData(
parsedCollection = "collection", parsedCollection = "collection",
@ -61,8 +63,8 @@ class MediaReadStreamsTaskCreatedListenerTest: TestBase() {
parsedSearchTitles = listOf("title"), parsedSearchTitles = listOf("title"),
mediaType = MediaType.Movie mediaType = MediaType.Movie
) )
) ).derivedOf(startEvent)
val startEvent = StartProcessingEvent(StartData(fileUri = "file://test.mkv", operation = emptySet()))
val result = listener.onEvent(parsedEvent, listOf(startEvent)) val result = listener.onEvent(parsedEvent, listOf(startEvent))

View File

@ -1,15 +1,10 @@
package no.iktdev.mediaprocessing.coordinator.listeners.events package no.iktdev.mediaprocessing.coordinator.listeners.events
import no.iktdev.eventi.models.Event import no.iktdev.eventi.models.Event
import no.iktdev.mediaprocessing.ffmpeg.data.AudioStream import no.iktdev.mediaprocessing.ffmpeg.data.*
import no.iktdev.mediaprocessing.ffmpeg.data.Disposition
import no.iktdev.mediaprocessing.ffmpeg.data.ParsedMediaStreams
import no.iktdev.mediaprocessing.ffmpeg.data.Tags
import no.iktdev.mediaprocessing.ffmpeg.data.VideoStream
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaStreamParsedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaStreamParsedEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksEncodeSelectedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksEncodeSelectedEvent
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -210,7 +205,7 @@ class MediaTracksEncodeSelectorTest: MediaSelectEncodeTracksListener() {
val audioStreams = listOf(dummyAudioStream(0, "jpn", 2), dummyAudioStream(1, "jpn", 6)) val audioStreams = listOf(dummyAudioStream(0, "jpn", 2), dummyAudioStream(1, "jpn", 6))
val parsedEvent = MediaStreamParsedEvent( val parsedEvent = MediaStreamParsedEvent(
ParsedMediaStreams(videoStream = videoStreams, audioStream = audioStreams, subtitleStream = emptyList()) ParsedMediaStreams(videoStream = videoStreams, audioStream = audioStreams, subtitleStream = emptyList())
) ).newReferenceId()
val result = onEvent(parsedEvent, emptyList()) as MediaTracksEncodeSelectedEvent val result = onEvent(parsedEvent, emptyList()) as MediaTracksEncodeSelectedEvent
assertEquals(0, result.selectedVideoTrack) assertEquals(0, result.selectedVideoTrack)
assertEquals(0, result.selectedAudioTrack) assertEquals(0, result.selectedAudioTrack)

View File

@ -8,7 +8,8 @@ import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaT
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksExtractSelectedEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.MediaTracksExtractSelectedEvent
import no.iktdev.mediaprocessing.shared.common.model.SubtitleItem import no.iktdev.mediaprocessing.shared.common.model.SubtitleItem
import no.iktdev.mediaprocessing.shared.common.model.SubtitleType import no.iktdev.mediaprocessing.shared.common.model.SubtitleType
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -78,7 +79,7 @@ class MediaSelectExtractTracksListenerTest: TestBase() {
dummySubtitleStream(0, "eng", SubtitleType.Dialogue), dummySubtitleStream(0, "eng", SubtitleType.Dialogue),
dummySubtitleStream(1, "eng", SubtitleType.Commentary) dummySubtitleStream(1, "eng", SubtitleType.Commentary)
) )
val event = MediaTracksDetermineSubtitleTypeEvent(subtitleTrackItems = items) val event = MediaTracksDetermineSubtitleTypeEvent(subtitleTrackItems = items).newReferenceId()
val result = listener.onEvent(event, emptyList()) as MediaTracksExtractSelectedEvent val result = listener.onEvent(event, emptyList()) as MediaTracksExtractSelectedEvent
assertEquals(listOf(0), result.selectedSubtitleTracks) assertEquals(listOf(0), result.selectedSubtitleTracks)
} }

View File

@ -1,8 +1,12 @@
package no.iktdev.mediaprocessing.processer.config package no.iktdev.mediaprocessing.processer.config
import org.jetbrains.annotations.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
@ConfigurationProperties(prefix = "directories") @ConfigurationProperties(prefix = "directories")
@Validated
data class DirectoryProperties( data class DirectoryProperties(
@field:NotNull
val logs: String, val logs: String,
) )

View File

@ -88,7 +88,7 @@ class SubtitleTaskListener(
TaskStatus.Cancelled -> "Canceled" TaskStatus.Cancelled -> "Canceled"
else -> "" else -> ""
} }
return ProcesserExtractResultEvent(null, status, error = message) return ProcesserExtractResultEvent(null, status, error = message).producedFrom(task)
} }
override fun getFfmpeg(): FFmpeg { override fun getFfmpeg(): FFmpeg {

View File

@ -94,7 +94,7 @@ class VideoTaskListener(
TaskStatus.Cancelled -> "Canceled" TaskStatus.Cancelled -> "Canceled"
else -> "" else -> ""
} }
return ProcesserEncodeResultEvent(null, null, status, error = message) return ProcesserEncodeResultEvent(null, null, status, error = message).producedFrom(task)
} }

View File

@ -1,8 +1,11 @@
package no.iktdev.mediaprocessing.processer package no.iktdev.mediaprocessing.processer
import no.iktdev.eventi.models.Event
import no.iktdev.eventi.models.Task
import no.iktdev.mediaprocessing.processer.config.DirectoryProperties import no.iktdev.mediaprocessing.processer.config.DirectoryProperties
import no.iktdev.mediaprocessing.processer.config.ExecutablesConfig import no.iktdev.mediaprocessing.processer.config.ExecutablesConfig
import no.iktdev.mediaprocessing.shared.common.configs.MediaPaths import no.iktdev.mediaprocessing.shared.common.configs.MediaPaths
import org.junit.jupiter.api.Assertions.assertEquals
object TestUtils { object TestUtils {
fun getFileUtil(): FileUtil { fun getFileUtil(): FileUtil {
@ -25,3 +28,12 @@ object TestUtils {
} }
} }
fun assertSameReferenceId(task: Task, event: Event?) {
requireNotNull(event) { "Event was null" }
assertEquals(
task.referenceId,
event.referenceId,
"Expected event to keep same referenceId as task"
)
}

View File

@ -8,12 +8,14 @@ import no.iktdev.eventi.tasks.TaskReporter
import no.iktdev.eventi.tasks.TaskTypeRegistry import no.iktdev.eventi.tasks.TaskTypeRegistry
import no.iktdev.mediaprocessing.ffmpeg.FFmpeg import no.iktdev.mediaprocessing.ffmpeg.FFmpeg
import no.iktdev.mediaprocessing.processer.TestUtils import no.iktdev.mediaprocessing.processer.TestUtils
import no.iktdev.mediaprocessing.processer.assertSameReferenceId
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserExtractResultEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserExtractResultEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleData import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleData
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleTask import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.ExtractSubtitleTask
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import java.util.* import java.util.*
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
@ -86,4 +88,86 @@ class SubtitleTaskListenerTest {
} }
@Test
@DisplayName("""
Når en event produseres fra en task
Hvis task har en gitt referenceId
:
Skal eventen ha samme referenceId
"""
)
fun producedFrom_keeps_referenceId() {
val task = ExtractSubtitleTask(
ExtractSubtitleData(
inputFile = "input.mp4",
outputFileName = "output.srt",
arguments = listOf("-y"),
language = "eng"
)
).newReferenceId()
val event = ProcesserExtractResultEvent(
status = TaskStatus.Completed
).producedFrom(task)
assertSameReferenceId(task, event)
}
@Test
@DisplayName("""
Når en task feiler og createIncompleteStateTaskEvent kalles
Hvis task har en referenceId
:
Skal eventen som returneres ha samme referenceId
""")
fun createIncompleteStateTaskEvent_keeps_referenceId() {
val task = ExtractSubtitleTask(
ExtractSubtitleData(
inputFile = "input.mp4",
outputFileName = "output.srt",
arguments = listOf("-y"),
language = "eng"
)
).newReferenceId()
val listener = SubtitleTaskListener(
fileUtil = TestUtils.getFileUtil(),
executableConfig = TestUtils.getExecutableConfig()
)
val event = listener.createIncompleteStateTaskEvent(
task = task,
status = TaskStatus.Failed,
exception = RuntimeException("boom")
)
assertSameReferenceId(task, event)
}
@Test
@DisplayName("""
Når VideoTaskListener kjører en EncodeTask
Hvis task har en referenceId
:
Skal resultat-eventen ha samme referenceId
""")
fun onTask_keeps_referenceId() = runTest {
val task = ExtractSubtitleTask(
ExtractSubtitleData(
inputFile = "input.mp4",
outputFileName = "output.srt",
arguments = listOf("-y"),
language = "eng"
)
).newReferenceId()
val listener = TestListener(delay = 10)
listener.accept(task, overrideReporter)
listener.getJob()?.join()
val event = listener.getResult()
assertTrue(event is ProcesserExtractResultEvent)
assertSameReferenceId(task, event)
}
} }

View File

@ -11,12 +11,14 @@ import no.iktdev.mediaprocessing.ffmpeg.FFmpeg
import no.iktdev.mediaprocessing.processer.CoordinatorClient import no.iktdev.mediaprocessing.processer.CoordinatorClient
import no.iktdev.mediaprocessing.processer.LocalProgressCache import no.iktdev.mediaprocessing.processer.LocalProgressCache
import no.iktdev.mediaprocessing.processer.TestUtils import no.iktdev.mediaprocessing.processer.TestUtils
import no.iktdev.mediaprocessing.processer.assertSameReferenceId
import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserEncodeResultEvent import no.iktdev.mediaprocessing.shared.common.event_task_contract.events.ProcesserEncodeResultEvent
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.EncodeData import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.EncodeData
import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.EncodeTask import no.iktdev.mediaprocessing.shared.common.event_task_contract.tasks.EncodeTask
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import java.util.* import java.util.*
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
@ -24,8 +26,9 @@ import kotlin.system.measureTimeMillis
class VideoTaskListenerTest { class VideoTaskListenerTest {
class TestListener(val delay: Long, coordinatorClient: CoordinatorClient): class TestListener(val delay: Long, coordinatorClient: CoordinatorClient) :
VideoTaskListener(coordinatorWebClient = coordinatorClient, VideoTaskListener(
coordinatorWebClient = coordinatorClient,
localProgress = LocalProgressCache(), localProgress = LocalProgressCache(),
fileUtil = TestUtils.getFileUtil(), fileUtil = TestUtils.getFileUtil(),
executableConfig = TestUtils.getExecutableConfig(), executableConfig = TestUtils.getExecutableConfig(),
@ -36,12 +39,13 @@ class VideoTaskListenerTest {
fun getResult(): Event? { fun getResult(): Event? {
return _result return _result
} }
override fun onComplete(task: Task, result: Event?) { override fun onComplete(task: Task, result: Event?) {
this._result = result this._result = result
} }
override fun getFfmpeg(): FFmpeg { override fun getFfmpeg(): FFmpeg {
return MockFFmpeg(delayMillis = delay, listener = MockFFmpeg.emptyListener()) return MockFFmpeg(delayMillis = delay, listener = MockFFmpeg.emptyListener())
} }
} }
@ -62,6 +66,7 @@ class VideoTaskListenerTest {
fun setup() { fun setup() {
TaskTypeRegistry.register(EncodeTask::class.java) TaskTypeRegistry.register(EncodeTask::class.java)
} }
private val coordinatorClient = mockk<CoordinatorClient>(relaxed = true) private val coordinatorClient = mockk<CoordinatorClient>(relaxed = true)
@Test @Test
@ -86,8 +91,85 @@ class VideoTaskListenerTest {
} }
assertTrue(time >= delay, "Expected onTask to wait at least $delay ms, waited for $time ms") assertTrue(time >= delay, "Expected onTask to wait at least $delay ms, waited for $time ms")
assertTrue(time <= (delay*2), "Expected onTask to wait less than ${(delay*2)} ms, waited for $time ms") assertTrue(time <= (delay * 2), "Expected onTask to wait less than ${(delay * 2)} ms, waited for $time ms")
} }
@Test
@DisplayName("""
Når en event produseres fra en task
Hvis task har en gitt referenceId
:
Skal eventen ha samme referenceId
"""
)
fun producedFrom_keeps_referenceId() {
val task = EncodeTask(
EncodeData(inputFile = "input.mp4", outputFileName = "output.mp4", arguments = listOf("-y"))
).newReferenceId()
val event = ProcesserEncodeResultEvent(
status = TaskStatus.Completed
).producedFrom(task)
assertSameReferenceId(task, event)
}
@Test
@DisplayName("""
Når en task feiler og createIncompleteStateTaskEvent kalles
Hvis task har en referenceId
:
Skal eventen som returneres ha samme referenceId
""")
fun createIncompleteStateTaskEvent_keeps_referenceId() {
val task = EncodeTask(
EncodeData(inputFile = "input.mp4", outputFileName = "output.mp4", arguments = listOf("-y"))
).newReferenceId()
val listener = VideoTaskListener(
coordinatorWebClient = coordinatorClient,
localProgress = LocalProgressCache(),
fileUtil = TestUtils.getFileUtil(),
executableConfig = TestUtils.getExecutableConfig()
)
val event = listener.createIncompleteStateTaskEvent(
task = task,
status = TaskStatus.Failed,
exception = RuntimeException("boom")
)
assertSameReferenceId(task, event)
}
@Test
@DisplayName("""
Når VideoTaskListener kjører en EncodeTask
Hvis task har en referenceId
:
Skal resultat-eventen ha samme referenceId
""")
fun onTask_keeps_referenceId() = runTest {
val task = EncodeTask(
EncodeData(
inputFile = "input.mp4",
outputFileName = "output.mp4",
arguments = listOf("-y")
)
).newReferenceId()
val listener = TestListener(delay = 10, coordinatorClient)
listener.accept(task, overrideReporter)
listener.getJob()?.join()
val event = listener.getResult()
assertTrue(event is ProcesserEncodeResultEvent)
assertSameReferenceId(task, event)
}
} }

View File

@ -1,5 +1,5 @@
[versions] [versions]
eventi = "1.0-rc38" eventi = "1.0-rc39"
exfl = "1.0-rc1" exfl = "1.0-rc1"
[libraries] [libraries]

View File

@ -9,6 +9,7 @@ import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializer import com.google.gson.JsonDeserializer
import com.google.gson.JsonPrimitive import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializer import com.google.gson.JsonSerializer
import no.iktdev.eventi.models.Event
import no.iktdev.eventi.models.store.TaskStatus import no.iktdev.eventi.models.store.TaskStatus
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertDoesNotThrow
@ -106,8 +107,9 @@ class TaskResultEventSerializationTest {
// --- 5. Fallback --- // --- 5. Fallback ---
null null
} }
val instance = ctor.callBy(args)
return ctor.callBy(args) if (instance is Event) { instance.newReferenceId() }
return instance
} }