package org.arquillian.cube.docker.impl.client.reporter;
import com.github.dockerjava.api.model.Statistics;
import com.github.dockerjava.api.model.Version;
import org.arquillian.cube.docker.impl.client.CubeDockerConfiguration;
import org.arquillian.cube.docker.impl.client.DefinitionFormat;
import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
import org.arquillian.cube.impl.model.LocalCubeRegistry;
import org.arquillian.cube.spi.Cube;
import org.arquillian.cube.spi.CubeRegistry;
import org.arquillian.cube.spi.event.lifecycle.AfterAutoStart;
import org.arquillian.cube.spi.event.lifecycle.BeforeStop;
import org.arquillian.reporter.api.builder.BuilderLoader;
import org.arquillian.reporter.api.event.SectionEvent;
import org.arquillian.reporter.api.event.Standalone;
import org.arquillian.reporter.api.model.entry.FileEntry;
import org.arquillian.reporter.api.model.entry.KeyValueEntry;
import org.arquillian.reporter.api.model.report.BasicReport;
import org.arquillian.reporter.api.model.report.Report;
import org.arquillian.reporter.config.ReporterConfiguration;
import org.jboss.arquillian.core.api.Event;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.IOException;
import java.util.*;
import static org.arquillian.cube.docker.impl.client.reporter.DockerEnvironmentReportKey.*;
import static org.arquillian.reporter.impl.asserts.ReportAssert.assertThatReport;
import static org.arquillian.reporter.impl.asserts.SectionAssert.assertThatSection;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class TakeDockerEnvironmentTest {
private static final String MULTIPLE_PORT_BINDING_SCENARIO =
"helloworld:\n" +
" image: dockercloud/hello-world\n" +
" exposedPorts: [8089/tcp]\n" +
" networkMode: host\n" +
" portBindings: [8080->80/tcp, 8081->81/tcp]";
private static final String CUBE_ID = "tomcat";
@Mock
DockerClientExecutor dockerClientExecutor;
@Mock
Version version;
@Mock
Event<SectionEvent> reportEvent;
@Mock
private Cube cube;
@Captor
ArgumentCaptor<SectionEvent> reportEventArgumentCaptor;
private CubeRegistry cubeRegistry;
@Mock
private Statistics statistics;
@Before
public void setUpCubeDockerExecutorAndBuilder() throws IOException {
configureDockerExecutor();
configureCube();
BuilderLoader.load();
}
private void configureDockerExecutor() {
when(version.getVersion()).thenReturn("1.1.0");
when(version.getOperatingSystem()).thenReturn("linux");
when(version.getKernelVersion()).thenReturn("3.1.0");
when(version.getApiVersion()).thenReturn("1.12");
when(version.getArch()).thenReturn("x86");
when(dockerClientExecutor.dockerHostVersion()).thenReturn(version);
}
private void configureCube() throws IOException {
cubeRegistry = new LocalCubeRegistry();
when(cube.getId()).thenReturn(CUBE_ID);
cubeRegistry.addCube(cube);
when(statistics.getNetworks()).thenReturn(getNetworks());
when(statistics.getMemoryStats()).thenReturn(getMemory());
when(statistics.getBlkioStats()).thenReturn(getIOStats());
when(dockerClientExecutor.statsContainer(CUBE_ID)).thenReturn(statistics);
}
private void createTakeDockerEnvironmentAndreportDockerEnvironment() {
final TakeDockerEnvironment takeDockerEnvironment = new TakeDockerEnvironment();
takeDockerEnvironment.reportEvent = reportEvent;
Map<String, String> configuration = new HashMap<>();
configuration.put(CubeDockerConfiguration.DOCKER_CONTAINERS, MULTIPLE_PORT_BINDING_SCENARIO);
configuration.put("definitionFormat", DefinitionFormat.CUBE.name());
takeDockerEnvironment.reportDockerEnvironment(new AfterAutoStart(), CubeDockerConfiguration.fromMap(configuration, null), dockerClientExecutor, getReporterConfiguration());
}
@Test
public void should_report_docker_info() {
createTakeDockerEnvironmentAndreportDockerEnvironment();
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final SectionEvent sectionEvent = reportEventArgumentCaptor.getValue();
assertThatSection(sectionEvent)
.hasSectionId(Standalone.getStandaloneId())
.hasReportOfTypeThatIsAssignableFrom(BasicReport.class);
final Report report = sectionEvent.getReport();
final List<Report> subReports = report.getSubReports();
assertThatReport(subReports.get(0))
.hasName(DOCKER_HOST_INFORMATION)
.hasNumberOfEntries(5)
.hasEntriesContaining(
new KeyValueEntry(DOCKER_VERSION, "1.1.0"),
new KeyValueEntry(DOCKER_OS, "linux"),
new KeyValueEntry(DOCKER_KERNEL, "3.1.0"),
new KeyValueEntry(DOCKER_API_VERSION, "1.12"),
new KeyValueEntry(DOCKER_ARCH, "x86"));
}
@Test
public void should_report_schema_of_docker_composition_and_network_topology() {
createTakeDockerEnvironmentAndreportDockerEnvironment();
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final SectionEvent sectionEvent = reportEventArgumentCaptor.getValue();
assertThatSection(sectionEvent)
.hasSectionId(Standalone.getStandaloneId())
.hasReportOfTypeThatIsAssignableFrom(BasicReport.class);
final Report report = sectionEvent.getReport();
assertThatReport(report)
.hasName(DOCKER_ENVIRONMENT)
.hasNumberOfSubReports(1)
.hasEntriesContaining(
new KeyValueEntry(DOCKER_COMPOSITION_SCHEMA, new FileEntry("reports/schemas/docker_composition.png")),
new KeyValueEntry(NETWORK_TOPOLOGY_SCHEMA, new FileEntry("reports/networks/docker_network_topology.png")));
}
@Test
public void should_report_log_file() throws IOException {
final TakeDockerEnvironment takeDockerEnvironment = new TakeDockerEnvironment();
takeDockerEnvironment.reportEvent = reportEvent;
takeDockerEnvironment.reportContainerLogs(new BeforeStop(CUBE_ID), dockerClientExecutor, getReporterConfiguration());
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final SectionEvent sectionEvent = reportEventArgumentCaptor.getValue();
assertThatSection(sectionEvent)
.hasSectionId(CUBE_ID)
.hasReportOfTypeThatIsAssignableFrom(BasicReport.class);
final Report report = sectionEvent.getReport();
assertThatReport(report)
.hasNumberOfEntries(1)
.hasEntriesContaining(new KeyValueEntry(LOG_PATH, new FileEntry("reports/logs/tomcat.log")));
}
/* @Test
public void should_report_container_network_stats() throws IOException, NoSuchMethodException {
final TakeDockerEnvironment takeDockerEnvironment = new TakeDockerEnvironment();
takeDockerEnvironment.propertyReportEvent = reportEvent;
takeDockerEnvironment.captureContainerStatsBeforeTest(new org.jboss.arquillian.test.spi.event.suite.Before(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_memory_stats")), dockerClientExecutor, cubeRegistry);
takeDockerEnvironment.reportContainerStatsAfterTest(new After(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_network_stats")), dockerClientExecutor, cubeRegistry);
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final PropertyReportEvent propertyReportEvent = reportEventArgumentCaptor.getValue();
final PropertyEntry propertyEntry = propertyReportEvent.getPropertyEntry();
assertThat(propertyEntry).isInstanceOf(GroupEntry.class);
GroupEntry parent = (GroupEntry) propertyEntry;
final List<PropertyEntry> rootEntries = parent.getPropertyEntries();
assertThat(rootEntries).hasSize(3);
List<PropertyEntry> entryList = rootEntries.get(2).getPropertyEntries();
assertThat(entryList).hasSize(1).extracting("class.simpleName").containsExactly("TableEntry");
TableEntry tableEntry = (TableEntry) entryList.get(0);
assertThat(tableEntry).extracting("tableHead").extracting("row").flatExtracting("cells").
hasSize(3).containsExactly(new TableCellEntry("Adapter"), new TableCellEntry("rx_bytes", 3, 1), new TableCellEntry("tx_bytes", 3, 1));
assertThat(tableEntry).extracting("tableBody").flatExtracting("rows").hasSize(3);
assertThat(tableEntry.getTableBody().getRows().get(1).getCells()).hasSize(7).extractingResultOf("getContent").
containsExactly("eth0", "724 B", "724 B", "0 B", "418 B", "418 B", "0 B");
assertThat(tableEntry.getTableBody().getRows().get(2).getCells()).hasSize(7).extractingResultOf("getContent").
containsExactly("Total", "724 B", "724 B", "0 B", "418 B", "418 B", "0 B");
}
@Test
public void should_report_container_memory_stats() throws IOException, NoSuchMethodException {
final TakeDockerEnvironment takeDockerEnvironment = new TakeDockerEnvironment();
takeDockerEnvironment.propertyReportEvent = reportEvent;
takeDockerEnvironment.captureContainerStatsBeforeTest(new org.jboss.arquillian.test.spi.event.suite.Before(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_memory_stats")), dockerClientExecutor, cubeRegistry);
takeDockerEnvironment.reportContainerStatsAfterTest(new After(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_memory_stats")), dockerClientExecutor, cubeRegistry);
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final PropertyReportEvent propertyReportEvent = reportEventArgumentCaptor.getValue();
final PropertyEntry propertyEntry = propertyReportEvent.getPropertyEntry();
assertThat(propertyEntry).isInstanceOf(GroupEntry.class);
GroupEntry parent = (GroupEntry) propertyEntry;
final List<PropertyEntry> rootEntries = parent.getPropertyEntries();
assertThat(rootEntries).hasSize(3);
List<PropertyEntry> entryList = rootEntries.get(0).getPropertyEntries();
assertThat(entryList).hasSize(1).extracting("class.simpleName").containsExactly("TableEntry");
TableEntry tableEntry = (TableEntry) entryList.get(0);
assertThat(tableEntry).extracting("tableHead").extracting("row").flatExtracting("cells").
hasSize(3).containsExactly(new TableCellEntry("usage", 3, 1), new TableCellEntry("max_usage", 3, 1), new TableCellEntry("limit"));
assertThat(tableEntry).extracting("tableBody").flatExtracting("rows").hasSize(2);
TableRowEntry rowEntry = tableEntry.getTableBody().getRows().get(1);
assertThat(rowEntry.getCells()).hasSize(7).extractingResultOf("getContent").
containsExactly("33.51 MiB", "33.51 MiB", "0 B", "34.11 MiB", "34.11 MiB", "0 B", "19.04 GiB");
}
@Test
public void should_report_container_blkio_stats() throws IOException, NoSuchMethodException {
final TakeDockerEnvironment takeDockerEnvironment = new TakeDockerEnvironment();
takeDockerEnvironment.propertyReportEvent = reportEvent;
takeDockerEnvironment.captureContainerStatsBeforeTest(new org.jboss.arquillian.test.spi.event.suite.Before(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_memory_stats")), dockerClientExecutor, cubeRegistry);
takeDockerEnvironment.reportContainerStatsAfterTest(new After(TakeDockerEnvironmentTest.class, TakeDockerEnvironmentTest.class.getMethod("should_report_container_blkio_stats")), dockerClientExecutor, cubeRegistry);
verify(reportEvent).fire(reportEventArgumentCaptor.capture());
final PropertyReportEvent propertyReportEvent = reportEventArgumentCaptor.getValue();
final PropertyEntry propertyEntry = propertyReportEvent.getPropertyEntry();
assertThat(propertyEntry).isInstanceOf(GroupEntry.class);
GroupEntry parent = (GroupEntry) propertyEntry;
final List<PropertyEntry> rootEntries = parent.getPropertyEntries();
assertThat(rootEntries).hasSize(3);
List<PropertyEntry> entryList = rootEntries.get(1).getPropertyEntries();
assertThat(entryList).hasSize(1).extracting("class.simpleName").containsExactly("TableEntry");
TableEntry tableEntry = (TableEntry) entryList.get(0);
assertThat(tableEntry).extracting("tableHead").extracting("row").flatExtracting("cells").
hasSize(2).containsExactly(new TableCellEntry("io_bytes_read", 3, 1), new TableCellEntry("io_bytes_write", 3, 1));
assertThat(tableEntry).extracting("tableBody").flatExtracting("rows").hasSize(2);
TableRowEntry rowEntry = tableEntry.getTableBody().getRows().get(1);
assertThat(rowEntry.getCells()).hasSize(6).extractingResultOf("getContent").
containsExactly("49.50 KiB", "49.50 KiB", "0 B", "0 B", "0 B", "0 B");
}
*/
private ReporterConfiguration getReporterConfiguration() {
return ReporterConfiguration.fromMap(new LinkedHashMap<>());
}
private Map<String, Object> getNetworks() {
Map<String, Object> nw = new LinkedHashMap<>();
Map<String, Integer> bytes = new LinkedHashMap<>();
bytes.put("rx_bytes", 724);
bytes.put("tx_bytes", 418);
bytes.put("rx_packets", 19);
nw.put("eth0", bytes);
return nw;
}
private Map<String, Object> getMemory() {
Map<String, Object> memory = new LinkedHashMap<>();
memory.put("usage", 35135488);
memory.put("max_usage", 35770368);
memory.put("limit", 20444532736L);
memory.put("stats", new LinkedHashMap<>());
return memory;
}
private Map<String, Object> getIOStats() {
Map<String, Object> blkIO = new LinkedHashMap<>();
List<LinkedHashMap<String, ?>> io = new ArrayList<>();
LinkedHashMap ioServiceRead = new LinkedHashMap();
ioServiceRead.put("major", 7);
ioServiceRead.put("minor", 0);
ioServiceRead.put("op", "Read");
ioServiceRead.put("value", 50688);
io.add(ioServiceRead);
LinkedHashMap ioServiceWrite = new LinkedHashMap();
ioServiceWrite.put("major", 7);
ioServiceWrite.put("minor", 0);
ioServiceWrite.put("op", "Write");
ioServiceWrite.put("value", 0);
io.add(ioServiceWrite);
LinkedHashMap ioServiceSync = new LinkedHashMap();
ioServiceSync.put("major", 7);
ioServiceSync.put("minor", 0);
ioServiceSync.put("op", "Sync");
ioServiceSync.put("value", 0);
io.add(ioServiceSync);
blkIO.put("io_service_bytes_recursive", io);
blkIO.put("io_time_recursive", new ArrayList<>());
return blkIO;
}
}