Skip to content

Commit

Permalink
Add ProcessLaunchHealthCheck (#51)
Browse files Browse the repository at this point in the history
* Add ProcessLaunchHealthCheck

Closes #41
  • Loading branch information
chrisrohr authored Dec 9, 2020
1 parent 0bac376 commit dd56eac
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.kiwiproject.dropwizard.util.health;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.kiwiproject.metrics.health.HealthCheckResults.newHealthyResult;
import static org.kiwiproject.metrics.health.HealthCheckResults.newUnhealthyResult;

import com.codahale.metrics.health.HealthCheck;
import lombok.extern.slf4j.Slf4j;
import org.kiwiproject.base.process.ProcessHelper;
import org.kiwiproject.io.KiwiIO;

/**
* Health check that checks if we are able to launch processes. This check attempts to launch a simple echo process
* and verifies the output is as expected.
*
* @implNote Only works on *nix-like systems, or maybe in Windows if there is an echo command installed and on the PATH.
*/
@Slf4j
public class ProcessLaunchHealthCheck extends HealthCheck {

static final String ECHO_MESSAGE = "Launch process health check";

private final ProcessHelper processes;

public ProcessLaunchHealthCheck(ProcessHelper processes) {
this.processes = processes;
}

@Override
protected Result check() {
try {
var process = processes.launch("echo", ECHO_MESSAGE);
var line = KiwiIO.readInputStreamOf(process, UTF_8);
return resultBasedOnEchoOutput(line);
} catch (Exception e) {
LOG.trace("Process launch health check is not healthy", e);
return newUnhealthyResult("Failed launching an 'echo' process: " + e.getMessage());
}
}

private static Result resultBasedOnEchoOutput(String line) {
if (ECHO_MESSAGE.equals(line.stripTrailing())) {
return newHealthyResult();
}

return newUnhealthyResult("Output [%s] from 'echo' does not match expected [%s]", line, ECHO_MESSAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package org.kiwiproject.dropwizard.util.health;

import static org.kiwiproject.base.KiwiStrings.f;
import static org.kiwiproject.dropwizard.util.health.ProcessLaunchHealthCheck.ECHO_MESSAGE;
import static org.kiwiproject.test.assertj.dropwizard.metrics.HealthCheckResultAssertions.assertThatHealthCheck;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.base.Charsets;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.kiwiproject.base.process.ProcessHelper;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;

@DisplayName("ProcessLaunchHealthCheck")
class ProcessLaunchHealthCheckTest {

private ProcessLaunchHealthCheck healthCheck;
private ProcessHelper processes;
private Process process;

@BeforeEach
void setup() {
process = mock(Process.class);
processes = mock(ProcessHelper.class);
healthCheck = new ProcessLaunchHealthCheck(processes);
}

@Nested
class IsHealthy {

@Test
void whenEchoProcessCanBeLaunched() {
when(processes.launch("echo", ECHO_MESSAGE)).thenReturn(process);

var inputStream = toInputStream(ECHO_MESSAGE);
when(process.getInputStream()).thenReturn(inputStream);

assertThatHealthCheck(healthCheck)
.isHealthy();
}

/**
* Only running on Linux and MacOS since we know for a fact that 'echo' exists there.
*/
@Test
@EnabledOnOs({OS.LINUX, OS.MAC})
void whenEchoProcessCanBeLaunched_UsingActualProcess() {
healthCheck = new ProcessLaunchHealthCheck(new ProcessHelper());

assertThatHealthCheck(healthCheck)
.isHealthy();
}
}

@Nested
class IsUnhealthy {

@Test
void whenEchoMessageDoesNotMatchExpectedOutput() {
when(processes.launch("echo", ECHO_MESSAGE)).thenReturn(process);

var droidsMessage = "These are not the droids you're looking for.. ";
var inputStream = toInputStream(droidsMessage);
when(process.getInputStream()).thenReturn(inputStream);

assertThatHealthCheck(healthCheck)
.isUnhealthy()
.hasMessage(f("Output [{}] from 'echo' does not match expected [{}]",
droidsMessage, ECHO_MESSAGE));
}

@Test
void whenExceptionIsThrown() {
var message = "Process launch failure";
IOException ioException = new IOException(message);
UncheckedIOException uncheckedIOException = new UncheckedIOException(ioException);

when(processes.launch("echo", ECHO_MESSAGE)).thenThrow(uncheckedIOException);

assertThatHealthCheck(healthCheck)
.isUnhealthy()
.hasMessageStartingWith("Failed launching an 'echo' process: ")
.hasMessageEndingWith(uncheckedIOException.getMessage());
}
}

private InputStream toInputStream(String value) {
return new ByteArrayInputStream(value.getBytes(Charsets.UTF_8));
}
}

0 comments on commit dd56eac

Please sign in to comment.