Skip to content

Commit

Permalink
Add support for testing sets in results for feature tests. (apache#2279)
Browse files Browse the repository at this point in the history
  • Loading branch information
kenhuuu authored Oct 16, 2023
1 parent 097b32e commit 4230c97
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ public void AssertResult(string characterizedAs, DataTable table = null)
}
Assert.True(expectedArrayContainsResultDictionary);
}
else if (resultItem is HashSet<object> resultItemSet)
{
var expectedArrayContainsResultAsSet = false;
foreach (var expectedItem in expectedArray)
{
if (expectedItem is not HashSet<object> expectedItemSet) continue;
if (!expectedItemSet.SetEquals(resultItemSet)) continue;
expectedArrayContainsResultAsSet = true;
break;
}
Assert.True(expectedArrayContainsResultAsSet);
}
else if (resultItem is double resultItemDouble &&
expectedArray.Select(e => e.GetType()).Any(t => t == typeof(decimal)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
{"g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("created").As("b").In("created").As("c").CyclicPath().From("a").To("b").Path()}},
{"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(0).V().Both().Coalesce<object>(__.Has("name","marko").Both(),__.Constant<object>(0)).CyclicPath().Path()}},
{"g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().In().Values<object>("name").Fold().Dedup(Scope.Local).Unfold<object>()}},
{"g_V_out_in_valuesXnameX_fold_dedupXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Map<object>(__.In().Values<object>("name").Fold().Dedup(Scope.Local))}},
{"g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().As("x").In().As("y").Select<object>("x","y").By("name").Fold().Dedup(Scope.Local,"x","y").Unfold<object>()}},
{"g_V_both_dedup_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Dedup().Values<object>("name")}},
{"g_V_both_hasXlabel_softwareX_dedup_byXlangX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Has(T.Label,"software").Dedup().By("lang").Values<object>("name")}},
Expand Down
33 changes: 31 additions & 2 deletions gremlin-go/driver/cucumber/cucumberSteps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/apache/tinkerpop/gremlin-go/v3/driver"
"github.com/cucumber/godog"
"math"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"sync"
"testing"

gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
"github.com/cucumber/godog"
)

type tinkerPopGraph struct {
Expand Down Expand Up @@ -652,6 +654,23 @@ func compareListEqualsWithoutOrder(expected []interface{}, actual []interface{})
break
}
}
} else if actualSet, ok := a.(*gremlingo.SimpleSet); ok {
// Set is a special case here because there is no TypeOf().Kind() for sets.
actualStringArray := makeSortedStringArrayFromSet(actualSet)

for i := len(expectedCopy) - 1; i >= 0; i-- {
curExpected := expectedCopy[i]
expectedSet, ok := curExpected.(*gremlingo.SimpleSet)
if ok {
expectedStringArray := makeSortedStringArrayFromSet(expectedSet)

if reflect.DeepEqual(actualStringArray, expectedStringArray) {
expectedCopy = append(expectedCopy[:i], expectedCopy[i+1:]...)
found = true
break
}
}
}
} else {
switch reflect.TypeOf(a).Kind() {
case reflect.Array, reflect.Slice:
Expand Down Expand Up @@ -761,6 +780,16 @@ func compareListEqualsWithOf(expected []interface{}, actual []interface{}) bool
return true
}

func makeSortedStringArrayFromSet(set *gremlingo.SimpleSet) []string {
var sortedStrings []string
for _, element := range set.ToSlice() {
sortedStrings = append(sortedStrings, fmt.Sprintf("%v", element))
}
sort.Sort(sort.StringSlice(sortedStrings))

return sortedStrings
}

func (tg *tinkerPopGraph) theTraversalOf(arg1 *godog.DocString) error {
traversal, err := GetTraversal(tg.scenario.Name, tg.g, tg.parameters)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions gremlin-go/driver/cucumber/gremlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).As("a").Out("created").As("b").In("created").As("c").CyclicPath().From("a").To("b").Path()}},
"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(0).V().Both().Coalesce(gremlingo.T__.Has("name", "marko").Both(), gremlingo.T__.Constant(0)).CyclicPath().Path()}},
"g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out().In().Values("name").Fold().Dedup(gremlingo.Scope.Local).Unfold()}},
"g_V_out_in_valuesXnameX_fold_dedupXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out().Map(gremlingo.T__.In().Values("name").Fold().Dedup(gremlingo.Scope.Local))}},
"g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out().As("x").In().As("y").Select("x", "y").By("name").Fold().Dedup(gremlingo.Scope.Local, "x", "y").Unfold()}},
"g_V_both_dedup_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Both().Dedup().Values("name")}},
"g_V_both_hasXlabel_softwareX_dedup_byXlangX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Both().Has(gremlingo.T.Label, "software").Dedup().By("lang").Values("name")}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const ignoredScenarios = {
// An associative array containing the scenario name as key, for example:
'g_withSideEffectXa_setX_V_both_name_storeXaX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
'g_V_out_in_valuesXnameX_fold_dedupXlocalX': new IgnoreError(ignoreReason.setNotSupported),
'g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
'g_V_shortestPath_edgesIncluded': new IgnoreError(ignoreReason.needsFurtherInvestigation),
'g_V_shortestPath_edgesIncluded_edgesXoutEX': new IgnoreError(ignoreReason.needsFurtherInvestigation),
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gremlin-python/src/main/python/radish/gremlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
'g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').as_('b').in_('created').as_('c').cyclicPath().from_('a').to('b').path())],
'g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path': [(lambda g:g.inject(0).V().both().coalesce(__.has('name','marko').both(),__.constant(0)).cyclicPath().path())],
'g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold': [(lambda g:g.V().out().in_().name.fold().dedup(Scope.local).unfold())],
'g_V_out_in_valuesXnameX_fold_dedupXlocalX': [(lambda g:g.V().out().map(__.in_().name.fold().dedup(Scope.local)))],
'g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold': [(lambda g:g.V().out().as_('x').in_().as_('y').select('x','y').by('name').fold().dedup(Scope.local,'x','y').unfold())],
'g_V_both_dedup_name': [(lambda g:g.V().both().dedup().name)],
'g_V_both_hasXlabel_softwareX_dedup_byXlangX_name': [(lambda g:g.V().both().has(T.label,'software').dedup().by('lang').name)],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,13 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("D\\[(.*)\\]"), Direction::valueOf));
add(Pair.with(Pattern.compile("M\\[(.*)\\]"), Merge::valueOf));

