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 2021/09/03 17:07:13 UTC
[tinkerpop] 01/02: TINKERPOP-2605 withSideEffect() allows null value
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2605
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 31ea72ae175e77f6e5d1f16239f048085726b187
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Sep 3 07:19:33 2021 -0400
TINKERPOP-2605 withSideEffect() allows null value
---
CHANGELOG.asciidoc | 1 +
docs/src/upgrade/release-3.5.x.asciidoc | 1 +
.../gremlin/process/traversal/Operator.java | 53 +++-
.../strategy/decoration/SideEffectStrategy.java | 2 +-
.../util/DefaultTraversalSideEffects.java | 4 -
.../gremlin/process/traversal/OperatorTest.java | 344 ++++++++++++++-------
.../util/DefaultTraversalSideEffectsTest.java | 26 ++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 4 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 4 +-
gremlin-python/src/main/python/radish/gremlin.py | 4 +-
.../GraphBinaryRemoteGraphComputerProvider.java | 4 +
.../GraphSONRemoteGraphComputerProvider.java | 4 +
.../remote/GryoRemoteGraphComputerProvider.java | 4 +
...emoteGraphGroovyTranslatorComputerProvider.java | 4 +
gremlin-test/features/map/Select.feature | 28 +-
.../process/traversal/step/map/SelectTest.java | 18 ++
16 files changed, 360 insertions(+), 145 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index edaff36..863f836 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -33,6 +33,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Improved handling of `null` when passed to `P` predicates.
* Handled `null` for mathematical reducing operations of `sum()`, `mean()`, `max()` and `min()`.
* Allowed `null` values in `Memory` for `GraphComputer`.
+* Allowed `null` assignment in `withSideEffect()`.
* Fixed problems with `inject(null)` variations where `null` was the only value being submitted.
* Fixed problem with `GroovyTranslator` and `inject(null,null)` which could be interpreted as the Groovy JDK extension `inject(Object,Closure).
* Fixed error where certain variants of `inject()` with `null` might not properly construct a traversal in .NET.
diff --git a/docs/src/upgrade/release-3.5.x.asciidoc b/docs/src/upgrade/release-3.5.x.asciidoc
index ac21888..a2e6d0a 100644
--- a/docs/src/upgrade/release-3.5.x.asciidoc
+++ b/docs/src/upgrade/release-3.5.x.asciidoc
@@ -42,6 +42,7 @@ failures, but now filter results. As these structural elements of the graph can'
filter all elements.
* `hasValue(null)` - Formerly this method would throw a general `NullPointerException`, but now it will filter as
expected.
+* `withSideEffect()` - This configuration step can now take a `null` for its value.
* `sum()`, `mean()`, `max()` and `min()` - These methods used to throw general `NullPointerException` failures, but
now ignore `null` values when other numbers are present. If all of the values in the stream are `null` then `hasNext()`
return `false`.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
index 4fada2f..ea84f2d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
@@ -34,6 +34,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* An addition function.
*
+ * @see NumberHelper#add(Number, Number)
* @since 3.0.0-incubating
*/
sum {
@@ -45,6 +46,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* A subtraction function.
*
+ * @see NumberHelper#sub(Number, Number)
* @since 3.0.0-incubating
*/
minus {
@@ -56,6 +58,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* A multiplication function.
*
+ * @see NumberHelper#mul(Number, Number)
* @since 3.0.0-incubating
*/
mult {
@@ -67,6 +70,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* A division function.
*
+ * @see NumberHelper#div(Number, Number)
* @since 3.0.0-incubating
*/
div {
@@ -78,6 +82,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* Selects the smaller of the values.
*
+ * @see NumberHelper#min(Number, Number)
* @since 3.0.0-incubating
*/
min {
@@ -89,6 +94,7 @@ public enum Operator implements BinaryOperator<Object> {
/**
* Selects the larger of the values.
*
+ * @see NumberHelper#max(Number, Number)
* @since 3.0.0-incubating
*/
max {
@@ -112,10 +118,24 @@ public enum Operator implements BinaryOperator<Object> {
/**
* Applies "and" to boolean values.
*
+ * <pre>
+ * a = true, b = null -> true
+ * a = false, b = null -> false
+ * a = null, b = true -> true
+ * a = null, b = false -> false
+ * a = null, b = null -> null
+ * </pre>
+ *
* @since 3.2.0-incubating
*/
and {
public Object apply(final Object a, final Object b) {
+ if (null == a || null == b) {
+ if (null == a && null == b)
+ return null;
+ else
+ return null == b ? a : b;
+ }
return ((boolean) a) && ((boolean) b);
}
},
@@ -123,25 +143,52 @@ public enum Operator implements BinaryOperator<Object> {
/**
* Applies "or" to boolean values.
*
+ * <pre>
+ * a = true, b = null -> true
+ * a = false, b = null -> false
+ * a = null, b = true -> true
+ * a = null, b = false -> false
+ * a = null, b = null -> null
+ * </pre>
+ *
* @since 3.2.0-incubating
*/
or {
public Object apply(final Object a, final Object b) {
+ if (null == a || null == b) {
+ if (null == a && null == b)
+ return null;
+ else
+ return null == b ? a : b;
+ }
return ((boolean) a) || ((boolean) b);
}
},
/**
- * Takes all objects in the second {@code Collection} and adds them to the first.
+ * Takes all objects in the second {@code Collection} and adds them to the first. If the first is {@code null},
+ * then the second {@code Collection} is returned and if the second is {@code null} then the first is returned.
+ * If both are {@code null} then {@code null} is returned. Arguments must be of type {@code Map} or
+ * {@code Collection}.
*
* @since 3.2.0-incubating
*/
addAll {
public Object apply(final Object a, final Object b) {
- if (a instanceof Map)
+ if (null == a || null == b) {
+ if (null == a && null == b)
+ return null;
+ else
+ return null == b ? a : b;
+ }
+
+ if (a instanceof Map && b instanceof Map)
((Map<?,?>) a).putAll((Map) b);
- else
+ else if (a instanceof Collection && a instanceof Collection)
((Collection<?>) a).addAll((Collection) b);
+ else
+ throw new IllegalArgumentException(String.format("Objects must be both of Map or Collection: a=%s b=%s",
+ a.getClass().getSimpleName(), b.getClass().getSimpleName()));
return a;
}
},
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index 430f5ab..ce794b8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -60,7 +60,7 @@ public final class SideEffectStrategy extends AbstractTraversalStrategy<Traversa
strategy = cloneStrategy;
traversalStrategies.addStrategies(strategy);
}
- strategy.sideEffects.add(new Triplet<>(key, null == value ? null : value instanceof Supplier ? (Supplier) value : new ConstantSupplier<>(value), reducer));
+ strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : new ConstantSupplier<>(value), reducer));
}
public boolean contains(final String sideEffectKey) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
index b512cf3..52f92a5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
@@ -77,7 +77,6 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
*/
@Override
public void set(final String key, final Object value) throws IllegalArgumentException {
- SideEffectHelper.validateSideEffectValue(value);
if (!this.keys.contains(key))
throw TraversalSideEffects.Exceptions.sideEffectKeyDoesNotExist(key);
this.objectMap.put(key, value);
@@ -88,7 +87,6 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
*/
@Override
public void add(final String key, final Object value) throws IllegalArgumentException {
- SideEffectHelper.validateSideEffectValue(value);
this.set(key, this.getReducer(key).apply(this.get(key), value));
}
@@ -99,7 +97,6 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
public <V> void register(final String key, final Supplier<V> initialValue, final BinaryOperator<V> reducer) {
SideEffectHelper.validateSideEffectKey(key);
this.keys.add(key);
- //this.objectMap.remove(key);
if (null != initialValue)
this.supplierMap.put(key, initialValue);
if (null != reducer)
@@ -113,7 +110,6 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
public <V> void registerIfAbsent(final String key, final Supplier<V> initialValue, final BinaryOperator<V> reducer) {
SideEffectHelper.validateSideEffectKey(key);
this.keys.add(key);
- //this.objectMap.remove(key);
if (null == this.supplierMap.get(key) && null != initialValue) {
this.supplierMap.put(key, initialValue);
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OperatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OperatorTest.java
index e498cae..ce433c6 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OperatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/OperatorTest.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.process.traversal;
import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -26,15 +27,241 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
-@RunWith(Parameterized.class)
+@RunWith(Enclosed.class)
public class OperatorTest {
+ @RunWith(Parameterized.class)
+ public static class LogicTest {
+ @Parameterized.Parameters(name = "{0}({1},{2}) = {3}")
+ public static Iterable<Object[]> data() {
+ return new ArrayList<>(Arrays.asList(new Object[][]{
+ {Operator.and, true, true, true},
+ {Operator.and, true, false, false},
+ {Operator.and, false, true, false},
+ {Operator.and, false, false, false},
+ {Operator.and, null, null, null},
+ {Operator.and, null, false, false},
+ {Operator.and, false, null, false},
+ {Operator.and, null, true, true},
+ {Operator.and, true, null, true},
+ {Operator.or, true, true, true},
+ {Operator.or, true, false, true},
+ {Operator.or, false, true, true},
+ {Operator.or, false, false, false},
+ {Operator.or, null, null, null},
+ {Operator.or, null, false, false},
+ {Operator.or, false, null, false},
+ {Operator.or, null, true, true},
+ {Operator.or, true, null, true},
+ }));
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Operator operator;
+
+ @Parameterized.Parameter(value = 1)
+ public Boolean a;
+
+ @Parameterized.Parameter(value = 2)
+ public Boolean b;
+
+ @Parameterized.Parameter(value = 3)
+ public Boolean expected;
+
+ @Test
+ public void shouldApplyOperator() {
+ assertEquals(expected, operator.apply(a, b));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class CollectionTest {
+ @Parameterized.Parameters(name = "{0}({1},{2}) = {3}")
+ public static Iterable<Object[]> data() {
+ return new ArrayList<>(Arrays.asList(new Object[][]{
+ {Operator.addAll, null, null, null},
+ {Operator.addAll, new ArrayList<>(Arrays.asList(1,2,3)), null, Arrays.asList(1,2,3)},
+ {Operator.addAll, null, new ArrayList<>(Arrays.asList(1,2,3)), Arrays.asList(1,2,3)},
+ {Operator.addAll, new ArrayList<>(Arrays.asList(1,2,3)), new ArrayList<>(Arrays.asList(4,5,6)), Arrays.asList(1,2,3,4,5,6)},
+ }));
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Operator operator;
+
+ @Parameterized.Parameter(value = 1)
+ public Collection a;
+
+ @Parameterized.Parameter(value = 2)
+ public Collection b;
+
+ @Parameterized.Parameter(value = 3)
+ public Collection expected;
+
+ @Test
+ public void shouldApplyOperator() {
+ assertEquals(expected, operator.apply(a, b));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class MapTest {
+ @Parameterized.Parameters(name = "{0}({1},{2}) = {3}")
+ public static Iterable<Object[]> data() {
+ return new ArrayList<>(Arrays.asList(new Object[][]{
+ {Operator.addAll, null, null, null},
+ {Operator.addAll, new HashMap<String,Integer>() {{ put("a", 1); }}, null, new HashMap<String,Integer>() {{ put("a", 1); }}},
+ {Operator.addAll, null, new HashMap<String,Integer>() {{ put("a", 1); }}, new HashMap<String,Integer>() {{ put("a", 1); }}},
+ {Operator.addAll, new HashMap<String,Integer>() {{ put("a", 1); }}, new HashMap<String,Integer>() {{ put("b", 2); }}, new HashMap<String,Integer>() {{ put("a", 1); put("b", 2); }}},
+ {Operator.addAll, new HashMap<String,Integer>() {{ put("a", 1); }}, new HashMap<String,Integer>() {{ put("a", 2); }}, new HashMap<String,Integer>() {{ put("a", 2); }}},
+ }));
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Operator operator;
+
+ @Parameterized.Parameter(value = 1)
+ public Map a;
+
+ @Parameterized.Parameter(value = 2)
+ public Map b;
+
+ @Parameterized.Parameter(value = 3)
+ public Map expected;
+
+ @Test
+ public void shouldApplyOperator() {
+ assertEquals(expected, operator.apply(a, b));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class NumberTest {
+ @Parameterized.Parameters(name = "{0}({1},{2}) = {3}")
+ public static Iterable<Object[]> data() {
+ return new ArrayList<>(Arrays.asList(new Object[][]{
+ {Operator.div, 10, 2, 5},
+ {Operator.div, 10l, 2l, 5l},
+ {Operator.div, 10f, 2f, 5f},
+ {Operator.div, 10d, 2d, 5d},
+ {Operator.div, 10, 2d, 5d},
+ {Operator.div, 10, 2f, 5f},
+ {Operator.div, 10d, 2, 5d},
+ {Operator.div, 10f, 2d, 5d},
+ {Operator.div, 10f, 2l, 5d},
+ {Operator.div, 10f, 2, 5f},
+ {Operator.div, BigInteger.TEN, 2, BigInteger.valueOf(5l)},
+ {Operator.div, BigInteger.TEN, 2f, BigDecimal.valueOf(5l)},
+ {Operator.div, BigDecimal.TEN, 2, BigDecimal.valueOf(5l)},
+ {Operator.div, CustomNumber.TEN, 2, BigDecimal.valueOf(5l)},
+ {Operator.max, 10, 2, 10},
+ {Operator.max, 10l, 2l, 10l},
+ {Operator.max, 10f, 2f, 10f},
+ {Operator.max, 10d, 2d, 10d},
+ {Operator.max, 2, 10, 10},
+ {Operator.max, 2l, 10l, 10l},
+ {Operator.max, 2f, 10f, 10f},
+ {Operator.max, 2d, 10d, 10d},
+ {Operator.max, 10, 2d, 10d},
+ {Operator.max, 10, 2f, 10f},
+ {Operator.max, 10d, 2, 10d},
+ {Operator.max, 10f, 2d, 10d},
+ {Operator.max, 10f, 2l, 10d},
+ {Operator.max, 10f, 2, 10f},
+ {Operator.max, BigInteger.TEN, 1, BigInteger.TEN},
+ {Operator.max, BigInteger.TEN, BigDecimal.ONE, BigDecimal.TEN},
+ {Operator.max, BigDecimal.TEN, 1, BigDecimal.TEN},
+ {Operator.max, 1, CustomNumber.TEN, BigDecimal.TEN},
+ {Operator.min, 10, 2, 2},
+ {Operator.min, 10l, 2l, 2l},
+ {Operator.min, 10f, 2f, 2f},
+ {Operator.min, 10d, 2d, 2d},
+ {Operator.min, 2, 10, 2},
+ {Operator.min, 2l, 10l, 2l},
+ {Operator.min, 2f, 10f, 2f},
+ {Operator.min, 2d, 10d, 2d},
+ {Operator.min, 10, 2d, 2d},
+ {Operator.min, 10, 2f, 2f},
+ {Operator.min, 10d, 2, 2d},
+ {Operator.min, 10f, 2d, 2d},
+ {Operator.min, 10f, 2l, 2d},
+ {Operator.min, 10f, 2, 2f},
+ {Operator.min, BigInteger.TEN, 1, BigInteger.ONE},
+ {Operator.min, BigInteger.TEN, BigDecimal.ONE, BigDecimal.ONE},
+ {Operator.min, BigDecimal.TEN, 1, BigDecimal.ONE},
+ {Operator.min, 1, CustomNumber.TEN, BigDecimal.ONE},
+ {Operator.minus, 10, 2, 8},
+ {Operator.minus, 10l, 2l, 8l},
+ {Operator.minus, 10f, 2f, 8f},
+ {Operator.minus, 10d, 2d, 8d},
+ {Operator.minus, 10, 2d, 8d},
+ {Operator.minus, 10, 2f, 8f},
+ {Operator.minus, 10d, 2, 8d},
+ {Operator.minus, 10f, 2d, 8d},
+ {Operator.minus, 10f, 2l, 8d},
+ {Operator.minus, 10f, 2, 8f},
+ {Operator.minus, BigInteger.TEN, 2, BigInteger.valueOf(8l)},
+ {Operator.minus, BigInteger.TEN, 2f, BigDecimal.valueOf(8d)},
+ {Operator.minus, BigDecimal.TEN, 2, BigDecimal.valueOf(8l)},
+ {Operator.minus, CustomNumber.TEN, 2, BigDecimal.valueOf(8l)},
+ {Operator.mult, 5, 4, 20},
+ {Operator.mult, 5l, 4l, 20l},
+ {Operator.mult, 5f, 4f, 20f},
+ {Operator.mult, 5d, 4d, 20d},
+ {Operator.mult, 5, 4d, 20d},
+ {Operator.mult, 5, 4f, 20f},
+ {Operator.mult, 5d, 4, 20d},
+ {Operator.mult, 5f, 4d, 20d},
+ {Operator.mult, 5f, 4l, 20d},
+ {Operator.mult, 5f, 4, 20f},
+ {Operator.mult, BigInteger.valueOf(5l), 4, BigInteger.valueOf(20l)},
+ {Operator.mult, BigInteger.valueOf(5l), 4f, BigDecimal.valueOf(20d)},
+ {Operator.mult, BigDecimal.valueOf(5d), 4, BigDecimal.valueOf(20d)},
+ {Operator.mult, CustomNumber.TEN, 2f, BigDecimal.valueOf(20d)},
+ {Operator.sum, 7, 3, 10},
+ {Operator.sum, 7l, 3l, 10l},
+ {Operator.sum, 7f, 3f, 10f},
+ {Operator.sum, 7d, 3d, 10d},
+ {Operator.sum, 7, 3d, 10d},
+ {Operator.sum, 7, 3f, 10f},
+ {Operator.sum, 7d, 3, 10d},
+ {Operator.sum, 7f, 3d, 10d},
+ {Operator.sum, 7f, 3l, 10d},
+ {Operator.sum, 7f, 3, 10f},
+ {Operator.sum, BigInteger.valueOf(7l), 3, BigInteger.TEN},
+ {Operator.sum, BigInteger.valueOf(7l), 3f, BigDecimal.valueOf(10d)},
+ {Operator.sum, BigDecimal.valueOf(7d), 3, BigDecimal.valueOf(10d)},
+ {Operator.sum, CustomNumber.TEN, CustomNumber.ONE, BigDecimal.valueOf(11l)}
+ }));
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Operator operator;
+
+ @Parameterized.Parameter(value = 1)
+ public Number a;
+
+ @Parameterized.Parameter(value = 2)
+ public Number b;
+
+ @Parameterized.Parameter(value = 3)
+ public Number expected;
+
+ @Test
+ public void shouldApplyOperator() {
+ assertEquals(expected, operator.apply(a, b));
+ }
+ }
+
/**
* Required to verify that Operator can handle Number type, that it doesn't know explicitly.
*/
@@ -74,119 +301,4 @@ public class OperatorTest {
return Integer.compare(n, anotherCustomNumber.n);
}
}
-
- @Parameterized.Parameters(name = "{0}({1},{2}) = {3}")
- public static Iterable<Object[]> data() {
- return new ArrayList<>(Arrays.asList(new Object[][]{
- {Operator.div, 10, 2, 5},
- {Operator.div, 10l, 2l, 5l},
- {Operator.div, 10f, 2f, 5f},
- {Operator.div, 10d, 2d, 5d},
- {Operator.div, 10, 2d, 5d},
- {Operator.div, 10, 2f, 5f},
- {Operator.div, 10d, 2, 5d},
- {Operator.div, 10f, 2d, 5d},
- {Operator.div, 10f, 2l, 5d},
- {Operator.div, 10f, 2, 5f},
- {Operator.div, BigInteger.TEN, 2, BigInteger.valueOf(5l)},
- {Operator.div, BigInteger.TEN, 2f, BigDecimal.valueOf(5l)},
- {Operator.div, BigDecimal.TEN, 2, BigDecimal.valueOf(5l)},
- {Operator.div, CustomNumber.TEN, 2, BigDecimal.valueOf(5l)},
- {Operator.max, 10, 2, 10},
- {Operator.max, 10l, 2l, 10l},
- {Operator.max, 10f, 2f, 10f},
- {Operator.max, 10d, 2d, 10d},
- {Operator.max, 2, 10, 10},
- {Operator.max, 2l, 10l, 10l},
- {Operator.max, 2f, 10f, 10f},
- {Operator.max, 2d, 10d, 10d},
- {Operator.max, 10, 2d, 10d},
- {Operator.max, 10, 2f, 10f},
- {Operator.max, 10d, 2, 10d},
- {Operator.max, 10f, 2d, 10d},
- {Operator.max, 10f, 2l, 10d},
- {Operator.max, 10f, 2, 10f},
- {Operator.max, BigInteger.TEN, 1, BigInteger.TEN},
- {Operator.max, BigInteger.TEN, BigDecimal.ONE, BigDecimal.TEN},
- {Operator.max, BigDecimal.TEN, 1, BigDecimal.TEN},
- {Operator.max, 1, CustomNumber.TEN, BigDecimal.TEN},
- {Operator.min, 10, 2, 2},
- {Operator.min, 10l, 2l, 2l},
- {Operator.min, 10f, 2f, 2f},
- {Operator.min, 10d, 2d, 2d},
- {Operator.min, 2, 10, 2},
- {Operator.min, 2l, 10l, 2l},
- {Operator.min, 2f, 10f, 2f},
- {Operator.min, 2d, 10d, 2d},
- {Operator.min, 10, 2d, 2d},
- {Operator.min, 10, 2f, 2f},
- {Operator.min, 10d, 2, 2d},
- {Operator.min, 10f, 2d, 2d},
- {Operator.min, 10f, 2l, 2d},
- {Operator.min, 10f, 2, 2f},
- {Operator.min, BigInteger.TEN, 1, BigInteger.ONE},
- {Operator.min, BigInteger.TEN, BigDecimal.ONE, BigDecimal.ONE},
- {Operator.min, BigDecimal.TEN, 1, BigDecimal.ONE},
- {Operator.min, 1, CustomNumber.TEN, BigDecimal.ONE},
- {Operator.minus, 10, 2, 8},
- {Operator.minus, 10l, 2l, 8l},
- {Operator.minus, 10f, 2f, 8f},
- {Operator.minus, 10d, 2d, 8d},
- {Operator.minus, 10, 2d, 8d},
- {Operator.minus, 10, 2f, 8f},
- {Operator.minus, 10d, 2, 8d},
- {Operator.minus, 10f, 2d, 8d},
- {Operator.minus, 10f, 2l, 8d},
- {Operator.minus, 10f, 2, 8f},
- {Operator.minus, BigInteger.TEN, 2, BigInteger.valueOf(8l)},
- {Operator.minus, BigInteger.TEN, 2f, BigDecimal.valueOf(8d)},
- {Operator.minus, BigDecimal.TEN, 2, BigDecimal.valueOf(8l)},
- {Operator.minus, CustomNumber.TEN, 2, BigDecimal.valueOf(8l)},
- {Operator.mult, 5, 4, 20},
- {Operator.mult, 5l, 4l, 20l},
- {Operator.mult, 5f, 4f, 20f},
- {Operator.mult, 5d, 4d, 20d},
- {Operator.mult, 5, 4d, 20d},
- {Operator.mult, 5, 4f, 20f},
- {Operator.mult, 5d, 4, 20d},
- {Operator.mult, 5f, 4d, 20d},
- {Operator.mult, 5f, 4l, 20d},
- {Operator.mult, 5f, 4, 20f},
- {Operator.mult, BigInteger.valueOf(5l), 4, BigInteger.valueOf(20l)},
- {Operator.mult, BigInteger.valueOf(5l), 4f, BigDecimal.valueOf(20d)},
- {Operator.mult, BigDecimal.valueOf(5d), 4, BigDecimal.valueOf(20d)},
- {Operator.mult, CustomNumber.TEN, 2f, BigDecimal.valueOf(20d)},
- {Operator.sum, 7, 3, 10},
- {Operator.sum, 7l, 3l, 10l},
- {Operator.sum, 7f, 3f, 10f},
- {Operator.sum, 7d, 3d, 10d},
- {Operator.sum, 7, 3d, 10d},
- {Operator.sum, 7, 3f, 10f},
- {Operator.sum, 7d, 3, 10d},
- {Operator.sum, 7f, 3d, 10d},
- {Operator.sum, 7f, 3l, 10d},
- {Operator.sum, 7f, 3, 10f},
- {Operator.sum, BigInteger.valueOf(7l), 3, BigInteger.TEN},
- {Operator.sum, BigInteger.valueOf(7l), 3f, BigDecimal.valueOf(10d)},
- {Operator.sum, BigDecimal.valueOf(7d), 3, BigDecimal.valueOf(10d)},
- {Operator.sum, CustomNumber.TEN, CustomNumber.ONE, BigDecimal.valueOf(11l)}
- }));
- }
-
- @Parameterized.Parameter(value = 0)
- public Operator operator;
-
- @Parameterized.Parameter(value = 1)
- public Number a;
-
- @Parameterized.Parameter(value = 2)
- public Number b;
-
- @Parameterized.Parameter(value = 3)
- public Number expected;
-
- @Test
- public void shouldApplyOperator() {
- assertEquals(expected, operator.apply(a, b));
- }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffectsTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffectsTest.java
index 679042d..9d1210f 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffectsTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffectsTest.java
@@ -26,8 +26,11 @@ import org.junit.Test;
import java.util.Arrays;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -37,6 +40,29 @@ import static org.junit.Assert.fail;
public class DefaultTraversalSideEffectsTest {
@Test
+ public void shouldAllowNulls() {
+ final TraversalSideEffects sideEffects = new DefaultTraversalSideEffects();
+ sideEffects.register("k", new ConstantSupplier<>(null), null);
+ assertNull(sideEffects.get("k"));
+
+ sideEffects.set("k", "x");
+ assertEquals("x", sideEffects.get("k"));
+
+ sideEffects.set("k", null);
+ assertNull(sideEffects.get("k"));
+
+ sideEffects.add("k", null);
+ assertNull(sideEffects.get("k"));
+
+ sideEffects.register("kand", new ConstantSupplier<>(null), Operator.and);
+ sideEffects.add("kand", null);
+ assertNull(sideEffects.get("kand"));
+
+ sideEffects.add("kand", true);
+ assertThat(sideEffects.get("kand"), is(true));
+ }
+
+ @Test
public void shouldOperateCorrectly() {
final TraversalSideEffects sideEffects = new DefaultTraversalSideEffects();
try {
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 6e606ea..74b346c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -522,7 +522,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasXageX_propertiesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name").Value<object>()}},
{"g_V_hasXageX_propertiesXname_ageX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name","age").Value<object>()}},
{"g_V_hasXageX_propertiesXage_nameX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("age","name").Value<object>()}},
- {"get_g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b")}},
+ {"g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b")}},
{"g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b").By("name")}},
{"g_VX1X_asXaX_outXknowsX_asXbX_selectXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a")}},
{"g_VX1X_asXaX_outXknowsX_asXbX_selectXaX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a").By("name")}},
@@ -550,7 +550,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_outE_weight_groupCount_unfold_selectXvaluesX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().OutE().Values<object>("weight").GroupCount<object>().Unfold<object>().Select<object>(Column.Values).Unfold<object>()}},
{"g_V_untilXout_outX_repeatXin_asXaX_in_asXbXX_selectXa_bX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Until(__.Out().Out()).Repeat(__.In().As("a").In().As("b")).Select<object>("a","b").By("name")}},
{"g_V_outE_weight_groupCount_selectXvaluesX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().OutE().Values<object>("weight").GroupCount<object>().Select<object>(Column.Values).Unfold<object>()}},
- {"g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b")}},
{"g_V_asXaX_whereXoutXknowsXX_selectXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Where(__.Out("knows")).Select<object>("a")}},
{"g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXfirst_aX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Repeat(__.Out().As("a")).Times(2).Select<object>(Pop.First,"a")}},
{"g_V_asXaX_outXknowsX_asXbX_localXselectXa_bX_byXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out("knows").As("b").Local<object>(__.Select<object>("a","b").By("name"))}},
@@ -586,6 +585,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Key)}},
{"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Value)}},
{"g_V_asXaX_selectXaX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Select<object>("a").By("age")}},
+ {"g_withSideEffectXk_nullX_injectXxX_selectXkX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("k",null).Inject("x").Select<object>("k")}},
{"g_V_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new VertexProgramStrategy(graphComputer: "org.apache.tinkerpop.gremlin.process.computer.GraphComputer")).V().Identity().ShortestPath()}},
{"g_V_both_dedup_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new VertexProgramStrategy(graphComputer: "org.apache.tinkerpop.gremlin.process.computer.GraphComputer")).V().Both().Dedup().ShortestPath()}},
{"g_V_shortestPath_edgesIncluded", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new VertexProgramStrategy(graphComputer: "org.apache.tinkerpop.gremlin.process.computer.GraphComputer")).V().Identity().ShortestPath().With("~tinkerpop.shortestPath.includeEdges")}},
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index c3f01ac..f0b3c50 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -511,7 +511,7 @@ const gremlins = {
g_V_hasXageX_propertiesXnameX: [function({g}) { return g.V().has("age").properties("name").value() }],
g_V_hasXageX_propertiesXname_ageX_value: [function({g}) { return g.V().has("age").properties("name","age").value() }],
g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return g.V().has("age").properties("age","name").value() }],
- get_g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b") }],
+ g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b") }],
g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b").by("name") }],
g_VX1X_asXaX_outXknowsX_asXbX_selectXaX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a") }],
g_VX1X_asXaX_outXknowsX_asXbX_selectXaX_byXnameX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a").by("name") }],
@@ -539,7 +539,6 @@ const gremlins = {
g_V_outE_weight_groupCount_unfold_selectXvaluesX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().unfold().select(Column.values).unfold() }],
g_V_untilXout_outX_repeatXin_asXaX_in_asXbXX_selectXa_bX_byXnameX: [function({g}) { return g.V().until(__.out().out()).repeat(__.in_().as("a").in_().as("b")).select("a","b").by("name") }],
g_V_outE_weight_groupCount_selectXvaluesX_unfold: [function({g}) { return g.V().outE().values("weight").groupCount().select(Column.values).unfold() }],
- g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX: [function({g, vid1}) { return g.V(vid1).as("a").out("knows").as("b").select("a","b") }],
g_V_asXaX_whereXoutXknowsXX_selectXaX: [function({g}) { return g.V().as("a").where(__.out("knows")).select("a") }],
g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXfirst_aX: [function({g, vid1}) { return g.V(vid1).as("a").repeat(__.out().as("a")).times(2).select(Pop.first,"a") }],
g_V_asXaX_outXknowsX_asXbX_localXselectXa_bX_byXnameXX: [function({g}) { return g.V().as("a").out("knows").as("b").local(__.select("a","b").by("name")) }],
@@ -575,6 +574,7 @@ const gremlins = {
g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.key) }],
g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.value) }],
g_V_asXaX_selectXaX_byXageX: [function({g}) { return g.V().as("a").select("a").by("age") }],
+ g_withSideEffectXk_nullX_injectXxX_selectXkX: [function({g}) { return g.withSideEffect("k",null).inject("x").select("k") }],
g_V_shortestPath: [function({g}) { return g.withStrategies(new VertexProgramStrategy(new Map([["graphComputer","org.apache.tinkerpop.gremlin.process.computer.GraphComputer"]]))).V().identity().shortestPath() }],
g_V_both_dedup_shortestPath: [function({g}) { return g.withStrategies(new VertexProgramStrategy(new Map([["graphComputer","org.apache.tinkerpop.gremlin.process.computer.GraphComputer"]]))).V().both().dedup().shortestPath() }],
g_V_shortestPath_edgesIncluded: [function({g}) { return g.withStrategies(new VertexProgramStrategy(new Map([["graphComputer","org.apache.tinkerpop.gremlin.process.computer.GraphComputer"]]))).V().identity().shortestPath().with_("~tinkerpop.shortestPath.includeEdges") }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index bfab55e..ac17b3b 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -496,7 +496,7 @@ world.gremlins = {
'g_V_hasXageX_propertiesXnameX': [(lambda g:g.V().has('age').properties('name').value())],
'g_V_hasXageX_propertiesXname_ageX_value': [(lambda g:g.V().has('age').properties('name','age').value())],
'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age','name').value())],
- 'get_g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b'))],
+ 'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b').by('name'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXaX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXaX_byXnameX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a').by('name'))],
@@ -524,7 +524,6 @@ world.gremlins = {
'g_V_outE_weight_groupCount_unfold_selectXvaluesX_unfold': [(lambda g:g.V().outE().weight.groupCount().unfold().select(Column.values).unfold())],
'g_V_untilXout_outX_repeatXin_asXaX_in_asXbXX_selectXa_bX_byXnameX': [(lambda g:g.V().until(__.out().out()).repeat(__.in_().as_('a').in_().as_('b')).select('a','b').by('name'))],
'g_V_outE_weight_groupCount_selectXvaluesX_unfold': [(lambda g:g.V().outE().weight.groupCount().select(Column.values).unfold())],
- 'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b'))],
'g_V_asXaX_whereXoutXknowsXX_selectXaX': [(lambda g:g.V().as_('a').where(__.out('knows')).select('a'))],
'g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXfirst_aX': [(lambda g, vid1=None:g.V(vid1).as_('a').repeat(__.out().as_('a')).times(2).select(Pop.first,'a'))],
'g_V_asXaX_outXknowsX_asXbX_localXselectXa_bX_byXnameXX': [(lambda g:g.V().as_('a').out('knows').as_('b').local(__.select('a','b').by('name')))],
@@ -560,6 +559,7 @@ world.gremlins = {
'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.key))],
'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.value))],
'g_V_asXaX_selectXaX_byXageX': [(lambda g:g.V().as_('a').select('a').by('age'))],
+ 'g_withSideEffectXk_nullX_injectXxX_selectXkX': [(lambda g:g.withSideEffect('k',None).inject('x').select('k'))],
'g_V_shortestPath': [(lambda g:g.withStrategies(*[TraversalStrategy('VertexProgramStrategy',{'graphComputer':'org.apache.tinkerpop.gremlin.process.computer.GraphComputer'}, 'org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy')]).V().identity().shortestPath())],
'g_V_both_dedup_shortestPath': [(lambda g:g.withStrategies(*[TraversalStrategy('VertexProgramStrategy',{'graphComputer':'org.apache.tinkerpop.gremlin.process.computer.GraphComputer'}, 'org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy')]).V().both().dedup().shortestPath())],
'g_V_shortestPath_edgesIncluded': [(lambda g:g.withStrategies(*[TraversalStrategy('VertexProgramStrategy',{'graphComputer':'org.apache.tinkerpop.gremlin.process.computer.GraphComputer'}, 'org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy')]).V().identity().shortestPath().with_('~tinkerpop.shortestPath.includeEdges'))],
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
index 54ab3df..f0d34dc 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphComputerProvider.java
@@ -104,6 +104,10 @@ import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComp
method = "g_injectXlistXnull_10_20_nullXX_meanXlocalX",
reason = "The inject() step is not supported by GraphComputer")
@Graph.OptOut(
+ test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+ method = "g_withSideEffectXk_nullX_injectXxX_selectXkX",
+ reason = "The inject() step is not supported by GraphComputer")
+@Graph.OptOut(
test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanTest",
method = "g_injectXnull_10_20_nullX_mean",
reason = "The inject() step is not supported by GraphComputer")
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
index 2678738..4932dde 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphComputerProvider.java
@@ -108,6 +108,10 @@ import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComp
method = "g_injectXnull_10_20_nullX_mean",
reason = "The inject() step is not supported by GraphComputer")
@Graph.OptOut(
+ test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+ method = "g_withSideEffectXk_nullX_injectXxX_selectXkX",
+ reason = "The inject() step is not supported by GraphComputer")
+@Graph.OptOut(
test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
method = "*",
reason = "The io() step is not supported generally by GraphComputer")
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
index 3d5c510..1240741 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GryoRemoteGraphComputerProvider.java
@@ -109,6 +109,10 @@ import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComp
method = "g_injectXnull_10_20_nullX_mean",
reason = "The inject() step is not supported by GraphComputer")
@Graph.OptOut(
+ test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+ method = "g_withSideEffectXk_nullX_injectXxX_selectXkX",
+ reason = "The inject() step is not supported by GraphComputer")
+@Graph.OptOut(
test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
method = "*",
reason = "The io() step is not supported generally by GraphComputer")
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
index 01b3a21..924992d 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GryoRemoteGraphGroovyTranslatorComputerProvider.java
@@ -111,6 +111,10 @@ import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComp
method = "g_injectXnull_10_20_nullX_mean",
reason = "The inject() step is not supported by GraphComputer")
@Graph.OptOut(
+ test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+ method = "g_withSideEffectXk_nullX_injectXxX_selectXkX",
+ reason = "The inject() step is not supported by GraphComputer")
+@Graph.OptOut(
test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadTest",
method = "*",
reason = "The io() step is not supported generally by GraphComputer")
diff --git a/gremlin-test/features/map/Select.feature b/gremlin-test/features/map/Select.feature
index 3169e0e..6da8ac6 100644
--- a/gremlin-test/features/map/Select.feature
+++ b/gremlin-test/features/map/Select.feature
@@ -17,7 +17,7 @@
Feature: Step - select()
- Scenario: get_g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX
+ Scenario: g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
And the traversal of
@@ -436,19 +436,6 @@ Feature: Step - select()
| d[2].l |
| d[1].l |
- Scenario: g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).as("a").out("knows").as("b").select("a", "b")
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | m[{"a":"v[marko]","b":"v[vadas]"}] |
- | m[{"a":"v[marko]","b":"v[josh]"}] |
-
Scenario: g_V_asXaX_whereXoutXknowsXX_selectXaX
Given the modern graph
And the traversal of
@@ -830,4 +817,15 @@ Feature: Step - select()
| null |
| d[32].i |
| null |
- | d[35].i |
\ No newline at end of file
+ | d[35].i |
+
+ Scenario: g_withSideEffectXk_nullX_injectXxX_selectXkX
+ Given the empty graph
+ And the traversal of
+ """
+ g.withSideEffect("k",null).inject("x").select("k")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | null |
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index f6c8d12..4b450ca 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -47,8 +47,11 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.identity;
import static org.apache.tinkerpop.gremlin.structure.Column.keys;
import static org.apache.tinkerpop.gremlin.structure.Column.values;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -162,6 +165,8 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
public abstract Traversal<Edge, Object> get_g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX(final Object e11Id);
+ public abstract Traversal<String, Object> get_g_withSideEffectXk_nullX_injectXxX_selectXkX();
+
// when labels don't exist
public abstract Traversal<Vertex, String> get_g_V_untilXout_outX_repeatXin_asXaXX_selectXaX_byXtailXlocalX_nameX();
@@ -896,6 +901,14 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
checkResults(Arrays.asList(29, 27, null, 32, null, 35), traversal);
}
+ @Test
+ public void g_withSideEffectXk_nullX_injectXxX_selectXkX() {
+ final Traversal<String, Object> traversal = get_g_withSideEffectXk_nullX_injectXxX_selectXkX();
+ printTraversalForm(traversal);
+ assertNull(traversal.next());
+ assertThat(traversal.hasNext(), is(false));
+ }
+
public static class Traversals extends SelectTest {
@Override
public Traversal<Vertex, Map<String, Vertex>> get_g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX(final Object v1Id) {
@@ -1224,5 +1237,10 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
public Traversal<Vertex, Object> get_g_V_asXaX_selectXaX_byXageX() {
return g.V().as("a").select("a").by("age");
}
+
+ @Override
+ public Traversal<String, Object> get_g_withSideEffectXk_nullX_injectXxX_selectXkX() {
+ return g.withSideEffect("k",null).inject("x").select("k");
+ }
}
}