From 38d48785f064b84d962701b9ceecf6ac99224afb Mon Sep 17 00:00:00 2001 From: Hugh Kaznowski Date: Wed, 23 Aug 2023 21:30:54 +0100 Subject: [PATCH] Working test --- .../surrealdb/refactor/DemoScenarioTest.java | 33 +++++--- .../java/com/surrealdb/refactor/Helpers.java | 16 ++++ .../driver/WsPlaintextConnection.java | 33 +++++--- .../driver/parsing/JsonQueryResultParser.java | 79 +++++++++++++++++++ .../exception/UnhandledProtocolResponse.java | 14 ++++ .../refactor/types/surrealdb/Number.java | 2 + .../refactor/types/surrealdb/ObjectValue.java | 18 +++++ .../refactor/types/surrealdb/Value.java | 11 +++ .../parsing/JsonQueryResultParserTest.java | 45 +++++++++++ .../refactor/driver/parsing/Tuple.java | 15 ++++ 10 files changed, 246 insertions(+), 20 deletions(-) create mode 100644 src/intTest/java/com/surrealdb/refactor/Helpers.java create mode 100644 src/main/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParser.java create mode 100644 src/main/java/com/surrealdb/refactor/exception/UnhandledProtocolResponse.java create mode 100644 src/main/java/com/surrealdb/refactor/types/surrealdb/ObjectValue.java create mode 100644 src/test/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParserTest.java create mode 100644 src/test/java/com/surrealdb/refactor/driver/parsing/Tuple.java diff --git a/src/intTest/java/com/surrealdb/refactor/DemoScenarioTest.java b/src/intTest/java/com/surrealdb/refactor/DemoScenarioTest.java index 4c39091b..eca617e4 100644 --- a/src/intTest/java/com/surrealdb/refactor/DemoScenarioTest.java +++ b/src/intTest/java/com/surrealdb/refactor/DemoScenarioTest.java @@ -1,5 +1,7 @@ package com.surrealdb.refactor; +import static com.surrealdb.refactor.Helpers.asMap; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import com.google.gson.JsonElement; @@ -10,6 +12,8 @@ import com.surrealdb.refactor.types.Credentials; import com.surrealdb.refactor.types.Param; import com.surrealdb.refactor.types.QueryBlockResult; +import com.surrealdb.refactor.types.surrealdb.Number; +import com.surrealdb.refactor.types.surrealdb.ObjectValue; import com.surrealdb.refactor.types.surrealdb.Value; import java.net.URI; import java.util.List; @@ -49,18 +53,25 @@ public void testDemoScenario() throws Exception { // Execute the query QueryBlockResult results = surrealDB.query(query.toString(), params); - // Validate the results of the multi-statement query + // Validate the results of the first statement in the query assertEquals(results.getResult().size(), 3, results.toString()); - assertEquals( - results.getResult().get(0).getResult().get(0).intoJson(), - asJson( - Tuple.of("name", new JsonPrimitive("leslie")), - Tuple.of("id", new JsonPrimitive("person:lamport")))); - assertEquals( - results.getResult().get(1).getResult().get(0).intoJson(), - asJson( - Tuple.of("name", new JsonPrimitive("leslie")), - Tuple.of("id", new JsonPrimitive("person:lamport")))); + Value expectedFirstValue = new Value(new ObjectValue(asMap( + Tuple.of("name", new Value("leslie")), + Tuple.of("id", new Value("person:lamport")) + ))); + List actual = results.getResult().get(0).getResult(); + assertArrayEquals(new Value[] {expectedFirstValue}, actual.toArray(new Value[0])); + + // Validate the results of the second statement in the query + Value expectedSecondValue = new Value(new ObjectValue( + asMap( + Tuple.of("name", new Value("leslie")), + Tuple.of("id", new Value("person:lamport")), + Tuple.of("year", new Value("2013.0")) + ) + )); + List actualSecondValue = results.getResult().get(1).getResult(); + assertArrayEquals(new Value[] {expectedSecondValue}, actualSecondValue.toArray(new Value[0])); } // ---------------------------------------------------------------- diff --git a/src/intTest/java/com/surrealdb/refactor/Helpers.java b/src/intTest/java/com/surrealdb/refactor/Helpers.java new file mode 100644 index 00000000..b1ff0192 --- /dev/null +++ b/src/intTest/java/com/surrealdb/refactor/Helpers.java @@ -0,0 +1,16 @@ +package com.surrealdb.refactor; + +import com.surrealdb.refactor.types.surrealdb.Value; + +import java.util.HashMap; +import java.util.Map; + +public class Helpers { + public static Map asMap(Tuple... data) { + Map obj = new HashMap<>(); + for (Tuple entry : data) { + obj.put(entry.key, entry.value); + } + return obj; + } +} diff --git a/src/main/java/com/surrealdb/refactor/driver/WsPlaintextConnection.java b/src/main/java/com/surrealdb/refactor/driver/WsPlaintextConnection.java index 0a7b95bb..8b9745c5 100644 --- a/src/main/java/com/surrealdb/refactor/driver/WsPlaintextConnection.java +++ b/src/main/java/com/surrealdb/refactor/driver/WsPlaintextConnection.java @@ -1,14 +1,12 @@ package com.surrealdb.refactor.driver; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; +import com.google.gson.*; +import com.surrealdb.refactor.driver.parsing.JsonQueryResultParser; import com.surrealdb.refactor.exception.SurrealDBUnimplementedException; import com.surrealdb.refactor.types.Credentials; import com.surrealdb.refactor.types.Param; import com.surrealdb.refactor.types.QueryBlockResult; import com.surrealdb.refactor.types.QueryResult; -import com.surrealdb.refactor.types.surrealdb.Value; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; @@ -19,9 +17,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler; import io.netty.handler.codec.http.websocketx.WebSocketVersion; import java.net.URI; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -74,8 +70,27 @@ public QueryBlockResult query(String query, List params) { } catch (InterruptedException | ExecutionException | TimeoutException e) { throw new RuntimeException(e); } - List casted = Arrays.asList(new Value(resp.toString())); - return new QueryBlockResult(List.of(new QueryResult(casted, "change this status", "change this time"))); + // Process the query list + if (!resp.has("result")) { + throw new SurrealDBUnimplementedException("todo create ticket", "The response for the query did not contain a result field"); + } + JsonElement outerResultJson = resp.get("result"); + QueryResult[] processedOuterResults; + if (outerResultJson.isJsonArray()) { + JsonArray outerResultArray = outerResultJson.getAsJsonArray(); + processedOuterResults = new QueryResult[outerResultArray.size()]; + for (int i=0; i() { diff --git a/src/main/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParser.java b/src/main/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParser.java new file mode 100644 index 00000000..b6a42bfa --- /dev/null +++ b/src/main/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParser.java @@ -0,0 +1,79 @@ +package com.surrealdb.refactor.driver.parsing; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.surrealdb.refactor.exception.SurrealDBUnimplementedException; +import com.surrealdb.refactor.exception.UnhandledProtocolResponse; +import com.surrealdb.refactor.types.QueryResult; +import com.surrealdb.refactor.types.surrealdb.ObjectValue; +import com.surrealdb.refactor.types.surrealdb.Value; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JsonQueryResultParser { + private static final String ARRAY = "Array"; + private static final String OBJECT = "Object"; + private static final String PRIMTIVE = "Primitive"; + private static final String NULL = "Null"; + + public QueryResult parse(JsonElement jsonElement) { + // Test + if (!jsonElement.isJsonObject()) { + throw new UnhandledProtocolResponse(String.format("Expected json object, but was %s", type(jsonElement))); + } + JsonObject jsonObject = jsonElement.getAsJsonObject(); + String status = forceGet(jsonObject, "status", new UnhandledProtocolResponse("Expected the object to have a status")).getAsString(); + String time = forceGet(jsonObject, "time", new UnhandledProtocolResponse("Expected the object to have a time")).getAsString(); + JsonElement result = forceGet(jsonObject, "result", new UnhandledProtocolResponse("Expected the object to contain a result")); + List valueList = new ArrayList<>(); + if (result.isJsonObject()) { + JsonObject object = result.getAsJsonObject(); + valueList.add(parseValue(object)); + } else if (result.isJsonArray()) { + JsonArray array = result.getAsJsonArray(); + for (JsonElement arrayElement: array) { + valueList.add(parseValue(arrayElement)); + } + } else { + throw new UnhandledProtocolResponse(String.format("Expected the result type in a result to be an object of array instead was: %s", type(jsonElement))); + } + return new QueryResult(valueList, status, time); + } + + private Value parseValue(JsonElement jsonElement) { + if (!jsonElement.isJsonObject()) { + throw new UnhandledProtocolResponse(String.format("Expected the result type to be object but was %s", type(jsonElement))); + } + Map objectProperties = new HashMap<>(); + JsonObject jsonObject = jsonElement.getAsJsonObject(); + for (Map.Entry entry: jsonObject.entrySet()) { + String value = entry.getValue().getAsString(); + objectProperties.put(entry.getKey(), new Value(value)); + } + return new Value(new ObjectValue(objectProperties)); + } + + private JsonElement forceGet(JsonObject jsonObject, String property, UnhandledProtocolResponse cause) { + if (!jsonObject.has(property)) { + throw cause; + } + return jsonObject.get(property); + } + + private static String type(JsonElement jsonElement) { + if (jsonElement.isJsonArray()) { + return ARRAY; + } else if (jsonElement.isJsonObject()) { + return OBJECT; + } else if (jsonElement.isJsonNull()) { + return NULL; + } else if (jsonElement.isJsonPrimitive()) { + return PRIMTIVE; + } + throw new SurrealDBUnimplementedException("todo create ticket", "really we should be doing more in depth handling of types to also give Value types"); + } +} diff --git a/src/main/java/com/surrealdb/refactor/exception/UnhandledProtocolResponse.java b/src/main/java/com/surrealdb/refactor/exception/UnhandledProtocolResponse.java new file mode 100644 index 00000000..9f167773 --- /dev/null +++ b/src/main/java/com/surrealdb/refactor/exception/UnhandledProtocolResponse.java @@ -0,0 +1,14 @@ +package com.surrealdb.refactor.exception; + +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +public class UnhandledProtocolResponse extends SurrealDBException{ + private final String message; + public UnhandledProtocolResponse(String message) { + super(message); + this.message = message; + } +} diff --git a/src/main/java/com/surrealdb/refactor/types/surrealdb/Number.java b/src/main/java/com/surrealdb/refactor/types/surrealdb/Number.java index 308bbc8b..24f4928f 100644 --- a/src/main/java/com/surrealdb/refactor/types/surrealdb/Number.java +++ b/src/main/java/com/surrealdb/refactor/types/surrealdb/Number.java @@ -1,11 +1,13 @@ package com.surrealdb.refactor.types.surrealdb; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; import java.util.Optional; @ToString +@EqualsAndHashCode public class Number { private final Float _float; diff --git a/src/main/java/com/surrealdb/refactor/types/surrealdb/ObjectValue.java b/src/main/java/com/surrealdb/refactor/types/surrealdb/ObjectValue.java new file mode 100644 index 00000000..9d701d6a --- /dev/null +++ b/src/main/java/com/surrealdb/refactor/types/surrealdb/ObjectValue.java @@ -0,0 +1,18 @@ +package com.surrealdb.refactor.types.surrealdb; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.util.Map; + +@Getter +@ToString +@EqualsAndHashCode +public class ObjectValue { + private final Map values; + + public ObjectValue(Map values) { + this.values = values; + } +} diff --git a/src/main/java/com/surrealdb/refactor/types/surrealdb/Value.java b/src/main/java/com/surrealdb/refactor/types/surrealdb/Value.java index 69e9856d..bf446fd1 100644 --- a/src/main/java/com/surrealdb/refactor/types/surrealdb/Value.java +++ b/src/main/java/com/surrealdb/refactor/types/surrealdb/Value.java @@ -4,15 +4,18 @@ import com.google.gson.JsonPrimitive; import com.surrealdb.refactor.exception.SurrealDBUnimplementedException; import com.surrealdb.refactor.types.IntoJson; +import lombok.EqualsAndHashCode; import lombok.ToString; import java.util.Optional; @ToString +@EqualsAndHashCode public class Value implements IntoJson { private final String string; private final Number number; + private final ObjectValue object; /** * Create a Value that represents a Strand type @@ -22,6 +25,7 @@ public class Value implements IntoJson { public Value(String string) { this.string = string; this.number = null; + this.object = null; } /** @@ -32,6 +36,13 @@ public Value(String string) { public Value(Number number) { this.string = null; this.number = number; + this.object = null; + } + + public Value(ObjectValue object) { + this.string = null; + this.number = null; + this.object = object; } public boolean isString() { diff --git a/src/test/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParserTest.java b/src/test/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParserTest.java new file mode 100644 index 00000000..06ffdcaa --- /dev/null +++ b/src/test/java/com/surrealdb/refactor/driver/parsing/JsonQueryResultParserTest.java @@ -0,0 +1,45 @@ +package com.surrealdb.refactor.driver.parsing; + + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.surrealdb.refactor.types.QueryResult; +import com.surrealdb.refactor.types.surrealdb.ObjectValue; +import com.surrealdb.refactor.types.surrealdb.Value; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class JsonQueryResultParserTest { + + @Test + public void regular_result() { + String rawJson = """ + {"result":[{"id":"person:lamport","name":"leslie"}],"status":"OK","time":"438.583µs"} + """; + + JsonElement jsonElement = JsonParser.parseString(rawJson); + QueryResult res = new JsonQueryResultParser().parse(jsonElement); + + assertEquals("OK", res.getStatus()); + assertEquals("438.583µs", res.getTime()); + Value expectedValue = new Value(new ObjectValue(asMap( + Tuple.of("id", new Value("person:lamport")), + Tuple.of("name", new Value("leslie")) + ))); + assertArrayEquals(new Value[] {expectedValue}, res.getResult().toArray(new Value[0])); + } + + private static Map asMap(Tuple... data) { + Map obj = new HashMap<>(); + for (Tuple entry : data) { + obj.put(entry.key, entry.value); + } + return obj; + } +} diff --git a/src/test/java/com/surrealdb/refactor/driver/parsing/Tuple.java b/src/test/java/com/surrealdb/refactor/driver/parsing/Tuple.java new file mode 100644 index 00000000..80dca6a8 --- /dev/null +++ b/src/test/java/com/surrealdb/refactor/driver/parsing/Tuple.java @@ -0,0 +1,15 @@ +package com.surrealdb.refactor.driver.parsing; + +public class Tuple { + final K key; + final V value; + + private Tuple(K key, V value) { + this.key = key; + this.value = value; + } + + public static Tuple of(K key, V value) { + return new Tuple<>(key, value); + } +}