Injects ProcessRunner to simplify testing, tests conda

This commit is contained in:
Guillaume Tâche
2024-08-27 20:50:10 +02:00
parent bf68d0a206
commit ae76707def
24 changed files with 810 additions and 110 deletions

View File

@@ -11,10 +11,12 @@ import com.github.gtache.autosubtitle.impl.FileVideoImpl;
import com.github.gtache.autosubtitle.impl.VideoInfoImpl;
import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFmpegBundledPath;
import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFmpegSystemPath;
import com.github.gtache.autosubtitle.process.impl.AbstractProcessRunner;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.inject.Inject;
import java.io.IOException;
@@ -34,21 +36,24 @@ import static java.util.Objects.requireNonNull;
/**
* FFmpeg implementation of {@link VideoConverter}
*/
public class FFmpegVideoConverter extends AbstractProcessRunner implements VideoConverter {
public class FFmpegVideoConverter implements VideoConverter {
private static final Logger logger = LogManager.getLogger(FFmpegVideoConverter.class);
private static final String TEMP_FILE_PREFIX = "autosubtitle";
private final Path bundledPath;
private final Path systemPath;
private final SubtitleConverterProvider converterProvider;
private final Preferences preferences;
private final ProcessRunner processRunner;
@Inject
FFmpegVideoConverter(@FFmpegBundledPath final Path bundledPath, @FFmpegSystemPath final Path systemPath,
final SubtitleConverterProvider converterProvider, final Preferences preferences) {
final SubtitleConverterProvider converterProvider, final Preferences preferences,
final ProcessRunner processRunner) {
this.bundledPath = requireNonNull(bundledPath);
this.systemPath = requireNonNull(systemPath);
this.converterProvider = requireNonNull(converterProvider);
this.preferences = requireNonNull(preferences);
this.processRunner = requireNonNull(processRunner);
}
@Override
@@ -197,4 +202,15 @@ public class FFmpegVideoConverter extends AbstractProcessRunner implements Video
private String getFFmpegPath() {
return Files.isRegularFile(bundledPath) ? bundledPath.toString() : systemPath.toString();
}
private void runListen(final List<String> args, final Duration duration) throws IOException {
final var listener = processRunner.startListen(args);
var line = listener.readLine();
final var processName = args.getFirst();
while (line != null) {
logger.info("[{}]: {}", processName, line);
line = listener.readLine();
}
listener.join(duration);
}
}

View File

@@ -6,7 +6,7 @@ import com.github.gtache.autosubtitle.impl.FileVideoImpl;
import com.github.gtache.autosubtitle.impl.VideoInfoImpl;
import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFprobeBundledPath;
import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFprobeSystemPath;
import com.github.gtache.autosubtitle.process.impl.AbstractProcessRunner;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import javax.inject.Inject;
import java.io.IOException;
@@ -20,20 +20,23 @@ import static java.util.Objects.requireNonNull;
/**
* FFprobe implementation of {@link VideoLoader}
*/
public class FFprobeVideoLoader extends AbstractProcessRunner implements VideoLoader {
public class FFprobeVideoLoader implements VideoLoader {
private final Path bundledPath;
private final Path systemPath;
private final ProcessRunner processRunner;
@Inject
FFprobeVideoLoader(@FFprobeBundledPath final Path bundledPath, @FFprobeSystemPath final Path systemPath) {
FFprobeVideoLoader(@FFprobeBundledPath final Path bundledPath, @FFprobeSystemPath final Path systemPath,
final ProcessRunner processRunner) {
this.bundledPath = requireNonNull(bundledPath);
this.systemPath = requireNonNull(systemPath);
this.processRunner = requireNonNull(processRunner);
}
@Override
public Video loadVideo(final Path path) throws IOException {
final var result = run(List.of(getFFprobePath(), "-v", "error", "-select_streams", "v", "-show_entries", "stream=width,height,duration", "-of", "csv=p=0", path.toString()), Duration.ofSeconds(5));
final var result = processRunner.run(List.of(getFFprobePath(), "-v", "error", "-select_streams", "v", "-show_entries", "stream=width,height,duration", "-of", "csv=p=0", path.toString()), Duration.ofSeconds(5));
final var resolution = result.output().getLast();
final var split = resolution.split(",");
final var width = Integer.parseInt(split[0]);

View File

@@ -2,6 +2,7 @@ package com.github.gtache.autosubtitle.setup.ffmpeg;
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
import com.github.gtache.autosubtitle.impl.Architecture;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.setup.SetupException;
import com.github.gtache.autosubtitle.setup.SetupManager;
import com.github.gtache.autosubtitle.setup.SetupStatus;
@@ -32,8 +33,8 @@ public class FFmpegSetupManager extends AbstractSetupManager {
@Inject
FFmpegSetupManager(final FFmpegSetupConfiguration configuration, final ArchiverProvider archiverProvider,
final HttpClient httpClient) {
super(httpClient);
final ProcessRunner processRunner, final HttpClient httpClient) {
super(processRunner, httpClient);
this.configuration = requireNonNull(configuration);
this.archiverProvider = requireNonNull(archiverProvider);
}
@@ -190,7 +191,7 @@ public class FFmpegSetupManager extends AbstractSetupManager {
}
private boolean checkSystemFFmpeg() throws IOException {
final var result = run(List.of(configuration.systemFFmpegPath().toString(), "-version"), Duration.ofSeconds(5));
final var result = processRunner().run(List.of(configuration.systemFFmpegPath().toString(), "-version"), Duration.ofSeconds(5));
return result.exitCode() == 0;
}

View File

@@ -3,6 +3,7 @@ package com.github.gtache.autosubtitle.ffmpeg;
import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.VideoInfo;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
@@ -24,6 +25,7 @@ import static org.mockito.Mockito.when;
class TestFFmpegVideoConverter {
private final FFmpegVideoConverter converter;
private final ProcessRunner runner;
private final SubtitleConverter subtitleConverter;
private final SubtitleConverterProvider subtitleConverterProvider;
private final Video video;
@@ -33,11 +35,12 @@ class TestFFmpegVideoConverter {
private final SubtitleCollection<?> collection;
private final Preferences preferences;
TestFFmpegVideoConverter(@Mock final SubtitleConverter subtitleConverter, @Mock final SubtitleConverterProvider subtitleConverterProvider, @Mock final Video video,
TestFFmpegVideoConverter(@Mock final SubtitleConverter subtitleConverter, @Mock final ProcessRunner runner, @Mock final SubtitleConverterProvider subtitleConverterProvider, @Mock final Video video,
@Mock final VideoInfo videoInfo, @Mock final SubtitleCollection<?> collection, @Mock final Preferences preferences) throws IOException {
final var output = (OS.getOS() == OS.WINDOWS ? System.getProperty("java.io.tmpdir") : "/tmp");
final var resource = OS.getOS() == OS.WINDOWS ? "fake-ffmpeg.exe" : "fake-ffmpeg.sh";
this.video = Objects.requireNonNull(video);
this.runner = Objects.requireNonNull(runner);
this.videoInfo = Objects.requireNonNull(videoInfo);
when(video.info()).thenReturn(videoInfo);
this.tmpFile = Files.createTempFile("fake-ffmpeg", resource.substring(resource.lastIndexOf('.')));
@@ -48,7 +51,7 @@ class TestFFmpegVideoConverter {
this.subtitleConverter = Objects.requireNonNull(subtitleConverter);
this.subtitleConverterProvider = Objects.requireNonNull(subtitleConverterProvider);
this.preferences = Objects.requireNonNull(preferences);
this.converter = new FFmpegVideoConverter(tmpFile, tmpFile, subtitleConverterProvider, preferences);
this.converter = new FFmpegVideoConverter(tmpFile, tmpFile, subtitleConverterProvider, preferences, runner);
this.collection = Objects.requireNonNull(collection);
}

View File

@@ -3,25 +3,32 @@ package com.github.gtache.autosubtitle.ffmpeg;
import com.github.gtache.autosubtitle.impl.FileVideoImpl;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.impl.VideoInfoImpl;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
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.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(MockitoExtension.class)
class TestFFmpegVideoLoader {
private final FFprobeVideoLoader loader;
private final ProcessRunner runner;
private final Path tmpFile;
private final Path outputPath;
TestFFmpegVideoLoader() throws IOException {
TestFFmpegVideoLoader(@Mock final ProcessRunner runner) throws IOException {
final var output = (OS.getOS() == OS.WINDOWS ? System.getProperty("java.io.tmpdir") : "/tmp");
final var resource = OS.getOS() == OS.WINDOWS ? "fake-ffprobe.exe" : "fake-ffprobe.sh";
this.tmpFile = Files.createTempFile("fake-ffprobe", resource.substring(resource.lastIndexOf('.')));
@@ -29,7 +36,8 @@ class TestFFmpegVideoLoader {
Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING);
}
this.outputPath = Path.of(output, "test-ffprobe-output.txt");
this.loader = new FFprobeVideoLoader(tmpFile, tmpFile);
this.runner = Objects.requireNonNull(runner);
this.loader = new FFprobeVideoLoader(tmpFile, tmpFile, runner);
}
@AfterEach