Skip to content

Commit 26881eb

Browse files
committed
Added support for property assertion
Property assertion isn't perfect but it's a best effort that at least lets the test suite exercise this data type a bit. Removed handlers for syntax no longer supported and fixed up some tests that were impacted. CTR
1 parent faf56dd commit 26881eb

File tree

10 files changed

+192
-58
lines changed

10 files changed

+192
-58
lines changed

docs/src/dev/developer/for-committers.asciidoc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,10 @@ included to further qualify the type of numeric. The following options are avail
412412
* Path - *p[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values that make up the `Path` should be added to
413413
between the square brackets. These values respect the type system thus allowing for creation of `Path` of vertices,
414414
edges, maps, and any other available type.
415+
* Property - *prop[_key_,_value_]* - The key is simply a string, and the value is expected to be a typed value using the
416+
syntax presented here.
415417
* Set - *s[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values that make up the set should be added to
416-
between the square brackets. These values respect the type system thus allowing for creation of sets of vertices,
418+
between the square brackets. These values respect the type system thus allowing to create sets of vertices,
417419
edges, maps, and any other available type.
418420
* String - Any value not using the system notation will be interpreted as
419421
a string by default.
@@ -423,6 +425,11 @@ such as null and spaces.
423425
* Vertex - *v[_xxx_]* - The "xxx" should be replaced with the "name" property of a vertex in the graph. This syntax may
424426
include the `.id` suffix which would indicate getting the vertex identifier or the `.sid` suffix which gets a string
425427
representation of the edge identifier.
428+
* VertexProperty - *vp[_xxx_]* - The "xxx" should be replaced with a representation of a vertex property in the form of
429+
the `vertex_name-key->value`. Note that the key is just a string and the value is a typed value using the syntax
430+
presented here.
431+
432+
vp[marko-name->marko]
426433
427434
In addition, parameter names should adhere to a common form as they hold some meaning to certain language variant
428435
implementations:

gremlin-go/driver/cucumber/cucumberSteps_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func init() {
5656
regexp.MustCompile(`^d\[(.*)]\.[n]$`): toBigInt,
5757
regexp.MustCompile(`^d\[(.*)]\.[i]$`): toInt32,
5858
regexp.MustCompile(`^vp\[(.+)]$`): toVertexProperty,
59+
regexp.MustCompile(`^prop\[(.+)]$`): toProperty,
5960
regexp.MustCompile(`^v\[(.+)]$`): toVertex,
6061
regexp.MustCompile(`^v\[(.+)]\.id$`): toVertexId,
6162
regexp.MustCompile(`^e\[(.+)]$`): toEdge,
@@ -174,6 +175,14 @@ func toInt32(stringVal, graphName string) interface{} {
174175
return int32(val)
175176
}
176177

178+
// Parse property as key/value pair.
179+
func toProperty(stringVal, graphName string) interface{} {
180+
commaIdx := strings.Index(stringVal, ",")
181+
key := stringVal[:commaIdx]
182+
value := parseValue(stringVal[commaIdx+1:], graphName)
183+
return &gremlingo.Property{Key: key, Value: value}
184+
}
185+
177186
// Parse vertex property.
178187
func toVertexProperty(name, graphName string) interface{} {
179188
if vp, ok := tg.getDataGraphFromMap(graphName).vertexProperties[name]; ok {

gremlin-go/driver/cucumber/gremlin.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,9 +1114,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
11141114
"g_E": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E()}},
11151115
"g_EX11X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"])}},
11161116
"g_EX11AsStringX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"])}},
1117-
"g_EXe11X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["e11"])}},
1118-
"g_EXe7_e11X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["e7"], p["e11"])}},
1119-
"g_EXlistXe7_e11XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}},
1117+
"g_EXeid7_eid11X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid7"], p["eid11"])}},
1118+
"g_EXlistXeid7_eid11XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}},
11201119
"g_EXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(nil)}},
11211120
"g_EXlistXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}},
11221121
"g_EX11_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"], nil)}},
@@ -1525,6 +1524,10 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
15251524
"g_V_hasXageX_propertiesXage_nameX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age").Properties("age", "name").Value()}},
15261525
"g_V_propertiesXname_age_nullX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("name", "age", nil).Value()}},
15271526
"g_V_valuesXname_age_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name", "age", nil)}},
1527+
"g_E_propertiesXweightX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties("weight")}},
1528+
"g_E_properties": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddV("person").Property("name", "bob").As("b").AddE("knows").From("a").To("b").Property("weight", 0.5).Property("since", int32(2020))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties()}},
1529+
"g_E_propertiesXsinceX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddV("person").Property("name", "bob").As("b").AddE("knows").From("a").To("b").Property("weight", 0.5).Property("since", int32(2020))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties("since")}},
1530+
"g_E_properties_multi_edges": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddV("person").Property("name", "bob").As("b").AddE("knows").From("a").To("b").Property("weight", 0.5).Property("since", int32(2020)).AddE("likes").From("a").To("b").Property("weight", 1.0).Property("tag", "friend")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties()}},
15281531
"g_injectX__feature___test__nullX_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("feature ", "one test ", nil, "", " ", " abc", "abc ", " abc ", "  ").RTrim()}},
15291532
"g_injectX__feature___test__nullX_rTrimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{" feature ", " one test ", nil, "", " ", " abc", "abc ", " abc ", "  "}).RTrim(gremlingo.Scope.Local)}},
15301533
"g_injectX__feature__X_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature ").RTrim()}},
@@ -1895,6 +1898,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
18951898
"g_V_properties_order_id": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties().Order().Id()}},
18961899
"g_E_properties_order_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddE("self").From("a").To("a").Property("weight", 0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(13)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(14)).AddE("self").From("a").To("a").Property("weight", 0.2).Property("a", int32(15))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties().Order().Value()}},
18971900
"g_E_properties_order_byXdescX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddE("self").From("a").To("a").Property("weight", 0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(13)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(14)).AddE("self").From("a").To("a").Property("weight", 0.2).Property("a", int32(15))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties().Order().By(gremlingo.Order.Desc).Value()}},
1901+
"g_E_properties_order": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddE("self").From("a").To("a").Property("weight", 0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(13)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(14)).AddE("self").From("a").To("a").Property("weight", 0.2).Property("a", int32(15))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties().Order()}},
1902+
"g_E_properties_order_byXdescX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "alice").As("a").AddE("self").From("a").To("a").Property("weight", 0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 1.0).Property("a", int32(13)).AddE("self").From("a").To("a").Property("weight", 0.4).Property("a", int32(14)).AddE("self").From("a").To("a").Property("weight", 0.2).Property("a", int32(15))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties().Order().By(gremlingo.Order.Desc)}},
18981903
"g_inject_order": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("zzz", "foo", uuid.MustParse("6100808b-62f9-42b7-957e-ed66c30f40d1"), []interface{}{"a", "b", "c", "d"}, 1, time.Date(2023, 8, 1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), []interface{}{"a", "b", "c"}, map[interface{}]interface{}{"a": "a", "b": "b" }, nil, 2.0, time.Date(2023, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), gremlingo.NewSimpleSet("x", "y", "z"), map[interface{}]interface{}{"a": "a", "b": false, "c": "c" }, "bar", uuid.MustParse("5100808b-62f9-42b7-957e-ed66c30f40d1"), true, false, math.Inf(1), math.NaN(), math.Inf(-1)).Order()}},
18991904
"g_inject_order_byXdescX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("zzz", "foo", uuid.MustParse("6100808b-62f9-42b7-957e-ed66c30f40d1"), []interface{}{"a", "b", "c", "d"}, 1, time.Date(2023, 8, 1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), []interface{}{"a", "b", "c"}, map[interface{}]interface{}{"a": "a", "b": "b" }, nil, 2.0, time.Date(2023, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), gremlingo.NewSimpleSet("x", "y", "z"), map[interface{}]interface{}{"a": "a", "b": false, "c": "c" }, "bar", uuid.MustParse("5100808b-62f9-42b7-957e-ed66c30f40d1"), true, false, math.Inf(1), math.NaN(), math.Inf(-1)).Order().By(gremlingo.Order.Desc)}},
19001905
"g_V_out_out_order_byXascX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out().Out().Order().By(gremlingo.Order.Asc)}},

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

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gremlin-python/src/main/python/tests/feature/feature_steps.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ def _convert(val, ctx):
369369
return __find_cached_element(ctx, graph_name, val[2:-1], "e")
370370
elif isinstance(val, str) and re.match(r"^vp\[.*\]$", val): # parse vertexproperty
371371
return __find_cached_element(ctx, graph_name, val[3:-1], "vp")
372+
elif isinstance(val, str) and re.match(r"^prop\[.+\]$", val): # parse property as key/value pair
373+
inner = val[5:-1]
374+
comma_idx = inner.index(",")
375+
key = inner[:comma_idx]
376+
value = _convert(inner[comma_idx + 1:], ctx)
377+
return Property(key, value, None)
372378
elif isinstance(val, str) and re.match(r"^m\[.*\]$", val): # parse json as a map
373379
return _convert(json.loads(val[2:-1]), ctx)
374380
elif isinstance(val, str) and re.match(r"^p\[.*\]$", val): # parse path
@@ -438,6 +444,9 @@ def _convert_results(val):
438444
if isinstance(val, Path):
439445
# kill out labels as they aren't in the assertion logic
440446
return Path([set([])], val.objects)
447+
elif isinstance(val, Property) and not isinstance(val, VertexProperty):
448+
# strip element for key/value only comparison with prop[...] syntax
449+
return Property(val.key, val.value, None)
441450
elif _is_nan(val):
442451
# we need to use the string form for NaN to test the results since float.nan != float.nan
443452
return "d[NaN]"

0 commit comments

Comments
 (0)