Skip to content

Commit

Permalink
Fixed incorrect test container logic that allowed tests to start befo…
Browse files Browse the repository at this point in the history
…re the container was fully started (#799)

Signed-off-by: dhoard <[email protected]>
Signed-off-by: Petr Dušák <[email protected]>
  • Loading branch information
dhoard authored and cspetrdusak committed May 12, 2023
1 parent e01e3d0 commit c7254a7
Show file tree
Hide file tree
Showing 29 changed files with 397 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ output.txt
pom.xml.versionsBackup
integration_test_suite/integration_tests/src/test/resources/common/**.jar
output.log
stress-test.log
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@

public class HttpHeader {

public static final String ACCEPT = "Accept";
public static final String AUTHORIZATION = "Authorization";

public static final String CONTENT_TYPE = "Content-Type";

private HttpHeader() {
// DO NOTHING
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ private MetricsParser() {

/**
* Method to parse a response as a list of Metric objects
* <p/>
* <p>
* A List is used because Metrics could have the same name, but with different labels
*
* @param content
* @param content content
* @return the return value
* @throws IOException
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,22 @@
*/
public class BaseResponse implements Response {

private Integer code;
public static final Response RESULT_401 = new BaseResponse().withCode(401);

private Headers headers;
private enum Status {
OBJECT_NULL,
OBJECT_CLASS_MISMATCH,
STATUS_CODE_MISMATCH,
HEADERS_MISMATCH_1,
HEADERS_MISMATCH_2,
HEADERS_MISMATCH_3,
CONTENT_MISMATCH_1,
MATCH }

private Integer code;
private Headers headers;
private boolean hasContent;
private String content;

private Headers.Builder headersBuilder;

/**
Expand Down Expand Up @@ -133,8 +142,16 @@ public String content() {
*/
@Override
public Response isSuperset(Response response) {
if (!checkSuperset(response)) {
throw new AssertionFailedError("Actual response isn't a superset of the expected response");
Status status = checkSuperset(response);
switch (status) {
case MATCH: {
break;
} default: {
throw new AssertionFailedError(
String.format(
"Actual response is not a superset of the expected response, error [%s]",
status));
}
}
return this;
}
Expand Down Expand Up @@ -205,42 +222,46 @@ public int hashCode() {
* @param o o
* @return the return value
*/
private boolean checkSuperset(Object o) {
private Status checkSuperset(Object o) {
if (this == o) {
return true;
return Status.MATCH;
}

if (o == null || getClass() != o.getClass()) {
return false;
if (o == null) {
return Status.OBJECT_NULL;
}

if (getClass() != o.getClass()) {
return Status.OBJECT_CLASS_MISMATCH;
}

BaseResponse that = (BaseResponse) o;

if (!Objects.equals(code, that.code)) {
return false;
if (!Objects.equals(this.code, that.code)) {
return Status.STATUS_CODE_MISMATCH;
}

if ((this.headers != null) && (that.headers == null)) {
return false;
} else if ((this.headers == null) && (that.headers != null)) {
return false;
} else if ((this.headers != null) && (that.headers != null)) {
if (this.headers != null && that.headers == null) {
return Status.HEADERS_MISMATCH_1;
} else if (this.headers == null && that.headers != null) {
return Status.HEADERS_MISMATCH_2;
} else if (this.headers != null && that.headers != null) {
Headers thatHeaders = that.headers;
for (String name : thatHeaders.names()) {
List<String> values = headers.values(name);
List<String> values = this.headers.values(name);
List<String> thatValues = thatHeaders.values(name);
for (String thatValue : thatValues) {
if (!values.contains(thatValue)) {
return false;
return Status.HEADERS_MISMATCH_3;
}
}
}
}

if (that.content != null) {
return Objects.equals(content, that.content);
} else {
return true;
if (that.content != null && !Objects.equals(this.content, that.content)) {
return Status.CONTENT_MISMATCH_1;
}

return Status.MATCH;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
public class HealthyRequest extends BaseRequest {

private static final String CONTENT = "Exporter is Healthy.";

/**
* Constructor
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,4 @@ public class HealthyResponse extends BaseResponse {
private static final String CONTENT = "Exporter is Healthy.";

public static final Response RESULT_200 = new BaseResponse().withCode(200).withContent(CONTENT);
public static final Response RESULT_401 = new BaseResponse().withCode(401);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,4 @@ public class MetricsResponse extends BaseResponse {
private static final String CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";

public static final BaseResponse RESULT_200 = new BaseResponse().withCode(200).withContentType(CONTENT_TYPE);
public static final BaseResponse RESULT_401 = new BaseResponse().withCode(401);

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

public class OpenMetricsResponse extends BaseResponse {

private static String CONTENT_TYPE = "application/openmetrics-text; version=1.0.0; charset=utf-8";
private static final String CONTENT_TYPE = "application/openmetrics-text; version=1.0.0; charset=utf-8";

public static final BaseResponse RESULT_200 = new BaseResponse().withCode(200).withContentType(CONTENT_TYPE);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,4 @@ public class PrometheusMetricsResponse extends BaseResponse {
private static final String CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";

public static final BaseResponse RESULT_200 = new BaseResponse().withCode(200).withContentType(CONTENT_TYPE);
public static final BaseResponse RESULT_401 = new BaseResponse().withCode(401);

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class Abstract_IT {
Expand All @@ -40,6 +41,21 @@ public class Abstract_IT {
private static final long MEMORY_BYTES = 1073741824; // 1GB
private static final long MEMORY_SWAP_BYTES = 2 * MEMORY_BYTES;

private static final Predicate<Integer> STATUS_CODE_200_OR_401_PREDICATE = new Predicate<>() {

/**
* Evaluates this predicate on the given argument.
*
* @param statusCode the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
@Override
public boolean test(Integer statusCode) {
return 200 == statusCode || 401 == statusCode;
}
};

/**
* Method to get the list of Docker image names
*
Expand Down Expand Up @@ -126,7 +142,7 @@ protected static GenericContainer<?> createStandaloneExporterContainer(
// Exporter container
GenericContainer<?> exporterContainer =
new GenericContainer<>(dockerImageName)
.waitingFor(Wait.forHttp("/"))
.waitingFor(Wait.forHttp("/").forStatusCodeMatching(STATUS_CODE_200_OR_401_PREDICATE))
.withClasspathResourceMapping("common", "/temp", BindMode.READ_ONLY)
.withClasspathResourceMapping(testName.replace(".", "/") + "/Standalone", "/temp", BindMode.READ_ONLY)
.withCreateContainerCmdModifier(c -> c.getHostConfig().withMemory(MEMORY_BYTES).withMemorySwap(MEMORY_SWAP_BYTES))
Expand Down Expand Up @@ -159,7 +175,7 @@ protected static GenericContainer<?> createJavaAgentApplicationContainer(
Network network, String dockerImageName, String testName) {
GenericContainer<?> applicationContainer =
new GenericContainer<>(dockerImageName)
.waitingFor(Wait.forHttp("/"))
.waitingFor(Wait.forLogMessage(".*Running.*", 1))
.withClasspathResourceMapping("common", "/temp", BindMode.READ_ONLY)
.withClasspathResourceMapping(testName.replace(".", "/") + "/JavaAgent", "/temp", BindMode.READ_ONLY)
.withCreateContainerCmdModifier(c -> c.getHostConfig().withMemory(MEMORY_BYTES).withMemorySwap(MEMORY_SWAP_BYTES))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright (C) 2022-2023 The Prometheus jmx_exporter Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.prometheus.jmx.test;

import io.prometheus.jmx.test.support.ContentConsumer;
import io.prometheus.jmx.test.support.HealthyRequest;
import io.prometheus.jmx.test.support.HealthyResponse;
import io.prometheus.jmx.test.support.MetricsRequest;
import io.prometheus.jmx.test.support.MetricsResponse;
import org.antublue.test.engine.api.Parameter;
import org.antublue.test.engine.api.ParameterMap;
import org.antublue.test.engine.api.TestEngine;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.shaded.com.google.common.util.concurrent.AtomicDouble;

import java.util.Collection;

import static io.prometheus.jmx.test.support.RequestResponseAssertions.assertThatResponseForRequest;
import static org.assertj.core.api.Assertions.assertThat;

public class AutoIncrementing_IT extends Abstract_IT {

private static final String BASE_URL = "http://localhost";

private static Network network;

private String testName;
private String dockerImageName;
private boolean isJava6;
private Mode mode;

private GenericContainer<?> applicationContainer;
private GenericContainer<?> exporterContainer;
private HttpClient httpClient;

@TestEngine.Parameter
public void parameter(Parameter parameter) {
ParameterMap parameterMap = parameter.value();
testName = getClass().getName();
dockerImageName = parameterMap.get(DOCKER_IMAGE_NAME);
isJava6 = parameterMap.get(IS_JAVA_6);
mode = parameterMap.get(MODE);
}

@TestEngine.BeforeClass
public static void beforeClass() {
network = createNetwork();
}

@TestEngine.BeforeAll
public void beforeAll() {
switch (mode) {
case JavaAgent: {
applicationContainer = createJavaAgentApplicationContainer(network, dockerImageName, testName);
applicationContainer.start();
httpClient = createHttpClient(applicationContainer, BASE_URL);
break;
}
case Standalone: {
applicationContainer = createStandaloneApplicationContainer(network, dockerImageName, testName);
applicationContainer.start();
exporterContainer = createStandaloneExporterContainer(network, dockerImageName, testName);
exporterContainer.start();
httpClient = createHttpClient(exporterContainer, BASE_URL);
break;
}
}
}

@TestEngine.Test
public void testHealthy() {
assertThatResponseForRequest(new HealthyRequest(httpClient))
.isSuperset(HealthyResponse.RESULT_200);
}

@TestEngine.Test
public void testMetrics() {
AtomicDouble value1 = new AtomicDouble();
AtomicDouble value2 = new AtomicDouble();
AtomicDouble value3 = new AtomicDouble();

assertThatResponseForRequest(new MetricsRequest(httpClient))
.isSuperset(MetricsResponse.RESULT_200)
.dispatch((ContentConsumer) content -> {
Collection<Metric> metrics = MetricsParser.parse(content);
metrics
.forEach(metric -> {
if (metric.getName().startsWith("io_prometheus_jmx_autoIncrementing")) {
assertThat(metric.getValue()).isGreaterThanOrEqualTo(1);
value1.set(metric.getValue());
}
});
});

assertThatResponseForRequest(new MetricsRequest(httpClient))
.isSuperset(MetricsResponse.RESULT_200)
.dispatch((ContentConsumer) content -> {
Collection<Metric> metrics = MetricsParser.parse(content);
metrics
.forEach(metric -> {
if (metric.getName().startsWith("io_prometheus_jmx_autoIncrementing")) {
value2.set(metric.getValue());
}
});
});

assertThatResponseForRequest(new MetricsRequest(httpClient))
.isSuperset(MetricsResponse.RESULT_200)
.dispatch((ContentConsumer) content -> {
Collection<Metric> metrics = MetricsParser.parse(content);
metrics
.forEach(metric -> {
if (metric.getName().startsWith("io_prometheus_jmx_autoIncrementing")) {
value3.set(metric.getValue());
}
});
});

// Use value1 as a baseline value
assertThat(value2.get()).isEqualTo(value1.get() + 1);
assertThat(value3.get()).isEqualTo(value2.get() + 1);
}

@TestEngine.AfterAll
public void afterAll() {
destroy(applicationContainer);
destroy(exporterContainer);
httpClient = null;
}

@TestEngine.AfterClass
public static void afterClass() {
destroy(network);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@ public void accept(String content) {
assertThat(metric.getName()).isEqualTo(metric.getName().toLowerCase());
metric
.getLabels()
.entrySet()
.stream()
.forEach(entry -> assertThat(entry.getKey()).isEqualTo(entry.getKey().toLowerCase()));
.forEach((key, value) -> assertThat(key).isEqualTo(key.toLowerCase()));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ public void accept(String content) {
.forEach(metric -> {
metric
.getLabels()
.entrySet()
.stream()
.forEach(entry -> assertThat(entry.getKey()).isEqualTo(entry.getKey().toLowerCase()));
.forEach((key, value) -> assertThat(key).isEqualTo(key.toLowerCase()));
});
}
}
Loading

0 comments on commit c7254a7

Please sign in to comment.