copy all .json and .html reports from docker container

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2020-10-29 15:39:54 +11:00
parent 7ced55d18b
commit d5222df896
2 changed files with 104 additions and 61 deletions

View File

@ -19,9 +19,7 @@
package org.eclipse.jetty.websocket.core.autobahn; package org.eclipse.jetty.websocket.core.autobahn;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -32,21 +30,22 @@ import java.util.List;
import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.exception.NotFoundException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser; import org.json.simple.parser.JSONParser;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.testcontainers.containers.BindMode; import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.startupcheck.StartupCheckStrategy;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerStatus;
import org.testcontainers.utility.TestcontainersConfiguration; import org.testcontainers.utility.TestcontainersConfiguration;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -54,7 +53,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@Testcontainers @Testcontainers
public class AutobahnTests public class AutobahnTests
{ {
static static
{ {
TestcontainersConfiguration.getInstance().getProperties().setProperty("transport.type", "httpclient5"); TestcontainersConfiguration.getInstance().getProperties().setProperty("transport.type", "httpclient5");
@ -62,76 +60,52 @@ public class AutobahnTests
private static final Logger LOG = LoggerFactory.getLogger(AutobahnTests.class); private static final Logger LOG = LoggerFactory.getLogger(AutobahnTests.class);
private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
private static final String CHOWN_REPORTS_CMD = "[ -d /target/reports ] && chown -R `stat -c '%u' /target/reports` /target/reports/* && touch done.txt";
private Path reportDir; private static Path reportDir;
private Path fuzzingServer; private static Path fuzzingServer;
private Path fuzzingClient; private static Path fuzzingClient;
Path baseDir; @BeforeAll
public static void before() throws Exception
@BeforeEach
public void before() throws Exception
{ {
String workspace; String workspace;
workspace = System.getenv().get("WORKSPACE"); workspace = System.getenv().get("WORKSPACE");
LOG.info("Workspace: {}", workspace); LOG.info("Workspace: {}", workspace);
LOG.info("User Dir: {}", USER_DIR); LOG.info("User Dir: {}", USER_DIR);
baseDir = USER_DIR;//(workspace != null) ? Paths.get(workspace) : USER_DIR;
LOG.info("Base Dir: {}", baseDir);
fuzzingServer = baseDir.resolve("fuzzingserver.json"); fuzzingServer = USER_DIR.resolve("fuzzingserver.json");
assertTrue(Files.exists(fuzzingServer), fuzzingServer + " not exists"); assertTrue(Files.exists(fuzzingServer), fuzzingServer + " not exists");
fuzzingClient = baseDir.resolve("fuzzingclient.json"); fuzzingClient = USER_DIR.resolve("fuzzingclient.json");
assertTrue(Files.exists(fuzzingClient), fuzzingClient + " not exists"); assertTrue(Files.exists(fuzzingClient), fuzzingClient + " not exists");
reportDir = baseDir.resolve("target/reports"); reportDir = USER_DIR.resolve("target/reports");
if (!Files.exists(reportDir)) IO.delete(reportDir.toFile());
Files.createDirectory(reportDir); Files.createDirectory(reportDir);
} }
@Test @Test
public void testClient() throws Exception public void testClient() throws Exception
{ {
// We need to chown the generated test results so host has permissions to delete files generated by container. GenericContainer<?> container = new GenericContainer<>("crossbario/autobahn-testsuite:latest")
try (GenericContainer<?> container = new GenericContainer<>("crossbario/autobahn-testsuite:latest") .withCommand("/bin/bash", "-c", "wstest -m fuzzingserver -s /config/fuzzingserver.json")
.withCommand("/bin/bash", "-c", "wstest -m fuzzingserver -s /config/fuzzingserver.json ; " + CHOWN_REPORTS_CMD)
.withExposedPorts(9001) .withExposedPorts(9001)
.withLogConsumer(new Slf4jLogConsumer(LOG))) .withLogConsumer(new Slf4jLogConsumer(LOG));
container.addFileSystemBind(fuzzingServer.toString(), "/config/fuzzingserver.json", BindMode.READ_ONLY);
try
{ {
container.addFileSystemBind(fuzzingServer.toString(), "/config/fuzzingserver.json", BindMode.READ_ONLY);
container.addFileSystemBind(reportDir.toString(), "/target/reports", BindMode.READ_WRITE);
// we simply declare it as started once we get the file
File indexJson = new File(reportDir.toFile(), "index.json");
container.withStartupCheckStrategy(new StartupCheckStrategy()
{
@Override
public StartupStatus checkStartupState(DockerClient dockerClient, String containerId )
{
try(InputStream done = dockerClient.copyArchiveFromContainerCmd( containerId, "done.txt" ).exec();
InputStream inputStream =
dockerClient.copyArchiveFromContainerCmd( containerId, "/target/reports/clients/index.json" ).exec();
TarArchiveInputStream tarInputStream = new TarArchiveInputStream( inputStream))
{
tarInputStream.getNextEntry();
Files.copy(tarInputStream, indexJson.toPath());
return StartupStatus.SUCCESSFUL;
} catch (NotFoundException e){
// ignore as file not ready yet
}
catch ( Exception e )
{
throw new RuntimeException(e.getMessage(),e);
}
// still no file so we declare this not ready yet
return StartupStatus.NOT_YET_KNOWN;
}
});
container.start(); container.start();
Integer mappedPort = container.getMappedPort(9001); Integer mappedPort = container.getMappedPort(9001);
CoreAutobahnClient.main(new String[]{"localhost", mappedPort.toString()}); CoreAutobahnClient.main(new String[]{"localhost", mappedPort.toString()});
IO.copy(reportDir.toFile(), baseDir.resolve("target/reports-client").toFile());
DockerClient dockerClient = container.getDockerClient();
String containerId = container.getContainerId();
copyFromContainer(dockerClient, containerId, reportDir, Paths.get("/target/reports/clients"));
}
finally
{
container.stop();
} }
LOG.info("Test Result Overview {}", reportDir.resolve("clients/index.html").toUri()); LOG.info("Test Result Overview {}", reportDir.resolve("clients/index.html").toUri());
@ -144,16 +118,15 @@ public class AutobahnTests
final int port = 9001; final int port = 9001;
org.testcontainers.Testcontainers.exposeHostPorts(port); org.testcontainers.Testcontainers.exposeHostPorts(port);
Server server = CoreAutobahnServer.startAutobahnServer(port); Server server = CoreAutobahnServer.startAutobahnServer(port);
// We need to chown the generated test results so host has permissions to delete files generated by container.
FileSignalWaitStrategy strategy = new FileSignalWaitStrategy(reportDir, Paths.get("/target/reports/servers"));
try (GenericContainer<?> container = new GenericContainer<>("crossbario/autobahn-testsuite:latest") try (GenericContainer<?> container = new GenericContainer<>("crossbario/autobahn-testsuite:latest")
.withCommand("/bin/bash", "-c", "wstest -m fuzzingclient -s /config/fuzzingclient.json ; " + CHOWN_REPORTS_CMD) .withCommand("/bin/bash", "-c", "wstest -m fuzzingclient -s /config/fuzzingclient.json" + FileSignalWaitStrategy.END_COMMAND)
.withLogConsumer(new Slf4jLogConsumer(LOG)) .withLogConsumer(new Slf4jLogConsumer(LOG))
.withStartupCheckStrategy(new OneShotStartupCheckStrategy().withTimeout(Duration.ofHours(1)))) .withStartupCheckStrategy(strategy))
{ {
container.addFileSystemBind(fuzzingClient.toString(), "/config/fuzzingclient.json", BindMode.READ_ONLY); container.addFileSystemBind(fuzzingClient.toString(), "/config/fuzzingclient.json", BindMode.READ_ONLY);
container.addFileSystemBind(reportDir.toString(), "/target/reports", BindMode.READ_WRITE);
container.start(); container.start();
IO.copy(reportDir.toFile(), baseDir.resolve("target/reports-server").toFile());
} }
finally finally
{ {
@ -163,6 +136,75 @@ public class AutobahnTests
LOG.info("Test Result Overview {}", reportDir.resolve("servers/index.html").toUri()); LOG.info("Test Result Overview {}", reportDir.resolve("servers/index.html").toUri());
} }
private static class FileSignalWaitStrategy extends StartupCheckStrategy
{
public static final String SIGNAL_FILE = "/signalComplete";
public static final String END_COMMAND = " && touch " + SIGNAL_FILE + " && sleep infinity";
Path _localDir;
Path _containerDir;
public FileSignalWaitStrategy(Path localDir, Path containerDir)
{
_localDir = localDir;
_containerDir = containerDir;
withTimeout(Duration.ofHours(2));
}
@Override
public StartupCheckStrategy.StartupStatus checkStartupState(DockerClient dockerClient, String containerId)
{
// If the container was stopped then we have failed to copy out the file.
if (DockerStatus.isContainerStopped(getCurrentState(dockerClient, containerId)))
return StartupStatus.FAILED;
try
{
dockerClient.copyArchiveFromContainerCmd(containerId, SIGNAL_FILE).exec().close();
}
catch (FileNotFoundException | NotFoundException e)
{
return StartupStatus.NOT_YET_KNOWN;
}
catch (Throwable t)
{
LOG.warn("Unknown Error", t);
return StartupStatus.FAILED;
}
try
{
copyFromContainer(dockerClient, containerId, _localDir, _containerDir);
return StartupStatus.SUCCESSFUL;
}
catch (Throwable t)
{
LOG.warn("Error copying reports", t);
return StartupStatus.FAILED;
}
}
}
private static void copyFromContainer(DockerClient dockerClient, String containerId, Path target, Path source) throws Exception
{
try (TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(dockerClient
.copyArchiveFromContainerCmd(containerId, source.toString())
.exec()))
{
ArchiveEntry archiveEntry;
while ((archiveEntry = tarArchiveInputStream.getNextEntry()) != null)
{
Path filePath = target.resolve(archiveEntry.getName());
if (archiveEntry.isDirectory())
{
if (!Files.exists(filePath))
Files.createDirectory(filePath);
continue;
}
Files.copy(tarArchiveInputStream, filePath);
}
}
}
private static List<AutobahnCaseResult> parseResults( String agentString, Path jsonPath) throws Exception { private static List<AutobahnCaseResult> parseResults( String agentString, Path jsonPath) throws Exception {
List<AutobahnCaseResult> results = new ArrayList<>(); List<AutobahnCaseResult> results = new ArrayList<>();

View File

@ -74,7 +74,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
public class CoreAutobahnClient public class CoreAutobahnClient
{ {
public static void main(String[] args) public static void main(String[] args) throws Exception
{ {
String hostname = "localhost"; String hostname = "localhost";
int port = 9001; int port = 9001;
@ -131,6 +131,7 @@ public class CoreAutobahnClient
catch (Throwable t) catch (Throwable t)
{ {
LOG.warn("Test Failed", t); LOG.warn("Test Failed", t);
throw t;
} }
finally finally
{ {