You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/12/29 20:15:12 UTC
[03/40] incubator-tinkerpop git commit: Validate bindings on the
server to ensure that they were String keys.
Validate bindings on the server to ensure that they were String keys.
Also, fixed a problem where error messages were not always propagating back to the client (usually around validation). They were being sent back in the result field rather than in the statusMessage field.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/55752d30
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/55752d30
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/55752d30
Branch: refs/heads/TINKERPOP-1035
Commit: 55752d30e48d4ace8e7375e4dd46ff0e633bb828
Parents: 48dca54
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Dec 16 09:47:02 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Dec 16 09:47:02 2015 -0500
----------------------------------------------------------------------
CHANGELOG.asciidoc | 2 +
.../server/handler/OpSelectorHandler.java | 2 +-
.../server/op/AbstractEvalOpProcessor.java | 22 +++++++--
.../server/op/control/ControlOpProcessor.java | 18 ++++----
.../server/op/session/SessionOpProcessor.java | 6 +--
.../server/op/standard/StandardOpProcessor.java | 6 +--
.../server/GremlinDriverIntegrateTest.java | 18 ++++++++
.../server/GremlinServerIntegrateTest.java | 48 +++++++++++++++++++-
8 files changed, 100 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4de69c1..e523508 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -30,6 +30,8 @@ TinkerPop 3.1.1 (NOT OFFICIALLY RELEASED YET)
* Added `strictTransactionManagement` to the Gremlin Server settings to indicate that the `aliases` parameter must be passed on requests and that transaction management will be scoped to the graphs provided in that argument.
* Fixed a `NullPointerException` bug in `PeerPressureVertexProgram` that occurred when an adjacency traversal was not provided.
* Standardized "test data directories" across all tests as generated by `TestHelper`.
+* Fixed a bug in Gremlin Server where error messages were not always being passed back in the `statusMessage` field of the `ResponseMessage`.
+* Added validation for parameter `bindings` to ensure that keys were `String` values.
* Improved Transaction Management consistency in Gremlin Server.
* Added `FileSandboxExtension` which takes a configuration file to white list methods and classes that can be used in `ScriptEngine` execution.
* Deprecated `SandboxExtension` and `SimpleSandboxExtension` in favor of `AbstractSandboxExtension` which provides better abstractions for those writing sandboxes.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 6ef65e2..1c7e20c 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@ -81,7 +81,7 @@ public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
else {
// invalid op processor selected so write back an error by way of OpProcessorException.
final String errorMessage = String.format("Invalid OpProcessor requested [%s]", msg.getProcessor());
- throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(errorMessage).create());
+ throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(errorMessage).create());
}
} catch (OpProcessorException ope) {
errorMeter.mark();
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index f3dfae1..ef97b37 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -53,6 +53,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import static com.codahale.metrics.MetricRegistry.name;
@@ -68,6 +70,11 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
/**
+ * Regex for validating that binding variables.
+ */
+ protected static final Pattern validBindingName = Pattern.compile("[a-zA-Z$_][a-zA-Z0-9$_]*");
+
+ /**
* This may or may not be the full set of invalid binding keys. It is dependent on the static imports made to
* Gremlin Server. This should get rid of the worst offenders though and provide a good message back to the
* calling client.
@@ -106,11 +113,11 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
break;
case Tokens.OPS_INVALID:
final String msgInvalid = String.format("Message could not be parsed. Check the format of the request. [%s]", message);
- throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).result(msgInvalid).create());
+ throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgInvalid).create());
default:
op = selectOther(message).orElseThrow(() -> {
final String msgDefault = String.format("Message with op code [%s] is not recognized.", message.getOp());
- return new OpProcessorException(msgDefault, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).result(msgDefault).create());
+ return new OpProcessorException(msgDefault, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgDefault).create());
});
}
@@ -120,14 +127,19 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
protected Optional<ThrowingConsumer<Context>> validateEvalMessage(final RequestMessage message) throws OpProcessorException {
if (!message.optionalArgs(Tokens.ARGS_GREMLIN).isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_EVAL, Tokens.ARGS_GREMLIN);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
if (message.optionalArgs(Tokens.ARGS_BINDINGS).isPresent()) {
- final Map<String, Object> bindings = (Map<String, Object>) message.getArgs().get(Tokens.ARGS_BINDINGS);
+ final Map bindings = (Map) message.getArgs().get(Tokens.ARGS_BINDINGS);
+ if (bindings.keySet().stream().anyMatch(k -> null == k || !(k instanceof String))) {
+ final String msg = String.format("The [%s] message is using one or more invalid binding keys - they must be of type String and cannot be null", Tokens.OPS_EVAL);
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
+ }
+
if (bindings.keySet().stream().anyMatch(invalidBindingsKeys::contains)) {
final String msg = String.format("The [%s] message is using at least one of the invalid binding key of [%s]. It conflicts with standard static imports to Gremlin Server.", Tokens.OPS_EVAL, invalidBindingKeysJoined);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/control/ControlOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/control/ControlOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/control/ControlOpProcessor.java
index 81807e9..e85dd5b 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/control/ControlOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/control/ControlOpProcessor.java
@@ -77,10 +77,10 @@ public class ControlOpProcessor implements OpProcessor {
break;
case Tokens.OPS_INVALID:
final String msgInvalid = String.format("Message could not be parsed. Check the format of the request. [%s]", message);
- throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).result(msgInvalid).create());
+ throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgInvalid).create());
default:
final String msgDefault = String.format("Message with op code [%s] is not recognized.", message.getOp());
- throw new OpProcessorException(msgDefault, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).result(msgDefault).create());
+ throw new OpProcessorException(msgDefault, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgDefault).create());
}
controlOpMeter.mark();
@@ -96,14 +96,14 @@ public class ControlOpProcessor implements OpProcessor {
final Optional<List> l = message.optionalArgs(Tokens.ARGS_IMPORTS);
if (!l.isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_IMPORT, Tokens.ARGS_IMPORTS);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
if (l.orElse(new ArrayList()).size() == 0) {
final String msg = String.format(
"A message with an [%s] op code requires that the [%s] argument has at least one import string specified.",
Tokens.OPS_IMPORT, Tokens.ARGS_IMPORTS);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
return Optional.empty();
@@ -114,13 +114,13 @@ public class ControlOpProcessor implements OpProcessor {
if (!infoType.isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument.",
Tokens.OPS_SHOW, Tokens.ARGS_INFO_TYPE);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
if (!Tokens.INFO_TYPES.contains(infoType.get())) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument with one of the following values [%s].",
Tokens.OPS_SHOW, Tokens.ARGS_INFO_TYPE, Tokens.INFO_TYPES);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
@@ -133,7 +133,7 @@ public class ControlOpProcessor implements OpProcessor {
if (!l.isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument.",
Tokens.OPS_USE, Tokens.ARGS_COORDINATES);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
final List coordinates = l.orElse(new ArrayList());
@@ -141,14 +141,14 @@ public class ControlOpProcessor implements OpProcessor {
final String msg = String.format(
"A message with an [%s] op code requires that the [%s] argument has at least one set of valid maven coordinates specified.",
Tokens.OPS_USE, Tokens.ARGS_COORDINATES);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
if (!coordinates.stream().allMatch(ControlOpProcessor::validateCoordinates)) {
final String msg = String.format(
"A message with an [%s] op code requires that all [%s] specified are valid maven coordinates with a group, artifact, and version.",
Tokens.OPS_USE, Tokens.ARGS_COORDINATES);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
return Optional.empty();
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
index cbfd34a..d5e5e7c 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
@@ -99,7 +99,7 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
// this must be an in-session request
if (!requestMessage.optionalArgs(Tokens.ARGS_SESSION).isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument", Tokens.OPS_CLOSE, Tokens.ARGS_SESSION);
- throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
return Optional.of(ctx -> {
@@ -107,7 +107,7 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
final Session sessionToClose = sessions.get(requestMessage.getArgs().get(Tokens.ARGS_SESSION).toString());
if (null == sessionToClose) {
final String msg = String.format("There was no session named %s to close", requestMessage.getArgs().get(Tokens.ARGS_SESSION).toString());
- throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
sessionToClose.kill();
@@ -128,7 +128,7 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
if (!message.optionalArgs(Tokens.ARGS_SESSION).isPresent()) {
final String msg = String.format("A message with an [%s] op code requires a [%s] argument", Tokens.OPS_EVAL, Tokens.ARGS_SESSION);
- throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(msg).create());
+ throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create());
}
return Optional.empty();
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
index 237a4b0..9c64593 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
@@ -105,7 +105,7 @@ public class StandardOpProcessor extends AbstractEvalOpProcessor {
if (hasRebindings && hasAliases) {
final String error = "Prefer use of the 'aliases' parameter over 'rebindings' and do not use both";
throw new OpProcessorException(error, ResponseMessage.build(msg)
- .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(error).create());
+ .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create());
}
final String rebindingOrAliasParameter = hasRebindings ? Tokens.ARGS_REBINDINGS : Tokens.ARGS_ALIASES;
@@ -139,7 +139,7 @@ public class StandardOpProcessor extends AbstractEvalOpProcessor {
final String error = String.format("Could not alias [%s] to [%s] as [%s] not in the Graph or TraversalSource global bindings",
aliasKv.getKey(), aliasKv.getValue(), aliasKv.getValue());
throw new OpProcessorException(error, ResponseMessage.build(msg)
- .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(error).create());
+ .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create());
}
}
} else {
@@ -147,7 +147,7 @@ public class StandardOpProcessor extends AbstractEvalOpProcessor {
if (context.getSettings().strictTransactionManagement) {
final String error = "Gremlin Server is configured with strictTransactionManagement as 'true' - the 'aliases' arguments must be provided";
throw new OpProcessorException(error, ResponseMessage.build(msg)
- .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(error).create());
+ .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index 4aae6f2..522aa6e 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -573,6 +573,24 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration
}
@Test
+ public void shouldReturnNiceMessageFromOpSelector() {
+ final Cluster cluster = Cluster.build().create();
+ final Client client = cluster.connect();
+
+ try {
+ final Map m = new HashMap<>();
+ m.put(null, "a null key will force a throw of OpProcessorException in message validation");
+ client.submit("1+1", m).all().get();
+ fail("Should throw an exception.");
+ } catch (Exception re) {
+ final Throwable root = ExceptionUtils.getRootCause(re);
+ assertEquals("The [eval] message is using one or more invalid binding keys - they must be of type String and cannot be null", root.getMessage());
+ } finally {
+ cluster.close();
+ }
+ }
+
+ @Test
public void shouldExecuteScriptInSession() throws Exception {
final Cluster cluster = Cluster.build().create();
final Client client = cluster.connect(name.getMethodName());
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/55752d30/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 6977100..6ec0796 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -248,7 +248,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
}
@Test
- public void shouldReturnInvalidRequestArgsWhenInvalidBindingKeyIsUsed() throws Exception {
+ public void shouldReturnInvalidRequestArgsWhenInvalidReservedBindingKeyIsUsed() throws Exception {
try (SimpleClient client = new WebSocketClient()) {
final Map<String, Object> bindings = new HashMap<>();
bindings.put(T.id.getAccessor(), "123");
@@ -271,6 +271,52 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
}
@Test
+ public void shouldReturnInvalidRequestArgsWhenInvalidTypeBindingKeyIsUsed() throws Exception {
+ try (SimpleClient client = new WebSocketClient()) {
+ final Map<Object, Object> bindings = new HashMap<>();
+ bindings.put(1, "123");
+ final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+ .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
+ .addArg(Tokens.ARGS_BINDINGS, bindings).create();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicBoolean pass = new AtomicBoolean(false);
+ client.submit(request, result -> {
+ if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
+ pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
+ latch.countDown();
+ }
+ });
+
+ if (!latch.await(3000, TimeUnit.MILLISECONDS))
+ fail("Request should have returned error, but instead timed out");
+ assertTrue(pass.get());
+ }
+ }
+
+ @Test
+ public void shouldReturnInvalidRequestArgsWhenInvalidNullBindingKeyIsUsed() throws Exception {
+ try (SimpleClient client = new WebSocketClient()) {
+ final Map<String, Object> bindings = new HashMap<>();
+ bindings.put(null, "123");
+ final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+ .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
+ .addArg(Tokens.ARGS_BINDINGS, bindings).create();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicBoolean pass = new AtomicBoolean(false);
+ client.submit(request, result -> {
+ if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
+ pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
+ latch.countDown();
+ }
+ });
+
+ if (!latch.await(3000, TimeUnit.MILLISECONDS))
+ fail("Request should have returned error, but instead timed out");
+ assertTrue(pass.get());
+ }
+ }
+
+ @Test
public void shouldBatchResultsByTwos() throws Exception {
try (SimpleClient client = new WebSocketClient()) {
final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)