Adds tests for common whisper
This commit is contained in:
@@ -22,5 +22,4 @@ public final class WhisperCommonSetupModule {
|
||||
final OS os) {
|
||||
return new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -72,45 +73,40 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
private void notifyListeners(final ExtractEvent event) {
|
||||
void notifyListeners(final ExtractEvent event) {
|
||||
listeners.forEach(listener -> listener.listen(event));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SubtitleCollection<Subtitle> extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException {
|
||||
if (video instanceof final File f) {
|
||||
return extract(f.path(), language, model, video.info().duration());
|
||||
return extract(new AudioOrVideo(video), language, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtitleCollection<Subtitle> extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException {
|
||||
return extract(new AudioOrVideo(audio), language, model);
|
||||
}
|
||||
|
||||
private SubtitleCollection<Subtitle> extract(final AudioOrVideo av, final Language language, final ExtractionModel model) throws ExtractException {
|
||||
if (av.inner() instanceof final File f) {
|
||||
return extract(f.path(), language, model, av.info().duration());
|
||||
} else {
|
||||
try {
|
||||
final var path = Files.createTempFile(AUTOSUBTITLE, video.info().videoFormat());
|
||||
try (final var in = video.getInputStream()) {
|
||||
Files.copy(in, path);
|
||||
final var ret = extract(path, language, model, video.info().duration());
|
||||
Files.deleteIfExists(path);
|
||||
return ret;
|
||||
}
|
||||
return dumpExtract(av, language, model);
|
||||
} catch (final IOException e) {
|
||||
throw new ExtractException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtitleCollection<Subtitle> extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException {
|
||||
if (audio instanceof final File f) {
|
||||
return extract(f.path(), language, model, audio.info().duration());
|
||||
} else {
|
||||
try {
|
||||
final var path = Files.createTempFile(AUTOSUBTITLE, audio.info().audioFormat());
|
||||
try (final var in = audio.getInputStream()) {
|
||||
Files.copy(in, path);
|
||||
final var ret = extract(path, language, model, audio.info().duration());
|
||||
Files.deleteIfExists(path);
|
||||
return ret;
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new ExtractException(e);
|
||||
}
|
||||
private SubtitleCollection<Subtitle> dumpExtract(final AudioOrVideo av, final Language language, final ExtractionModel model) throws ExtractException, IOException {
|
||||
final var path = Files.createTempFile(AUTOSUBTITLE, "." + av.info().format());
|
||||
try (final var in = av.getInputStream()) {
|
||||
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
|
||||
return extract(path, language, model, av.info().duration());
|
||||
} finally {
|
||||
Files.deleteIfExists(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.extractor.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.Audio;
|
||||
import com.github.gtache.autosubtitle.AudioInfo;
|
||||
import com.github.gtache.autosubtitle.Video;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Used internally for the Whisper subtitle extractor. Either audio or video must be not null
|
||||
*
|
||||
* @param audio The possible audio
|
||||
* @param video The possible video
|
||||
*/
|
||||
public record AudioOrVideo(Audio audio, Video video) implements Audio {
|
||||
|
||||
public AudioOrVideo {
|
||||
if (audio == null) {
|
||||
requireNonNull(video);
|
||||
} else if (video != null) {
|
||||
throw new IllegalArgumentException("Either audio or video must be null");
|
||||
}
|
||||
}
|
||||
|
||||
public AudioOrVideo(final Audio audio) {
|
||||
this(audio, null);
|
||||
}
|
||||
|
||||
public AudioOrVideo(final Video video) {
|
||||
this(null, video);
|
||||
}
|
||||
|
||||
public <T> T inner() {
|
||||
return (T) (audio == null ? video : audio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
if (audio == null) {
|
||||
return video.getInputStream();
|
||||
} else {
|
||||
return audio.getInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioInfo info() {
|
||||
if (audio == null) {
|
||||
return video.info();
|
||||
} else {
|
||||
return audio.info();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.github.gtache.autosubtitle.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Whisper implementation of {@link ExtractionModelProvider}
|
||||
*/
|
||||
@Singleton
|
||||
public class WhisperExtractionModelProvider implements ExtractionModelProvider {
|
||||
|
||||
@Inject
|
||||
WhisperExtractionModelProvider() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ExtractionModel> getAvailableExtractionModels() {
|
||||
return Arrays.asList(WhisperModels.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractionModel getDefaultExtractionModel() {
|
||||
return WhisperModels.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractionModel getExtractionModel(final String name) {
|
||||
return WhisperModels.valueOf(name.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import com.github.gtache.autosubtitle.setup.whisper.WhisperSetupConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
class TestWhisperCommonSetupModule {
|
||||
|
||||
@Test
|
||||
void testWhisperSetupConfiguration() {
|
||||
final var root = mock(Path.class);
|
||||
final var venvPath = mock(Path.class);
|
||||
final var pythonVersion = "3.10";
|
||||
final var os = OS.LINUX;
|
||||
final var expected = new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||
assertEquals(expected, WhisperCommonSetupModule.providesWhisperSetupConfiguration(root, venvPath, pythonVersion, os));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.github.gtache.autosubtitle.setup.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import com.github.gtache.autosubtitle.process.ProcessRunner;
|
||||
import com.github.gtache.autosubtitle.setup.SetupException;
|
||||
import com.github.gtache.autosubtitle.setup.conda.CondaSetupManager;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.github.gtache.autosubtitle.setup.SetupStatus.BUNDLE_INSTALLED;
|
||||
import static com.github.gtache.autosubtitle.setup.SetupStatus.NOT_INSTALLED;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestAbstractWhisperSetupManager {
|
||||
|
||||
private final CondaSetupManager condaSetupManager;
|
||||
private final WhisperSetupConfiguration configuration;
|
||||
private final ProcessRunner processRunner;
|
||||
private final HttpClient httpClient;
|
||||
private final AbstractWhisperSetupManager setupManager;
|
||||
|
||||
TestAbstractWhisperSetupManager(@Mock final CondaSetupManager condaSetupManager, @Mock final WhisperSetupConfiguration configuration,
|
||||
@Mock final ProcessRunner processRunner, @Mock final HttpClient httpClient) {
|
||||
this.condaSetupManager = Objects.requireNonNull(condaSetupManager);
|
||||
when(condaSetupManager.name()).thenReturn("conda");
|
||||
this.configuration = Objects.requireNonNull(configuration);
|
||||
this.processRunner = Objects.requireNonNull(processRunner);
|
||||
this.httpClient = Objects.requireNonNull(httpClient);
|
||||
this.setupManager = spy(new DummyWhisperSetupManager(condaSetupManager, configuration, processRunner, httpClient));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetStatus() throws SetupException {
|
||||
assertEquals(NOT_INSTALLED, setupManager.getStatus());
|
||||
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||
assertEquals(BUNDLE_INSTALLED, setupManager.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInstallAlreadyInstalled() throws SetupException {
|
||||
final var venvPath = Paths.get("path");
|
||||
when(configuration.venvPath()).thenReturn(venvPath);
|
||||
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||
setupManager.install();
|
||||
verify(condaSetupManager, never()).install();
|
||||
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||
verify(setupManager, never()).installWhisper();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInstallWhisper() throws SetupException {
|
||||
final var venvPath = Paths.get("path");
|
||||
when(configuration.venvPath()).thenReturn(venvPath);
|
||||
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||
setupManager.install();
|
||||
verify(condaSetupManager, never()).install();
|
||||
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||
verify(setupManager).installWhisper();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInstallVenv() throws SetupException {
|
||||
final var venvPath = Paths.get("path");
|
||||
final var pythonVersion = "3.10";
|
||||
when(configuration.venvPath()).thenReturn(venvPath);
|
||||
when(configuration.pythonVersion()).thenReturn(pythonVersion);
|
||||
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||
setupManager.install();
|
||||
verify(condaSetupManager, never()).install();
|
||||
verify(condaSetupManager).createVenv(venvPath, pythonVersion);
|
||||
verify(setupManager, never()).installWhisper();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInstallConda() throws SetupException {
|
||||
final var venvPath = Paths.get("path");
|
||||
final var pythonVersion = "3.10";
|
||||
when(configuration.venvPath()).thenReturn(venvPath);
|
||||
when(configuration.pythonVersion()).thenReturn(pythonVersion);
|
||||
when(condaSetupManager.isInstalled()).thenReturn(false);
|
||||
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||
setupManager.install();
|
||||
verify(condaSetupManager).install();
|
||||
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||
verify(setupManager, never()).installWhisper();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUninstall(@TempDir final Path tempDir) throws SetupException, IOException {
|
||||
final var subfolder = tempDir.resolve("subfolder");
|
||||
Files.createDirectory(subfolder);
|
||||
final var subfile = subfolder.resolve("subfile");
|
||||
Files.createFile(subfile);
|
||||
final var rootFile = tempDir.resolve("rootfile");
|
||||
Files.createFile(rootFile);
|
||||
when(configuration.root()).thenReturn(tempDir);
|
||||
setupManager.uninstall();
|
||||
assertFalse(Files.exists(tempDir));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateNotAvailable() throws SetupException {
|
||||
setupManager.update();
|
||||
verify(condaSetupManager).isUpdateAvailable();
|
||||
verify(condaSetupManager, never()).update();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateAvailable() throws SetupException {
|
||||
when(condaSetupManager.isUpdateAvailable()).thenReturn(true);
|
||||
setupManager.update();
|
||||
verify(condaSetupManager).isUpdateAvailable();
|
||||
verify(condaSetupManager).update();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPythonPath() {
|
||||
final var path = Paths.get("path");
|
||||
when(configuration.venvPath()).thenReturn(path);
|
||||
when(configuration.os()).thenReturn(OS.WINDOWS);
|
||||
assertEquals(path.resolve("python.exe"), setupManager.getPythonPath());
|
||||
when(configuration.os()).thenReturn(OS.LINUX);
|
||||
assertEquals(path.resolve("python"), setupManager.getPythonPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(null, configuration, processRunner, httpClient));
|
||||
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, null, processRunner, httpClient));
|
||||
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, configuration, null, httpClient));
|
||||
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, configuration, processRunner, null));
|
||||
}
|
||||
|
||||
private static final class DummyWhisperSetupManager extends AbstractWhisperSetupManager {
|
||||
|
||||
private DummyWhisperSetupManager(final CondaSetupManager condaSetupManager, final WhisperSetupConfiguration configuration, final ProcessRunner processRunner, final HttpClient httpClient) {
|
||||
super(condaSetupManager, configuration, processRunner, httpClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installWhisper() throws SetupException {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isWhisperInstalled() throws SetupException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Dummy";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.github.gtache.autosubtitle.setup.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestWhisperSetupConfiguration {
|
||||
|
||||
private final Path root;
|
||||
private final Path venvPath;
|
||||
private final String pythonVersion;
|
||||
private final OS os;
|
||||
|
||||
TestWhisperSetupConfiguration(@Mock final Path root, @Mock final Path venvPath) {
|
||||
this.root = Objects.requireNonNull(root);
|
||||
this.venvPath = Objects.requireNonNull(venvPath);
|
||||
this.pythonVersion = "3.10";
|
||||
this.os = OS.LINUX;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
final var configuration = new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||
assertEquals(root, configuration.root());
|
||||
assertEquals(venvPath, configuration.venvPath());
|
||||
assertEquals(pythonVersion, configuration.pythonVersion());
|
||||
assertEquals(os, configuration.os());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(null, venvPath, pythonVersion, os));
|
||||
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, null, pythonVersion, os));
|
||||
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, venvPath, null, os));
|
||||
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, venvPath, pythonVersion, null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.extractor.whisper;
|
||||
|
||||
import com.github.gtache.autosubtitle.Audio;
|
||||
import com.github.gtache.autosubtitle.AudioInfo;
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.Video;
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.impl.FileAudioImpl;
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import com.github.gtache.autosubtitle.process.ProcessListener;
|
||||
import com.github.gtache.autosubtitle.process.ProcessResult;
|
||||
import com.github.gtache.autosubtitle.process.ProcessRunner;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractException;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.impl.ExtractEventImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestAbstractWhisperSubtitleExtractor {
|
||||
|
||||
private final Path venvPath;
|
||||
private final SubtitleConverter<Subtitle> converter;
|
||||
private final SubtitleConverterProvider converterProvider;
|
||||
private final ProcessRunner processRunner;
|
||||
private final ProcessListener processListener;
|
||||
private final ProcessResult processResult;
|
||||
private final OS os;
|
||||
private final DummyWhisperSubtitleExtractor extractor;
|
||||
|
||||
private final AudioInfo audioInfo;
|
||||
private final VideoInfo videoInfo;
|
||||
private final ExtractionModel extractionModel;
|
||||
private final SubtitleCollection<Subtitle> collection;
|
||||
|
||||
|
||||
TestAbstractWhisperSubtitleExtractor(@Mock final SubtitleConverterProvider converterProvider, @Mock final SubtitleConverter<Subtitle> converter,
|
||||
@Mock final ProcessRunner processRunner, @Mock final ProcessListener processListener,
|
||||
@Mock final ProcessResult processResult, @Mock final VideoInfo videoInfo,
|
||||
@Mock final AudioInfo audioInfo, @Mock final ExtractionModel extractionModel,
|
||||
@Mock final SubtitleCollection<Subtitle> collection) throws IOException {
|
||||
this.venvPath = Path.of("venv");
|
||||
this.os = OS.LINUX;
|
||||
this.converterProvider = Objects.requireNonNull(converterProvider);
|
||||
this.converter = Objects.requireNonNull(converter);
|
||||
doReturn(converter).when(converterProvider).getConverter("json");
|
||||
this.processRunner = Objects.requireNonNull(processRunner);
|
||||
this.processListener = Objects.requireNonNull(processListener);
|
||||
this.processResult = Objects.requireNonNull(processResult);
|
||||
when(processRunner.startListen(anyList())).thenReturn(processListener);
|
||||
when(processListener.join(Duration.ofHours(1))).thenReturn(processResult);
|
||||
this.extractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, os);
|
||||
|
||||
this.audioInfo = Objects.requireNonNull(audioInfo);
|
||||
when(audioInfo.format()).thenReturn("mp3");
|
||||
this.videoInfo = Objects.requireNonNull(videoInfo);
|
||||
when(videoInfo.format()).thenReturn("mp4");
|
||||
this.extractionModel = Objects.requireNonNull(extractionModel);
|
||||
this.collection = Objects.requireNonNull(collection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotifyListeners() {
|
||||
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||
final var event = mock(ExtractEvent.class);
|
||||
extractor.addListener(listener1);
|
||||
extractor.addListener(listener2);
|
||||
|
||||
extractor.notifyListeners(event);
|
||||
|
||||
verify(listener1).listen(event);
|
||||
verify(listener2).listen(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveListener() {
|
||||
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||
extractor.addListener(listener1);
|
||||
extractor.addListener(listener2);
|
||||
extractor.removeListener(listener2);
|
||||
extractor.notifyListeners(mock(ExtractEvent.class));
|
||||
verify(listener1).listen(any());
|
||||
verifyNoInteractions(listener2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveListeners() {
|
||||
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||
extractor.addListener(listener1);
|
||||
extractor.addListener(listener2);
|
||||
extractor.removeListeners();
|
||||
extractor.notifyListeners(mock(ExtractEvent.class));
|
||||
verifyNoInteractions(listener1, listener2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractAudioNotFileException() throws IOException {
|
||||
final var audio = mock(Audio.class);
|
||||
when(audio.info()).thenReturn(audioInfo);
|
||||
when(audio.getInputStream()).thenThrow(IOException.class);
|
||||
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractAudioFileException() throws IOException {
|
||||
final var path = Paths.get("path");
|
||||
final var audio = new FileAudioImpl(path, audioInfo);
|
||||
doThrow(IOException.class).when(processListener).readLine();
|
||||
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractAudioFileParseException() throws ParseException {
|
||||
final var path = Paths.get("path.path");
|
||||
final var audio = new FileAudioImpl(path, audioInfo);
|
||||
doThrow(ParseException.class).when(converter).parse(any(Path.class));
|
||||
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||
verify(converter).parse(any(Path.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractAudioFileBadResultCode() {
|
||||
final var path = Paths.get("path");
|
||||
final var audio = new FileAudioImpl(path, audioInfo);
|
||||
when(processResult.exitCode()).thenReturn(1);
|
||||
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractVideoNotFileException() throws IOException {
|
||||
final var video = mock(Video.class);
|
||||
when(video.info()).thenReturn(videoInfo);
|
||||
when(video.getInputStream()).thenThrow(IOException.class);
|
||||
assertThrows(ExtractException.class, () -> extractor.extract(video, Language.EN, extractionModel));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractVideoFile() throws IOException, ParseException, ExtractException {
|
||||
final var video = mock(Video.class);
|
||||
when(video.info()).thenReturn(videoInfo);
|
||||
final var in = new ByteArrayInputStream("test".getBytes());
|
||||
when(video.getInputStream()).thenReturn(in);
|
||||
when(converter.parse(any(Path.class))).thenReturn(collection);
|
||||
assertEquals(collection, extractor.extract(video, Language.EN, extractionModel));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReadLines() throws IOException, ExtractException, ParseException {
|
||||
final var video = mock(Video.class);
|
||||
when(video.info()).thenReturn(videoInfo);
|
||||
when(videoInfo.duration()).thenReturn(100000L);
|
||||
final var in = new ByteArrayInputStream("test".getBytes());
|
||||
when(video.getInputStream()).thenReturn(in);
|
||||
when(converter.parse(any(Path.class))).thenReturn(collection);
|
||||
when(processListener.readLine()).thenReturn("Progress: 1.7abcd", "[00:12.234 --> 00:13.234] Hello", "98%|bbb", "abcd", null);
|
||||
final var listener = mock(SubtitleExtractorListener.class);
|
||||
extractor.addListener(listener);
|
||||
assertEquals(collection, extractor.extract(video, Language.EN, extractionModel));
|
||||
verify(listener).listen(new ExtractEventImpl("Progress: 1.7abcd", 0.017));
|
||||
verify(listener).listen(new ExtractEventImpl("[00:12.234 --> 00:13.234] Hello", 0.13234));
|
||||
verify(listener).listen(new ExtractEventImpl("98%|bbb", 0.98));
|
||||
verify(listener).listen(new ExtractEventImpl("abcd", 0.98));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPythonPath() {
|
||||
assertEquals(venvPath.resolve("python"), extractor.getPythonPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPythonPathWindows() {
|
||||
final var windowsExtractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, OS.WINDOWS);
|
||||
assertEquals(venvPath.resolve("python.exe"), windowsExtractor.getPythonPath());
|
||||
}
|
||||
|
||||
private static final class DummyWhisperSubtitleExtractor extends AbstractWhisperSubtitleExtractor {
|
||||
|
||||
private DummyWhisperSubtitleExtractor(final Path venvPath, final SubtitleConverterProvider converterProvider, final ProcessRunner processRunner, final OS os) {
|
||||
super(venvPath, converterProvider, processRunner, os);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> createArgs(final Path path, final Language language, final ExtractionModel model, final Path outputDir) {
|
||||
return List.of(path.toString(), language.toString(), model.toString(), outputDir.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.gtache.autosubtitle.whisper;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TestWhisperModels {
|
||||
|
||||
@Test
|
||||
void testHasEnglishSpecific() {
|
||||
for (final var model : WhisperModels.values()) {
|
||||
assertEquals(model != WhisperModels.LARGE, model.hasEnglishSpecific());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user