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

@@ -6,6 +6,9 @@ import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.modules.archive.impl.ArchiveModule;
import com.github.gtache.autosubtitle.modules.setup.impl.SetupModule;
import com.github.gtache.autosubtitle.modules.subtitle.impl.SubtitleModule;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.process.impl.ProcessRunnerImpl;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -22,6 +25,9 @@ public abstract class CoreModule {
}
@Binds
abstract ProcessRunner bindsProcessRunner(final ProcessRunnerImpl processRunner);
@Provides
static OS providesOS() {
final var os = OS.getOS();

View File

@@ -6,16 +6,22 @@ import com.github.gtache.autosubtitle.process.ProcessRunner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.inject.Inject;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
/**
* Base implementation of {@link ProcessRunner}
* Implementation of {@link ProcessRunner}
*/
public abstract class AbstractProcessRunner implements ProcessRunner {
public class ProcessRunnerImpl implements ProcessRunner {
private static final Logger logger = LogManager.getLogger(AbstractProcessRunner.class);
private static final Logger logger = LogManager.getLogger(ProcessRunnerImpl.class);
@Inject
ProcessRunnerImpl() {
}
@Override
public ProcessResult run(final List<String> args, final Duration duration) throws IOException {
@@ -37,22 +43,5 @@ public abstract class AbstractProcessRunner implements ProcessRunner {
return new ProcessListenerImpl(process);
}
/**
* Runs a process and writes the output to the log
*
* @param args the command
* @param duration The maximum duration to wait for
* @return the result
* @throws IOException if an error occurs
*/
protected ProcessResult runListen(final List<String> args, final Duration duration) throws IOException {
final var listener = startListen(args);
var line = listener.readLine();
final var processName = args.getFirst();
while (line != null) {
logger.info("[{}]: {}", processName, line);
line = listener.readLine();
}
return listener.join(duration);
}
}

View File

@@ -1,6 +1,6 @@
package com.github.gtache.autosubtitle.setup.impl;
import com.github.gtache.autosubtitle.process.impl.AbstractProcessRunner;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.setup.SetupAction;
import com.github.gtache.autosubtitle.setup.SetupEvent;
import com.github.gtache.autosubtitle.setup.SetupException;
@@ -28,27 +28,23 @@ import static java.util.Objects.requireNonNull;
/**
* Base class for all {@link SetupManager} implementations
*/
public abstract class AbstractSetupManager extends AbstractProcessRunner implements SetupManager {
public abstract class AbstractSetupManager implements SetupManager {
private static final Logger logger = LogManager.getLogger(AbstractSetupManager.class);
private final Set<SetupListener> listeners;
private final HttpClient httpClient;
private final ProcessRunner processRunner;
/**
* Instantiates the manager with a default client
*/
protected AbstractSetupManager() {
this(HttpClient.newHttpClient());
}
/**
* Instantiates the manager with the given client
* Instantiates the manager with the given runner and client
*
* @param httpClient The HTTP client to use
* @param processRunner The process runner
* @param httpClient The HTTP client to use
*/
protected AbstractSetupManager(final HttpClient httpClient) {
this.listeners = new HashSet<>();
protected AbstractSetupManager(final ProcessRunner processRunner, final HttpClient httpClient) {
this.processRunner = requireNonNull(processRunner);
this.httpClient = requireNonNull(httpClient);
this.listeners = new HashSet<>();
}
@Override
@@ -100,6 +96,13 @@ public abstract class AbstractSetupManager extends AbstractProcessRunner impleme
}
}
/**
* @return The process runner used by this manager
*/
protected ProcessRunner processRunner() {
return processRunner;
}
/**
* @return Retrieves the setup status
* @throws SetupException if an error occurred

View File

@@ -1,6 +1,7 @@
package com.github.gtache.autosubtitle.process.impl;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -10,25 +11,25 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class TestAbstractProcessRunner {
class TestProcessRunnerImpl {
private static final List<String> ARGS = OS.getOS() == OS.WINDOWS ? List.of("powershell.exe", "-Command", "\"echo '1\n2\n3'\"") : List.of("echo", "1\n2\n3");
private final DummyProcessRunner dummyProcessRunner;
private final ProcessRunner runner;
TestAbstractProcessRunner() {
this.dummyProcessRunner = new DummyProcessRunner();
TestProcessRunnerImpl() {
this.runner = new ProcessRunnerImpl();
}
@Test
void testRun() throws IOException {
final var expected = new ProcessResultImpl(0, List.of("1", "2", "3"));
final var actual = dummyProcessRunner.run(ARGS, Duration.ofSeconds(5));
final var actual = runner.run(ARGS, Duration.ofSeconds(5));
assertEquals(expected, actual);
}
@Test
void testStart() throws IOException, InterruptedException {
final var process = dummyProcessRunner.start(ARGS);
final var process = runner.start(ARGS);
process.waitFor();
assertEquals(0, process.exitValue());
final var read = new String(process.getInputStream().readAllBytes());
@@ -38,7 +39,7 @@ class TestAbstractProcessRunner {
@Test
void testStartListen() throws IOException {
final var listener = dummyProcessRunner.startListen(ARGS);
final var listener = runner.startListen(ARGS);
assertEquals("1", listener.readLine());
assertEquals("2", listener.readLine());
assertEquals("3", listener.readLine());
@@ -47,15 +48,4 @@ class TestAbstractProcessRunner {
assertEquals(0, result.exitCode());
assertEquals(List.of("1", "2", "3"), result.output());
}
@Test
void testRunListen() throws IOException {
final var result = dummyProcessRunner.runListen(ARGS, Duration.ofSeconds(5));
assertEquals(0, result.exitCode());
assertEquals(List.of("1", "2", "3"), result.output());
}
private static final class DummyProcessRunner extends AbstractProcessRunner {
}
}

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.setup.impl;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.setup.SetupAction;
import com.github.gtache.autosubtitle.setup.SetupEvent;
import com.github.gtache.autosubtitle.setup.SetupException;
@@ -29,18 +30,21 @@ class TestAbstractSetupManager {
private final SetupListener listener2;
private final SetupEvent event;
private final SetupAction setupAction;
private final ProcessRunner processRunner;
private final HttpClient httpClient;
TestAbstractSetupManager(@Mock final SetupListener listener1,
@Mock final SetupListener listener2,
@Mock final SetupEvent event,
@Mock final SetupAction setupAction,
@Mock final ProcessRunner processRunner,
@Mock final HttpClient httpClient) {
this.manager = spy(new DummySetupManager(httpClient));
this.manager = spy(new DummySetupManager(processRunner, httpClient));
this.listener1 = requireNonNull(listener1);
this.listener2 = requireNonNull(listener2);
this.event = requireNonNull(event);
this.setupAction = requireNonNull(setupAction);
this.processRunner = requireNonNull(processRunner);
this.httpClient = requireNonNull(httpClient);
}
@@ -223,13 +227,13 @@ class TestAbstractSetupManager {
@Test
void testIllegal() {
assertThrows(NullPointerException.class, () -> new DummySetupManager(null));
assertThrows(NullPointerException.class, () -> new DummySetupManager(null, null));
}
private static final class DummySetupManager extends AbstractSetupManager {
private DummySetupManager(final HttpClient httpClient) {
super(httpClient);
private DummySetupManager(final ProcessRunner processRunner, final HttpClient httpClient) {
super(processRunner, httpClient);
}
@Override