Skip to content

Commit 007fd22

Browse files
authored
[TINKERPOP-3149] Prevent multiple by modulators for sack step and changed GroupCount.feature test to verify the error message received. (#3102)
1 parent 5b7eea5 commit 007fd22

9 files changed

Lines changed: 25 additions & 3 deletions

File tree

CHANGELOG.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ This release also includes changes from <<release-3-7-XXX, 3.7.XXX>>.
6666
* Added missing strategies in `gremlin-go`, updated certain strategies to take varargs and updated `GoTranslatorVisitor` for corresponding translations.
6767
* Fixed `BigInt` and `BigDecimal` parsing in `gremlin-go` cucumber test suite, fixed `UnscaledValue` type in `BigDecimal` struct and added `ParseBigDecimal` method.
6868
* Added validation to `valueMap()`/`propertyMap()`/`groupCount()` to prevent an invalid usage of multiple `by()` modulators.
69-
* Added validation to `groupCount()` to prevent an invalid usage of multiple `by()` modulators.
69+
* Added validation to `groupCount()` and `sack()` to prevent an invalid usage of multiple `by()` modulators.
7070
* Deprecated `ProcessLimitedStandardSuite` and `ProcessLimitedComputerSuite` in favor of `ProcessEmbeddedStandardSuite` and `ProcessEmbeddedComputerSuite` respectively.
7171
* Deprecated `ProcessStandardSuite` and the `ProcessComputerSuite` in favor of Gherkin testing and the `ProcessEmbeddedStandardSuite` and `ProcessEmbeddedComputerSuite` for testing JVM-specific Gremlin behaviors.
7272
* Removed lambda oriented Gremlin testing from Gherkin test suite.

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ public SackValueStep(final Traversal.Admin traversal, final BiFunction<A, B, A>
5151

5252
@Override
5353
public void modulateBy(final Traversal.Admin<?, ?> sackTraversal) {
54+
if (this.sackTraversal != null) {
55+
throw new IllegalStateException("Sack step can only have one by modulator");
56+
}
5457
this.sackTraversal = this.integrateChild(sackTraversal);
5558
}
5659

gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStepTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Arrays;
2828
import java.util.List;
2929
import java.util.Map;
30+
import org.junit.Test;
3031

3132
/**
3233
* @author Daniel Kuppitz (http://gremlin.guru)
@@ -49,4 +50,9 @@ protected List<Traversal> getTraversals() {
4950
})
5051
);
5152
}
53+
54+
@Test(expected = IllegalStateException.class)
55+
public void shouldThrowForMultipleByModulators() {
56+
__.sack(Operator.assign).by("age").by("name");
57+
}
5258
}

gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,7 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
16401640
{"g_V_sackXassignX_byXageX_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sack(Operator.Assign).By("age").Sack<object>()}},
16411641
{"g_withSackXBigInteger_TEN_powX1000X_assignX_V_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(p["xx1"], Operator.Assign).V().Local<object>(__.Out("knows").Barrier(Barrier.NormSack)).In("knows").Barrier().Sack<object>()}},
16421642
{"g_withSackX2X_V_sackXdivX_byXconstantX4_0XX_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(2).V().Sack(Operator.Div).By(__.Constant<object>(p["xx1"])).Sack<object>()}},
1643+
{"g_V_sackXassignX_byXageX_byXnameX_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sack(Operator.Assign).By("age").By("name").Sack<object>()}},
16431644
{"g_V_sideEffectXidentityX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().SideEffect(__.Identity())}},
16441645
{"g_V_sideEffectXidentity_valuesXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().SideEffect(__.Identity().Values<object>("name"))}},
16451646
{"g_V_sideEffectXpropertyXage_22X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("age", 21), (g,p) =>g.V().SideEffect(__.Property("age", 22)), (g,p) =>g.V().Has("age", 21), (g,p) =>g.V().Has("age", 22)}},

gremlin-go/driver/cucumber/gremlin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
16091609
"g_V_sackXassignX_byXageX_sack": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Sack(gremlingo.Operator.Assign).By("age").Sack()}},
16101610
"g_withSackXBigInteger_TEN_powX1000X_assignX_V_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSack(p["xx1"], gremlingo.Operator.Assign).V().Local(gremlingo.T__.Out("knows").Barrier(gremlingo.Barrier.NormSack)).In("knows").Barrier().Sack()}},
16111611
"g_withSackX2X_V_sackXdivX_byXconstantX4_0XX_sack": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSack(2).V().Sack(gremlingo.Operator.Div).By(gremlingo.T__.Constant(p["xx1"])).Sack()}},
1612+
"g_V_sackXassignX_byXageX_byXnameX_sack": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Sack(gremlingo.Operator.Assign).By("age").By("name").Sack()}},
16121613
"g_V_sideEffectXidentityX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().SideEffect(gremlingo.T__.Identity())}},
16131614
"g_V_sideEffectXidentity_valuesXnameXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().SideEffect(gremlingo.T__.Identity().Values("name"))}},
16141615
"g_V_sideEffectXpropertyXage_22X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("age", 21)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().SideEffect(gremlingo.T__.Property("age", 22))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", 21)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age", 22)}},

gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gremlin-python/src/main/python/radish/gremlin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@
16121612
'g_V_sackXassignX_byXageX_sack': [(lambda g:g.V().sack(Operator.assign).by('age').sack())],
16131613
'g_withSackXBigInteger_TEN_powX1000X_assignX_V_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack': [(lambda g, xx1=None:g.with_sack(xx1, Operator.assign).V().local(__.out('knows').barrier(Barrier.norm_sack)).in_('knows').barrier().sack())],
16141614
'g_withSackX2X_V_sackXdivX_byXconstantX4_0XX_sack': [(lambda g, xx1=None:g.with_sack(2).V().sack(Operator.div).by(__.constant(xx1)).sack())],
1615+
'g_V_sackXassignX_byXageX_byXnameX_sack': [(lambda g:g.V().sack(Operator.assign).by('age').by('name').sack())],
16151616
'g_V_sideEffectXidentityX': [(lambda g:g.V().side_effect(__.identity()))],
16161617
'g_V_sideEffectXidentity_valuesXnameXX': [(lambda g:g.V().side_effect(__.identity().values('name')))],
16171618
'g_V_sideEffectXpropertyXage_22X': [(lambda g:g.add_v('person').property('age', 21)), (lambda g:g.V().side_effect(__.property('age', 22))), (lambda g:g.V().has('age', 21)), (lambda g:g.V().has('age', 22))],

gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/GroupCount.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,4 @@ Feature: Step - groupCount()
243243
g.V().out("created").groupCount("x").by("name").by("age")
244244
"""
245245
When iterated to list
246-
Then the traversal will raise an error
246+
Then the traversal will raise an error with message containing text of "GroupCount step can only have one by modulator"

gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Sack.feature

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,13 @@ Feature: Step - sack()
140140
| d[0.5].d |
141141
| d[0.5].d |
142142
| d[0.5].d |
143-
| d[0.5].d |
143+
| d[0.5].d |
144+
145+
Scenario: g_V_sackXassignX_byXageX_byXnameX_sack
146+
Given the modern graph
147+
And the traversal of
148+
"""
149+
g.V().sack(assign).by("age").by("name").sack()
150+
"""
151+
When iterated to list
152+
Then the traversal will raise an error with message containing text of "Sack step can only have one by modulator"

0 commit comments

Comments
 (0)