Skip to content

Commit

Permalink
[V1] external container itests (#387)
Browse files Browse the repository at this point in the history
* External container integration tests (#376)

* Update instructions for manual itest rerun

* Set up test container inside a pod

* Add basic external container discovery test

Add test and utils to run an external container within the test pod, check that ContainerJFR discovers it, and then tear down

* Move utility classes into util package

* Mark test as disabled rather than commented out

* Rename base class

* Set pod name as property rather than hard-coded

* Refactoring

* Correct BasicCommandChannelIT expected hostnames
  • Loading branch information
andrewazores authored Jan 8, 2021
1 parent 3050fbb commit e62cce5
Show file tree
Hide file tree
Showing 14 changed files with 352 additions and 30 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Unit tests can be run with `mvn test`. Integration tests and additional quality
tools can be run with `mvn verify`.

To re-run integration tests without a rebuild, do
`mvn exec:exec@start-container failsafe:integration-test
exec:exec@stop-container`.
`mvn exec:exec@create-pod exec:exec@start-container exec:exec@wait-for-container
failsafe:integration-test exec:exec@stop-container exec:exec@destroy-pod`.

An OCI image can be built to your local `podman` image registry using
`mvn package`. This will normally be a full-fledged image including built
Expand Down
44 changes: 39 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<containerjfr.webPort>8181</containerjfr.webPort>
<containerjfr.listenPort>9090</containerjfr.listenPort>
<containerjfr.itest.webPort>8181</containerjfr.itest.webPort>
<containerjfr.itest.podName>container-jfr-itests</containerjfr.itest.podName>

<org.apache.maven.plugins.compiler.version>3.6.1</org.apache.maven.plugins.compiler.version>
<org.apache.maven.plugins.surefire.version>3.0.0-M4</org.apache.maven.plugins.surefire.version>
Expand Down Expand Up @@ -212,6 +213,26 @@
</additionalClasspathElements>
</configuration>
<executions>
<execution>
<id>create-pod</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${imageBuilder}</executable>
<arguments>
<argument>pod</argument>
<argument>create</argument>
<argument>--replace</argument>
<argument>--name=${containerjfr.itest.podName}</argument>
<argument>--publish</argument>
<argument>${containerjfr.rjmxPort}:${containerjfr.rjmxPort}</argument>
<argument>--publish</argument>
<argument>${containerjfr.itest.webPort}:${containerjfr.itest.webPort}</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
Expand All @@ -222,16 +243,12 @@
<executable>${imageBuilder}</executable>
<arguments>
<argument>run</argument>
<argument>--hostname=container-jfr</argument>
<argument>--pod=${containerjfr.itest.podName}</argument>
<argument>--name=container-jfr-itest</argument>
<argument>--mount</argument>
<argument>type=tmpfs,target=/flightrecordings</argument>
<argument>--mount</argument>
<argument>type=tmpfs,target=/templates</argument>
<argument>--publish</argument>
<argument>${containerjfr.rjmxPort}:${containerjfr.rjmxPort}</argument>
<argument>--publish</argument>
<argument>${containerjfr.itest.webPort}:${containerjfr.itest.webPort}</argument>
<argument>--env</argument>
<argument>CONTAINER_JFR_DISABLE_JMX_AUTH=true</argument>
<argument>--env</argument>
Expand Down Expand Up @@ -288,6 +305,22 @@
</arguments>
</configuration>
</execution>
<execution>
<id>destroy-pod</id>
<phase>post-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${imageBuilder}</executable>
<arguments>
<argument>pod</argument>
<argument>rm</argument>
<argument>--force</argument>
<argument>${containerjfr.itest.podName}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
Expand Down Expand Up @@ -320,6 +353,7 @@
<configuration>
<systemPropertyVariables>
<containerJfrWebPort>${containerjfr.itest.webPort}</containerJfrWebPort>
<containerJfrPodName>${containerjfr.itest.podName}</containerJfrPodName>
</systemPropertyVariables>
</configuration>
</plugin>
Expand Down
11 changes: 5 additions & 6 deletions src/test/java/itest/BasicCommandChannelIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@
import org.junit.jupiter.api.Test;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import itest.util.Utils;

public class BasicCommandChannelIT extends ITestBase {
public class BasicCommandChannelIT extends TestBase {

@Test
public void shouldGetPingResponse() throws Exception {
Expand All @@ -75,7 +76,7 @@ public void shouldGetHostnameResponse() throws Exception {
JsonObject resp = sendMessage("hostname").get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertResponseStatus(resp);
String hostname = resp.getString("payload");
MatcherAssert.assertThat(hostname, Matchers.equalTo("container-jfr"));
MatcherAssert.assertThat(hostname, Matchers.equalTo("container-jfr-itests"));
}

@Test
Expand All @@ -84,9 +85,7 @@ public void shouldGetUrlResponse() throws Exception {
assertResponseStatus(resp);
String url = resp.getString("payload");
MatcherAssert.assertThat(
url,
Matchers.equalTo(
String.format("http://0.0.0.0:%d", IntegrationTestUtils.WEB_PORT)));
url, Matchers.equalTo(String.format("http://0.0.0.0:%d", Utils.WEB_PORT)));
}

@Test
Expand Down Expand Up @@ -120,7 +119,7 @@ public void shouldGetScanTargetsResponse() throws Exception {
new JsonObject(
Map.of(
"connectUrl",
"service:jmx:rmi:///jndi/rmi://container-jfr:9091/jmxrmi",
"service:jmx:rmi:///jndi/rmi://container-jfr-itests:9091/jmxrmi",
"alias",
"com.redhat.rhjmc.containerjfr.ContainerJfr"));
MatcherAssert.assertThat(
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/itest/ClientAssetsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

public class ClientAssetsIT extends ITestBase {
public class ClientAssetsIT extends TestBase {

static File file;
static Document doc;
Expand Down
5 changes: 3 additions & 2 deletions src/test/java/itest/ClientUrlIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@
import org.junit.jupiter.api.Test;
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpRequest;
import itest.util.Utils;

public class ClientUrlIT extends ITestBase {
public class ClientUrlIT extends TestBase {

HttpRequest<Buffer> req;

Expand Down Expand Up @@ -122,6 +123,6 @@ public void shouldReturnJsonMessage() throws Exception {
Matchers.equalTo(
String.format(
"{\"clientUrl\":\"ws://0.0.0.0:%d/api/v1/command\"}",
IntegrationTestUtils.WEB_PORT)));
Utils.WEB_PORT)));
}
}
117 changes: 117 additions & 0 deletions src/test/java/itest/ConnectToExternalTargetsIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*-
* #%L
* Container JFR
* %%
* Copyright (C) 2020 Red Hat, Inc.
* %%
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or data
* (collectively the "Software"), free of charge and under any and all copyright
* rights in the Software, and any and all patent rights owned or freely
* licensable by each licensor hereunder covering either (i) the unmodified
* Software as contributed to or provided by such licensor, or (ii) the Larger
* Works (as defined below), to deal in both
*
* (a) the Software, and
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software (each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
* The above copyright notice and either this complete permission notice or at
* a minimum a reference to the UPL must be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* #L%
*/
package itest;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import io.vertx.core.json.JsonArray;
import itest.util.Podman;

class ConnectToExternalTargetsIT extends TestBase {

static final List<String> CONTAINERS = new ArrayList<>();

@BeforeAll
static void setup() throws Exception {
Set<String> specs = Set.of("quay.io/andrewazores/vertx-fib-demo:0.3.0");
for (String spec : specs) {
CONTAINERS.add(Podman.run(spec));
}
for (String id : CONTAINERS) {
Podman.waitForContainerState(id, "running");
}
Thread.sleep(7_500L); // wait for JDP to discover new containers
}

@AfterAll
static void cleanup() throws Exception {
for (String id : CONTAINERS) {
Podman.rm(id);
}
}

@Test
void testOtherContainerFound() throws Exception {
CompletableFuture<JsonArray> resp = new CompletableFuture<>();
webClient
.get("/api/v1/targets")
.send(
ar -> {
if (assertRequestStatus(ar, resp)) {
resp.complete(ar.result().bodyAsJsonArray());
}
});
JsonArray listResp = resp.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
Set<Map<String, String>> actual = new HashSet<>(listResp.getList());
// ordering may not be guaranteed so use a Set, but there should be no duplicates and so
// size should not change
MatcherAssert.assertThat(actual.size(), Matchers.equalTo(listResp.size()));
Set<Map<String, String>> expected =
Set.of(
Map.of(
"connectUrl",
String.format(
"service:jmx:rmi:///jndi/rmi://%s:9091/jmxrmi",
Podman.POD_NAME),
"alias",
"com.redhat.rhjmc.containerjfr.ContainerJfr"),
Map.of(
"connectUrl",
String.format(
"service:jmx:rmi:///jndi/rmi://%s:9093/jmxrmi",
Podman.POD_NAME),
"alias",
"es.andrewazor.demo.Main"));
MatcherAssert.assertThat(actual, Matchers.equalTo(expected));
}
}
2 changes: 1 addition & 1 deletion src/test/java/itest/GrafanaDashboardIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpRequest;

public class GrafanaDashboardIT extends ITestBase {
public class GrafanaDashboardIT extends TestBase {

HttpRequest<Buffer> req;

Expand Down
7 changes: 5 additions & 2 deletions src/test/java/itest/GrafanaDatasourceIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpRequest;

public class GrafanaDatasourceIT extends ITestBase {
public class GrafanaDatasourceIT extends TestBase {

HttpRequest<Buffer> req;

Expand All @@ -61,7 +63,8 @@ void createRequest() {

// Disabled for now due to conflict with UploadRecordingIT;
// See https://github.com/rh-jmc-team/container-jfr/pull/229
// @Test
@Disabled
@Test
public void shouldFail() throws Exception {
CompletableFuture<Integer> future = new CompletableFuture<>();
req.send(
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/itest/NoopAuthIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpRequest;

public class NoopAuthIT extends ITestBase {
public class NoopAuthIT extends TestBase {

HttpRequest<Buffer> req;

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/itest/RecordingWorkflowIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

public class RecordingWorkflowIT extends ITestBase {
public class RecordingWorkflowIT extends TestBase {

static final String TARGET_ID = "localhost";
static final String TEST_RECORDING_NAME = "workflow_itest";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,18 @@
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import itest.util.Utils;

public abstract class ITestBase {
public abstract class TestBase {

static final int REQUEST_TIMEOUT_SECONDS = 30;
static final WebClient webClient = IntegrationTestUtils.getWebClient();
static final WebClient webClient = Utils.getWebClient();

static CompletableFuture<JsonObject> sendMessage(String command, String... args)
throws InterruptedException, ExecutionException, TimeoutException {
CompletableFuture<JsonObject> future = new CompletableFuture<>();

IntegrationTestUtils.HTTP_CLIENT.webSocket(
Utils.HTTP_CLIENT.webSocket(
getClientUrl().get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS),
ar -> {
if (ar.failed()) {
Expand Down Expand Up @@ -176,7 +177,7 @@ private static CompletableFuture<Path> fireDownloadRequest(
new Exception(String.format("HTTP %d", resp.statusCode())));
return;
}
FileSystem fs = IntegrationTestUtils.getFileSystem();
FileSystem fs = Utils.getFileSystem();
String file = fs.createTempFileBlocking(filename, fileSuffix);
fs.writeFileBlocking(file, ar.result().body());
future.complete(Paths.get(file));
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/itest/UploadRecordingIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpResponse;

public class UploadRecordingIT extends ITestBase {
public class UploadRecordingIT extends TestBase {

static final String TARGET_ID = "localhost";
static final String RECORDING_NAME = "upload_recording_it_rec";
Expand Down
Loading

0 comments on commit e62cce5

Please sign in to comment.