diff --git a/ezyhttp-client/pom.xml b/ezyhttp-client/pom.xml
index 8b369df8..2a5ce9f2 100644
--- a/ezyhttp-client/pom.xml
+++ b/ezyhttp-client/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-client
diff --git a/ezyhttp-core/pom.xml b/ezyhttp-core/pom.xml
index 8dadc95c..d94e7177 100644
--- a/ezyhttp-core/pom.xml
+++ b/ezyhttp-core/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-core
diff --git a/ezyhttp-server-boot/pom.xml b/ezyhttp-server-boot/pom.xml
index f480f965..624382b5 100644
--- a/ezyhttp-server-boot/pom.xml
+++ b/ezyhttp-server-boot/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-boot
diff --git a/ezyhttp-server-core/pom.xml b/ezyhttp-server-core/pom.xml
index 9e967d8a..237c92b2 100644
--- a/ezyhttp-server-core/pom.xml
+++ b/ezyhttp-server-core/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-core
diff --git a/ezyhttp-server-graphql/pom.xml b/ezyhttp-server-graphql/pom.xml
index 08e6f7d0..db4c4aee 100644
--- a/ezyhttp-server-graphql/pom.xml
+++ b/ezyhttp-server-graphql/pom.xml
@@ -6,7 +6,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-graphql
ezyhttp-server-graphql
diff --git a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/data/GraphQLDataFilter.java b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/data/GraphQLDataFilter.java
index 1797a35e..346a471c 100644
--- a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/data/GraphQLDataFilter.java
+++ b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/data/GraphQLDataFilter.java
@@ -17,8 +17,8 @@ public Map filter(
) {
Map answer = new HashMap<>();
Map parentMap = null;
- Stack stack = new Stack<>();
- stack.add(new StackEntry(queryDefinition, data));
+ Deque stack = new ArrayDeque<>();
+ stack.push(new StackEntry(queryDefinition, data));
while (!stack.isEmpty()) {
StackEntry entry = stack.pop();
String parentName = entry.field.getName();
diff --git a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/exception/GraphQLObjectMapperException.java b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/exception/GraphQLObjectMapperException.java
index b7764574..40ebf668 100644
--- a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/exception/GraphQLObjectMapperException.java
+++ b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/exception/GraphQLObjectMapperException.java
@@ -8,6 +8,13 @@ public class GraphQLObjectMapperException extends IllegalArgumentException {
private final Object errors;
+ public GraphQLObjectMapperException(
+ Object errors
+ ) {
+ super(errors.toString());
+ this.errors = errors;
+ }
+
public GraphQLObjectMapperException(
Object errors,
Throwable cause
diff --git a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/scheme/GraphQLSchemaParser.java b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/scheme/GraphQLSchemaParser.java
index 1f6ecd91..99324372 100644
--- a/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/scheme/GraphQLSchemaParser.java
+++ b/ezyhttp-server-graphql/src/main/java/com/tvd12/ezyhttp/server/graphql/scheme/GraphQLSchemaParser.java
@@ -7,8 +7,9 @@
import com.tvd12.ezyhttp.server.graphql.query.GraphQLQueryDefinition;
import lombok.AllArgsConstructor;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.Map;
-import java.util.Stack;
import static com.tvd12.ezyfox.io.EzyStrings.EMPTY_STRING;
@@ -24,7 +25,7 @@ public GraphQLSchema parseQuery(
) {
String query = standardize(queryToParse);
- Stack stack = new Stack<>();
+ Deque stack = new ArrayDeque<>();
GraphQLSchema.Builder schemaBuilder = GraphQLSchema.builder();
int queryLength = query.length();
@@ -36,7 +37,7 @@ public GraphQLSchema parseQuery(
if (stack.isEmpty()) {
GraphQLQueryDefinition.Builder queryBuilder =
GraphQLQueryDefinition.builder();
- stack.add(queryBuilder);
+ stack.push(queryBuilder);
continue;
}
@@ -46,12 +47,15 @@ public GraphQLSchema parseQuery(
nameLength = 0;
}
GraphQLField.Builder childBuilder = GraphQLField.builder();
- stack.add(childBuilder);
+ stack.push(childBuilder);
continue;
}
if (ch == '(') {
- GraphQLField.Builder childBuilder = stack.peek();
+ GraphQLField.Builder childBuilder = peekFieldStackItemOrThrow(
+ stack,
+ "there is no child"
+ );
StringBuilder argumentsBuilder = new StringBuilder();
i = extractQueryArguments(
argumentsBuilder,
@@ -106,7 +110,10 @@ public GraphQLSchema parseQuery(
nameLength = 0;
}
- GraphQLField.Builder parentBuilder = stack.peek();
+ GraphQLField.Builder parentBuilder = peekFieldStackItemOrThrow(
+ stack,
+ "there is no parent case curly brace close"
+ );
parentBuilder.addField(childBuilder.build());
if (stack.size() == 1) {
@@ -119,7 +126,7 @@ public GraphQLSchema parseQuery(
if (stack.isEmpty()) {
GraphQLQueryDefinition.Builder queryBuilder =
GraphQLQueryDefinition.builder();
- stack.add(queryBuilder);
+ stack.push(queryBuilder);
nameLength = 0;
continue;
}
@@ -134,7 +141,7 @@ public GraphQLSchema parseQuery(
GraphQLQueryDefinition.Builder queryBuilder =
GraphQLQueryDefinition.builder();
- stack.add(queryBuilder);
+ stack.push(queryBuilder);
continue;
}
@@ -146,11 +153,14 @@ public GraphQLSchema parseQuery(
nameLength = 0;
}
- GraphQLField.Builder parentBuilder = stack.peek();
+ GraphQLField.Builder parentBuilder = peekFieldStackItemOrThrow(
+ stack,
+ "there is no parent case space"
+ );
parentBuilder.addField(childBuilder.build());
GraphQLField.Builder newChildBuilder = GraphQLField.builder();
- stack.add(newChildBuilder);
+ stack.push(newChildBuilder);
} else {
nameBuffer[nameLength++] = ch;
}
@@ -282,4 +292,20 @@ private int extractQueryArguments(
}
return i;
}
+
+ private GraphQLField.Builder peekFieldStackItemOrThrow(
+ Deque stack,
+ String message
+ ) {
+ GraphQLField.Builder parentBuilder = stack.peek();
+ if (parentBuilder == null) {
+ throw new GraphQLObjectMapperException(
+ EzyMapBuilder.mapBuilder()
+ .put("arguments", "invalid")
+ .put("message", message)
+ .toMap()
+ );
+ }
+ return parentBuilder;
+ }
}
diff --git a/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/data/GraphQLRequestTest.java b/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/data/GraphQLRequestTest.java
new file mode 100644
index 00000000..aa153e8c
--- /dev/null
+++ b/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/data/GraphQLRequestTest.java
@@ -0,0 +1,41 @@
+package com.tvd12.ezyhttp.server.graphql.test.data;
+
+import com.tvd12.ezyhttp.server.graphql.data.GraphQLRequest;
+import com.tvd12.test.assertion.Asserts;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GraphQLRequestTest {
+
+ @Test
+ public void getVariablesReturnsEmptyMapWhenUnset() {
+ // given
+ GraphQLRequest request = new GraphQLRequest();
+
+ // when
+ Map variables = request.getVariables();
+
+ // then
+ Asserts.assertEquals(variables, Collections.emptyMap(), false);
+ Asserts.assertTrue(variables.isEmpty());
+ }
+
+ @Test
+ public void getVariablesReturnsProvidedMap() {
+ // given
+ GraphQLRequest request = new GraphQLRequest();
+ Map provided = new HashMap<>();
+ provided.put("hello", "world");
+ request.setVariables(provided);
+
+ // when
+ Map variables = request.getVariables();
+
+ // then
+ Asserts.assertEquals(variables, provided, false);
+ Asserts.assertEquals(variables.get("hello"), "world");
+ }
+}
diff --git a/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/scheme/GraphQLSchemaParserTest.java b/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/scheme/GraphQLSchemaParserTest.java
index 1d54cf01..0f9ac568 100644
--- a/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/scheme/GraphQLSchemaParserTest.java
+++ b/ezyhttp-server-graphql/src/test/java/com/tvd12/ezyhttp/server/graphql/test/scheme/GraphQLSchemaParserTest.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tvd12.ezyfox.util.EzyMapBuilder;
+import com.tvd12.ezyhttp.server.graphql.data.GraphQLField;
import com.tvd12.ezyhttp.server.graphql.exception.GraphQLObjectMapperException;
import com.tvd12.ezyhttp.server.graphql.json.GraphQLObjectMapperFactory;
import com.tvd12.ezyhttp.server.graphql.scheme.GraphQLSchema;
@@ -12,8 +13,12 @@
import com.tvd12.test.util.RandomUtil;
import org.testng.annotations.Test;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Deque;
import java.util.Map;
public class GraphQLSchemaParserTest {
@@ -501,4 +506,80 @@ public void parseQueryInvalidArgument6Test() {
// then
Asserts.assertEqualsType(e, GraphQLObjectMapperException.class);
}
+
+ @Test
+ public void parseQueryNoChildBeforeArgumentsTest() {
+ // given
+ GraphQLSchemaParser instance = new GraphQLSchemaParser(
+ new ObjectMapper()
+ );
+
+ // when
+ Throwable e = Asserts.assertThrows(() ->
+ instance.parseQuery(
+ "(id: 1)",
+ Collections.emptyMap()
+ )
+ );
+
+ // then
+ Asserts.assertEqualsType(e, GraphQLObjectMapperException.class);
+ GraphQLObjectMapperException exception = (GraphQLObjectMapperException) e;
+ Asserts.assertEquals(
+ exception.getErrors(),
+ EzyMapBuilder.mapBuilder()
+ .put("arguments", "invalid")
+ .put("message", "there is no child")
+ .toMap(),
+ false
+ );
+ }
+
+ @Test
+ public void requireParentBuilderWithEmptyStackTest() {
+ // given
+ GraphQLSchemaParser instance = new GraphQLSchemaParser(
+ new ObjectMapper()
+ );
+ Deque stack = new ArrayDeque<>();
+
+ // when
+ final Method method;
+ try {
+ method = GraphQLSchemaParser.class.getDeclaredMethod(
+ "peekFieldStackItemOrThrow",
+ Deque.class,
+ String.class
+ );
+ } catch (NoSuchMethodException ex) {
+ throw new IllegalStateException(
+ "method requireParentBuilder should exist",
+ ex
+ );
+ }
+ method.setAccessible(true);
+ Throwable e = Asserts.assertThrows(() -> {
+ try {
+ method.invoke(
+ instance,
+ stack,
+ "there is no parent case curly brace close"
+ );
+ } catch (InvocationTargetException ex) {
+ throw ex.getCause();
+ }
+ });
+
+ // then
+ Asserts.assertEqualsType(e, GraphQLObjectMapperException.class);
+ GraphQLObjectMapperException exception = (GraphQLObjectMapperException) e;
+ Asserts.assertEquals(
+ exception.getErrors(),
+ EzyMapBuilder.mapBuilder()
+ .put("arguments", "invalid")
+ .put("message", "there is no parent case curly brace close")
+ .toMap(),
+ false
+ );
+ }
}
diff --git a/ezyhttp-server-jetty/pom.xml b/ezyhttp-server-jetty/pom.xml
index ca0365f0..9ee950b8 100644
--- a/ezyhttp-server-jetty/pom.xml
+++ b/ezyhttp-server-jetty/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-jetty
diff --git a/ezyhttp-server-management/pom.xml b/ezyhttp-server-management/pom.xml
index e6f95f12..6512e95f 100644
--- a/ezyhttp-server-management/pom.xml
+++ b/ezyhttp-server-management/pom.xml
@@ -6,7 +6,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-management
ezyhttp-server-management
diff --git a/ezyhttp-server-thymeleaf/pom.xml b/ezyhttp-server-thymeleaf/pom.xml
index 5fb8dc56..5dd22003 100644
--- a/ezyhttp-server-thymeleaf/pom.xml
+++ b/ezyhttp-server-thymeleaf/pom.xml
@@ -6,7 +6,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-thymeleaf
ezyhttp-server-thymeleaf
diff --git a/ezyhttp-server-tomcat/pom.xml b/ezyhttp-server-tomcat/pom.xml
index e9b006a6..34af3739 100644
--- a/ezyhttp-server-tomcat/pom.xml
+++ b/ezyhttp-server-tomcat/pom.xml
@@ -5,7 +5,7 @@
com.tvd12
ezyhttp
- 1.4.7
+ 1.4.8
ezyhttp-server-tomcat
diff --git a/pom.xml b/pom.xml
index eec80bff..ae1cf855 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
1.0.7
ezyhttp
- 1.4.7
+ 1.4.8
pom
ezyhttp