From 3565a6c30f6e3ad3c0d985201fc51654b8bdd6bf Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Wed, 18 Feb 2026 09:00:52 +1300
Subject: [PATCH 01/89] WIP
---
pom.xml | 5 +
.../v1/vectorize/EnvironmentalRequest.java | 6 +
.../api/v1/vectorize/ITCollection.java | 148 +++++++++++++
.../jsonapi/api/v1/vectorize/ITElement.java | 15 ++
.../sgv2/jsonapi/api/v1/vectorize/ITFile.java | 22 ++
.../jsonapi/api/v1/vectorize/ITMetadata.java | 3 +
.../api/v1/vectorize/IntegrationEnv.java | 35 ++++
.../api/v1/vectorize/IntegrationJob.java | 62 ++++++
.../v1/vectorize/IntegrationJobRunner.java | 34 +++
.../api/v1/vectorize/IntegrationTest.java | 42 ++++
.../v1/vectorize/IntegrationTestRunner.java | 197 ++++++++++++++++++
.../api/v1/vectorize/IntegrationWorkflow.java | 11 +
.../jsonapi/api/v1/vectorize/RunnerBase.java | 34 +++
.../api/v1/vectorize/TestAssertion.java | 5 +
.../jsonapi/api/v1/vectorize/TestItem.java | 12 ++
.../jsonapi/api/v1/vectorize/TestRequest.java | 89 ++++++++
.../jsonapi/api/v1/vectorize/VectorizeIT.java | 24 +++
.../api/v1/vectorize/VectorizeUnit.java | 22 ++
.../assertions/AssertionFactory.java | 12 ++
.../v1/vectorize/assertions/Documents.java | 18 ++
.../v1/vectorize/assertions/ITAssertion.java | 11 +
.../api/v1/vectorize/assertions/Response.java | 13 ++
.../integration-tests/vectorize/open-ai.json | 30 +++
.../vectorize/vectorize-base.json | 83 ++++++++
.../vectorize/vectorize-workflow.json | 56 +++++
25 files changed, 989 insertions(+)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITCollection.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITElement.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITFile.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITMetadata.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationEnv.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJob.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationTest.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationTestRunner.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationWorkflow.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/RunnerBase.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestAssertion.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestItem.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeIT.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeUnit.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/ITAssertion.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
create mode 100644 src/test/resources/integration-tests/vectorize/open-ai.json
create mode 100644 src/test/resources/integration-tests/vectorize/vectorize-base.json
create mode 100644 src/test/resources/integration-tests/vectorize/vectorize-workflow.json
diff --git a/pom.xml b/pom.xml
index e64847c597..1bcfa72c12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,11 @@
+
+ com.jayway.jsonpath
+ json-path
+ 2.10.0
+
io.quarkus
quarkus-arc
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
new file mode 100644
index 0000000000..82587e992b
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
@@ -0,0 +1,6 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+public interface EnvironmentalRequest {
+
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITCollection.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITCollection.java
new file mode 100644
index 0000000000..44268839cb
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITCollection.java
@@ -0,0 +1,148 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.jayway.jsonpath.Configuration;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
+import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class ITCollection {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private final Configuration config =
+ Configuration.builder()
+ .jsonProvider(new JacksonJsonNodeJsonProvider())
+ .mappingProvider(new JacksonMappingProvider())
+ .build();
+
+ List itFiles;
+
+ private ITCollection(List itFiles) {
+ this.itFiles = itFiles;
+ for (ITFile file : itFiles) {
+ if (file.element() instanceof IntegrationTest it){
+ it.expand(this);
+ }
+ }
+ }
+
+ public IntegrationWorkflow workflowFirstByName(String name) {
+ var path = "$.meta[?(@.name == '%s')]".formatted(name);
+
+ var itFile =
+ match(ITElement.ITElementKind.WORKFLOW, path).stream()
+ .findFirst()
+ .orElseThrow(
+ () ->
+ new IllegalArgumentException(
+ "No IT file found with meta.name == '%s'".formatted(name)));
+ return (IntegrationWorkflow) itFile.element();
+ }
+
+ public IntegrationTest testsFirstByName(String name) {
+ return testsByName(name).getFirst();
+ }
+
+ public List testsByName(String name) {
+ var path = "$.meta[?(@.name == '%s')]".formatted(name);
+
+ return match(ITElement.ITElementKind.TEST, path).stream()
+ .map(itFile -> (IntegrationTest) itFile.element())
+ .toList();
+ }
+
+ private List byKind(ITElement.ITElementKind kind) {
+ return itFiles.stream().filter(itFile -> itFile.element().kind() == kind).toList();
+ }
+
+ private List match(ITElement.ITElementKind kind, String jsonPath) {
+ var compiled = JsonPath.compile(jsonPath);
+
+ return byKind(kind).stream().filter(itFile -> hasMatch(itFile.root(), compiled)).toList();
+ }
+
+ private boolean hasMatch(JsonNode root, JsonPath compiled) {
+ var pathResult = JsonPath.using(config).parse(root).read(compiled);
+
+ return switch (pathResult) {
+ case null -> false;
+ case java.util.Collection> c -> !c.isEmpty();
+ case java.util.Map, ?> m -> !m.isEmpty();
+ case ArrayNode a -> !a.isEmpty();
+ case ObjectNode o -> !o.isEmpty();
+ default -> true;
+ };
+ }
+
+ static ITCollection loadAll(String path) {
+ final Path dir = resourceDir(path);
+
+ List itFiles = new ArrayList<>();
+
+ try (Stream s = Files.walk(dir)) {
+ itFiles =
+ s.filter(Files::isRegularFile)
+ .filter(p -> p.getFileName().toString().endsWith(".json"))
+ .map(ITCollection::loadOne)
+ .toList();
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed reading test resources under: " + dir, e);
+ }
+ return new ITCollection(itFiles);
+ }
+
+ private static ITFile loadOne(Path file) {
+ try {
+ var root = MAPPER.readTree(file.toFile());
+
+ JsonNode kindNode = root.path("meta").path("kind");
+ if (!kindNode.isTextual()) {
+ throw new IllegalArgumentException("Missing/invalid meta.kind in " + file);
+ }
+
+ var kind = kindNode.asText();
+ var element =
+ switch (kind.toUpperCase()) {
+ case "TEST" -> MAPPER.treeToValue(root, IntegrationTest.class);
+ case "WORKFLOW" -> MAPPER.treeToValue(root, IntegrationWorkflow.class);
+ default ->
+ throw new IllegalArgumentException("Unknown meta.kind '" + kind + "' in " + file);
+ };
+ return new ITFile(element, root);
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed parsing JSON file: " + file, e);
+ }
+ }
+
+ private static Path resourceDir(String path) {
+ String normalized = path.startsWith("/") ? path.substring(1) : path;
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ URL url = cl.getResource(normalized);
+ if (url == null) {
+ throw new IllegalArgumentException("Test resource folder not found: " + path);
+ }
+
+ try {
+ // Works for file: URLs; if you run tests from a jar, switch to getResourceAsStream-based
+ // walking.
+ return Paths.get(url.toURI());
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Bad resource URI for: " + path + " -> " + url, e);
+ }
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITElement.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITElement.java
new file mode 100644
index 0000000000..e2314448be
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITElement.java
@@ -0,0 +1,15 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+public interface ITElement {
+
+ ITElementKind kind();
+
+ ITMetadata meta();
+
+ // void setJson(JsonNode json);
+
+ enum ITElementKind {
+ TEST,
+ WORKFLOW
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITFile.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITFile.java
new file mode 100644
index 0000000000..85f9087916
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITFile.java
@@ -0,0 +1,22 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class ITFile {
+
+ private final ITElement element;
+ private final JsonNode root;
+
+ ITFile(ITElement element, JsonNode root) {
+ this.element = element;
+ this.root = root;
+ }
+
+ public ITElement element() {
+ return element;
+ }
+
+ public JsonNode root() {
+ return root;
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITMetadata.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITMetadata.java
new file mode 100644
index 0000000000..828a6dfd77
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/ITMetadata.java
@@ -0,0 +1,3 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+public record ITMetadata(String name, String kind) {}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationEnv.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationEnv.java
new file mode 100644
index 0000000000..f8346c2c42
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationEnv.java
@@ -0,0 +1,35 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Map;
+
+public record IntegrationEnv(Map vars) {
+ private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationEnv.class);
+
+ private static final List SCHEMA_IDENTIFIER = List.of("COLLECTION_NAME");
+
+ public IntegrationEnv {
+
+ for (var name : SCHEMA_IDENTIFIER) {
+ if (vars.containsKey(name)) {
+ var oldValue = vars.get(name);
+ var newValue = oldValue.replaceAll("[^A-Za-z0-9_]", "_");
+
+ if (newValue.length() > 48){
+ throw new RuntimeException("Schema Identifier longer than 48 characters %s=%s".formatted(name,newValue));
+ }
+ LOGGER.info("XXX Updated IntegrationEnv value because it is a Schema Identifier key={}, oldValue={}, newValue={}",name,oldValue,newValue);
+ vars.put(name, newValue);
+ }
+ }
+ }
+ public String requiredValue(String name){
+ if (vars.containsKey(name)){
+ return vars.get(name);
+ }
+ throw new RuntimeException(String.format("Required parameter %s not found", name));
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJob.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJob.java
new file mode 100644
index 0000000000..cc34b490cb
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJob.java
@@ -0,0 +1,62 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+
+import io.stargate.sgv2.jsonapi.api.model.command.CommandErrorFactory;
+import org.apache.commons.text.StringSubstitutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public record IntegrationJob(
+ ITMetadata meta,
+ Map fromEnvironment,
+ Map variables,
+ Map> matrix,
+ List tests) {
+ private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationJob.class);
+
+
+ public List allEnvironments() {
+
+ Map fromEnv = new HashMap<>();
+ for (Map.Entry entry : fromEnvironment.entrySet()) {
+ var value = System.getenv(entry.getValue());
+ if (value== null) {
+ throw new RuntimeException("Environment variable " + entry.getValue() + " is undefined");
+ }
+ fromEnv.put(entry.getKey(), value);
+ }
+
+ // TODO: handle more matrix
+ var modelList = matrix.get("MODEL");
+
+ List
+ */
public record BodyAssertion(
String bodyPath,
Matcher> matcher
) implements AssertionMatcher {
public void match(APIResponse apiResponse) {
-
apiResponse.validatableResponse().body(bodyPath(), matcher());
}
}
\ No newline at end of file
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
index 0dafee15c2..cd4dbc5078 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
@@ -1,18 +1,30 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.Matchers.hasSize;
+/**
+ * Assertions that check the `document` or `documents` in the `data` field
+ * of the API result.
+ *
+ * See {@link TestAssertion}
+ *
+ */
public class Documents {
- public static AssertionMatcher count(JsonNode args) {
+ static {
+ AssertionMatcher.FACTORY_REGISTRY.register(Documents.class);
+ }
+
+ public static AssertionMatcher count(TestCommand testCommand, JsonNode args) {
var expectedCount = args.asInt();
return new BodyAssertion("data.documents", hasSize(expectedCount));
}
- public static AssertionMatcher isExactly(JsonNode args) {
+ public static AssertionMatcher isExactly(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("data.document", jsonEquals(args));
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
new file mode 100644
index 0000000000..f9424f0aee
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
@@ -0,0 +1,16 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import org.apache.http.HttpStatus;
+
+public class Http {
+
+ static {
+ AssertionMatcher.FACTORY_REGISTRY.register(Http.class);
+ }
+
+ public static AssertionMatcher success(TestCommand testCommand, JsonNode args){
+ return apiResponse -> apiResponse.validatableResponse().statusCode(HttpStatus.SC_OK);
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
index b1e2e31583..afb54bce38 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
@@ -1,26 +1,64 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+
+import java.util.List;
import static io.stargate.sgv2.jsonapi.api.v1.ResponseAssertions.*;
import static org.hamcrest.Matchers.hasSize;
+
+/**
+ * Assertions that check the structure of the API response, e.g. should it have a `data` field
+ *
+ * See {@link TestAssertion}
+ *
+ */
public class Response {
- public static AssertionMatcher isFindSuccess(JsonNode args) {
+ static {
+ AssertionMatcher.FACTORY_REGISTRY.register(Response.class);
+ }
+
+ /**
+ * Checks the hTTP status AND the shape of the response doc
+ */
+ public static List isSuccess(TestCommand testCommand, JsonNode args) {
+
+ var commandName = testCommand.commandName();
+ var responseDocMatcher = switch (commandName.getCommandType()){
+ case DDL -> new TestAssertion.AssertionDefinition( "Response.isDDLSuccess", null);
+ case DML ->
+ switch (commandName) {
+ case FIND_ONE, FIND -> new TestAssertion.AssertionDefinition( "Response.isFindSuccess", null);
+ case FIND_ONE_AND_DELETE, FIND_ONE_AND_REPLACE, FIND_ONE_AND_UPDATE -> new TestAssertion.AssertionDefinition( "Response.isFindAndSuccess", null);
+ case INSERT_ONE, INSERT_MANY -> new TestAssertion.AssertionDefinition( "Response.isWriteSuccess", null);
+ default -> throw new IllegalStateException("No isSuccess mapping for command name: " + commandName);
+ };
+ case ADMIN -> throw new IllegalStateException("No isSuccess mapping for command name: " + commandName);
+ };
+
+
+ return TestAssertion.buildAssertions(testCommand, List.of(new TestAssertion.AssertionDefinition("Http.success", null), responseDocMatcher));
+ }
+
+ public static AssertionMatcher isFindSuccess(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("$", responseIsFindSuccess());
}
- public static AssertionMatcher isFindAndSuccess(JsonNode args) {
+ public static AssertionMatcher isFindAndSuccess(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("$", responseIsFindAndSuccess());
}
- public static AssertionMatcher isWriteSuccess(JsonNode args) {
+ public static AssertionMatcher isWriteSuccess(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("$", responseIsWriteSuccess());
}
- public static AssertionMatcher isDDLSuccess(JsonNode args) {
+ public static AssertionMatcher isDDLSuccess(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("$", responseIsDDLSuccess());
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
new file mode 100644
index 0000000000..40750ef352
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
@@ -0,0 +1,42 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import org.junit.jupiter.api.DynamicNode;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+public record SingleTestAssertion(
+ String name,
+ JsonNode args,
+ AssertionMatcher matcher
+) implements TestAssertion {
+
+ public void run(TestResponse testResponse) {
+
+ try {
+ matcher.match(testResponse.apiResponse());
+ } catch (AssertionError e) {
+ System.out.printf("Failed Assertion: name=%s, args=%s", name, args);
+ throw e;
+ } catch (Exception e) {
+ System.out.printf("Error In Assertion: name=%s, args=%s", name, args);
+ throw e;
+ }
+ }
+
+ @Override
+ public DynamicNode testNodes(AtomicReference testResponse) {
+
+ return dynamicTest(name(), () -> {
+ var resp = testResponse.get();
+ if (resp == null) {
+ throw new IllegalStateException("Response is null");
+ }
+ run(resp);
+ }
+ );
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
index f1b4fddad2..adc9bd703f 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
@@ -1,11 +1,18 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
public class Status {
- public static AssertionMatcher isExactly(JsonNode args) {
+
+ static {
+ AssertionMatcher.FACTORY_REGISTRY.register(Status.class);
+ }
+
+
+ public static AssertionMatcher isExactly(TestCommand testCommand, JsonNode args) {
return new BodyAssertion("status", jsonEquals(args));
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Statuscode.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Statuscode.java
deleted file mode 100644
index fac78c63b9..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Statuscode.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-
-import org.apache.http.HttpStatus;
-import org.testcontainers.shaded.com.fasterxml.jackson.databind.JsonNode;
-
-public class Statuscode {
-
- public static AssertionMatcher success(JsonNode args){
- return apiResponse -> apiResponse.validatableResponse().statusCode(HttpStatus.SC_OK);
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
index 1182d6b985..812ee10f02 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
@@ -1,107 +1,66 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.model.command.CommandName;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCase;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import org.junit.jupiter.api.DynamicNode;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
-public record TestAssertion(
- String name,
- JsonNode args,
- AssertionMatcher matcher
-) {
+public interface TestAssertion {
- public void run(TestResponse testResponse) {
+ String name();
- try{
- matcher.match(testResponse.apiResponse());
- }
- catch (AssertionError e) {
- System.out.printf("Failed Assertion: name=%s, args=%s", name, args);
- throw e;
- }
- catch (Exception e) {
- System.out.printf("Error In Assertion: name=%s, args=%s", name, args);
- throw e;
- }
- }
- public static List forSuccess(CommandName commandName) {
-
- var builder = Stream.builder()
- .add(new AssertionDefinition("Statuscode.success", null));
-
- switch (commandName) {
- case INSERT_ONE, INSERT_MANY -> {
- builder.add(new AssertionDefinition("Response.isWriteSuccess", null));
- }
- case CREATE_KEYSPACE, DROP_KEYSPACE, CREATE_NAMESPACE, DROP_NAMESPACE, DELETE_COLLECTION, CREATE_COLLECTION -> {
- builder.add(new AssertionDefinition("Response.isDDLSuccess", null));
- }
- }
- return buildAssertions(builder.build());
- }
+ JsonNode args();
+ void run(TestResponse testResponse);
- public static List buildAssertions(TestCase testCase) {
+ DynamicNode testNodes(AtomicReference testResponse);
- return buildAssertions(testCase.asserts().properties().stream()
- .map(AssertionDefinition::create));
- }
- private static List buildAssertions(Stream defs) {
+ static List forSuccess(TestCommand testCommand) {
- return defs.map(
- def -> {
- var assertFactory = findAssertionFactory(def.name());
- AssertionMatcher matcher;
- try {
- matcher = (AssertionMatcher) assertFactory.invoke(null, def.args());
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- return new TestAssertion(def.name(), def.args(), matcher);
- }
- ).toList();
+ var builder = Stream.builder()
+ .add(new AssertionDefinition("Response.isSuccess", null));
+ return buildAssertions(testCommand, builder.build());
}
- private static Method findAssertionFactory(String key) {
- // "validatableResponse.isFindSuccess"
+ static List buildAssertions(TestCase testCase) {
- int dot = key.indexOf('.');
- String typeName = key.substring(0, dot);
- String funcName = key.substring(dot + 1);
+ var defs = testCase.asserts().properties().stream()
+ .map(AssertionDefinition::create);
+ return buildAssertions(testCase.command(), defs);
+ }
- String qualifiedTypeName =
- "io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions."
- + Character.toUpperCase(typeName.charAt(0))
- + typeName.substring(1).toLowerCase();
+ static List buildAssertions(TestCommand testCommand, List defs) {
- try {
- Class> cls = Class.forName(qualifiedTypeName);
+ return buildAssertions(testCommand, defs.stream());
+ }
- var factoryMethod = Arrays.stream(cls.getMethods())
- .filter(m -> m.getName().equalsIgnoreCase(funcName))
- .filter(m -> Modifier.isStatic(m.getModifiers()))
- .findFirst()
- .orElseThrow();
+ static List buildAssertions(TestCommand testCommand, Stream defs) {
+ return defs.map(
+ def -> buildAssertion(testCommand, def)
+ ).toList();
+ }
- return factoryMethod;
- } catch (ReflectiveOperationException e) {
- throw new RuntimeException("Invalid assertion: " + key, e);
- }
+ private static TestAssertion buildAssertion(TestCommand testCommand, AssertionDefinition def) {
+
+ return switch (AssertionMatcher.FACTORY_REGISTRY.get(def.name())) {
+ case AssertionMatcher.AssertionMatcherFactory factory ->
+ new SingleTestAssertion(def.name(), def.args(), factory.apply(testCommand, def.args()));
+ case AssertionMatcher.TestAssertionContainerFactory factory ->
+ new TestAssertionContainer(def.name(), def.args(), factory.apply(testCommand, def.args));
+ default -> throw new IllegalStateException("Unknown TestAssertionFactory: " + def.name());
+ };
}
- private record AssertionDefinition(String name, JsonNode args) {
+ record AssertionDefinition(String name, JsonNode args) {
static AssertionDefinition create(Map.Entry def) {
return new AssertionDefinition(def.getKey(), def.getValue());
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
new file mode 100644
index 0000000000..acf447b355
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
@@ -0,0 +1,47 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import org.junit.jupiter.api.DynamicNode;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+public record TestAssertionContainer(
+ String name,
+ JsonNode args,
+ List assertions
+) implements TestAssertion {
+
+ @Override
+ public void run(TestResponse testResponse) {
+ for (TestAssertion assertion : assertions) {
+ try{
+ assertion.run(testResponse);
+ }
+ catch (AssertionError e) {
+ System.out.printf("Failed Assertion Container: name=%s, args=%s\n\t Caused By: name=%s, args=%s", name, args,
+ assertion.name(), assertion.args());
+ throw e;
+ }
+ catch (Exception e) {
+ System.out.printf("Error In Assertion Container: name=%s, args=%s\n\t Caused By: name=%s, args=%s", name, args,
+ assertion.name(), assertion.args());
+ throw e;
+ }
+ }
+ }
+
+ @Override
+ public DynamicNode testNodes(AtomicReference testResponse) {
+
+ var childs = assertions.stream()
+ .map(assertion -> assertion.testNodes(testResponse))
+ .toList();
+
+ return dynamicContainer(name, childs);
+ }
+}
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-base.json b/src/test/resources/integration-tests/vectorize/vectorize-base.json
index 69940a3b62..4793799423 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-base.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-base.json
@@ -55,8 +55,8 @@
}
},
"asserts": {
- "response.isFindSuccess": null,
- "documents.count": 4
+ "response.isSuccess": null,
+ "documents.count": 3
}
},
{
From 0af33b1ed336ecbcdef2c0ab76d7ea885c68837a Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Thu, 26 Feb 2026 13:40:45 +1300
Subject: [PATCH 09/89] WIP - assertion template
---
.../jsonapi/api/v1/vectorize/TestPlan.java | 4 +-
.../assertions/AssertionMatcher.java | 12 +++++
.../assertions/AssertionTemplates.java | 49 +++++++++++++++++++
.../api/v1/vectorize/assertions/Response.java | 15 +++---
.../assertions/TemplatedAssertions.java | 40 +++++++++++++++
.../vectorize/assertions/TestAssertion.java | 4 +-
.../assertions/assertion-templates.json | 12 +++++
.../vectorize/vectorize-base.json | 4 +-
8 files changed, 126 insertions(+), 14 deletions(-)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
create mode 100644 src/test/resources/integration-tests/assertions/assertion-templates.json
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
index 11d60aefa7..09f40ac141 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
@@ -1,8 +1,11 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionTemplates;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
+import java.io.IOException;
+import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -14,7 +17,6 @@
public record TestPlan(Target target, SpecFiles specFiles, Set workflows){
-
public static TestPlan create(String targetName, List workflows){
var targetConfigs = TargetConfigurationss.loadAll("integration-tests/targets/targets.json");
var target = new Target(targetConfigs.configuration(targetName));
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
index ed8c7cd4dd..2405419e15 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
@@ -69,6 +69,18 @@ public void register(Class> cls) {
public AssertionFactory> get(String name){
var normalName = name.toLowerCase();
+
+ int pos = normalName.indexOf('.');
+ if (pos < 0){
+ throw new IllegalArgumentException("Name must have a dot: " + name);
+ }
+ var type = normalName.substring(0, pos);
+ var func = normalName.substring(pos + 1);
+
+ if (type.equals( "template")) {
+ return TemplatedAssertions.getFactory(func);
+ }
+
var factoryMethod = factoryMethods.get(normalName);
if (factoryMethod == null) {
loadClassFor(name);
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
new file mode 100644
index 0000000000..82476b8ce6
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
@@ -0,0 +1,49 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TargetConfigurationss;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestSpecMeta;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public record AssertionTemplates(
+ TestSpecMeta meta,
+ ObjectNode templates
+) {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ public static AssertionTemplates load(){
+
+ final Path dir = resourceDir("integration-tests/assertions/assertion-templates.json");
+
+ try {
+ return MAPPER.readValue(dir.toFile(), AssertionTemplates.class);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Path resourceDir(String path) {
+ String normalized = path.startsWith("/") ? path.substring(1) : path;
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ URL url = cl.getResource(normalized);
+ if (url == null) {
+ throw new IllegalArgumentException("Test resource folder not found: " + path);
+ }
+
+ try {
+ // Works for file: URLs; if you run tests from a jar, switch to getResourceAsStream-based
+ // walking.
+ return Paths.get(url.toURI());
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Bad resource URI for: " + path + " -> " + url, e);
+ }
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
index afb54bce38..d198db2fc5 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
@@ -26,23 +26,20 @@ public class Response {
/**
* Checks the hTTP status AND the shape of the response doc
*/
- public static List isSuccess(TestCommand testCommand, JsonNode args) {
+ public static AssertionMatcher isSuccess(TestCommand testCommand, JsonNode args) {
var commandName = testCommand.commandName();
- var responseDocMatcher = switch (commandName.getCommandType()){
- case DDL -> new TestAssertion.AssertionDefinition( "Response.isDDLSuccess", null);
+ return switch (commandName.getCommandType()){
+ case DDL -> isDDLSuccess(testCommand, args);
case DML ->
switch (commandName) {
- case FIND_ONE, FIND -> new TestAssertion.AssertionDefinition( "Response.isFindSuccess", null);
- case FIND_ONE_AND_DELETE, FIND_ONE_AND_REPLACE, FIND_ONE_AND_UPDATE -> new TestAssertion.AssertionDefinition( "Response.isFindAndSuccess", null);
- case INSERT_ONE, INSERT_MANY -> new TestAssertion.AssertionDefinition( "Response.isWriteSuccess", null);
+ case FIND_ONE, FIND -> Response.isFindSuccess(testCommand, args);
+ case FIND_ONE_AND_DELETE, FIND_ONE_AND_REPLACE, FIND_ONE_AND_UPDATE -> Response.isFindAndSuccess(testCommand, args);
+ case INSERT_ONE, INSERT_MANY -> Response.isWriteSuccess(testCommand, args);
default -> throw new IllegalStateException("No isSuccess mapping for command name: " + commandName);
};
case ADMIN -> throw new IllegalStateException("No isSuccess mapping for command name: " + commandName);
};
-
-
- return TestAssertion.buildAssertions(testCommand, List.of(new TestAssertion.AssertionDefinition("Http.success", null), responseDocMatcher));
}
public static AssertionMatcher isFindSuccess(TestCommand testCommand, JsonNode args) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
new file mode 100644
index 0000000000..9b624b1f70
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
@@ -0,0 +1,40 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+
+import java.util.List;
+
+public class TemplatedAssertions {
+
+ private static final AssertionTemplates assertions = AssertionTemplates.load();
+
+ public static AssertionMatcher.TestAssertionContainerFactory getFactory(String templateName){
+
+ JsonNode template = null;
+ for (var entry : assertions.templates().properties()){
+ if (entry.getKey().equalsIgnoreCase(templateName)) {
+ template = entry.getValue();
+ break;
+ }
+ }
+
+ if (template == null) {
+ throw new IllegalArgumentException("Assertion template not found: " + templateName);
+ }
+ if (! (template instanceof ObjectNode templateObject)){
+ throw new IllegalArgumentException("Assertion template is not an object: " + templateName);
+ }
+
+ return new AssertionMatcher.TestAssertionContainerFactory(){
+ @Override
+ public List apply(TestCommand testCommand, JsonNode jsonNode) {
+ return templateObject.properties().stream()
+ .map(entry -> new TestAssertion.AssertionDefinition(entry.getKey(), entry.getValue()))
+ .map(def -> TestAssertion.buildAssertion(testCommand, def))
+ .toList();
+ }
+ };
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
index 812ee10f02..b01736cef1 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
@@ -25,7 +25,7 @@ public interface TestAssertion {
static List forSuccess(TestCommand testCommand) {
var builder = Stream.builder()
- .add(new AssertionDefinition("Response.isSuccess", null));
+ .add(new AssertionDefinition("template.isSuccess", null));
return buildAssertions(testCommand, builder.build());
}
@@ -49,7 +49,7 @@ static List buildAssertions(TestCommand testCommand, Stream
diff --git a/src/test/resources/integration-tests/assertions/assertion-templates.json b/src/test/resources/integration-tests/assertions/assertion-templates.json
new file mode 100644
index 0000000000..848d321756
--- /dev/null
+++ b/src/test/resources/integration-tests/assertions/assertion-templates.json
@@ -0,0 +1,12 @@
+{
+ "meta": {
+ "name": "assertions-templates",
+ "kind": "assertionTemplate"
+ },
+ "templates": {
+ "isSuccess": {
+ "http.success" : null,
+ "response.isSuccess": null
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-base.json b/src/test/resources/integration-tests/vectorize/vectorize-base.json
index 4793799423..d35b10db0f 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-base.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-base.json
@@ -55,7 +55,7 @@
}
},
"asserts": {
- "response.isSuccess": null,
+ "template.isSuccess": null,
"documents.count": 3
}
},
@@ -77,7 +77,7 @@
}
},
"asserts": {
- "response.isFindAndSuccess": null,
+ "response.isSuccess": null,
"documents.isExactly": {
"_id": "Inception",
"name": "Inception",
From bcf32711e9f565464f61e4bf3d4c8581ca25806b Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Fri, 27 Feb 2026 13:34:34 +1300
Subject: [PATCH 10/89] WIP
---
.../api/v1/vectorize/TestEnvironment.java | 3 +-
.../assertions/TemplatedAssertions.java | 26 ++++-
.../assertions/assertion-templates.json | 48 +++++++-
.../vectorize/vectorize-base.json | 2 +-
.../vectorize/vectorize-workflow.json | 105 ++++++++++++++++--
5 files changed, 166 insertions(+), 18 deletions(-)
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
index 85de1077af..8ae7f368c7 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
@@ -110,7 +110,8 @@ public static String toSafeSchemaIdentifier(String name){
var newValue = PATTERN_NOT_WORD_CHARS.matcher(name).replaceAll("_");
if (newValue.length() > 48){
- throw new RuntimeException("Schema Identifier longer than 48 characters %s=%s".formatted(name,newValue));
+ return newValue.substring(0, 47);
+// throw new RuntimeException("Schema Identifier longer than 48 characters orginalName=%s, afterNormalisation==%s".formatted(name,newValue));
}
return newValue;
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
index 9b624b1f70..d6c6380c2d 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
@@ -27,14 +27,28 @@ public static AssertionMatcher.TestAssertionContainerFactory getFactory(String t
throw new IllegalArgumentException("Assertion template is not an object: " + templateName);
}
- return new AssertionMatcher.TestAssertionContainerFactory(){
- @Override
- public List apply(TestCommand testCommand, JsonNode jsonNode) {
- return templateObject.properties().stream()
+ return switch (templateName.toLowerCase()) {
+ case "issuccess" ->
+ (AssertionMatcher.TestAssertionContainerFactory) (testCommand, args) -> {
+ var commandTemplate = templateObject.get(testCommand.commandName().getApiName());
+ if (commandTemplate == null) {
+ throw new IllegalArgumentException(
+ "isSuccess Assertion template not found for command: "
+ + testCommand.commandName().getApiName());
+ }
+ return runTemplate((ObjectNode) commandTemplate, testCommand, args);
+ };
+ default ->
+ throw new IllegalArgumentException(
+ "Assertion template not found: " + templateName);
+ };
+ }
+
+ private static List runTemplate(ObjectNode template, TestCommand testCommand, JsonNode args) {
+ return template.properties().stream()
.map(entry -> new TestAssertion.AssertionDefinition(entry.getKey(), entry.getValue()))
.map(def -> TestAssertion.buildAssertion(testCommand, def))
.toList();
- }
- };
}
+
}
diff --git a/src/test/resources/integration-tests/assertions/assertion-templates.json b/src/test/resources/integration-tests/assertions/assertion-templates.json
index 848d321756..394f9bad4c 100644
--- a/src/test/resources/integration-tests/assertions/assertion-templates.json
+++ b/src/test/resources/integration-tests/assertions/assertion-templates.json
@@ -4,9 +4,51 @@
"kind": "assertionTemplate"
},
"templates": {
- "isSuccess": {
- "http.success" : null,
- "response.isSuccess": null
+ "isSuccess": {
+ "createCollection": {
+ "http.success": null,
+ "response.isDDLSuccess": null
+ },
+ "createKeyspace": {
+ "http.success": null,
+ "response.isDDLSuccess": null
+ },
+ "deleteCollection": {
+ "http.success": null,
+ "response.isDDLSuccess": null
+ },
+ "dropKeyspace": {
+ "http.success": null,
+ "response.isDDLSuccess": null
+ },
+ "find": {
+ "http.success": null,
+ "response.isFindSuccess": null
+ },
+ "findOne": {
+ "http.success": null,
+ "response.isFindSuccess": null
+ },
+ "insertOne": {
+ "http.success": null,
+ "response.isWriteSuccess": null
+ },
+ "insertMany": {
+ "http.success": null,
+ "response.isWriteSuccess": null
+ },
+ "findOneAndDelete": {
+ "http.success": null,
+ "response.isFindAndSuccess": null
+ },
+ "findOneAndReplace": {
+ "http.success": null,
+ "response.isFindAndSuccess": null
+ },
+ "findOneAndUpdate": {
+ "http.success": null,
+ "response.isFindAndSuccess": null
+ }
}
}
}
\ No newline at end of file
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-base.json b/src/test/resources/integration-tests/vectorize/vectorize-base.json
index d35b10db0f..ffc69bf60f 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-base.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-base.json
@@ -77,7 +77,7 @@
}
},
"asserts": {
- "response.isSuccess": null,
+ "template.isSuccess": null,
"documents.isExactly": {
"_id": "Inception",
"name": "Inception",
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
index 6045d6a7dc..ad16917a2a 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
@@ -10,11 +10,10 @@
"tags": []
},
"fromEnvironment": {
- "x-embedding-api-key": "x-embedding-api-key",
+ "x-embedding-api-key": "x_embedding_api_key",
"Token": "Token"
},
"variables": {
-
"PROVIDER": "openai",
"COLLECTION_NAME": "${PROVIDER}-${MODEL}"
},
@@ -33,13 +32,11 @@
"meta": {
"name": "voyageAI-vectorize",
"tags": [
- "disabled"
]
},
"fromEnvironment": {
"x-embedding-api-key": "voyageAI_KEY",
- "Token" : "Token"
-
+ "Token": "Token"
},
"variables": {
"PROVIDER": "voyageAI",
@@ -61,11 +58,12 @@
{
"meta": {
"name": "jinaAI-vectorize",
- "tags": ["disabled"]
+ "tags": [
+ ]
},
"fromEnvironment": {
"x-embedding-api-key": "jinaAI_KEY",
- "Token" : "Token"
+ "Token": "Token"
},
"variables": {
"PROVIDER": "jinaAI",
@@ -83,6 +81,99 @@
"tests": [
"vectorize-header-auth"
]
+ },
+ {
+ "meta": {
+ "name": "huggingface-non-dedicated-vectorize",
+ "tags": []
+ },
+ "fromEnvironment": {
+ "x-embedding-api-key": "huggingface_KEY",
+ "Token": "Token"
+ },
+ "variables": {
+ "PROVIDER": "huggingface",
+ "COLLECTION_NAME": "${PROVIDER}-${MODEL}"
+ },
+ "matrix": {
+ "MODEL": [
+ "sentence-transformers/all-MiniLM-L6-v2",
+ "intfloat/multilingual-e5-large",
+ "intfloat/multilingual-e5-large-instruct",
+ "BAAI/bge-small-en-v1.5",
+ "BAAI/bge-base-en-v1.5",
+ "BAAI/bge-large-en-v1.5"
+ ]
+ },
+ "tests": [
+ "vectorize-header-auth"
+ ]
+ },
+ {
+ "meta": {
+ "name": "mistral-vectorize",
+ "tags": []
+ },
+ "fromEnvironment": {
+ "x-embedding-api-key": "mistral_KEY",
+ "Token": "Token"
+ },
+ "variables": {
+ "PROVIDER": "mistral",
+ "COLLECTION_NAME": "${PROVIDER}-${MODEL}"
+ },
+ "matrix": {
+ "MODEL": [
+ "mistral-embed"
+ ]
+ },
+ "tests": [
+ "vectorize-header-auth"
+ ]
+ },
+ {
+ "meta": {
+ "name": "upstageAI-vectorize",
+ "tags": []
+ },
+ "fromEnvironment": {
+ "x-embedding-api-key": "upstageAI_KEY",
+ "Token": "Token"
+ },
+ "variables": {
+ "PROVIDER": "upstageAI",
+ "COLLECTION_NAME": "${PROVIDER}-${MODEL}"
+ },
+ "matrix": {
+ "MODEL": [
+ "solar-embedding-1-large"
+ ]
+ },
+ "tests": [
+ "vectorize-header-auth"
+ ]
+ },
+ {
+ "meta": {
+ "name": "nvidia-vectorize",
+ "tags": []
+ },
+ "fromEnvironment": {
+ "x-embedding-api-key": "Token",
+ "Token": "Token"
+ },
+ "variables": {
+ "PROVIDER": "nvidia",
+ "COLLECTION_NAME": "${PROVIDER}-${MODEL}"
+ },
+ "matrix": {
+ "MODEL": [
+ "NV-Embed-QA"
+ ]
+ },
+ "tests": [
+ "vectorize-header-auth"
+ ]
}
]
}
\ No newline at end of file
From 0d8294f2c451e65acfbed1b2e0fa6a1be32fc0df Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Mon, 2 Mar 2026 14:43:29 +1300
Subject: [PATCH 11/89] WIP structure tidy
---
.../jsonapi/api/v1/ResponseAssertions.java | 2 +-
.../jsonapi/api/v1/vectorize/APIResponse.java | 3 +-
.../jsonapi/api/v1/vectorize/Backend.java | 2 +
.../api/v1/vectorize/CassandraBackend.java | 4 +-
.../v1/vectorize/IntegrationJobRunner.java | 3 +-
.../sgv2/jsonapi/api/v1/vectorize/Job.java | 10 +-
.../jsonapi/api/v1/vectorize/SpecFile.java | 22 ---
.../jsonapi/api/v1/vectorize/SpecFiles.java | 152 ------------------
.../sgv2/jsonapi/api/v1/vectorize/Target.java | 4 +-
.../jsonapi/api/v1/vectorize/TestCase.java | 4 +-
.../api/v1/vectorize/TestCaseResult.java | 1 +
.../api/v1/vectorize/TestEnvironment.java | 2 +-
.../jsonapi/api/v1/vectorize/TestPlan.java | 8 +-
.../api/v1/vectorize/TestRequestRunner.java | 3 +-
.../jsonapi/api/v1/vectorize/TestSpec.java | 15 --
.../api/v1/vectorize/TestSpecMeta.java | 6 -
.../jsonapi/api/v1/vectorize/TestSuite.java | 89 ----------
.../api/v1/vectorize/TestSuiteRunner.java | 1 +
.../jsonapi/api/v1/vectorize/Workflow.java | 36 -----
.../assertions/AssertionMatcher.java | 146 -----------------
.../assertions/AssertionTemplates.java | 49 ------
.../vectorize/assertions/BodyAssertion.java | 15 +-
.../v1/vectorize/assertions/Describable.java | 7 +
.../DescribableAssertionMatcher.java | 30 ++++
.../v1/vectorize/assertions/Documents.java | 2 +-
.../api/v1/vectorize/assertions/Http.java | 7 +-
.../api/v1/vectorize/assertions/Response.java | 2 +-
.../assertions/SingleTestAssertion.java | 33 +++-
.../api/v1/vectorize/assertions/Status.java | 2 +-
.../assertions/TemplatedAssertions.java | 54 -------
.../vectorize/assertions/TestAssertion.java | 70 +++++---
.../assertions/assertion-templates.json | 2 +-
.../vectorize/vectorize-base.json | 12 +-
.../vectorize/vectorize-header-auth.json | 2 +-
.../vectorize/vectorize-workflow.json | 18 ++-
35 files changed, 186 insertions(+), 632 deletions(-)
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFile.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFiles.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpec.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpecMeta.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuite.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Workflow.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Describable.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/ResponseAssertions.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/ResponseAssertions.java
index 7176eb94c2..ae02dd0235 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/ResponseAssertions.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/ResponseAssertions.java
@@ -87,7 +87,7 @@ public class ResponseAssertions {
FieldMatcher.errors(hasErrors));
final String msg =
- "%s: Response fields %s:%s, %s:%s, %s:%s"
+ "%s: %s:%s, %s:%s, %s:%s"
.formatted(
message,
Presence.REQUIRED,
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java
index 5f14d2b5c1..05120514be 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java
@@ -1,8 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import io.restassured.response.ValidatableResponse;
public record APIResponse (APIRequest apiRequest,
- ValidatableResponse validatableResponse) {
+ ValidatableResponse validatable) {
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
index eff80f178d..6e6a147e69 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
@@ -1,5 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
import org.junit.jupiter.api.DynamicNode;
import java.util.Optional;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java
index 76a31a96e3..916ff8582a 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java
@@ -40,7 +40,7 @@ public Optional beforeJob(TestPlan testPlan, Job job) {
var env = job.withoutMatrix(testPlan);
var setupRequest = new TestRequest(
env.substitutor().replace("createKeyspace: ${KEYSPACE_NAME}"),
- command, testPlan.target(), env, TestAssertion.forSuccess(command));
+ command, testPlan.target(), env, TestAssertion.forSuccess( testPlan, command));
return Optional.of(setupRequest.testNodes());
}
@@ -59,7 +59,7 @@ public Optional afterJob(TestPlan testPlan, Job job) {
var env = job.withoutMatrix(testPlan);
var setupRequest = new TestRequest(
env.substitutor().replace("dropKeyspace: ${KEYSPACE_NAME}"),
- command, testPlan.target(), job.withoutMatrix(testPlan), TestAssertion.forSuccess(command));
+ command, testPlan.target(), job.withoutMatrix(testPlan), TestAssertion.forSuccess(testPlan,command));
return Optional.of(setupRequest.testNodes());
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
index 1aeec9bcf3..12551cdd5a 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
@@ -1,7 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-import java.util.ArrayList;
-import java.util.List;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.SpecFiles;
public class IntegrationJobRunner {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
index 14d851175d..93935df839 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
@@ -1,11 +1,13 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecKind;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecMeta;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
import org.junit.jupiter.api.DynamicContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
@@ -39,14 +41,14 @@ public DynamicContainer testNode(TestPlan testPlan) {
}
public Stream testSuites(TestPlan testPlan) {
- List allTests = new ArrayList<>();
+ Stream.Builder allTests = Stream.builder();
tests()
.forEach(
testName -> {
- allTests.addAll(testPlan.specFiles().testByName(testName));
+ testPlan.specFiles().byNameAsType(TestSuite.class, testName).forEach(allTests) ;
});
- return allTests.stream();
+ return allTests.build();
}
public TestEnvironment withoutMatrix(TestPlan testPlan) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFile.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFile.java
deleted file mode 100644
index 5bcfc17bb4..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFile.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-public class SpecFile {
-
- private final TestSpec spec;
- private final JsonNode rootNode;
-
- SpecFile(TestSpec spec, JsonNode rootNode) {
- this.spec = spec;
- this.rootNode = rootNode;
- }
-
- public TestSpec spec() {
- return spec;
- }
-
- public JsonNode root() {
- return rootNode;
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFiles.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFiles.java
deleted file mode 100644
index 1f363a2817..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/SpecFiles.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.JsonPath;
-import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
-import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-
-/**
- * Collection of all the test spec files read for this execution.
- */
-public class SpecFiles {
-
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- private static final Configuration JSON_PATH_CONFIG =
- Configuration.builder()
- .jsonProvider(new JacksonJsonNodeJsonProvider())
- .mappingProvider(new JacksonMappingProvider())
- .build();
-
- List specFiles;
-
- private SpecFiles(List specFiles) {
- this.specFiles = specFiles;
-
- for (SpecFile file : specFiles) {
- if (file.spec() instanceof TestSuite it){
- it.expand(this);
- }
- }
- }
-
- public Workflow workflowFirstByName(String name) {
- var path = "$.meta[?(@.name == '%s')]".formatted(name);
-
- var itFile =
- match(TestSpec.TestSpecKind.WORKFLOW, path).stream()
- .findFirst()
- .orElseThrow(
- () ->
- new IllegalArgumentException(
- "No IT file found with meta.name == '%s'".formatted(name)));
- return (Workflow) itFile.spec();
- }
-
- public TestSuite testFirstByName(String name) {
- return testByName(name).getFirst();
- }
-
- public List testByName(String name) {
- var path = "$.meta[?(@.name == '%s')]".formatted(name);
-
- return match(TestSpec.TestSpecKind.TEST, path).stream()
- .map(itFile -> (TestSuite) itFile.spec())
- .toList();
- }
-
- public Stream byKind(TestSpec.TestSpecKind kind) {
- return specFiles.stream().filter(itFile -> itFile.spec().kind() == kind);
- }
-
- private List match(TestSpec.TestSpecKind kind, String jsonPath) {
- var compiled = JsonPath.compile(jsonPath);
-
- return byKind(kind).filter(itFile -> hasMatch(itFile.root(), compiled)).toList();
- }
-
- private boolean hasMatch(JsonNode root, JsonPath compiled) {
- var pathResult = JsonPath.using(JSON_PATH_CONFIG).parse(root).read(compiled);
-
- return switch (pathResult) {
- case null -> false;
- case java.util.Collection> c -> !c.isEmpty();
- case java.util.Map, ?> m -> !m.isEmpty();
- case ArrayNode a -> !a.isEmpty();
- case ObjectNode o -> !o.isEmpty();
- default -> true;
- };
- }
-
- static SpecFiles loadAll(String path) {
- final Path dir = resourceDir(path);
-
- List itFiles = new ArrayList<>();
-
- try (Stream s = Files.walk(dir)) {
- itFiles =
- s.filter(Files::isRegularFile)
- .filter(p -> p.getFileName().toString().endsWith(".json"))
- .map(SpecFiles::loadOne)
- .toList();
- } catch (IOException e) {
- throw new UncheckedIOException("Failed reading test resources under: " + dir, e);
- }
- return new SpecFiles(itFiles);
- }
-
- private static SpecFile loadOne(Path file) {
- try {
- var root = MAPPER.readTree(file.toFile());
-
- JsonNode kindNode = root.path("meta").path("kind");
- if (!kindNode.isTextual()) {
- throw new IllegalArgumentException("Missing/invalid meta.kind in " + file);
- }
-
- var kind = kindNode.asText();
- var element =
- switch (kind.toUpperCase()) {
- case "TEST" -> MAPPER.treeToValue(root, TestSuite.class);
- case "WORKFLOW" -> MAPPER.treeToValue(root, Workflow.class);
- default ->
- throw new IllegalArgumentException("Unknown meta.kind '" + kind + "' in " + file);
- };
- return new SpecFile(element, root);
- } catch (IOException e) {
- throw new UncheckedIOException("Failed parsing JSON file: " + file, e);
- }
- }
-
- private static Path resourceDir(String path) {
- String normalized = path.startsWith("/") ? path.substring(1) : path;
-
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- URL url = cl.getResource(normalized);
- if (url == null) {
- throw new IllegalArgumentException("Test resource folder not found: " + path);
- }
-
- try {
- // Works for file: URLs; if you run tests from a jar, switch to getResourceAsStream-based
- // walking.
- return Paths.get(url.toURI());
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Bad resource URI for: " + path + " -> " + url, e);
- }
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
index 805732df42..8aa2e50a05 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
@@ -1,5 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
import org.junit.jupiter.api.DynamicNode;
import java.util.HashMap;
@@ -52,7 +54,7 @@ public Optional afterJob(TestPlan testPlan,Job job){
return backend.afterJob(testPlan, job);
}
- public Optional beforeTestSuite(TestPlan testPlan,TestSuite test, TestEnvironment env){
+ public Optional beforeTestSuite(TestPlan testPlan, TestSuite test, TestEnvironment env){
return backend.beforeTestSuite(testPlan, test, env);
}
public Optional afterTestSuite(TestPlan testPlan,TestSuite test, TestEnvironment env){
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
index 2508eb985e..cb49caa5c5 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
@@ -15,11 +15,11 @@ public record TestCase(
String include) {
- DynamicContainer testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
+ public DynamicContainer testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
var testRequest = new TestRequest(
"TestCase: name=%s".formatted(name, command.commandName()),
- command(), testPlan.target(), testEnvironment, TestAssertion.buildAssertions(this));
+ command(), testPlan.target(), testEnvironment, TestAssertion.buildAssertions(testPlan, this));
return testRequest.testNodes();
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
index 297adb22ca..eccc7429db 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
@@ -1,6 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
public record TestCaseResult(
TestSuite integrationTest,
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
index 8ae7f368c7..9f0e0bbdf2 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
@@ -1,5 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
import org.apache.commons.text.StringSubstitutor;
import org.apache.commons.text.lookup.StringLookupFactory;
import org.junit.jupiter.api.DynamicContainer;
@@ -10,7 +11,6 @@
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
-import java.util.stream.Stream;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
index 09f40ac141..146247776e 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
@@ -1,11 +1,9 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionTemplates;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.*;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
-import java.io.IOException;
-import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -21,14 +19,14 @@ public static TestPlan create(String targetName, List workflows){
var targetConfigs = TargetConfigurationss.loadAll("integration-tests/targets/targets.json");
var target = new Target(targetConfigs.configuration(targetName));
- var specFiles = SpecFiles.loadAll("integration-tests/vectorize");
+ var specFiles = SpecFiles.loadAll(List.of("integration-tests/vectorize", "integration-tests/assertions/assertion-templates.json"));
return new TestPlan(target, specFiles, Set.copyOf(workflows));
}
public Stream selectedWorkflows(){
- return specFiles.byKind(TestSpec.TestSpecKind.WORKFLOW)
+ return specFiles.byKind(TestSpecKind.WORKFLOW)
.filter(specFile ->
workflows.isEmpty() || workflows.contains(specFile.spec().meta().name())
)
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
index 06388569cc..294c2c11d0 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
@@ -1,8 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-import org.junit.jupiter.api.DynamicTest;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import java.util.Collection;
import java.util.Objects;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpec.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpec.java
deleted file mode 100644
index 01f0a1ce73..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpec.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-public interface TestSpec {
-
- TestSpecKind kind();
-
- TestSpecMeta meta();
-
- // void setJson(JsonNode json);
-
- enum TestSpecKind {
- TEST,
- WORKFLOW
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpecMeta.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpecMeta.java
deleted file mode 100644
index fcf919b4a2..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSpecMeta.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import java.util.List;
-
-public record TestSpecMeta(String name, String kind,
- List tags) {}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuite.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuite.java
deleted file mode 100644
index b027f17031..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuite.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
-import org.junit.jupiter.api.DynamicContainer;
-import org.junit.jupiter.api.DynamicNode;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
-
-public record TestSuite(TestSpecMeta meta, List setup, List tests, List cleanup)
- implements TestSpec {
-
- @Override
- public TestSpecKind kind() {
- return TestSpecKind.TEST;
- }
-
- public DynamicContainer testNode(TestPlan testPlan, List allEnvs) {
-
- var desc = "TestSuite: %s ".formatted(
- meta.name());
-
- return dynamicContainer(
- desc,
- allEnvs.stream()
- .map(testEnv -> testEnv.testNode(testPlan, this))
- );
- }
-
- Collection extends DynamicNode> testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
-
- List nodes = new ArrayList<>();
-
- int i = 1;
- for (TestCommand setupCommand : setup()) {
- var setupRequest = new TestRequest(
- "SetupRequest[%s]: %s".formatted(i++, setupCommand.commandName()),
- setupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(setupCommand));
-
- nodes.add(setupRequest.testNodes());
- }
-
- for (var testCase : tests()) {
- nodes.add(testCase.testNodesForEnvironment(testPlan, testEnvironment));
- }
-
- for (TestCommand cleanupCommand : cleanup()) {
- var cleanupRequest = new TestRequest(
- "CleanupRequest[%s]: %s".formatted(i++, cleanupCommand.commandName()),
- cleanupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(cleanupCommand));
- nodes.add(cleanupRequest.testNodes());
- }
-
- return nodes;
-
- }
- public void expand(SpecFiles itCollection) {
-
- List expandedSetup = new ArrayList<>();
- for (TestCommand command : setup) {
- if (command.includeFrom() != null){
- var includedTest = itCollection.testFirstByName(command.includeFrom());
- expandedSetup.addAll(includedTest.setup());
- }
- else {
- expandedSetup.add(command);
- }
- }
- setup.clear();
- setup.addAll(expandedSetup);
-
- List expandedTests = new ArrayList<>();
- for (TestCase item : tests) {
- if (item.include() != null ){
- var includedTest = itCollection.testFirstByName(item.include());
- expandedTests.addAll(includedTest.tests());
- }
- else {
- expandedTests.add(item);
- }
- }
- tests.clear();
- tests.addAll(expandedTests);
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
index 3aaabe045a..b697b4e04c 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
@@ -1,6 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Workflow.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Workflow.java
deleted file mode 100644
index ed3666de1e..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Workflow.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import org.junit.jupiter.api.DynamicContainer;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
-
-public record Workflow(TestSpecMeta meta, List jobs) implements TestSpec {
-
- @Override
- public TestSpecKind kind() {
- return TestSpecKind.WORKFLOW;
- }
-
- public Stream activeJobs(){
- return jobs().stream()
- .filter(job -> !job.meta().tags().contains("disabled"));
- }
-
-
- public DynamicContainer testNode(TestPlan testPlan) {
-
- var desc = "Workflow: %s ".formatted(
- meta.name());
-
- var jobNodes = activeJobs()
- .map(job -> job.testNode(testPlan));
-
- return dynamicContainer(
- desc,
- testPlan.addLifecycle(this, jobNodes));
- }
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
index 2405419e15..70d4225013 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
@@ -1,17 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
-import org.assertj.core.api.AssertFactory;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BiFunction;
/**
* Contract for running an assertion on the response from the API.
@@ -27,139 +16,4 @@ public interface AssertionMatcher {
*/
void match(APIResponse apiResponse);
- AssertionFactoryRegistry FACTORY_REGISTRY = new AssertionFactoryRegistry();
-
- /**
- * Assertions int the test case are used to find Assertion factories in the code,
- * they are called with the TestCommand they need to run against so you
- * know what the command is, and any args from the JSON for the test case.
- *
- * Use the {@link SingleFactory} signature if your factory returns a single matcher, which is
- * normal. Use the {@link MultiFactory} signature if you want to return more than one.
- *
- */
-
- interface AssertionFactory extends BiFunction {}
-
- interface AssertionMatcherFactory extends AssertionFactory {
- }
-
- interface TestAssertionContainerFactory extends AssertionFactory> {}
-
- class AssertionFactoryRegistry {
-
- private final Map> factoryMethods = new ConcurrentHashMap<>();
-
- public void register(Class> cls) {
- for (var method : cls.getMethods()) {
- if (isValidFactoryMethod(method)) {
- var factoryKey = cls.getSimpleName().toLowerCase()
- + "."
- + method.getName().toLowerCase();
-
- // NOTE: not checking the generic of the list
- AssertionFactory> wrapped = (method.getReturnType() == AssertionMatcher.class) ?
- new AssertionMatcherFactoryWrapper(method)
- :
- new TestAssertionContainerFactoryWrapper(method);
- factoryMethods.put(factoryKey, wrapped);
- }
- }
- }
-
- public AssertionFactory> get(String name){
- var normalName = name.toLowerCase();
-
- int pos = normalName.indexOf('.');
- if (pos < 0){
- throw new IllegalArgumentException("Name must have a dot: " + name);
- }
- var type = normalName.substring(0, pos);
- var func = normalName.substring(pos + 1);
-
- if (type.equals( "template")) {
- return TemplatedAssertions.getFactory(func);
- }
-
- var factoryMethod = factoryMethods.get(normalName);
- if (factoryMethod == null) {
- loadClassFor(name);
- }
-
- factoryMethod = factoryMethods.get(normalName);
- if (factoryMethod == null) {
- throw new IllegalArgumentException("Unknown assertion factory. (normalised)name: %s known=%s".formatted(name,factoryMethods.keySet()));
- }
- return factoryMethod;
- }
-
- private static final String PACKAGE =
- "io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions";
-
- private void loadClassFor(String key) {
-
- int dot = key.indexOf('.');
- if (dot < 0) {
- return;
- }
-
- var typeName = key.substring(0, dot);
-
- var className =
- PACKAGE + "."
- + Character.toUpperCase(typeName.charAt(0))
- + typeName.substring(1);
-
- try {
- Class.forName(className);
-
- // class static initializer should call register()
-
- } catch (ClassNotFoundException ignored) {
- // expected if class does not exist
- }
- }
-
- private record AssertionMatcherFactoryWrapper(Method method) implements AssertionMatcherFactory {
-
- @SuppressWarnings("unchecked")
- @Override
- public AssertionMatcher apply(TestCommand testCommand, JsonNode args) {
- try {
- return (AssertionMatcher) method.invoke(null, testCommand, args);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- private record TestAssertionContainerFactoryWrapper(Method method) implements TestAssertionContainerFactory {
-
- @SuppressWarnings("unchecked")
- @Override
- public List apply(TestCommand testCommand, JsonNode args) {
- try {
- return (List) method.invoke(null, testCommand, args);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- private static boolean isValidFactoryMethod(Method method) {
-
- if (!Modifier.isStatic(method.getModifiers())) {
- return false;
- }
-
- if ((!List.class.isAssignableFrom(method.getReturnType())) && method.getReturnType() != AssertionMatcher.class) {
- return false;
- }
- var p = method.getParameterTypes();
- return p.length == 2
- && p[0] == TestCommand.class
- && p[1] == JsonNode.class;
- }
-
- }
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
deleted file mode 100644
index 82476b8ce6..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionTemplates.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TargetConfigurationss;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestSpecMeta;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public record AssertionTemplates(
- TestSpecMeta meta,
- ObjectNode templates
-) {
-
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- public static AssertionTemplates load(){
-
- final Path dir = resourceDir("integration-tests/assertions/assertion-templates.json");
-
- try {
- return MAPPER.readValue(dir.toFile(), AssertionTemplates.class);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static Path resourceDir(String path) {
- String normalized = path.startsWith("/") ? path.substring(1) : path;
-
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- URL url = cl.getResource(normalized);
- if (url == null) {
- throw new IllegalArgumentException("Test resource folder not found: " + path);
- }
-
- try {
- // Works for file: URLs; if you run tests from a jar, switch to getResourceAsStream-based
- // walking.
- return Paths.get(url.toURI());
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Bad resource URI for: " + path + " -> " + url, e);
- }
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
index 0f048667f9..6416d294f3 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
@@ -2,6 +2,7 @@
import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
/**
* Assertions that check the body of the response using a {@link Matcher} form hamcrest.
@@ -16,9 +17,19 @@
public record BodyAssertion(
String bodyPath,
Matcher> matcher
-) implements AssertionMatcher {
+) implements Describable, AssertionMatcher {
+ @Override
public void match(APIResponse apiResponse) {
- apiResponse.validatableResponse().body(bodyPath(), matcher());
+ apiResponse.validatable().body(bodyPath(), matcher());
+ }
+
+ @Override
+ public String describe() {
+ var describable = new StringDescription();
+ matcher.describeTo(describable);
+
+ // called should truncate if it wants to limit it
+ return "body('%s') - %s".formatted(bodyPath(), describable.toString());
}
}
\ No newline at end of file
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Describable.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Describable.java
new file mode 100644
index 0000000000..fc1a0a5f67
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Describable.java
@@ -0,0 +1,7 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+@FunctionalInterface
+public interface Describable {
+
+ String describe();
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
new file mode 100644
index 0000000000..9e001ac0c6
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
@@ -0,0 +1,30 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
+import org.jspecify.annotations.NonNull;
+
+public record DescribableAssertionMatcher(
+ String description,
+ AssertionMatcher matcher
+) implements Describable, AssertionMatcher {
+
+
+ public static DescribableAssertionMatcher described(String description, AssertionMatcher matcher) {
+ return new DescribableAssertionMatcher(description, matcher);
+ }
+
+ @Override
+ public void match(APIResponse apiResponse) {
+ matcher.match(apiResponse);
+ }
+
+ @Override
+ public String describe() {
+ return toString();
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return description();
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
index cd4dbc5078..3deb8135af 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
@@ -16,7 +16,7 @@
public class Documents {
static {
- AssertionMatcher.FACTORY_REGISTRY.register(Documents.class);
+ AssertionFactory.REGISTRY.register(Documents.class);
}
public static AssertionMatcher count(TestCommand testCommand, JsonNode args) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
index f9424f0aee..f1afc680dd 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
@@ -4,13 +4,16 @@
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
import org.apache.http.HttpStatus;
+import static io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.DescribableAssertionMatcher.described;
+
public class Http {
static {
- AssertionMatcher.FACTORY_REGISTRY.register(Http.class);
+ AssertionFactory.REGISTRY.register(Http.class);
}
public static AssertionMatcher success(TestCommand testCommand, JsonNode args){
- return apiResponse -> apiResponse.validatableResponse().statusCode(HttpStatus.SC_OK);
+ return described("http status is groovy", apiResponse -> apiResponse.validatable().statusCode(HttpStatus.SC_OK));
+// return apiResponse -> apiResponse.validatable().statusCode(HttpStatus.SC_OK);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
index d198db2fc5..f085e91877 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
@@ -20,7 +20,7 @@
public class Response {
static {
- AssertionMatcher.FACTORY_REGISTRY.register(Response.class);
+ AssertionFactory.REGISTRY.register(Response.class);
}
/**
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
index 40750ef352..1cfd9ac457 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
@@ -2,11 +2,17 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import io.stargate.sgv2.jsonapi.service.schema.tables.ApiSupportDef;
+import org.hamcrest.SelfDescribing;
+import org.hamcrest.StringDescription;
import org.junit.jupiter.api.DynamicNode;
+import java.lang.reflect.Executable;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+import static org.junit.jupiter.api.DynamicTest.stream;
public record SingleTestAssertion(
String name,
@@ -30,11 +36,36 @@ public void run(TestResponse testResponse) {
@Override
public DynamicNode testNodes(AtomicReference testResponse) {
- return dynamicTest(name(), () -> {
+ var original = (matcher instanceof Describable d) ?
+ d.describe()
+ :
+ null;
+
+ var truncated = ( original != null && original.length() > 60) ?
+ original.substring(0, 57) + "..."
+ :
+ original;
+
+ var testDesc = truncated == null ?
+ name()
+ :
+ "%s [%s]".formatted(name(), truncated);
+
+ // if we truncated the description of the test, we then want to pipe to std out when running
+ // because it will not be full in the test tree
+ var stdoutMessage = (original != null && !Objects.equals(truncated, original)) ?
+ "%s [%s]".formatted(name(), original)
+ :
+ null;
+
+ return dynamicTest(testDesc, () -> {
var resp = testResponse.get();
if (resp == null) {
throw new IllegalStateException("Response is null");
}
+ if (stdoutMessage != null) {
+ System.out.printf(stdoutMessage);
+ }
run(resp);
}
);
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
index adc9bd703f..4ae2703a89 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
@@ -8,7 +8,7 @@
public class Status {
static {
- AssertionMatcher.FACTORY_REGISTRY.register(Status.class);
+ AssertionFactory.REGISTRY.register(Status.class);
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
deleted file mode 100644
index d6c6380c2d..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TemplatedAssertions.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
-
-import java.util.List;
-
-public class TemplatedAssertions {
-
- private static final AssertionTemplates assertions = AssertionTemplates.load();
-
- public static AssertionMatcher.TestAssertionContainerFactory getFactory(String templateName){
-
- JsonNode template = null;
- for (var entry : assertions.templates().properties()){
- if (entry.getKey().equalsIgnoreCase(templateName)) {
- template = entry.getValue();
- break;
- }
- }
-
- if (template == null) {
- throw new IllegalArgumentException("Assertion template not found: " + templateName);
- }
- if (! (template instanceof ObjectNode templateObject)){
- throw new IllegalArgumentException("Assertion template is not an object: " + templateName);
- }
-
- return switch (templateName.toLowerCase()) {
- case "issuccess" ->
- (AssertionMatcher.TestAssertionContainerFactory) (testCommand, args) -> {
- var commandTemplate = templateObject.get(testCommand.commandName().getApiName());
- if (commandTemplate == null) {
- throw new IllegalArgumentException(
- "isSuccess Assertion template not found for command: "
- + testCommand.commandName().getApiName());
- }
- return runTemplate((ObjectNode) commandTemplate, testCommand, args);
- };
- default ->
- throw new IllegalArgumentException(
- "Assertion template not found: " + templateName);
- };
- }
-
- private static List runTemplate(ObjectNode template, TestCommand testCommand, JsonNode args) {
- return template.properties().stream()
- .map(entry -> new TestAssertion.AssertionDefinition(entry.getKey(), entry.getValue()))
- .map(def -> TestAssertion.buildAssertion(testCommand, def))
- .toList();
- }
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
index b01736cef1..887c1300a1 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
@@ -3,11 +3,16 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCase;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.AssertionTemplateSpec;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.SpecFiles;
+import org.assertj.core.api.AssertFactory;
import org.junit.jupiter.api.DynamicNode;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
@@ -22,50 +27,73 @@ public interface TestAssertion {
DynamicNode testNodes(AtomicReference testResponse);
- static List forSuccess(TestCommand testCommand) {
+ static List forSuccess(TestPlan testPlan, TestCommand testCommand) {
var builder = Stream.builder()
- .add(new AssertionDefinition("template.isSuccess", null));
+ .add(new AssertionDefinition("Templated.isSuccess", null));
- return buildAssertions(testCommand, builder.build());
+ return buildAssertions(testPlan, testCommand, builder.build());
}
- static List buildAssertions(TestCase testCase) {
+ static List buildAssertions(TestPlan testPlan, TestCase testCase) {
var defs = testCase.asserts().properties().stream()
.map(AssertionDefinition::create);
- return buildAssertions(testCase.command(), defs);
+ return buildAssertions(testPlan, testCase.command(), defs);
}
- static List buildAssertions(TestCommand testCommand, List defs) {
-
- return buildAssertions(testCommand, defs.stream());
- }
-
- static List buildAssertions(TestCommand testCommand, Stream defs) {
+ static List buildAssertions(TestPlan testPlan, TestCommand testCommand, Stream defs) {
return defs.map(
- def -> buildAssertion(testCommand, def)
+ def -> buildAssertion(testPlan, testCommand, def)
).toList();
}
- public static TestAssertion buildAssertion(TestCommand testCommand, AssertionDefinition def) {
-
- return switch (AssertionMatcher.FACTORY_REGISTRY.get(def.name())) {
- case AssertionMatcher.AssertionMatcherFactory factory ->
- new SingleTestAssertion(def.name(), def.args(), factory.apply(testCommand, def.args()));
- case AssertionMatcher.TestAssertionContainerFactory factory ->
- new TestAssertionContainer(def.name(), def.args(), factory.apply(testCommand, def.args));
- default -> throw new IllegalStateException("Unknown TestAssertionFactory: " + def.name());
- };
+ static TestAssertion buildAssertion(TestPlan testPlan, TestCommand testCommand, AssertionDefinition def) {
+ return def.addFactory(AssertionFactory.REGISTRY).build(testPlan, testCommand);
}
+ /**
+ *
+ */
record AssertionDefinition(String name, JsonNode args) {
static AssertionDefinition create(Map.Entry def) {
return new AssertionDefinition(def.getKey(), def.getValue());
}
+ AssertionDefWithFactory addFactory(AssertionFactoryRegistry registry) {
+
+ var factory = registry.getWrapped(name());
+ if (factory == null) {
+ throw new IllegalStateException("Unknown Assertion Factory name=" + name());
+ }
+ return new AssertionDefWithFactory(factory, args);
+ }
}
+ /**
+ *
+ */
+ record AssertionDefWithFactory(AssertionFactory.WrappedMethod method, JsonNode args){
+
+ TestAssertion build(TestPlan testPlan, TestCommand testCommand) {
+
+ return switch (method) {
+ case AssertionFactory.WrappedAssertionMatcherFactory factory ->
+ new SingleTestAssertion(method.properName(), args(), factory.create(testCommand, args()));
+
+ case AssertionFactory.TemplatedAssertionFactory factory ->{
+
+ var template = testPlan.specFiles().byType(AssertionTemplateSpec.class)
+ .flatMap(assertTemplate -> assertTemplate.templateFor(method.properName()).stream())
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("Unknown Assertion Template name=" + method.properName()));
+
+ yield new TestAssertionContainer(method.properName(), args(), factory.create(testPlan, template, testCommand, args()));
+ }
+ };
+ }
+
+ }
}
diff --git a/src/test/resources/integration-tests/assertions/assertion-templates.json b/src/test/resources/integration-tests/assertions/assertion-templates.json
index 394f9bad4c..76bcea748e 100644
--- a/src/test/resources/integration-tests/assertions/assertion-templates.json
+++ b/src/test/resources/integration-tests/assertions/assertion-templates.json
@@ -1,7 +1,7 @@
{
"meta": {
"name": "assertions-templates",
- "kind": "assertionTemplate"
+ "kind": "assertion_template"
},
"templates": {
"isSuccess": {
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-base.json b/src/test/resources/integration-tests/vectorize/vectorize-base.json
index ffc69bf60f..43f07afb92 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-base.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-base.json
@@ -1,7 +1,7 @@
{
"meta": {
"name": "vectorize-base",
- "kind" : "test"
+ "kind" : "test_suite"
},
"setup": [
{
@@ -55,8 +55,8 @@
}
},
"asserts": {
- "template.isSuccess": null,
- "documents.count": 3
+ "Templated.isSuccess": null,
+ "Documents.count": 3
}
},
{
@@ -77,8 +77,8 @@
}
},
"asserts": {
- "template.isSuccess": null,
- "documents.isExactly": {
+ "Templated.isSuccess": null,
+ "Documents.isExactly": {
"_id": "Inception",
"name": "Inception",
"genre": "Science Fiction",
@@ -87,7 +87,7 @@
],
"status": "active"
},
- "status.isExactly" : {
+ "Status.isExactly" : {
"matchedCount": 1,
"modifiedCount": 1
}
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-header-auth.json b/src/test/resources/integration-tests/vectorize/vectorize-header-auth.json
index 11d61833f1..2aa9cd3053 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-header-auth.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-header-auth.json
@@ -1,7 +1,7 @@
{
"meta": {
"name": "vectorize-header-auth",
- "kind": "test"
+ "kind": "test_suite"
},
"setup": [
{
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
index ad16917a2a..5cbfce0258 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
@@ -32,6 +32,7 @@
"meta": {
"name": "voyageAI-vectorize",
"tags": [
+ "disabled"
]
},
"fromEnvironment": {
@@ -59,6 +60,7 @@
"meta": {
"name": "jinaAI-vectorize",
"tags": [
+ "disabled"
]
},
"fromEnvironment": {
@@ -85,7 +87,9 @@
{
"meta": {
"name": "huggingface-non-dedicated-vectorize",
- "tags": []
+ "tags": [
+ "disabled"
+ ]
},
"fromEnvironment": {
"x-embedding-api-key": "huggingface_KEY",
@@ -112,7 +116,9 @@
{
"meta": {
"name": "mistral-vectorize",
- "tags": []
+ "tags": [
+ "disabled"
+ ]
},
"fromEnvironment": {
"x-embedding-api-key": "mistral_KEY",
@@ -134,7 +140,9 @@
{
"meta": {
"name": "upstageAI-vectorize",
- "tags": []
+ "tags": [
+ "disabled"
+ ]
},
"fromEnvironment": {
"x-embedding-api-key": "upstageAI_KEY",
@@ -156,7 +164,9 @@
{
"meta": {
"name": "nvidia-vectorize",
- "tags": []
+ "tags": [
+ "disabled"
+ ]
},
"fromEnvironment": {
"x-embedding-api-key": "Token",
From 2507b6836f27d7bdb7399131fa768facfdad3b90 Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Mon, 2 Mar 2026 14:44:05 +1300
Subject: [PATCH 12/89] missinh files
---
.../assertions/AssertionFactory.java | 126 +++++++++++++++++
.../assertions/AssertionFactoryRegistry.java | 51 +++++++
.../vectorize/assertions/AssertionName.java | 44 ++++++
.../api/v1/vectorize/assertions/Http.java | 1 -
.../v1/vectorize/assertions/Templated.java | 35 +++++
.../testspec/AssertionTemplateSpec.java | 21 +++
.../api/v1/vectorize/testspec/SpecFile.java | 22 +++
.../api/v1/vectorize/testspec/SpecFiles.java | 132 ++++++++++++++++++
.../api/v1/vectorize/testspec/TestSpec.java | 15 ++
.../v1/vectorize/testspec/TestSpecKind.java | 14 ++
.../v1/vectorize/testspec/TestSpecMeta.java | 10 ++
.../api/v1/vectorize/testspec/TestSuite.java | 90 ++++++++++++
.../api/v1/vectorize/testspec/Workflow.java | 34 +++++
13 files changed, 594 insertions(+), 1 deletion(-)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionName.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/AssertionTemplateSpec.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFile.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpec.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecKind.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecMeta.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
new file mode 100644
index 0000000000..08ce531266
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
@@ -0,0 +1,126 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+/**
+
+ */
+
+public sealed interface AssertionFactory {
+
+ public static final AssertionFactoryRegistry REGISTRY = new AssertionFactoryRegistry();
+
+ @FunctionalInterface
+ non-sealed interface AssertionMatcherFactory extends AssertionFactory {
+ AssertionMatcher create(TestCommand testCommand, JsonNode args);
+ }
+
+ @FunctionalInterface
+ non-sealed interface TemplatedAssertionFactory extends AssertionFactory {
+ List create(TestPlan testPlan, JsonNode template, TestCommand testCommand, JsonNode args);
+ }
+
+ static boolean isValidFactoryMethod(Method method) {
+
+ if (!Modifier.isStatic(method.getModifiers())) {
+ return false;
+ }
+
+ // NOTE: not checked the type of the list, lazy
+ if (List.class.isAssignableFrom(method.getReturnType())) {
+ var p = method.getParameterTypes();
+ return p.length == 4
+ && p[0] == TestPlan.class
+ && p[1] == JsonNode.class
+ && p[2] == TestCommand.class
+ && p[3] == JsonNode.class;
+ }
+
+ if (method.getReturnType() == AssertionMatcher.class) {
+ var p = method.getParameterTypes();
+ return p.length == 2
+ && p[0] == TestCommand.class
+ && p[1] == JsonNode.class;
+ }
+ return false;
+ }
+
+ abstract sealed class WrappedMethod
+ permits WrappedAssertionMatcherFactory, WrappedTemplatedAssertionFactory {
+
+ private final Class> clazz;
+ private final Method method;
+ private final AssertionName assertionName;
+
+ protected WrappedMethod(Class> clazz, Method method) {
+ this.clazz = clazz;
+ this.method = method;
+ this.assertionName = new AssertionName(clazz.getSimpleName(), method.getName());
+ }
+
+ static WrappedMethod of(Class> clazz, Method method) {
+ return (method.getReturnType() == AssertionMatcher.class) ?
+ new WrappedAssertionMatcherFactory(clazz, method)
+ :
+ new WrappedTemplatedAssertionFactory(clazz, method);
+ }
+
+ public Class> clazz() {
+ return clazz;
+ }
+
+ public Method method() {
+ return method;
+ }
+
+ public String properName() {
+ return AssertionName.properName(method);
+ }
+
+ public AssertionName assertionName() {
+ return assertionName;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T invoke(Object... args) {
+ try {
+ return (T) method.invoke(null, args);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ final class WrappedAssertionMatcherFactory extends WrappedMethod
+ implements AssertionMatcherFactory {
+
+ WrappedAssertionMatcherFactory(Class> clazz, Method method) {
+ super(clazz, method);
+ }
+
+ @Override
+ public AssertionMatcher create(TestCommand testCommand, JsonNode args) {
+ return invoke(testCommand, args);
+ }
+ }
+
+ final class WrappedTemplatedAssertionFactory extends WrappedMethod
+ implements TemplatedAssertionFactory {
+
+ WrappedTemplatedAssertionFactory(Class> clazz, Method method) {
+ super(clazz, method);
+ }
+
+ @Override
+ public List create(TestPlan testPlan, JsonNode template, TestCommand testCommand, JsonNode args) {
+ return invoke(testPlan, template, testCommand, args);
+ }
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
new file mode 100644
index 0000000000..fb51179491
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
@@ -0,0 +1,51 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class AssertionFactoryRegistry {
+
+ private final Map factoryMethods = new ConcurrentHashMap<>();
+
+
+ public void register(Class> cls) {
+ for (var method : cls.getMethods()) {
+ if ( AssertionFactory.isValidFactoryMethod(method)) {
+ var wrapped = AssertionFactory.WrappedMethod.of(cls, method);
+ factoryMethods.put(wrapped.assertionName(), wrapped);
+ }
+ }
+ }
+
+ public AssertionFactory.WrappedMethod getWrapped(String fullKey) {
+ var normalisedName = AssertionName.from(fullKey);
+
+ var factoryMethod = factoryMethods.get(normalisedName);
+ if (factoryMethod == null) {
+ loadClassFor(normalisedName);
+ }
+
+ factoryMethod = factoryMethods.get(normalisedName);
+ if (factoryMethod == null) {
+ throw new IllegalArgumentException("Unknown assertion factory. (normalised)name: %s known=%s".formatted(normalisedName, factoryMethods.keySet()));
+ }
+ return factoryMethod;
+ }
+
+ private void loadClassFor(AssertionName normalisedName) {
+
+ try {
+ Class.forName(normalisedName.properClassName());
+ // class static initializer should call register()
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Unknown assertion factory. normalisedName=%s, properClassName()=%s".formatted(normalisedName, normalisedName.properClassName()), e);
+ }
+ }
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionName.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionName.java
new file mode 100644
index 0000000000..96ec5b54b7
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionName.java
@@ -0,0 +1,44 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import java.lang.reflect.Method;
+
+public record AssertionName(String typeName, String funcName) {
+
+ private static final String PACKAGE =
+ "io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions";
+
+ public AssertionName{
+ typeName = typeName.toLowerCase();
+ funcName = funcName.toLowerCase();
+ }
+
+ public static AssertionName from(String fullKey) {
+
+ int pos = fullKey.indexOf('.');
+ if (pos < 0) {
+ throw new IllegalArgumentException("fullKey must have a dot: " + fullKey);
+ }
+ var type = fullKey.substring(0, pos);
+ var func = fullKey.substring(pos + 1);
+ return new AssertionName(type, func);
+ }
+
+ public static String properName(Class> clazz, Method method ) {
+ return clazz.getSimpleName() + '.' + method.getName();
+ }
+
+ public static String properName(Method method ) {
+ return method.getName();
+ }
+
+
+ public String properClassName() {
+ return PACKAGE + "."
+ + Character.toUpperCase(typeName.charAt(0))
+ + typeName.substring(1);
+ }
+
+ public String normalisedKey() {
+ return typeName + "." + funcName;
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
index f1afc680dd..387aa05b39 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
@@ -14,6 +14,5 @@ public class Http {
public static AssertionMatcher success(TestCommand testCommand, JsonNode args){
return described("http status is groovy", apiResponse -> apiResponse.validatable().statusCode(HttpStatus.SC_OK));
-// return apiResponse -> apiResponse.validatable().statusCode(HttpStatus.SC_OK);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
new file mode 100644
index 0000000000..4c14df897c
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
@@ -0,0 +1,35 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.AssertionTemplateSpec;
+
+import java.util.List;
+
+public class Templated {
+
+ static {
+ AssertionFactory.REGISTRY.register(Templated.class);
+ }
+
+ public static List isSuccess(TestPlan testPlan, JsonNode template, TestCommand testCommand, JsonNode args){
+ var commandTemplate = template.get(testCommand.commandName().getApiName());
+ if (commandTemplate == null) {
+ throw new IllegalArgumentException(
+ "isSuccess Assertion template not found for command: "
+ + testCommand.commandName().getApiName());
+ }
+ return runTemplate(testPlan, (ObjectNode) commandTemplate, testCommand, args);
+ }
+
+
+ private static List runTemplate(TestPlan testPlan, ObjectNode template, TestCommand testCommand, JsonNode args) {
+ return template.properties().stream()
+ .map(entry -> new TestAssertion.AssertionDefinition(entry.getKey(), entry.getValue()))
+ .map(def -> TestAssertion.buildAssertion(testPlan, testCommand, def))
+ .toList();
+ }
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/AssertionTemplateSpec.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/AssertionTemplateSpec.java
new file mode 100644
index 0000000000..a67c679468
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/AssertionTemplateSpec.java
@@ -0,0 +1,21 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.quarkus.smallrye.health.runtime.SmallRyeIndividualHealthGroupHandler;
+import io.stargate.sgv2.jsonapi.api.v1.util.scenarios.ThreeClusteringKeysTableScenario;
+import io.stargate.sgv2.jsonapi.service.schema.collections.CqlColumnMatcher;
+
+import java.util.Map;
+import java.util.Optional;
+
+public record AssertionTemplateSpec(
+ TestSpecMeta meta,
+ Map templates
+) implements TestSpec {
+
+ public Optional templateFor(String name){
+
+ return Optional.ofNullable(templates.get(name));
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFile.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFile.java
new file mode 100644
index 0000000000..a3ddf724d7
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFile.java
@@ -0,0 +1,22 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.jspecify.annotations.NonNull;
+
+import java.io.File;
+
+public record SpecFile(
+ File file,
+ TestSpec spec,
+ JsonNode root) {
+
+ @Override
+ public @NonNull String toString() {
+ return new StringBuilder("SpecFile{")
+ .append("file=")
+ .append(file)
+ .append("spec.meta=")
+ .append(spec.meta())
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
new file mode 100644
index 0000000000..a526b34914
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
@@ -0,0 +1,132 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * Collection of all the test spec files read for this execution.
+ */
+public class SpecFiles {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper()
+ .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
+
+ private final List specFiles;
+
+ private SpecFiles(List specFiles) {
+ this.specFiles = specFiles;
+
+ for (SpecFile file : specFiles) {
+ if (file.spec() instanceof TestSuite it){
+ it.expand(this);
+ }
+ }
+ }
+
+ public static SpecFiles loadAll(List paths) {
+
+ var specFiles = resourceDirs(paths)
+ .flatMap(SpecFiles::loadAll)
+ .toList();
+ return new SpecFiles(specFiles);
+ }
+
+ public Stream byKind(TestSpecKind kind) {
+ return specFiles.stream()
+ .filter(itFile -> itFile.spec().meta().kind() == kind);
+ }
+
+ public Stream byType(Class clazz) {
+ return byKind(TestSpecKind.fromType(clazz))
+ .map(specFile -> specFile.spec().asSpecType(clazz));
+ }
+
+ public Stream byName(TestSpecKind kind, String name) {
+ return match(kind, specFiles -> specFiles.meta().name().equals(name));
+ }
+
+ public Stream byNameAsType(Class clazz, String name) {
+ return match(TestSpecKind.fromType(clazz), specFiles -> specFiles.meta().name().equals(name))
+ .map(specFile -> specFile.spec().asSpecType(clazz));
+ }
+
+
+ private Stream match(TestSpecKind kind, Predicate predicate) {
+ return byKind(kind)
+ .filter(specFile -> predicate.test(specFile.spec()));
+ }
+
+ private static Stream loadAll(Path path) {
+
+ try (Stream pathStream = Files.walk(path)) {
+ return pathStream.filter(Files::isRegularFile)
+ .filter(SpecFiles::isJsonFile)
+ .map(SpecFiles::loadOne)
+ .toList() // force so the files are read before closing
+ .stream();
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed reading test resources under: " + path , e);
+ }
+ }
+
+ private static SpecFile loadOne(Path path) {
+ var file = path.toFile();
+ try {
+ var root = MAPPER.readTree(file);
+
+ var kindNode = root.path("meta").path("kind");
+ if (!kindNode.isTextual()) {
+ throw new IllegalArgumentException("Missing/invalid meta.kind in " + file);
+ }
+
+ var element =
+ switch (TestSpecKind.valueOf(kindNode.asText().toUpperCase())) {
+ case ASSERTION_TEMPLATE -> MAPPER.treeToValue(root, AssertionTemplateSpec.class);
+ case TEST_SUITE -> MAPPER.treeToValue(root, TestSuite.class);
+ case WORKFLOW -> MAPPER.treeToValue(root, Workflow.class);
+
+ };
+ return new SpecFile(file, element, root);
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed parsing JSON file: " + file, e);
+ }
+ }
+
+ private static boolean isJsonFile(Path file) {
+ return file.getFileName().toString().endsWith(".json");
+ }
+
+ private static Stream resourceDirs(List paths) {
+
+ var cl = Thread.currentThread().getContextClassLoader();
+
+ return paths.stream().map(
+ path -> {
+ String normalized = path.startsWith("/") ? path.substring(1) : path;
+
+ var url = cl.getResource(normalized);
+ if (url == null) {
+ throw new IllegalArgumentException("Test resource folder not found: " + path);
+ }
+
+ try {
+ // Works for file: URLs; if you run tests from a jar, switch to getResourceAsStream-based
+ // walking.
+ return Paths.get(url.toURI());
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Bad resource URI for: " + path + " -> " + url, e);
+ }
+ }
+ );
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpec.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpec.java
new file mode 100644
index 0000000000..f1871db67b
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpec.java
@@ -0,0 +1,15 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+public sealed interface TestSpec permits Workflow, TestSuite, AssertionTemplateSpec {
+
+ TestSpecMeta meta();
+
+ default T asSpecType(Class type) {
+
+ if (!type.isInstance(this)) {
+ throw new IllegalArgumentException(
+ "TestSpec is not of required type. expected=%s, spec.meta=%s".formatted(type, meta()));
+ }
+ return type.cast(this);
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecKind.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecKind.java
new file mode 100644
index 0000000000..f1a8a28171
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecKind.java
@@ -0,0 +1,14 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+public enum TestSpecKind {
+ ASSERTION_TEMPLATE,
+ TEST_SUITE,
+ WORKFLOW;
+
+ public static TestSpecKind fromType(Class clazz) {
+ if (clazz == AssertionTemplateSpec.class) { return ASSERTION_TEMPLATE; }
+ if (clazz == TestSuite.class) { return TEST_SUITE; }
+ if (clazz == Workflow.class) { return WORKFLOW; }
+ throw new IllegalArgumentException("Unknown TestSpec type: " + clazz);
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecMeta.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecMeta.java
new file mode 100644
index 0000000000..d42034dbe2
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSpecMeta.java
@@ -0,0 +1,10 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import java.util.List;
+
+public record TestSpecMeta(String name,
+ TestSpecKind kind,
+ List tags) {
+
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
new file mode 100644
index 0000000000..7f67c6786a
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
@@ -0,0 +1,90 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.*;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
+import org.junit.jupiter.api.DynamicContainer;
+import org.junit.jupiter.api.DynamicNode;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
+
+public record TestSuite(TestSpecMeta meta, List setup, List tests, List cleanup)
+ implements TestSpec {
+
+
+ public DynamicContainer testNode(TestPlan testPlan, List allEnvs) {
+
+ var desc = "TestSuite: %s ".formatted(
+ meta.name());
+
+ return dynamicContainer(
+ desc,
+ allEnvs.stream()
+ .map(testEnv -> testEnv.testNode(testPlan, this))
+ );
+ }
+
+ public Collection extends DynamicNode> testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
+
+ List nodes = new ArrayList<>();
+
+ int i = 1;
+ for (TestCommand setupCommand : setup()) {
+ var setupRequest = new TestRequest(
+ "SetupRequest[%s]: %s".formatted(i++, setupCommand.commandName()),
+ setupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(testPlan, setupCommand));
+
+ nodes.add(setupRequest.testNodes());
+ }
+
+ for (var testCase : tests()) {
+ nodes.add(testCase.testNodesForEnvironment(testPlan, testEnvironment));
+ }
+
+ for (TestCommand cleanupCommand : cleanup()) {
+ var cleanupRequest = new TestRequest(
+ "CleanupRequest[%s]: %s".formatted(i++, cleanupCommand.commandName()),
+ cleanupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(testPlan,cleanupCommand));
+ nodes.add(cleanupRequest.testNodes());
+ }
+
+ return nodes;
+
+ }
+
+ public void expand(SpecFiles specFiles) {
+
+ List expandedSetup = new ArrayList<>();
+ for (TestCommand command : setup) {
+ if (command.includeFrom() != null) {
+ var includedTest = specFiles.byNameAsType(TestSuite.class, command.includeFrom())
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("Included TestSuite Setup not found. parent=%s, included=%s".formatted(meta().name(), command.includeFrom())));
+
+ expandedSetup.addAll(includedTest.setup());
+ } else {
+ expandedSetup.add(command);
+ }
+ }
+ setup.clear();
+ setup.addAll(expandedSetup);
+
+ List expandedTests = new ArrayList<>();
+ for (TestCase testCase : tests) {
+ if (testCase.include() != null) {
+ var includedTest = specFiles.byNameAsType(TestSuite.class, testCase.include())
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("Included TestSuite TestCase not found. parent=%s, included=%s".formatted(meta().name(), testCase.include())));
+
+ expandedTests.addAll(includedTest.tests());
+ } else {
+ expandedTests.add(testCase);
+ }
+ }
+ tests.clear();
+ tests.addAll(expandedTests);
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
new file mode 100644
index 0000000000..c9b9d3da24
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
@@ -0,0 +1,34 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import org.junit.jupiter.api.DynamicContainer;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
+
+public record Workflow(TestSpecMeta meta, List jobs) implements TestSpec {
+
+
+ public Stream activeJobs(){
+ return jobs().stream()
+ .filter(job -> !job.meta().tags().contains("disabled"));
+ }
+
+
+ public DynamicContainer testNode(TestPlan testPlan) {
+
+ var desc = "Workflow: %s ".formatted(
+ meta.name());
+
+ var jobNodes = activeJobs()
+ .map(job -> job.testNode(testPlan));
+
+ return dynamicContainer(
+ desc,
+ testPlan.addLifecycle(this, jobNodes));
+ }
+
+}
From ac60249857aa78a7e78989852fc738305ca9ba1e Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Tue, 3 Mar 2026 13:07:03 +1300
Subject: [PATCH 13/89] WIP - begin added TestURI
---
.../api/v1/vectorize/AstraBackend.java | 14 --
.../jsonapi/api/v1/vectorize/Backend.java | 38 -----
.../sgv2/jsonapi/api/v1/vectorize/Job.java | 10 +-
.../sgv2/jsonapi/api/v1/vectorize/Target.java | 39 +++--
.../jsonapi/api/v1/vectorize/TestCase.java | 5 +-
.../api/v1/vectorize/TestEnvironment.java | 11 +-
.../jsonapi/api/v1/vectorize/TestPlan.java | 42 +++--
.../jsonapi/api/v1/vectorize/TestRequest.java | 22 ++-
.../assertions/SingleTestAssertion.java | 4 +-
.../vectorize/assertions/TestAssertion.java | 3 +-
.../assertions/TestAssertionContainer.java | 6 +-
.../v1/vectorize/backends/AstraBackend.java | 12 ++
.../api/v1/vectorize/backends/Backend.java | 12 ++
.../{ => backends}/CassandraBackend.java | 16 +-
.../lifecycle/TestPlanLifecycle.java | 36 ++++
.../api/v1/vectorize/testspec/TestSuite.java | 19 ++-
.../api/v1/vectorize/testspec/TestUri.java | 159 ++++++++++++++++++
.../api/v1/vectorize/testspec/Workflow.java | 8 +-
.../vectorize/vectorize-workflow.json | 3 +-
19 files changed, 343 insertions(+), 116 deletions(-)
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/AstraBackend.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => backends}/CassandraBackend.java (72%)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/AstraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/AstraBackend.java
deleted file mode 100644
index e7296f0e4d..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/AstraBackend.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import org.apache.commons.lang3.RandomStringUtils;
-
-import static io.stargate.sgv2.jsonapi.api.v1.vectorize.TestEnvironment.toSafeSchemaIdentifier;
-
-public class AstraBackend extends Backend {
-
- @Override
- public void updateJobForTarget(Job job) {
-
- job.variables().put("KEYSPACE_NAME", "default_keyspace");
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
deleted file mode 100644
index 6e6a147e69..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Backend.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
-import org.junit.jupiter.api.DynamicNode;
-
-import java.util.Optional;
-
-public abstract class Backend {
-
- public void updateJobForTarget(Job job){
- }
-
- public Optional beforeWorkflow(TestPlan testPlan, Workflow workflow) {
- return Optional.empty();
- }
-
- public Optional afterWorkflow(TestPlan testPlan, Workflow workflow) {
- return Optional.empty();
- }
-
- public Optional beforeJob(TestPlan testPlan, Job job) {
- return Optional.empty();
- }
-
- public Optional afterJob(TestPlan testPlan, Job job) {
- return Optional.empty();
- }
-
- public Optional beforeTestSuite(TestPlan testPlan, TestSuite test, TestEnvironment env) {
- return Optional.empty();
- }
-
- public Optional afterTestSuite(TestPlan testPlan, TestSuite test, TestEnvironment env) {
- return Optional.empty();
- }
-}
-
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
index 93935df839..2a7b7b92c2 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
@@ -3,6 +3,7 @@
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecKind;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecMeta;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.junit.jupiter.api.DynamicContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,7 +26,9 @@ public record Job(
private static final Logger LOGGER = LoggerFactory.getLogger(Job.class);
- public DynamicContainer testNode(TestPlan testPlan) {
+ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder) {
+
+ uriBuilder.addSegment(TestUri.Segment.JOB, meta.name());
var desc = "Job: %s ".formatted(
meta.name());
@@ -33,11 +36,12 @@ public DynamicContainer testNode(TestPlan testPlan) {
testPlan.updateJobForTarget(this);
var allEnvs = allEnvironments(testPlan);
var testSuiteNodes = testSuites(testPlan)
- .map(testSuite -> testSuite.testNode(testPlan, allEnvs));
+ .map(testSuite -> testSuite.testNode(testPlan, uriBuilder.clone(), allEnvs));
return dynamicContainer(
desc,
- testPlan.addLifecycle(this, testSuiteNodes));
+ uriBuilder.build().uri(),
+ testPlan.addLifecycle(uriBuilder.clone(),this, testSuiteNodes));
}
public Stream testSuites(TestPlan testPlan) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
index 8aa2e50a05..d7460153cb 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
@@ -1,16 +1,21 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.AstraBackend;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.Backend;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.CassandraBackend;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle.TestPlanLifecycle;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
import org.junit.jupiter.api.DynamicNode;
import java.util.HashMap;
import java.util.Optional;
-public class Target {
+public class Target implements TestPlanLifecycle {
private final TargetConfiguration targetConfiguration;
- private final Backend backend;
+ private final Backend backend;
private final TestEnvironment env;
public Target(TargetConfiguration targetConfiguration) {
@@ -40,24 +45,30 @@ public APIRequest apiRequest(TestCommand testCommand, TestEnvironment env){
return new APIRequest(targetConfiguration.connection(), env, testCommand.withEnvironment(env));
}
- public Optional beforeWorkflow(TestPlan testPlan, Workflow workflow){
- return backend.beforeWorkflow(testPlan, workflow);
+ @Override
+ public Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, Workflow workflow){
+ return backend.beforeWorkflow(testPlan, uriBuilder,workflow);
}
- public Optional afterWorkflow(TestPlan testPlan,Workflow workflow){
- return backend.afterWorkflow(testPlan, workflow);
+ @Override
+ public Optional afterWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder,Workflow workflow){
+ return backend.afterWorkflow(testPlan, uriBuilder,workflow);
}
- public Optional beforeJob(TestPlan testPlan,Job job){
- return backend.beforeJob(testPlan, job);
+ @Override
+ public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBuilder,Job job){
+ return backend.beforeJob(testPlan, uriBuilder,job);
}
- public Optional afterJob(TestPlan testPlan,Job job){
- return backend.afterJob(testPlan, job);
+ @Override
+ public Optional afterJob(TestPlan testPlan,TestUri.Builder uriBuilder,Job job){
+ return backend.afterJob(testPlan,uriBuilder, job);
}
- public Optional beforeTestSuite(TestPlan testPlan, TestSuite test, TestEnvironment env){
- return backend.beforeTestSuite(testPlan, test, env);
+ @Override
+ public Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ return backend.beforeTestSuite(testPlan,uriBuilder, test, env);
}
- public Optional afterTestSuite(TestPlan testPlan,TestSuite test, TestEnvironment env){
- return backend.afterTestSuite(testPlan, test, env);
+ @Override
+ public Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ return backend.afterTestSuite(testPlan, uriBuilder,test, env);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
index cb49caa5c5..6e03d965ab 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCase.java
@@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.junit.jupiter.api.DynamicContainer;
public record TestCase(
@@ -15,13 +16,13 @@ public record TestCase(
String include) {
- public DynamicContainer testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
+ public DynamicContainer testNodesForEnvironment(TestPlan testPlan, TestUri.Builder uriBuilder, TestEnvironment testEnvironment) {
var testRequest = new TestRequest(
"TestCase: name=%s".formatted(name, command.commandName()),
command(), testPlan.target(), testEnvironment, TestAssertion.buildAssertions(testPlan, this));
- return testRequest.testNodes();
+ return testRequest.testNodes(uriBuilder);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
index 9f0e0bbdf2..327f6dbc7f 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
@@ -1,6 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.apache.commons.text.StringSubstitutor;
import org.apache.commons.text.lookup.StringLookupFactory;
import org.junit.jupiter.api.DynamicContainer;
@@ -31,15 +32,17 @@ public TestEnvironment(Map vars) {
this.vars.putAll(vars);
}
- public DynamicContainer testNode(TestPlan testPlan, TestSuite testSuite) {
+ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuite testSuite) {
- var desc = "TestEnv: %s ".formatted(description());
+ var d = description();
+ uriBuilder.addSegment(TestUri.Segment.ENV, d);
+ var desc = "TestEnv: %s ".formatted(d);
- var envNodes = testSuite.testNodesForEnvironment(testPlan, this).stream();
+ var envNodes = testSuite.testNodesForEnvironment(testPlan, uriBuilder.clone(), this).stream();
return DynamicContainer.dynamicContainer(
desc,
- testPlan.addLifecycle(testSuite, this, envNodes));
+ testPlan.addLifecycle(uriBuilder.clone(), testSuite, this, envNodes));
}
private String description(){
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
index 146247776e..0b88e28a6e 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
@@ -1,6 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.*;
+import org.eclipse.aether.util.artifact.OverlayArtifactTypeRegistry;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
@@ -41,11 +42,15 @@ public Stream testNode() {
workflows.isEmpty() ? "" : String.join(", ", workflows)
);
+ var uriBuilder = TestUri.builder(TestUri.Scheme.TESTRUN)
+ .addSegment(TestUri.Segment.TARGET, target.configuration().name());
+
return Stream.of(
dynamicContainer(
desc,
+ uriBuilder.build().uri(),
selectedWorkflows()
- .map(workflow -> workflow.testNode(this))
+ .map(workflow -> workflow.testNode(this, uriBuilder.clone()))
)
);
}
@@ -54,10 +59,10 @@ public void updateJobForTarget(Job job){
target.updateJobForTarget(job);
}
- private static Optional containerIfPresent(String namePrefix, TestSpecMeta meta, Optional dynamicNode){
+ private static Optional containerIfPresent(TestUri.Builder uriBuilder, String namePrefix, TestSpecMeta meta, Optional dynamicNode){
return dynamicNode
.map(
- node -> dynamicContainer(namePrefix + ": " + meta.name(), Stream.of(node))
+ node -> dynamicContainer(namePrefix + ": " + meta.name(), uriBuilder.build().uri(), Stream.of(node))
);
}
@@ -65,35 +70,44 @@ private static Stream streamIfPresent(Optional co
return container.stream().flatMap(Stream::of);
}
- private static Stream lifecycleNodes(String namePrefix, TestSpecMeta meta, Supplier> nodeSupplier){
+ private static Stream lifecycleNodes(TestUri.Builder uriBuilder, String namePrefix, TestSpecMeta meta, Supplier> nodeSupplier){
var targetDynamicNode = nodeSupplier.get();
- return streamIfPresent(containerIfPresent(namePrefix, meta, targetDynamicNode));
+ return streamIfPresent(containerIfPresent(uriBuilder, namePrefix, meta, targetDynamicNode));
}
- public Stream extends DynamicNode> addLifecycle(Workflow workflow, Stream extends DynamicNode> dynamicNodes){
+ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, Workflow workflow, Stream extends DynamicNode> dynamicNodes){
+
+ var beforeUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "before-workflow");
+ var afterUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "after-workflow");
return Stream.concat(
- lifecycleNodes("Before Workflow", workflow.meta(), () -> target.beforeWorkflow(this, workflow)),
+ lifecycleNodes(beforeUriBuilder, "Before Workflow", workflow.meta(), () -> target.beforeWorkflow(this,beforeUriBuilder, workflow)),
Stream.concat(dynamicNodes,
- lifecycleNodes("After Workflow", workflow.meta(), () -> target.afterWorkflow(this, workflow)))
+ lifecycleNodes(afterUriBuilder, "After Workflow", workflow.meta(), () -> target.afterWorkflow(this, afterUriBuilder, workflow)))
);
}
- public Stream extends DynamicNode> addLifecycle(Job job, Stream extends DynamicNode> dynamicNodes){
+ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, Job job, Stream extends DynamicNode> dynamicNodes){
+
+ var beforeUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "before-job");
+ var afterUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "after-job");
return Stream.concat(
- lifecycleNodes("Before Job", job.meta(), () -> target.beforeJob(this, job)),
+ lifecycleNodes(beforeUriBuilder, "Before Job", job.meta(), () -> target.beforeJob(this,beforeUriBuilder, job)),
Stream.concat(dynamicNodes,
- lifecycleNodes("After Job", job.meta(), () -> target.afterJob(this, job)))
+ lifecycleNodes(afterUriBuilder, "After Job", job.meta(), () -> target.afterJob(this,afterUriBuilder, job)))
);
}
- public Stream extends DynamicNode> addLifecycle(TestSuite testSuite, TestEnvironment environment, Stream extends DynamicNode> dynamicNodes){
+ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, TestSuite testSuite, TestEnvironment environment, Stream extends DynamicNode> dynamicNodes){
+
+ var beforeUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "before-test-suite");
+ var afterUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "after-test-suite");
return Stream.concat(
- lifecycleNodes("Before TestSuite", testSuite.meta(), () -> target.beforeTestSuite(this, testSuite, environment)),
+ lifecycleNodes(beforeUriBuilder, "Before TestSuite", testSuite.meta(), () -> target.beforeTestSuite(this, beforeUriBuilder,testSuite, environment)),
Stream.concat(dynamicNodes,
- lifecycleNodes("After TestSuite", testSuite.meta(), () -> target.afterTestSuite(this, testSuite, environment)))
+ lifecycleNodes( afterUriBuilder, "After TestSuite", testSuite.meta(), () -> target.afterTestSuite(this, afterUriBuilder,testSuite, environment)))
);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
index e888362095..8233b640af 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
@@ -1,12 +1,14 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Stream;
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@@ -24,24 +26,32 @@ public TestResponse execute() {
return new TestResponse(this, apiRequest, apiRequest.execute());
}
- public DynamicContainer testNodes() {
+ public DynamicContainer testNodes(TestUri.Builder uriBuilder) {
+
+ uriBuilder.addSegment(TestUri.Segment.REQUEST, name());
+
+ Stream.Builder nodesBuilder = Stream.builder();;
- List nodes = new ArrayList<>();
AtomicReference atomicResponse = new AtomicReference<>();
// Execute the request, and set so the assertions can pull the response after.
- nodes.add(dynamicTest("Command: " + testCommand.commandName().getApiName(), () -> atomicResponse.set(execute())));
+ var commandUriBuilder = uriBuilder.clone();
+ commandUriBuilder.addSegment(TestUri.Segment.COMMAND, testCommand.commandName().getApiName());
+ nodesBuilder.add(dynamicTest("Command: " + testCommand.commandName().getApiName(),
+ commandUriBuilder.build().uri(),
+ () -> atomicResponse.set(execute())));
// tests for each assertion
+ var assertionsUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.ASSERTION_CONTAINER, "assertions");
var assertionTests = testAssertions().stream().map(
- testAssertion -> testAssertion.testNodes(atomicResponse))
+ testAssertion -> testAssertion.testNodes(assertionsUriBuilder.clone(), atomicResponse))
.toList();
// if we have assertion tests, put them in a container
if (!assertionTests.isEmpty()) {
- nodes.add(dynamicContainer("Assertions", assertionTests));
+ nodesBuilder.add(dynamicContainer("Assertions", assertionTests));
}
- return dynamicContainer("Request: " + name, nodes);
+ return dynamicContainer("Request: " + name, uriBuilder.build().uri(), nodesBuilder.build());
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
index 1cfd9ac457..387164c560 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import io.stargate.sgv2.jsonapi.service.schema.tables.ApiSupportDef;
import org.hamcrest.SelfDescribing;
import org.hamcrest.StringDescription;
@@ -34,8 +35,9 @@ public void run(TestResponse testResponse) {
}
@Override
- public DynamicNode testNodes(AtomicReference testResponse) {
+ public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
+ uriBuilder.addSegment(TestUri.Segment.ASSERTION, name());
var original = (matcher instanceof Describable d) ?
d.describe()
:
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
index 887c1300a1..6b9c5ccb36 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
@@ -7,6 +7,7 @@
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.AssertionTemplateSpec;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.SpecFiles;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.assertj.core.api.AssertFactory;
import org.junit.jupiter.api.DynamicNode;
@@ -24,7 +25,7 @@ public interface TestAssertion {
void run(TestResponse testResponse);
- DynamicNode testNodes(AtomicReference testResponse);
+ DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse);
static List forSuccess(TestPlan testPlan, TestCommand testCommand) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
index acf447b355..1af420a1b9 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.junit.jupiter.api.DynamicNode;
import java.util.List;
@@ -36,10 +37,11 @@ public void run(TestResponse testResponse) {
}
@Override
- public DynamicNode testNodes(AtomicReference testResponse) {
+ public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
+ uriBuilder.addSegment(TestUri.Segment.ASSERTION, name());
var childs = assertions.stream()
- .map(assertion -> assertion.testNodes(testResponse))
+ .map(assertion -> assertion.testNodes(uriBuilder.clone(), testResponse))
.toList();
return dynamicContainer(name, childs);
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java
new file mode 100644
index 0000000000..528fadf7bf
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java
@@ -0,0 +1,12 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+
+public class AstraBackend extends Backend {
+
+ @Override
+ public void updateJobForTarget(Job job) {
+
+ job.variables().put("KEYSPACE_NAME", "default_keyspace");
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java
new file mode 100644
index 0000000000..95acf200eb
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java
@@ -0,0 +1,12 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle.TestPlanLifecycle;
+
+public abstract class Backend implements TestPlanLifecycle {
+
+ public void updateJobForTarget(Job job){
+ }
+
+}
+
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java
similarity index 72%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java
index 916ff8582a..ac2585d4c2 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/CassandraBackend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java
@@ -1,8 +1,12 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestRequest;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.DynamicNode;
@@ -26,7 +30,7 @@ public void updateJobForTarget(Job job) {
}
@Override
- public Optional beforeJob(TestPlan testPlan, Job job) {
+ public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBuilder, Job job) {
var command = TestCommand.fromJson(
"""
@@ -42,11 +46,11 @@ public Optional beforeJob(TestPlan testPlan, Job job) {
env.substitutor().replace("createKeyspace: ${KEYSPACE_NAME}"),
command, testPlan.target(), env, TestAssertion.forSuccess( testPlan, command));
- return Optional.of(setupRequest.testNodes());
+ return Optional.of(setupRequest.testNodes(uriBuilder));
}
@Override
- public Optional afterJob(TestPlan testPlan, Job job) {
+ public Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuilder,Job job) {
var command = TestCommand.fromJson(
"""
{
@@ -61,6 +65,6 @@ public Optional afterJob(TestPlan testPlan, Job job) {
env.substitutor().replace("dropKeyspace: ${KEYSPACE_NAME}"),
command, testPlan.target(), job.withoutMatrix(testPlan), TestAssertion.forSuccess(testPlan,command));
- return Optional.of(setupRequest.testNodes());
+ return Optional.of(setupRequest.testNodes(uriBuilder));
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
new file mode 100644
index 0000000000..31eb1dee36
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
@@ -0,0 +1,36 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestEnvironment;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
+import org.junit.jupiter.api.DynamicNode;
+
+import java.util.Optional;
+
+public interface TestPlanLifecycle {
+
+ default Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, Workflow workflow){
+ return Optional.empty();
+ }
+ default Optional afterWorkflow(TestPlan testPlan,TestUri.Builder uriBuilder, Workflow workflow){
+ return Optional.empty();
+ }
+
+ default Optional beforeJob(TestPlan testPlan,TestUri.Builder uriBuilder, Job job){
+ return Optional.empty();
+ }
+ default Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuilder, Job job){
+ return Optional.empty();
+ }
+
+ default Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ return Optional.empty();
+ }
+ default Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ return Optional.empty();
+ }
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
index 7f67c6786a..b8e0da0c30 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestSuite.java
@@ -15,40 +15,47 @@ public record TestSuite(TestSpecMeta meta, List setup, List allEnvs) {
+ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder, List allEnvs) {
+
+ uriBuilder.addSegment(TestUri.Segment.SUITE, meta().name());
var desc = "TestSuite: %s ".formatted(
meta.name());
return dynamicContainer(
desc,
+ uriBuilder.build().uri(),
allEnvs.stream()
- .map(testEnv -> testEnv.testNode(testPlan, this))
+ .map(testEnv -> testEnv.testNode(testPlan, uriBuilder.clone(), this))
);
}
- public Collection extends DynamicNode> testNodesForEnvironment(TestPlan testPlan, TestEnvironment testEnvironment) {
+ public Collection extends DynamicNode> testNodesForEnvironment(TestPlan testPlan, TestUri.Builder uriBuilder, TestEnvironment testEnvironment) {
List nodes = new ArrayList<>();
int i = 1;
+ var setupUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.STAGE, "setup");
+
for (TestCommand setupCommand : setup()) {
var setupRequest = new TestRequest(
"SetupRequest[%s]: %s".formatted(i++, setupCommand.commandName()),
setupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(testPlan, setupCommand));
- nodes.add(setupRequest.testNodes());
+ nodes.add(setupRequest.testNodes(setupUriBuilder.clone()));
}
+ var testUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.STAGE, "test");
for (var testCase : tests()) {
- nodes.add(testCase.testNodesForEnvironment(testPlan, testEnvironment));
+ nodes.add(testCase.testNodesForEnvironment(testPlan, testUriBuilder.clone(), testEnvironment));
}
+ var cleanupUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.STAGE, "cleanup");
for (TestCommand cleanupCommand : cleanup()) {
var cleanupRequest = new TestRequest(
"CleanupRequest[%s]: %s".formatted(i++, cleanupCommand.commandName()),
cleanupCommand, testPlan.target(), testEnvironment, TestAssertion.forSuccess(testPlan,cleanupCommand));
- nodes.add(cleanupRequest.testNodes());
+ nodes.add(cleanupRequest.testNodes(cleanupUriBuilder.clone()));
}
return nodes;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java
new file mode 100644
index 0000000000..ffd68873ed
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java
@@ -0,0 +1,159 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import io.stargate.sgv2.jsonapi.service.operation.builder.LiteralTerm;
+
+import java.net.URI;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toMap;
+
+public record TestUri(
+ Scheme scheme,
+ List segments) {
+
+ public static TestUri.Builder builder(Scheme scheme){
+ return new TestUri.Builder(scheme);
+ }
+
+ public Segment leafType(){
+ return segments.getLast().segment;
+ }
+
+ public URI uri() {
+ var path = segments.stream()
+ .map(SegmentValue::toString)
+ .collect(joining("/"));
+ return URI.create(scheme.name() + "://" + path);
+ }
+
+ public static TestUri parse(URI uri) {
+
+ var builder = builder(Scheme.valueOf(uri.getScheme().toLowerCase()));
+ SegmentValue.parse(uri)
+ .forEach(builder::addSegment);
+ return builder.build();
+ }
+
+ public enum Scheme {
+ TESTPLAN,
+ TESTRUN;
+
+ public String pathName() {
+ return name().toLowerCase();
+ }
+ }
+
+ public enum Segment {
+ TARGET(null),
+ LIFECYCLE(null), // used in multiple places
+ WORKFLOW(TARGET),
+ JOB(WORKFLOW),
+ SUITE(JOB),
+ ENV(SUITE),
+ STAGE(ENV),
+ REQUEST(STAGE),
+ COMMAND(REQUEST),
+ ASSERTION_CONTAINER(REQUEST),
+ ASSERTION(ASSERTION_CONTAINER);
+
+ private final Segment parent;
+
+ Segment(Segment parent) {
+ this.parent = parent;
+ }
+
+ public Segment parent() {
+ return parent;
+ }
+
+ public boolean isParentValid(Segment segment) {
+ // XXX TODO: needs work
+ return true;
+ //return (parent == null) || (parent == segment) || (segment == LIFECYCLE) ;
+ }
+
+ public String pathName() {
+ return name().toLowerCase();
+ }
+ }
+
+ public record SegmentValue(Segment segment, String value) {
+
+ private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9\\-_.~]");
+
+ public SegmentValue{
+ Objects.requireNonNull(segment, "segment must not be null");
+ Objects.requireNonNull(value, "value must not be null");
+ }
+
+ public static Stream parse(URI uri) {
+ return Arrays.stream(uri.getPath().split("/"))
+ .map(SegmentValue::parse);
+ }
+
+ public static SegmentValue parse(String segmentKeyValue) {
+ var parts = segmentKeyValue.split("=", 2);
+ if (parts.length != 2) {
+ throw new IllegalArgumentException("Invalid segment, expected key=value format: " + segmentKeyValue);
+ }
+ try {
+ return new SegmentValue(Segment.valueOf(parts[0].toUpperCase()), parts[1]);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Unknown segment key: " + parts[0]);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return segment.name() + "=" + INVALID_CHARS.matcher(value).replaceAll("_");
+ }
+ }
+
+
+ public static class Builder {
+
+ private final Scheme scheme;
+ private final List segmentValues;
+
+ protected Builder(Scheme scheme) {
+ this(scheme, new ArrayList<>());
+ }
+
+ private Builder(Scheme scheme, List segmentValues) {
+ this.scheme = Objects.requireNonNull(scheme, "scheme must not be null");
+ this.segmentValues = Objects.requireNonNull(segmentValues, "segmentValues must not be null");
+ }
+
+ public Builder addSegment(SegmentValue segmentValue) {
+ segmentValues.add(segmentValue);
+ return this;
+ }
+
+ public Builder addSegment(Segment segment, String value) {
+ segmentValues.add(new SegmentValue(segment, value));
+ return this;
+ }
+
+ public Builder clone(){
+ return new Builder(scheme, segmentValues);
+ }
+
+ public TestUri build() {
+ for (int i = 0; i < segmentValues.size(); i++) {
+ var current = segmentValues.get(i);
+ var previous = i == 0 ? null : segmentValues.get(i - 1).segment();
+ if (!current.segment().isParentValid(previous)) {
+ throw new IllegalArgumentException(
+ "Invalid segment order. segment=%s expected parent=%s but previous=%s"
+ .formatted(current.segment(), current.segment().parent(), previous));
+
+ }
+ }
+ return new TestUri(scheme, List.copyOf(segmentValues));
+ }
+ }
+
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
index c9b9d3da24..8732fd0610 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Workflow.java
@@ -18,17 +18,19 @@ public Stream activeJobs(){
}
- public DynamicContainer testNode(TestPlan testPlan) {
+ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder) {
+ uriBuilder.addSegment(TestUri.Segment.WORKFLOW, meta().name());
var desc = "Workflow: %s ".formatted(
meta.name());
var jobNodes = activeJobs()
- .map(job -> job.testNode(testPlan));
+ .map(job -> job.testNode(testPlan, uriBuilder.clone()));
return dynamicContainer(
desc,
- testPlan.addLifecycle(this, jobNodes));
+ uriBuilder.build().uri(),
+ testPlan.addLifecycle(uriBuilder.clone(), this, jobNodes));
}
}
diff --git a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
index 5cbfce0258..e08ff4c5e3 100644
--- a/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
+++ b/src/test/resources/integration-tests/vectorize/vectorize-workflow.json
@@ -7,7 +7,7 @@
{
"meta": {
"name": "open-ai-vectorize",
- "tags": []
+ "tags": ["disable"]
},
"fromEnvironment": {
"x-embedding-api-key": "x_embedding_api_key",
@@ -32,7 +32,6 @@
"meta": {
"name": "voyageAI-vectorize",
"tags": [
- "disabled"
]
},
"fromEnvironment": {
From 4c9c2399d52f6c1dae8bb8262b73743e64c99d0f Mon Sep 17 00:00:00 2001
From: Aaron Morton
Date: Wed, 11 Mar 2026 10:44:26 +1300
Subject: [PATCH 14/89] WIP - refactor
---
.../v1/vectorize/EnvironmentalRequest.java | 6 --
.../v1/vectorize/IntegrationJobRunner.java | 50 ----------------
.../jsonapi/api/v1/vectorize/RunnerBase.java | 15 -----
.../api/v1/vectorize/TargetConfiguration.java | 4 --
.../api/v1/vectorize/TestCaseResult.java | 17 ------
.../jsonapi/api/v1/vectorize/TestPlan.java | 26 ++++----
.../api/v1/vectorize/TestRequestRunner.java | 28 ---------
.../api/v1/vectorize/TestSuiteRunner.java | 51 ----------------
.../api/v1/vectorize/VectorizeAstra.java | 2 +-
.../api/v1/vectorize/VectorizeUnit.java | 60 -------------------
.../assertions/AssertionFactory.java | 2 +-
.../assertions/AssertionFactoryRegistry.java | 6 --
.../assertions/AssertionMatcher.java | 2 +-
.../vectorize/assertions/BodyAssertion.java | 2 +-
.../DescribableAssertionMatcher.java | 2 +-
.../v1/vectorize/assertions/Documents.java | 2 +-
.../api/v1/vectorize/assertions/Http.java | 2 +-
.../api/v1/vectorize/assertions/Response.java | 6 +-
.../assertions/SingleTestAssertion.java | 46 ++++----------
.../api/v1/vectorize/assertions/Status.java | 2 +-
.../v1/vectorize/assertions/Templated.java | 3 +-
.../vectorize/assertions/TestAssertion.java | 15 ++---
.../assertions/TestAssertionContainer.java | 8 +--
.../lifecycle/TestPlanLifecycle.java | 18 +++---
.../vectorize/{ => messaging}/APIRequest.java | 9 ++-
.../{ => messaging}/APIResponse.java | 2 +-
.../{backends => targets}/AstraBackend.java | 4 +-
.../{backends => targets}/Backend.java | 4 +-
.../CassandraBackend.java | 18 +++---
.../vectorize/{ => targets}/Connection.java | 2 +-
.../v1/vectorize/{ => targets}/Target.java | 35 ++++++-----
.../testrun/DynamicTestExecutable.java | 60 +++++++++++++++++++
.../TestRunEnv.java} | 24 ++++----
.../TestRunRequest.java} | 29 ++++-----
.../TestRunResponse.java} | 9 +--
.../{testspec => testrun}/TestUri.java | 7 +--
.../api/v1/vectorize/{ => testspec}/Job.java | 33 +++++-----
.../api/v1/vectorize/testspec/SpecFiles.java | 7 ++-
.../testspec/TargetConfiguration.java | 6 ++
.../TargetsSpec.java} | 17 ++++--
.../v1/vectorize/{ => testspec}/TestCase.java | 12 ++--
.../vectorize/{ => testspec}/TestCommand.java | 5 +-
.../api/v1/vectorize/testspec/TestSpec.java | 2 +-
.../v1/vectorize/testspec/TestSpecKind.java | 6 +-
.../{TestSuite.java => TestSuiteSpec.java} | 17 +++---
.../{Workflow.java => WorkflowSpec.java} | 19 +++---
.../integration-tests/targets/targets.json | 6 +-
.../vectorize/vectorize-workflow.json | 3 +-
48 files changed, 271 insertions(+), 440 deletions(-)
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/RunnerBase.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfiguration.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeUnit.java
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => messaging}/APIRequest.java (87%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => messaging}/APIResponse.java (73%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{backends => targets}/AstraBackend.java (58%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{backends => targets}/Backend.java (61%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{backends => targets}/CassandraBackend.java (78%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => targets}/Connection.java (82%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => targets}/Target.java (65%)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/DynamicTestExecutable.java
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{TestEnvironment.java => testrun/TestRunEnv.java} (87%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{TestRequest.java => testrun/TestRunRequest.java} (61%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{TestResponse.java => testrun/TestRunResponse.java} (75%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{testspec => testrun}/TestUri.java (95%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => testspec}/Job.java (69%)
create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetConfiguration.java
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{TargetConfigurationss.java => testspec/TargetsSpec.java} (75%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => testspec}/TestCase.java (55%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/{ => testspec}/TestCommand.java (95%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/{TestSuite.java => TestSuiteSpec.java} (80%)
rename src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/{Workflow.java => WorkflowSpec.java} (58%)
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
deleted file mode 100644
index 82587e992b..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/EnvironmentalRequest.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-public interface EnvironmentalRequest {
-
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
deleted file mode 100644
index 12551cdd5a..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/IntegrationJobRunner.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.SpecFiles;
-
-public class IntegrationJobRunner {
-
- private final Target target;
- private final SpecFiles itCollection;
- private final Job job;
-
- public IntegrationJobRunner(Target target, SpecFiles itCollection, Job job) {
- this.target = target;
- this.itCollection = itCollection;
- this.job = job;
- }
-
-// public void run() {
-//
-// target.jobStarting(job);
-// var allEnvs = job.allEnvironments();
-//
-// List allTests = new ArrayList<>();
-// job.tests()
-// .forEach(
-// testName -> {
-// allTests.addAll(itCollection.testByName(testName));
-// });
-//
-// try{
-//
-// for (TestSuite test : allTests) {
-// for (TestEnvironment env : allEnvs) {
-//
-// try{
-// target.testStarting(test, env);
-// var testRunner = new IntegrationTestRunner( itCollection, target, test, env);
-// testRunner.run();
-// }
-// finally{
-// target.testFinished(test, env);
-// }
-//
-// }
-// }
-// }
-// finally {
-// target.jobFinished(job);
-// }
-// }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/RunnerBase.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/RunnerBase.java
deleted file mode 100644
index ceb8576e45..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/RunnerBase.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import org.junit.jupiter.api.DynamicNode;
-import org.junit.jupiter.api.DynamicTest;
-import org.junit.jupiter.api.function.Executable;
-
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-
-public abstract class RunnerBase implements Executable {
-
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfiguration.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfiguration.java
deleted file mode 100644
index 58874c620d..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfiguration.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-public record TargetConfiguration(String name, String backend, Connection connection) {
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
deleted file mode 100644
index eccc7429db..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestCaseResult.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-
-public record TestCaseResult(
- TestSuite integrationTest,
- TestCase testCase, // Nullable
- TestResponse testResponse,
- AssertionError error,
- AssertionMatcher failedAssertion
-) {
-
- public boolean failed(){
- return error != null;
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
index 0b88e28a6e..1476fdf3d4 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestPlan.java
@@ -1,7 +1,10 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.targets.Target;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.*;
-import org.eclipse.aether.util.artifact.OverlayArtifactTypeRegistry;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
@@ -12,26 +15,29 @@
import java.util.stream.Stream;
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
-import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-public record TestPlan(Target target, SpecFiles specFiles, Set workflows){
+public record TestPlan(Target target, SpecFiles specFiles, Set workflows, boolean ignoreDisabled){
public static TestPlan create(String targetName, List workflows){
- var targetConfigs = TargetConfigurationss.loadAll("integration-tests/targets/targets.json");
+ return create(targetName, workflows, true);
+ }
+
+ public static TestPlan create(String targetName, List workflows, boolean ignoreDisabled){
+ var targetConfigs = TargetsSpec.loadAll("integration-tests/targets/targets.json");
var target = new Target(targetConfigs.configuration(targetName));
var specFiles = SpecFiles.loadAll(List.of("integration-tests/vectorize", "integration-tests/assertions/assertion-templates.json"));
- return new TestPlan(target, specFiles, Set.copyOf(workflows));
+ return new TestPlan(target, specFiles, Set.copyOf(workflows), ignoreDisabled);
}
- public Stream selectedWorkflows(){
+ public Stream selectedWorkflows(){
return specFiles.byKind(TestSpecKind.WORKFLOW)
.filter(specFile ->
workflows.isEmpty() || workflows.contains(specFile.spec().meta().name())
)
- .map(testSpec -> (Workflow) testSpec.spec());
+ .map(testSpec -> (WorkflowSpec) testSpec.spec());
}
public Stream testNode() {
@@ -50,7 +56,7 @@ public Stream testNode() {
desc,
uriBuilder.build().uri(),
selectedWorkflows()
- .map(workflow -> workflow.testNode(this, uriBuilder.clone()))
+ .map(workflow -> workflow.testNode(this, uriBuilder.clone(), ignoreDisabled))
)
);
}
@@ -75,7 +81,7 @@ private static Stream lifecycleNodes(TestUri.Builder uriBuilder, St
return streamIfPresent(containerIfPresent(uriBuilder, namePrefix, meta, targetDynamicNode));
}
- public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, Workflow workflow, Stream extends DynamicNode> dynamicNodes){
+ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, WorkflowSpec workflow, Stream extends DynamicNode> dynamicNodes){
var beforeUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "before-workflow");
var afterUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "after-workflow");
@@ -99,7 +105,7 @@ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, Jo
);
}
- public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, TestSuite testSuite, TestEnvironment environment, Stream extends DynamicNode> dynamicNodes){
+ public Stream extends DynamicNode> addLifecycle(TestUri.Builder uriBuilder, TestSuiteSpec testSuite, TestRunEnv environment, Stream extends DynamicNode> dynamicNodes){
var beforeUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "before-test-suite");
var afterUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.LIFECYCLE, "after-test-suite");
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
deleted file mode 100644
index 294c2c11d0..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequestRunner.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-
-import java.util.Objects;
-
-import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-
-public class TestRequestRunner extends RunnerBase{
-
- private final TestRequest testRequest;
- private final TestSuite testSuite;
- private final TestCase testCase;
-
- public TestRequestRunner(TestRequest testRequest, TestSuite testSuite, TestCase testCase ) {
- this.testRequest = Objects.requireNonNull(testRequest, "testRequest must not be null");
-
- this.testSuite = testSuite;
- this.testCase = testCase;
- }
-
- @Override
- public void execute() throws Throwable {
-
-// testRequest.execute().validate(testSuite, testCase);
- }
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
deleted file mode 100644
index b697b4e04c..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestSuiteRunner.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static io.restassured.RestAssured.given;
-
-public class TestSuiteRunner extends RunnerBase {
- private static final Logger LOGGER = LoggerFactory.getLogger(TestSuiteRunner.class);
-
-
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- private final TestPlan testPlan;
- private final TestSuite testSuite;
- private final TestEnvironment testEnvironment;
-
- public TestSuiteRunner(
- TestPlan testPlan, TestSuite testSuite, TestEnvironment testEnvironment) {
- this.testPlan = testPlan;
- this.testSuite = testSuite;
- this.testEnvironment = testEnvironment;
- }
-
-
-
- @Override
- public void execute() throws Throwable {
-
-
-
-// for (TestCase testCase : testSuite.tests()) {
-// var testRequest = new TestRequest(testCase.command(), testPlan.target(), testEnvironment, TestAssertion.buildAssertions(testCase));
-// var testResponse = testRequest.execute();
-// var testCaseResult = testResponse.validate(testSuite, testCase);
-//
-// if (testCaseResult.failed()){
-// LOGGER.warn("TestCase FAILED: test.name={}, testCase.name={}, failedAssertion={}, error={}",
-// testCaseResult.integrationTest().meta().name(),testCaseResult.testCase().name(), testCaseResult.failedAssertion(), String.valueOf(testCaseResult.error()));
-// }
-// else{
-// LOGGER.info("TestCase PASSED: test.name={}, testCase.name={}",
-// testCaseResult.integrationTest().meta().name(),testCaseResult.testCase().name());
-// }
-// }
-
- }
-
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeAstra.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeAstra.java
index effb9182aa..a2a2c61cc4 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeAstra.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeAstra.java
@@ -17,7 +17,7 @@ public class VectorizeAstra {
@TestFactory
Stream jobs() {
- var testPlan = TestPlan.create("astra-dev", List.of("all-vectorize-workflow"));
+ var testPlan = TestPlan.create("astra-dev", List.of("all-vectorize-workflow"), false);
return testPlan.testNode();
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeUnit.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeUnit.java
deleted file mode 100644
index 782e37bc7b..0000000000
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/VectorizeUnit.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
-
-import org.eclipse.aether.util.artifact.OverlayArtifactTypeRegistry;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class VectorizeUnit {
- private static final Logger LOGGER = LoggerFactory.getLogger(VectorizeUnit.class);
-
- @Test
- public void doTest() {
-
-// var targets = TargetConfigurationss.loadAll("integration-tests/targets/targets.json");
-// var integrationTarget = new Target(targets.configuration("local"));
-//
-// var itCollection = ITCollection.loadAll("integration-tests/vectorize");
-//
-// var workflow = itCollection.workflowFirstByName("all-vectorize-workflow");
-
-// var testPlan = TestPlan.create("local", List.of("all-vectorize-workflow"));
-//
-//
-// // SEQUENTIAL
-// integrationTarget.workflowStarting(workflow);
-// try {
-// for (var job : jobs) {
-// LOGGER.info("Starting job {}", job.meta());
-// new IntegrationJobRunner(integrationTarget, itCollection, job).run();
-// }
-// } finally {
-// integrationTarget.workflowFinished(workflow);
-// }
-
- // Parallel
-// int maxConcurrentJobs = 2;
-// integrationTarget.workflowStarting(workflow);
-// try {
-// var executor = java.util.concurrent.Executors.newFixedThreadPool(maxConcurrentJobs);
-// try {
-// var futures = jobs.stream()
-// .map(job -> java.util.concurrent.CompletableFuture.runAsync(() -> {
-// LOGGER.info("Starting job {}", job.meta());
-// new IntegrationJobRunner(integrationTarget, itCollection, job).run();
-// }, executor))
-// .toList();
-//
-// // wait for all, fail if any failed
-// futures.forEach(java.util.concurrent.CompletableFuture::join);
-// } finally {
-// executor.shutdown();
-// }
-// } finally {
-// integrationTarget.workflowFinished(workflow);
-// }
-
- }
-}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
index 08ce531266..5bff302b56 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactory.java
@@ -1,7 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
import java.lang.reflect.InvocationTargetException;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
index fb51179491..cc86703088 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionFactoryRegistry.java
@@ -1,11 +1,5 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
index 70d4225013..60c911e337 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/AssertionMatcher.java
@@ -1,6 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIResponse;
/**
* Contract for running an assertion on the response from the API.
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
index 6416d294f3..5393ea3df9 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/BodyAssertion.java
@@ -1,6 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIResponse;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
index 9e001ac0c6..2b3e3942a1 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/DescribableAssertionMatcher.java
@@ -1,6 +1,6 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.APIResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIResponse;
import org.jspecify.annotations.NonNull;
public record DescribableAssertionMatcher(
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
index 3deb8135af..fc5bdf5dbd 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Documents.java
@@ -1,7 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.Matchers.hasSize;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
index 387aa05b39..5958d9b4ee 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Http.java
@@ -1,7 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import org.apache.http.HttpStatus;
import static io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.DescribableAssertionMatcher.described;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
index f085e91877..65d0283b73 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Response.java
@@ -1,11 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.NullNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
-
-import java.util.List;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import static io.stargate.sgv2.jsonapi.api.v1.ResponseAssertions.*;
import static org.hamcrest.Matchers.hasSize;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
index 387164c560..88773fdd81 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/SingleTestAssertion.java
@@ -1,15 +1,11 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
-import io.stargate.sgv2.jsonapi.service.schema.tables.ApiSupportDef;
-import org.hamcrest.SelfDescribing;
-import org.hamcrest.StringDescription;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.DynamicTestExecutable;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import org.junit.jupiter.api.DynamicNode;
-import java.lang.reflect.Executable;
-import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@@ -21,7 +17,7 @@ public record SingleTestAssertion(
AssertionMatcher matcher
) implements TestAssertion {
- public void run(TestResponse testResponse) {
+ public void run(TestRunResponse testResponse) {
try {
matcher.match(testResponse.apiResponse());
@@ -35,41 +31,25 @@ public void run(TestResponse testResponse) {
}
@Override
- public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
+ public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
- uriBuilder.addSegment(TestUri.Segment.ASSERTION, name());
- var original = (matcher instanceof Describable d) ?
+ var matcherDesc = (matcher instanceof Describable d) ?
d.describe()
:
- null;
+ "";
- var truncated = ( original != null && original.length() > 60) ?
- original.substring(0, 57) + "..."
- :
- original;
-
- var testDesc = truncated == null ?
- name()
- :
- "%s [%s]".formatted(name(), truncated);
-
- // if we truncated the description of the test, we then want to pipe to std out when running
- // because it will not be full in the test tree
- var stdoutMessage = (original != null && !Objects.equals(truncated, original)) ?
- "%s [%s]".formatted(name(), original)
- :
- null;
-
- return dynamicTest(testDesc, () -> {
+ var executable = new DynamicTestExecutable(
+ "%s [%s]".formatted(name(), matcherDesc),
+ uriBuilder.addSegment(TestUri.Segment.ASSERTION, name()),
+ () -> {
var resp = testResponse.get();
if (resp == null) {
throw new IllegalStateException("Response is null");
}
- if (stdoutMessage != null) {
- System.out.printf(stdoutMessage);
- }
run(resp);
}
);
+
+ return executable.testNode();
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
index 4ae2703a89..722607068a 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Status.java
@@ -1,7 +1,7 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
index 4c14df897c..cc86644ab7 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/Templated.java
@@ -2,9 +2,8 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.AssertionTemplateSpec;
import java.util.List;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
index 6b9c5ccb36..d212c54cf9 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertion.java
@@ -1,19 +1,16 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCase;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCase;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunResponse;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.AssertionTemplateSpec;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.SpecFiles;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
-import org.assertj.core.api.AssertFactory;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import org.junit.jupiter.api.DynamicNode;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
@@ -23,9 +20,9 @@ public interface TestAssertion {
JsonNode args();
- void run(TestResponse testResponse);
+ void run(TestRunResponse testResponse);
- DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse);
+ DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse);
static List forSuccess(TestPlan testPlan, TestCommand testCommand) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
index 1af420a1b9..81bf82d9c9 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/assertions/TestAssertionContainer.java
@@ -1,8 +1,8 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions;
import com.fasterxml.jackson.databind.JsonNode;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestResponse;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunResponse;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import org.junit.jupiter.api.DynamicNode;
import java.util.List;
@@ -18,7 +18,7 @@ public record TestAssertionContainer(
) implements TestAssertion {
@Override
- public void run(TestResponse testResponse) {
+ public void run(TestRunResponse testResponse) {
for (TestAssertion assertion : assertions) {
try{
assertion.run(testResponse);
@@ -37,7 +37,7 @@ public void run(TestResponse testResponse) {
}
@Override
- public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
+ public DynamicNode testNodes(TestUri.Builder uriBuilder, AtomicReference testResponse) {
uriBuilder.addSegment(TestUri.Segment.ASSERTION, name());
var childs = assertions.stream()
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
index 31eb1dee36..90420cf48d 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/lifecycle/TestPlanLifecycle.java
@@ -1,21 +1,21 @@
package io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestEnvironment;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuiteSpec;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.WorkflowSpec;
import org.junit.jupiter.api.DynamicNode;
import java.util.Optional;
public interface TestPlanLifecycle {
- default Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, Workflow workflow){
+ default Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, WorkflowSpec workflow){
return Optional.empty();
}
- default Optional afterWorkflow(TestPlan testPlan,TestUri.Builder uriBuilder, Workflow workflow){
+ default Optional afterWorkflow(TestPlan testPlan,TestUri.Builder uriBuilder, WorkflowSpec workflow){
return Optional.empty();
}
@@ -26,10 +26,10 @@ default Optional afterJob(TestPlan testPlan, TestUri.Builder uriBu
return Optional.empty();
}
- default Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ default Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuiteSpec test, TestRunEnv env){
return Optional.empty();
}
- default Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ default Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuiteSpec test, TestRunEnv env){
return Optional.empty();
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIRequest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIRequest.java
similarity index 87%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIRequest.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIRequest.java
index e57f2768d1..00db656092 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIRequest.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIRequest.java
@@ -1,4 +1,4 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -8,6 +8,9 @@
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import io.stargate.sgv2.jsonapi.api.model.command.CommandTarget;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.targets.Connection;
import io.stargate.sgv2.jsonapi.config.constants.HttpConstants;
import java.util.Map;
@@ -24,10 +27,10 @@ public class APIRequest {
private static String DB_PATH = "/";
private final Connection connection;
- private final TestEnvironment integrationEnv;
+ private final TestRunEnv integrationEnv;
private final ObjectNode request;
- public APIRequest(Connection connection, TestEnvironment integrationEnv, ObjectNode request ) {
+ public APIRequest(Connection connection, TestRunEnv integrationEnv, ObjectNode request ) {
this.connection = connection;
this.integrationEnv = integrationEnv;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIResponse.java
similarity index 73%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIResponse.java
index 05120514be..0e407326fa 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/APIResponse.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/messaging/APIResponse.java
@@ -1,4 +1,4 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging;
import io.restassured.response.ValidatableResponse;
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/AstraBackend.java
similarity index 58%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/AstraBackend.java
index 528fadf7bf..7c2e58f046 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/AstraBackend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/AstraBackend.java
@@ -1,6 +1,6 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.targets;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
public class AstraBackend extends Backend {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Backend.java
similarity index 61%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Backend.java
index 95acf200eb..027bf7bcaa 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/Backend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Backend.java
@@ -1,6 +1,6 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.targets;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle.TestPlanLifecycle;
public abstract class Backend implements TestPlanLifecycle {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/CassandraBackend.java
similarity index 78%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/CassandraBackend.java
index ac2585d4c2..1f7767e3ae 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/backends/CassandraBackend.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/CassandraBackend.java
@@ -1,18 +1,18 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.backends;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.targets;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.Job;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestRequest;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunRequest;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.DynamicNode;
import java.util.Optional;
-import static io.stargate.sgv2.jsonapi.api.v1.vectorize.TestEnvironment.toSafeSchemaIdentifier;
+import static io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv.toSafeSchemaIdentifier;
/**
* Cassandra:Y2Fzc2FuZHJh:Y2Fzc2FuZHJh
@@ -42,7 +42,7 @@ public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBui
""");
var env = job.withoutMatrix(testPlan);
- var setupRequest = new TestRequest(
+ var setupRequest = new TestRunRequest(
env.substitutor().replace("createKeyspace: ${KEYSPACE_NAME}"),
command, testPlan.target(), env, TestAssertion.forSuccess( testPlan, command));
@@ -50,7 +50,7 @@ public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBui
}
@Override
- public Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuilder,Job job) {
+ public Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuilder, Job job) {
var command = TestCommand.fromJson(
"""
{
@@ -61,7 +61,7 @@ public Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuil
""");
var env = job.withoutMatrix(testPlan);
- var setupRequest = new TestRequest(
+ var setupRequest = new TestRunRequest(
env.substitutor().replace("dropKeyspace: ${KEYSPACE_NAME}"),
command, testPlan.target(), job.withoutMatrix(testPlan), TestAssertion.forSuccess(testPlan,command));
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Connection.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Connection.java
similarity index 82%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Connection.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Connection.java
index f21099f4fa..16e6d01fdc 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Connection.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Connection.java
@@ -1,4 +1,4 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.targets;
public record Connection(
String domain,
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Target.java
similarity index 65%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Target.java
index d7460153cb..67e845fee0 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Target.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/targets/Target.java
@@ -1,12 +1,15 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.targets;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.AstraBackend;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.Backend;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.backends.CassandraBackend;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.*;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.lifecycle.TestPlanLifecycle;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Workflow;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIRequest;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.Job;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TargetConfiguration;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuiteSpec;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.WorkflowSpec;
import org.junit.jupiter.api.DynamicNode;
import java.util.HashMap;
@@ -16,11 +19,11 @@ public class Target implements TestPlanLifecycle {
private final TargetConfiguration targetConfiguration;
private final Backend backend;
- private final TestEnvironment env;
+ private final TestRunEnv env;
public Target(TargetConfiguration targetConfiguration) {
this.targetConfiguration = targetConfiguration;
- this.env = new TestEnvironment(new HashMap<>());
+ this.env = new TestRunEnv(new HashMap<>());
this.backend = switch (targetConfiguration.backend()) {
case "cassandra" -> new CassandraBackend();
@@ -41,34 +44,34 @@ public void updateJobForTarget(Job job){
}
- public APIRequest apiRequest(TestCommand testCommand, TestEnvironment env){
+ public APIRequest apiRequest(TestCommand testCommand, TestRunEnv env){
return new APIRequest(targetConfiguration.connection(), env, testCommand.withEnvironment(env));
}
@Override
- public Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, Workflow workflow){
+ public Optional beforeWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, WorkflowSpec workflow){
return backend.beforeWorkflow(testPlan, uriBuilder,workflow);
}
@Override
- public Optional afterWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder,Workflow workflow){
+ public Optional afterWorkflow(TestPlan testPlan, TestUri.Builder uriBuilder, WorkflowSpec workflow){
return backend.afterWorkflow(testPlan, uriBuilder,workflow);
}
@Override
- public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBuilder,Job job){
+ public Optional beforeJob(TestPlan testPlan, TestUri.Builder uriBuilder, Job job){
return backend.beforeJob(testPlan, uriBuilder,job);
}
@Override
- public Optional afterJob(TestPlan testPlan,TestUri.Builder uriBuilder,Job job){
+ public Optional afterJob(TestPlan testPlan, TestUri.Builder uriBuilder, Job job){
return backend.afterJob(testPlan,uriBuilder, job);
}
@Override
- public Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ public Optional beforeTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuiteSpec test, TestRunEnv env){
return backend.beforeTestSuite(testPlan,uriBuilder, test, env);
}
@Override
- public Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder,TestSuite test, TestEnvironment env){
+ public Optional afterTestSuite(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuiteSpec test, TestRunEnv env){
return backend.afterTestSuite(testPlan, uriBuilder,test, env);
}
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/DynamicTestExecutable.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/DynamicTestExecutable.java
new file mode 100644
index 0000000000..d09b28820e
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/DynamicTestExecutable.java
@@ -0,0 +1,60 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun;
+
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.function.Executable;
+
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+public class DynamicTestExecutable implements Executable {
+
+ private final String description;
+ private final TestUri testUri;
+ private final Executable executable;
+
+ private final String trimmedDisplayName;
+ private final boolean isTrimmed;
+
+ public DynamicTestExecutable(String description, TestUri.Builder testUri, Executable executable) {
+ this(description, testUri.build(), executable);
+ }
+
+ @SuppressWarnings("StringEquality")
+ public DynamicTestExecutable(String description, TestUri testUri, Executable executable) {
+ this.description = description;
+ this.testUri = testUri;
+ this.executable = executable;
+
+ var truncated = ( description != null && description.length() > 60) ?
+ description.substring(0, 57) + "..."
+ :
+ description;
+
+ this.trimmedDisplayName = truncated;
+ this.isTrimmed = truncated != description;
+ }
+
+ public String trimmedDisplayName(){
+ return trimmedDisplayName;
+ }
+
+ public DynamicTest testNode(){
+ return dynamicTest(trimmedDisplayName, testUri.uri(), this);
+ }
+
+ @Override
+ public void execute() throws Throwable {
+ beforeExecute();
+ executable.execute();
+ afterExecute();
+ }
+
+ private void beforeExecute(){
+ if (isTrimmed) {
+ System.out.printf(description + "\n");
+ }
+ }
+
+ private void afterExecute(){
+ System.out.printf("Executed - " + testUri.uri().toString() + "\n");
+ }
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunEnv.java
similarity index 87%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunEnv.java
index 327f6dbc7f..d45adf0b8a 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestEnvironment.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunEnv.java
@@ -1,7 +1,7 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuiteSpec;
import org.apache.commons.text.StringSubstitutor;
import org.apache.commons.text.lookup.StringLookupFactory;
import org.junit.jupiter.api.DynamicContainer;
@@ -15,24 +15,24 @@
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-public class TestEnvironment {
+public class TestRunEnv {
- private static final Logger LOGGER = LoggerFactory.getLogger(TestEnvironment.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(TestRunEnv.class);
private static final Pattern PATTERN_NOT_WORD_CHARS = Pattern.compile("\\W+");
private static final Set SCHEMA_IDENTIFIER = Set.of("KEYSPACE_NAME", "COLLECTION_NAME");
private final Map vars = new HashMap<>();
- public TestEnvironment(){
+ public TestRunEnv(){
this(new HashMap<>());
}
- public TestEnvironment(Map vars) {
+ public TestRunEnv(Map vars) {
this.vars.putAll(vars);
}
- public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuite testSuite) {
+ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder, TestSuiteSpec testSuite) {
var d = description();
uriBuilder.addSegment(TestUri.Segment.ENV, d);
@@ -64,15 +64,15 @@ private String description(){
.toString();
}
- private TestEnvironment(TestEnvironment other){
+ private TestRunEnv(TestRunEnv other){
this.vars.putAll(other.vars);
}
- public TestEnvironment clone(){
- return new TestEnvironment(this);
+ public TestRunEnv clone(){
+ return new TestRunEnv(this);
}
- public TestEnvironment put(TestEnvironment other){
+ public TestRunEnv put(TestRunEnv other){
this.vars.putAll(other.vars);
return this;
}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunRequest.java
similarity index 61%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunRequest.java
index 8233b640af..2c362efd32 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestRequest.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunRequest.java
@@ -1,11 +1,11 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun;
import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.TestAssertion;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.targets.Target;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestCommand;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicNode;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
@@ -13,17 +13,17 @@
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-public record TestRequest(
+public record TestRunRequest(
String name,
TestCommand testCommand,
Target target,
- TestEnvironment testEnvironment,
+ TestRunEnv testEnvironment,
List testAssertions) {
- public TestResponse execute() {
+ public TestRunResponse execute() {
var apiRequest = target.apiRequest(testCommand, testEnvironment);
- return new TestResponse(this, apiRequest, apiRequest.execute());
+ return new TestRunResponse(this, apiRequest, apiRequest.execute());
}
public DynamicContainer testNodes(TestUri.Builder uriBuilder) {
@@ -32,14 +32,15 @@ public DynamicContainer testNodes(TestUri.Builder uriBuilder) {
Stream.Builder nodesBuilder = Stream.builder();;
- AtomicReference atomicResponse = new AtomicReference<>();
+ AtomicReference atomicResponse = new AtomicReference<>();
// Execute the request, and set so the assertions can pull the response after.
- var commandUriBuilder = uriBuilder.clone();
- commandUriBuilder.addSegment(TestUri.Segment.COMMAND, testCommand.commandName().getApiName());
- nodesBuilder.add(dynamicTest("Command: " + testCommand.commandName().getApiName(),
- commandUriBuilder.build().uri(),
- () -> atomicResponse.set(execute())));
+ var commandExecutable = new DynamicTestExecutable(
+ "Command: " + testCommand.commandName().getApiName(),
+ uriBuilder.clone().addSegment(TestUri.Segment.COMMAND, testCommand.commandName().getApiName()),
+ () -> atomicResponse.set(execute())
+ );
+ nodesBuilder.add(commandExecutable.testNode());
// tests for each assertion
var assertionsUriBuilder = uriBuilder.clone().addSegment(TestUri.Segment.ASSERTION_CONTAINER, "assertions");
@@ -49,7 +50,7 @@ public DynamicContainer testNodes(TestUri.Builder uriBuilder) {
// if we have assertion tests, put them in a container
if (!assertionTests.isEmpty()) {
- nodesBuilder.add(dynamicContainer("Assertions", assertionTests));
+ nodesBuilder.add(dynamicContainer("Assertions",assertionsUriBuilder.build().uri(), assertionTests.stream()));
}
return dynamicContainer("Request: " + name, uriBuilder.build().uri(), nodesBuilder.build());
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestResponse.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunResponse.java
similarity index 75%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestResponse.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunResponse.java
index a80e796e89..df39678b70 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TestResponse.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestRunResponse.java
@@ -1,9 +1,10 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.assertions.AssertionMatcher;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIRequest;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.messaging.APIResponse;
-public record TestResponse(
- TestRequest testRequest,
+public record TestRunResponse(
+ TestRunRequest testRequest,
APIRequest apiRequest,
APIResponse apiResponse
) {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestUri.java
similarity index 95%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestUri.java
index ffd68873ed..5764078afa 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TestUri.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testrun/TestUri.java
@@ -1,6 +1,4 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
-
-import io.stargate.sgv2.jsonapi.service.operation.builder.LiteralTerm;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun;
import java.net.URI;
import java.util.*;
@@ -38,7 +36,6 @@ public static TestUri parse(URI uri) {
}
public enum Scheme {
- TESTPLAN,
TESTRUN;
public String pathName() {
@@ -138,7 +135,7 @@ public Builder addSegment(Segment segment, String value) {
}
public Builder clone(){
- return new Builder(scheme, segmentValues);
+ return new Builder(scheme, new ArrayList<>(segmentValues));
}
public TestUri build() {
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Job.java
similarity index 69%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Job.java
index 2a7b7b92c2..cbc8280b46 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/Job.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/Job.java
@@ -1,9 +1,8 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecKind;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSpecMeta;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestSuite;
-import io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec.TestUri;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestRunEnv;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.TestPlan;
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.testrun.TestUri;
import org.junit.jupiter.api.DynamicContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,19 +43,19 @@ public DynamicContainer testNode(TestPlan testPlan, TestUri.Builder uriBuilder)
testPlan.addLifecycle(uriBuilder.clone(),this, testSuiteNodes));
}
- public Stream testSuites(TestPlan testPlan) {
- Stream.Builder allTests = Stream.builder();
+ public Stream testSuites(TestPlan testPlan) {
+ Stream.Builder allTests = Stream.builder();
tests()
.forEach(
testName -> {
- testPlan.specFiles().byNameAsType(TestSuite.class, testName).forEach(allTests) ;
+ testPlan.specFiles().byNameAsType(TestSuiteSpec.class, testName).forEach(allTests) ;
});
return allTests.build();
}
- public TestEnvironment withoutMatrix(TestPlan testPlan) {
+ public TestRunEnv withoutMatrix(TestPlan testPlan) {
- var fromEnv = new TestEnvironment();
+ var fromEnv = new TestRunEnv();
for (Map.Entry entry : fromEnvironment.entrySet()) {
var value = System.getenv(entry.getValue());
@@ -66,13 +65,13 @@ public TestEnvironment withoutMatrix(TestPlan testPlan) {
fromEnv.put(entry.getKey(), value);
}
- var fromVariables = new TestEnvironment(variables);
+ var fromVariables = new TestRunEnv(variables);
return fromEnv.clone().put(fromVariables);
}
- public List allEnvironments(TestPlan testPlan) {
+ public List allEnvironments(TestPlan testPlan) {
- var fromEnv = new TestEnvironment();
+ var fromEnv = new TestRunEnv();
for (Map.Entry entry : fromEnvironment.entrySet()) {
var value = System.getenv(entry.getValue());
@@ -82,18 +81,18 @@ public List allEnvironments(TestPlan testPlan) {
fromEnv.put(entry.getKey(), value);
}
- var fromVariables = new TestEnvironment(variables);
+ var fromVariables = new TestRunEnv(variables);
// TODO: handle more matrix
- List fromMatrix = new ArrayList<>();
+ List fromMatrix = new ArrayList<>();
matrix.get("MODEL").forEach(
model -> {
- var env = new TestEnvironment();
+ var env = new TestRunEnv();
env.put("MODEL", model);
fromMatrix.add(env);
});
- List allEnvs = new ArrayList<>();
+ List allEnvs = new ArrayList<>();
for (var matrixEnv : fromMatrix) {
var completeEnv = fromEnv
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
index a526b34914..bf0e4eac9b 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/SpecFiles.java
@@ -27,7 +27,7 @@ private SpecFiles(List specFiles) {
this.specFiles = specFiles;
for (SpecFile file : specFiles) {
- if (file.spec() instanceof TestSuite it){
+ if (file.spec() instanceof TestSuiteSpec it){
it.expand(this);
}
}
@@ -92,8 +92,9 @@ private static SpecFile loadOne(Path path) {
var element =
switch (TestSpecKind.valueOf(kindNode.asText().toUpperCase())) {
case ASSERTION_TEMPLATE -> MAPPER.treeToValue(root, AssertionTemplateSpec.class);
- case TEST_SUITE -> MAPPER.treeToValue(root, TestSuite.class);
- case WORKFLOW -> MAPPER.treeToValue(root, Workflow.class);
+ case TARGETS -> MAPPER.treeToValue(root, TargetsSpec.class);
+ case TEST_SUITE -> MAPPER.treeToValue(root, TestSuiteSpec.class);
+ case WORKFLOW -> MAPPER.treeToValue(root, WorkflowSpec.class);
};
return new SpecFile(file, element, root);
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetConfiguration.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetConfiguration.java
new file mode 100644
index 0000000000..92491b097a
--- /dev/null
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetConfiguration.java
@@ -0,0 +1,6 @@
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+
+import io.stargate.sgv2.jsonapi.api.v1.vectorize.targets.Connection;
+
+public record TargetConfiguration(String name, String backend, Connection connection) {
+}
diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfigurationss.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetsSpec.java
similarity index 75%
rename from src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfigurationss.java
rename to src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetsSpec.java
index 2fe7182b16..abf6ea45db 100644
--- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/TargetConfigurationss.java
+++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/vectorize/testspec/TargetsSpec.java
@@ -1,5 +1,6 @@
-package io.stargate.sgv2.jsonapi.api.v1.vectorize;
+package io.stargate.sgv2.jsonapi.api.v1.vectorize.testspec;
+import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
@@ -11,12 +12,16 @@
import java.util.List;
import java.util.Set;
-public record TargetConfigurationss(List targets) {
+public record TargetsSpec(
+ TestSpecMeta meta,
+ List