test(media): 覆盖转码认领与非法媒资 id
This commit is contained in:
1 parent
08eddc9ed2
commit
ad84704d28
4 files changed
+68
-49
No files matched your search
+17
-47
@@ -15,9 +15,7 @@ import com.fruitshorts.media.vo.TranscodeTriggerRespVO;
|
||||
import com.fruitshorts.media.vo.UploadCompleteReqVO;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -40,10 +38,6 @@ class MediaServiceTranscodePipelineTest {
|
||||
private static final Long EPISODE_ID = 31L;
|
||||
private static final Long DRAMA_ID = 7L;
|
||||
private static final String SOURCE_URL = "/files/episode/202610/video.mp4";
|
||||
private static final String OBJECT_KEY = "episode/202610/video.mp4";
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
private MediaAssetMapper mediaAssetMapper;
|
||||
private MediaUploadTaskMapper uploadTaskMapper;
|
||||
@@ -99,70 +93,46 @@ class MediaServiceTranscodePipelineTest {
|
||||
@Test
|
||||
void should_return_not_found_when_triggering_transcode_for_missing_media() {
|
||||
given(mediaAssetMapper.selectOne(any())).willReturn(null);
|
||||
given(episodeVideoSourcePort.resolve(404L)).willReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> mediaService.triggerTranscode(404L))
|
||||
.isInstanceOf(com.fruitshorts.common.exception.ServiceException.class)
|
||||
.hasMessage("媒资不存在");
|
||||
verify(transcodeService, never()).trigger(any(), anyString());
|
||||
verify(transcodeService, never()).trigger(
|
||||
any(), anyString(), any(), any());
|
||||
verify(episodeVideoSourcePort, never()).resolveByVideoUrl(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_trigger_transcode_and_mark_asset_queued() {
|
||||
void should_bind_episode_by_video_url_before_triggering_transcode() {
|
||||
MediaAsset asset = asset("video.mp4");
|
||||
given(mediaAssetMapper.selectOne(any())).willReturn(asset);
|
||||
given(transcodeService.trigger(ASSET_ID, SOURCE_URL))
|
||||
given(episodeVideoSourcePort.resolveByVideoUrl(SOURCE_URL))
|
||||
.willReturn(Optional.of(episodeSource()));
|
||||
given(transcodeService.trigger(ASSET_ID, SOURCE_URL, DRAMA_ID, EPISODE_ID))
|
||||
.willReturn(new TranscodeTriggerRespVO(100L, TranscodeService.STATUS_QUEUED));
|
||||
|
||||
TranscodeTriggerRespVO result = mediaService.triggerTranscode(ASSET_ID);
|
||||
|
||||
assertThat(result.getTaskId()).isEqualTo(100L);
|
||||
assertThat(result.getStatus()).isEqualTo(TranscodeService.STATUS_QUEUED);
|
||||
verify(episodeVideoSourcePort).link(EPISODE_ID, ASSET_ID);
|
||||
assertThat(asset.getStatus()).isEqualTo("transcoding");
|
||||
assertThat(asset.getTranscodeStatus()).isEqualTo(TranscodeService.STATUS_QUEUED);
|
||||
verify(mediaAssetMapper).updateById(asset);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_resolve_existing_media_asset_by_episode_video_url() {
|
||||
void should_reject_existing_media_when_no_episode_uses_video_url() {
|
||||
MediaAsset asset = asset("video.mp4");
|
||||
given(mediaAssetMapper.selectOne(any())).willReturn(null).willReturn(asset);
|
||||
given(storageService.objectKeyOf(SOURCE_URL)).willReturn(OBJECT_KEY);
|
||||
given(episodeVideoSourcePort.resolve(EPISODE_ID))
|
||||
.willReturn(Optional.of(episodeSource()));
|
||||
given(transcodeService.trigger(ASSET_ID, SOURCE_URL))
|
||||
.willReturn(new TranscodeTriggerRespVO(100L, TranscodeService.STATUS_QUEUED));
|
||||
given(mediaAssetMapper.selectOne(any())).willReturn(asset);
|
||||
given(episodeVideoSourcePort.resolveByVideoUrl(SOURCE_URL))
|
||||
.willReturn(Optional.empty());
|
||||
|
||||
TranscodeTriggerRespVO result = mediaService.triggerTranscode(EPISODE_ID);
|
||||
|
||||
assertThat(result.getTaskId()).isEqualTo(100L);
|
||||
verify(episodeVideoSourcePort).link(EPISODE_ID, ASSET_ID);
|
||||
verify(transcodeService).trigger(ASSET_ID, SOURCE_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_register_legacy_media_asset_when_episode_file_exists() throws Exception {
|
||||
Path file = tempDir.resolve("video.mp4");
|
||||
Files.writeString(file, "legacy-video");
|
||||
given(mediaAssetMapper.selectOne(any())).willReturn(null);
|
||||
doAnswer(invocation -> {
|
||||
MediaAsset inserted = invocation.getArgument(0);
|
||||
inserted.setId(ASSET_ID);
|
||||
return 1;
|
||||
}).when(mediaAssetMapper).insert(any(MediaAsset.class));
|
||||
given(storageService.objectKeyOf(SOURCE_URL)).willReturn(OBJECT_KEY);
|
||||
given(storageService.fileFor(OBJECT_KEY)).willReturn(file);
|
||||
given(episodeVideoSourcePort.resolve(EPISODE_ID))
|
||||
.willReturn(Optional.of(episodeSource()));
|
||||
given(transcodeService.trigger(ASSET_ID, SOURCE_URL))
|
||||
.willReturn(new TranscodeTriggerRespVO(100L, TranscodeService.STATUS_QUEUED));
|
||||
|
||||
TranscodeTriggerRespVO result = mediaService.triggerTranscode(EPISODE_ID);
|
||||
|
||||
assertThat(result.getTaskId()).isEqualTo(100L);
|
||||
verify(episodeVideoSourcePort).link(EPISODE_ID, ASSET_ID);
|
||||
verify(mediaAssetMapper).insert(any(MediaAsset.class));
|
||||
verify(transcodeService).trigger(ASSET_ID, SOURCE_URL);
|
||||
assertThatThrownBy(() -> mediaService.triggerTranscode(ASSET_ID))
|
||||
.isInstanceOf(com.fruitshorts.common.exception.ServiceException.class)
|
||||
.hasMessage("媒资未绑定分集视频");
|
||||
verify(transcodeService, never()).trigger(
|
||||
any(), anyString(), any(), any());
|
||||
}
|
||||
|
||||
private void givenCompletedUpload(String fileName) {
|
||||
|
||||
+25
-1
@@ -20,7 +20,10 @@ import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -38,6 +41,7 @@ import static org.mockito.Mockito.verify;
|
||||
* ① 认领任务靠状态条件更新,抢不到就是 null(多进程同时跑也只有一个能转);
|
||||
* ② objectKey → 本地路径要挡住目录穿越。
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class TranscodeClaimAndStorageTest {
|
||||
|
||||
/**
|
||||
@@ -98,6 +102,10 @@ class TranscodeClaimAndStorageTest {
|
||||
|
||||
@Test
|
||||
void should_exclude_unbound_queued_task_from_claim_query() {
|
||||
TranscodeTask unbound = task(3L);
|
||||
unbound.setMediaAssetId(88L);
|
||||
unbound.setEpisodeId(0L);
|
||||
given(transcodeTaskMapper.selectList(any())).willReturn(java.util.List.of(unbound));
|
||||
given(transcodeTaskMapper.selectOne(any())).willReturn(null);
|
||||
|
||||
assertThat(transcodeService.claimNext()).isNull();
|
||||
@@ -105,7 +113,23 @@ class TranscodeClaimAndStorageTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<Wrapper<TranscodeTask>> captor = ArgumentCaptor.forClass(Wrapper.class);
|
||||
verify(transcodeTaskMapper).selectOne(captor.capture());
|
||||
assertThat(captor.getValue().getSqlSegment()).contains("episode_id >");
|
||||
assertThat(captor.getValue().getSqlSegment())
|
||||
.contains("episode_id >")
|
||||
.contains("media_asset_id >")
|
||||
.contains("source_url");
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_log_skip_reason_when_queued_task_has_no_episode(CapturedOutput output) {
|
||||
TranscodeTask unbound = task(9L);
|
||||
unbound.setMediaAssetId(88L);
|
||||
unbound.setEpisodeId(0L);
|
||||
given(transcodeTaskMapper.selectList(any())).willReturn(java.util.List.of(unbound));
|
||||
given(transcodeTaskMapper.selectOne(any())).willReturn(null);
|
||||
|
||||
assertThat(transcodeService.claimNext()).isNull();
|
||||
|
||||
assertThat(output).contains("跳过转码任务 9").contains("episode_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -68,7 +69,7 @@ class TranscodeServiceTriggerTest {
|
||||
assertThat(second.getTaskId()).isEqualTo(10L);
|
||||
assertThat(second.getStatus()).isEqualTo(TranscodeService.STATUS_QUEUED);
|
||||
verify(taskMapper, never()).insert(any(TranscodeTask.class));
|
||||
verify(taskMapper).update(any(), any());
|
||||
verify(taskMapper, atLeastOnce()).update(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in new issue
Block a user