From 4a4cb1d9fc5485ad878080d916b5007b0ad258e3 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Wed, 26 Feb 2025 10:14:36 -0500 Subject: [PATCH] flesh out tests --- .../java/io/cryostat/AbstractTestBase.java | 97 ++++++ .../AbstractTransactionalTestBase.java | 76 +--- .../discovery/DiscoveryPluginTest.java | 282 +++++++++++++++ .../io/cryostat/discovery/DiscoveryTest.java | 68 ---- src/test/java/itest/DiscoveryPluginIT.java | 326 ------------------ 5 files changed, 380 insertions(+), 469 deletions(-) create mode 100644 src/test/java/io/cryostat/AbstractTestBase.java create mode 100644 src/test/java/io/cryostat/discovery/DiscoveryPluginTest.java delete mode 100644 src/test/java/itest/DiscoveryPluginIT.java diff --git a/src/test/java/io/cryostat/AbstractTestBase.java b/src/test/java/io/cryostat/AbstractTestBase.java new file mode 100644 index 000000000..88e734448 --- /dev/null +++ b/src/test/java/io/cryostat/AbstractTestBase.java @@ -0,0 +1,97 @@ +/* + * Copyright The Cryostat 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.cryostat; + +import static io.restassured.RestAssured.given; + +import java.time.Duration; + +import io.cryostat.util.HttpStatusCodeIdentifier; + +import io.restassured.http.ContentType; +import jakarta.inject.Inject; +import org.apache.http.client.utils.URLEncodedUtils; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jboss.logging.Logger; +import org.junit.jupiter.api.BeforeEach; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; + +public abstract class AbstractTestBase { + + public static final String SELF_JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi"; + public static String SELF_JMX_URL_ENCODED = + URLEncodedUtils.formatSegments(SELF_JMX_URL).substring(1); + public static final String SELFTEST_ALIAS = "selftest"; + + @ConfigProperty(name = "storage.buckets.archives.name") + String archivesBucket; + + @ConfigProperty(name = "test.storage.timeout", defaultValue = "5m") + Duration storageTimeout; + + @ConfigProperty(name = "test.storage.retry", defaultValue = "5s") + Duration storageRetry; + + @Inject Logger logger; + @Inject S3Client storage; + + @BeforeEach + void waitForStorage() throws InterruptedException { + long totalTime = 0; + while (!bucketExists(archivesBucket)) { + long start = System.nanoTime(); + Thread.sleep(storageRetry.toMillis()); + long elapsed = System.nanoTime() - start; + totalTime += elapsed; + if (Duration.ofNanos(totalTime).compareTo(storageTimeout) > 0) { + throw new IllegalStateException("Storage took too long to become ready"); + } + } + } + + private boolean bucketExists(String bucket) { + boolean exists = false; + try { + exists = + HttpStatusCodeIdentifier.isSuccessCode( + storage.headBucket(HeadBucketRequest.builder().bucket(bucket).build()) + .sdkHttpResponse() + .statusCode()); + logger.debugv("Storage bucket \"{0}\" exists? {1}", bucket, exists); + } catch (Exception e) { + logger.warn(e); + } + return exists; + } + + protected int defineSelfCustomTarget() { + return given().basePath("/") + .log() + .all() + .contentType(ContentType.URLENC) + .formParam("connectUrl", SELF_JMX_URL) + .formParam("alias", SELFTEST_ALIAS) + .when() + .post("/api/v4/targets") + .then() + .log() + .all() + .extract() + .jsonPath() + .getInt("id"); + } +} diff --git a/src/test/java/io/cryostat/AbstractTransactionalTestBase.java b/src/test/java/io/cryostat/AbstractTransactionalTestBase.java index 6c6537570..cf17984a7 100644 --- a/src/test/java/io/cryostat/AbstractTransactionalTestBase.java +++ b/src/test/java/io/cryostat/AbstractTransactionalTestBase.java @@ -15,72 +15,15 @@ */ package io.cryostat; -import static io.restassured.RestAssured.given; - -import java.time.Duration; - -import io.cryostat.util.HttpStatusCodeIdentifier; - -import io.restassured.http.ContentType; import jakarta.inject.Inject; -import org.apache.http.client.utils.URLEncodedUtils; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.flywaydb.core.Flyway; -import org.jboss.logging.Logger; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.HeadBucketRequest; - -public abstract class AbstractTransactionalTestBase { - - public static final String SELF_JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi"; - public static String SELF_JMX_URL_ENCODED = - URLEncodedUtils.formatSegments(SELF_JMX_URL).substring(1); - public static final String SELFTEST_ALIAS = "selftest"; - - @ConfigProperty(name = "storage.buckets.archives.name") - String archivesBucket; - - @ConfigProperty(name = "test.storage.timeout", defaultValue = "5m") - Duration storageTimeout; - @ConfigProperty(name = "test.storage.retry", defaultValue = "5s") - Duration storageRetry; +public abstract class AbstractTransactionalTestBase extends AbstractTestBase { - @Inject Logger logger; - @Inject S3Client storage; @Inject Flyway flyway; - @BeforeEach - void waitForStorage() throws InterruptedException { - long totalTime = 0; - while (!bucketExists(archivesBucket)) { - long start = System.nanoTime(); - Thread.sleep(storageRetry.toMillis()); - long elapsed = System.nanoTime() - start; - totalTime += elapsed; - if (Duration.ofNanos(totalTime).compareTo(storageTimeout) > 0) { - throw new IllegalStateException("Storage took too long to become ready"); - } - } - } - - private boolean bucketExists(String bucket) { - boolean exists = false; - try { - exists = - HttpStatusCodeIdentifier.isSuccessCode( - storage.headBucket(HeadBucketRequest.builder().bucket(bucket).build()) - .sdkHttpResponse() - .statusCode()); - logger.debugv("Storage bucket \"{0}\" exists? {1}", bucket, exists); - } catch (Exception e) { - logger.warn(e); - } - return exists; - } - @BeforeEach void migrate() { flyway.migrate(); @@ -91,21 +34,4 @@ void cleanup() { flyway.clean(); flyway.migrate(); } - - protected int defineSelfCustomTarget() { - return given().basePath("/") - .log() - .all() - .contentType(ContentType.URLENC) - .formParam("connectUrl", SELF_JMX_URL) - .formParam("alias", SELFTEST_ALIAS) - .when() - .post("/api/v4/targets") - .then() - .log() - .all() - .extract() - .jsonPath() - .getInt("id"); - } } diff --git a/src/test/java/io/cryostat/discovery/DiscoveryPluginTest.java b/src/test/java/io/cryostat/discovery/DiscoveryPluginTest.java new file mode 100644 index 000000000..d9165782e --- /dev/null +++ b/src/test/java/io/cryostat/discovery/DiscoveryPluginTest.java @@ -0,0 +1,282 @@ +/* + * Copyright The Cryostat 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.cryostat.discovery; + +import static io.restassured.RestAssured.given; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.cryostat.AbstractTransactionalTestBase; +import io.cryostat.targets.Target; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +@QuarkusTest +public class DiscoveryPluginTest extends AbstractTransactionalTestBase { + + @Nested + class Validations { + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {"invalid uri", "no.protocol.example.com"}) + void rejectsInvalidCallback(String callback) { + var payload = new HashMap<>(); + payload.put("callback", callback); + payload.put("realm", "test"); + given().log() + .all() + .when() + .body(payload) + .contentType(ContentType.JSON) + .post("/api/v4/discovery") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(400); + } + + @ParameterizedTest + @NullAndEmptySource + void rejectsInvalidRealmName(String realm) { + var payload = new HashMap<>(); + payload.put("callback", "http://example.com"); + payload.put("realm", realm); + given().log() + .all() + .when() + .body(payload) + .contentType(ContentType.JSON) + .post("/api/v4/discovery") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(400); + } + + @Test + void rejectsPublishForUnregisteredPlugin() { + given().log() + .all() + .when() + .body(List.of()) + .contentType(ContentType.JSON) + .post("/api/v4/discovery/abcd1234") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(404); + } + } + + @Test + void workflow() { + // store credentials + var credentialId = + given().log() + .all() + .when() + .formParams( + Map.of( + "username", + "user", + "password", + "pass", + "matchExpression", + "target.connectUrl ==" + + " 'http://localhost:8081/health/liveness'")) + .contentType(ContentType.URLENC) + .post("/api/v4/credentials") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(201) + .contentType(ContentType.JSON) + .extract() + .jsonPath() + .getLong("id"); + + // register + var realmName = "test_realm"; + var callback = + String.format( + "http://storedcredentials:%d@localhost:8081/health/liveness", credentialId); + var registration = + given().log() + .all() + .when() + .body(Map.of("realm", realmName, "callback", callback)) + .contentType(ContentType.JSON) + .post("/api/v4/discovery") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(200) + .contentType(ContentType.JSON) + .extract() + .jsonPath(); + var pluginId = registration.getString("id"); + var pluginToken = registration.getString("token"); + MatcherAssert.assertThat(pluginId, Matchers.is(Matchers.not(Matchers.emptyOrNullString()))); + MatcherAssert.assertThat( + pluginToken, Matchers.is(Matchers.not(Matchers.emptyOrNullString()))); + + // test what happens if we publish an update that we have no discoverable targets + given().log() + .all() + .when() + .body(List.of()) + .contentType(ContentType.JSON) + .queryParams(Map.of("token", pluginToken)) + .post(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(204); + + // test what happens if we try to publish an invalid node - in this case, one containing no + // target definition + var node = new Node(null, BaseNodeType.JVM.name(), null); + given().log() + .all() + .when() + .body(List.of(node)) + .contentType(ContentType.JSON) + .queryParams(Map.of("token", pluginToken)) + .post(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(400); + + // test what happens if we publish an acceptable singleton list + var target = new Target(URI.create("http://localhost:8081"), "test-node"); + node = new Node("test-node", BaseNodeType.JVM.name(), target); + given().log() + .all() + .when() + .body(List.of(node)) + .contentType(ContentType.JSON) + .queryParams(Map.of("token", pluginToken)) + .post(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(204); + + // refresh + var refreshedRegistration = + given().log() + .all() + .when() + .body( + Map.of( + "id", + pluginId, + "token", + pluginToken, + "realm", + realmName, + "callback", + callback)) + .contentType(ContentType.JSON) + .post("/api/v4/discovery") + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(200) + .contentType(ContentType.JSON) + .extract() + .jsonPath(); + var refreshedPluginId = refreshedRegistration.getString("id"); + var refreshedPluginToken = refreshedRegistration.getString("token"); + MatcherAssert.assertThat(refreshedPluginId, Matchers.equalTo(pluginId)); + MatcherAssert.assertThat(refreshedPluginToken, Matchers.not(Matchers.equalTo(pluginToken))); + + // deregister + given().log() + .all() + .when() + .queryParams(Map.of("token", pluginToken)) + .delete(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(204); + + // double deregister + given().log() + .all() + .when() + .queryParams(Map.of("token", pluginToken)) + .delete(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(404); + + // publish update when not registered + given().log() + .all() + .when() + .body(List.of(node)) + .contentType(ContentType.JSON) + .queryParams(Map.of("token", pluginToken)) + .post(String.format("/api/v4/discovery/%s", pluginId)) + .then() + .log() + .all() + .and() + .assertThat() + .statusCode(404); + } + + record Node(String name, String nodeType, Target target) {} + + record Target(URI connectUrl, String alias) {} +} diff --git a/src/test/java/io/cryostat/discovery/DiscoveryTest.java b/src/test/java/io/cryostat/discovery/DiscoveryTest.java index 18d623f9f..726e24d62 100644 --- a/src/test/java/io/cryostat/discovery/DiscoveryTest.java +++ b/src/test/java/io/cryostat/discovery/DiscoveryTest.java @@ -17,7 +17,6 @@ import static io.restassured.RestAssured.given; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,14 +27,7 @@ import io.restassured.http.ContentType; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.NullAndEmptySource; -import org.junit.jupiter.params.provider.ValueSource; @QuarkusTest @TestHTTPEndpoint(Discovery.class) @@ -95,64 +87,4 @@ void getDiscoveryPlugins() { Matchers.equalTo("id"), Matchers.not(Matchers.blankOrNullString()))); } } - - @Nested - class PluginValidations { - @ParameterizedTest - @NullAndEmptySource - @ValueSource(strings = {"invalid uri", "no.protocol.example.com"}) - void rejectsInvalidCallback(String callback) { - Map payload = new HashMap<>(); - payload.put("callback", callback); - payload.put("realm", "test"); - given().log() - .all() - .when() - .body(payload) - .contentType(ContentType.JSON) - .post("/api/v4/discovery") - .then() - .log() - .all() - .and() - .assertThat() - .statusCode(400); - } - - @ParameterizedTest - @NullAndEmptySource - void rejectsInvalidRealmName(String realm) { - Map payload = new HashMap<>(); - payload.put("callback", "http://example.com"); - payload.put("realm", realm); - given().log() - .all() - .when() - .body(payload) - .contentType(ContentType.JSON) - .post("/api/v4/discovery") - .then() - .log() - .all() - .and() - .assertThat() - .statusCode(400); - } - - @Test - void rejectsPublishForUnregisteredPlugin() { - given().log() - .all() - .when() - .body(List.of()) - .contentType(ContentType.JSON) - .post("/api/v4/discovery/abcd1234") - .then() - .log() - .all() - .and() - .assertThat() - .statusCode(404); - } - } } diff --git a/src/test/java/itest/DiscoveryPluginIT.java b/src/test/java/itest/DiscoveryPluginIT.java deleted file mode 100644 index e17b1597f..000000000 --- a/src/test/java/itest/DiscoveryPluginIT.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright The Cryostat 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 itest; - -import java.net.URI; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.json.JsonArray; -import io.vertx.core.json.JsonObject; -import itest.bases.StandardSelfTest; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -@QuarkusIntegrationTest -@Disabled("TODO") -@TestMethodOrder(OrderAnnotation.class) -class DiscoveryPluginIT extends StandardSelfTest { - - final String realm = getClass().getSimpleName(); - final URI callback = URI.create("http://localhost:8181/"); - private static volatile String id; - private static volatile String token; - - @Test - @Order(1) - void shouldBeAbleToRegister() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", realm, "callback", callback)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonObject()); - }); - JsonObject resp = response.get(); - JsonObject info = resp.getJsonObject("data").getJsonObject("result"); - DiscoveryPluginIT.id = info.getString("id"); - DiscoveryPluginIT.token = info.getString("token"); - MatcherAssert.assertThat(id, Matchers.not(Matchers.emptyOrNullString())); - MatcherAssert.assertThat(token, Matchers.not(Matchers.emptyOrNullString())); - } - - @Test - @Order(2) - void shouldFailToRegisterWithNonUriCallback() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", realm, "callback", "not a valid URI")); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(3) - void shouldBeAbleToUpdate() throws InterruptedException, ExecutionException { - JsonObject service = new JsonObject(Map.of("connectUrl", callback, "alias", "mynode")); - JsonObject target = - new JsonObject( - Map.of( - "target", - service, - "name", - getClass().getSimpleName(), - "nodeType", - "JVM")); - JsonArray subtree = new JsonArray(List.of(target)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery/" + id) - .addQueryParam("token", token) - .sendJson( - subtree, - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().body()); - }); - response.get(); - } - - @Test - @Order(4) - void shouldFailToUpdateWithInvalidSubtreeJson() - throws InterruptedException, ExecutionException { - JsonObject service = new JsonObject(Map.of("connectUrl", callback, "alias", "mynode")); - JsonObject target = - new JsonObject( - Map.of( - "target", - service, - "name", - getClass().getSimpleName(), - "nodeType", - "JVM")); - JsonArray subtree = new JsonArray(List.of(target)); - String body = subtree.encode().replaceAll("\\[", "").replaceAll("\\]", ""); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery/" + id) - .addQueryParam("token", token) - .sendBuffer( - Buffer.buffer(body), - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(5) - void shouldFailToReregisterWithoutToken() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", realm, "callback", callback)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(6) - void shouldBeAbleToRefreshToken() throws InterruptedException, ExecutionException { - JsonObject body = - new JsonObject( - Map.of("id", id, "realm", realm, "callback", callback, "token", token)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - // intentionally don't include this header on refresh - it should still work - // .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonObject()); - }); - JsonObject resp = response.get(); - JsonObject info = resp.getJsonObject("data").getJsonObject("result"); - String newId = info.getString("id"); - MatcherAssert.assertThat(newId, Matchers.equalTo(DiscoveryPluginIT.id)); - MatcherAssert.assertThat(newId, Matchers.not(Matchers.emptyOrNullString())); - DiscoveryPluginIT.id = newId; - - String newToken = info.getString("token"); - MatcherAssert.assertThat(newToken, Matchers.not(Matchers.equalTo(DiscoveryPluginIT.token))); - MatcherAssert.assertThat(token, Matchers.not(Matchers.emptyOrNullString())); - DiscoveryPluginIT.token = newToken; - } - - @Test - @Order(7) - void shouldBeAbleToDeregister() throws InterruptedException, ExecutionException { - CompletableFuture response = new CompletableFuture<>(); - webClient - .delete("/api/v4/discovery/" + id) - .addQueryParam("token", token) - .send( - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(200)); - } - - @Test - @Order(8) - void shouldFailToDoubleDeregister() throws InterruptedException, ExecutionException { - CompletableFuture response = new CompletableFuture<>(); - webClient - .delete("/api/v4/discovery/" + id) - .addQueryParam("token", token) - .send( - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(404)); - } - - @Test - @Order(9) - void shouldFailToUpdateUnregisteredPluginID() throws InterruptedException, ExecutionException { - JsonObject service = new JsonObject(Map.of("connectUrl", callback, "alias", "mynode")); - JsonObject target = - new JsonObject( - Map.of( - "target", - service, - "name", - getClass().getSimpleName(), - "nodeType", - "JVM")); - JsonArray subtree = new JsonArray(List.of(target)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery/" + UUID.randomUUID()) - .addQueryParam("token", token) - .sendJson( - subtree, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(404)); - } - - @Test - @Order(10) - void shouldFailToRegisterNullCallback() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", realm)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(11) - void shouldFailToRegisterEmptyCallback() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", realm, "callback", "")); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(12) - void shouldFailToRegisterNullRealm() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("callback", callback)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } - - @Test - @Order(13) - void shouldFailToRegisterEmptyRealm() throws InterruptedException, ExecutionException { - JsonObject body = new JsonObject(Map.of("realm", "", "callback", callback)); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v4/discovery") - .putHeader("Authorization", "None") - .sendJson( - body, - ar -> { - response.complete(ar.result().statusCode()); - }); - int code = response.get(); - MatcherAssert.assertThat(code, Matchers.equalTo(400)); - } -}