add(Pair.with(Pattern.compile("c\\[(.*)\\]"), s -> {
throw new AssumptionViolatedException("This test uses a lambda as a parameter which is not supported by gremlin-language");
}));
add(Pair.with(Pattern.compile("c\\[(.*)\\]"), s -> Collections.emptySet()));
add(Pair.with(Pattern.compile("s\\[\\]"), s -> {
throw new AssumptionViolatedException("This test uses a empty Set as a parameter which is not supported by gremlin-language");
}));
add(Pair.with(Pattern.compile("s\\[(.*)\\]"), s -> {
throw new AssumptionViolatedException("This test uses a Set as a parameter which is not supported by gremlin-language");
final String[] items = s.split(",");
return Stream.of(items).map(String::trim).map(x -> convertToObject(x)).collect(Collectors.toSet());
}));

add(Pair.with(Pattern.compile("(null)"), s -> null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ Feature: Step - dedup()
| josh |
| peter |

@GraphComputerVerificationStarGraphExceeded
Scenario: g_V_out_in_valuesXnameX_fold_dedupXlocalX
Given the modern graph
And the traversal of
"""
g.V().out().map(__.in().values("name").fold().dedup(Scope.local))
"""
When iterated to list
Then the result should be unordered
| result |
| s[peter,marko,josh] |
| s[marko,peter,josh] |
| s[josh,marko,peter] |
| s[marko] |
| s[josh] |
| s[marko] |

Scenario: g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold
Given the modern graph
And the traversal of
Expand Down

0 comments on commit 4230c97

Please sign in to comment.