Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 20 additions & 22 deletions integration/cypher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"testing"

"github.com/specterops/dawgs/graph"
Expand All @@ -33,20 +34,20 @@ import (

// caseFile represents one JSON test case file.
type caseFile struct {
Dataset string `json:"dataset"`
Skip string `json:"skip,omitempty"`
Cases []testCase `json:"cases"`
Dataset string `json:"dataset"`
SkipDrivers []string `json:"skip_drivers,omitempty"`
Cases []testCase `json:"cases"`
}

// testCase is a single test: a Cypher query and an assertion on its result.
// Cases with a "fixture" field run in a write transaction that rolls back,
// so the inline data doesn't persist.
type testCase struct {
Name string `json:"name"`
Skip string `json:"skip,omitempty"`
Cypher string `json:"cypher"`
Assert json.RawMessage `json:"assert"`
Fixture *opengraph.Graph `json:"fixture,omitempty"`
Name string `json:"name"`
SkipDrivers []string `json:"skip_drivers,omitempty"`
Cypher string `json:"cypher"`
Assert json.RawMessage `json:"assert"`
Fixture *opengraph.Graph `json:"fixture,omitempty"`
}

func TestCypher(t *testing.T) {
Expand Down Expand Up @@ -91,24 +92,29 @@ func TestCypher(t *testing.T) {

db, ctx := SetupDB(t, datasetNames...)

driver := *driverFlag

for _, g := range groups {
ClearGraph(t, db, ctx)
LoadDataset(t, db, ctx, g.dataset)

for _, cf := range g.files {
if cf.Skip != "" {
t.Run(cf.Skip, func(t *testing.T) {
t.Skipf("skipped: %s", cf.Skip)
})
if slices.Contains(cf.SkipDrivers, driver) {
continue
}

for _, tc := range cf.Cases {
t.Run(tc.Name, func(t *testing.T) {
if tc.Skip != "" {
t.Skipf("skipped: %s", tc.Skip)
if slices.Contains(tc.SkipDrivers, driver) {
t.Skipf("skipped for driver %s", driver)
}

defer func() {
if r := recover(); r != nil {
t.Fatalf("panic: %v", r)
}
}()

check := parseAssertion(t, tc.Assert)

if tc.Fixture != nil {
Expand Down Expand Up @@ -327,11 +333,3 @@ func assertContainsNodeWithProp(key, expected string) func(*testing.T, graph.Res
}
}

// formatCaseSummary is used for logging.
func formatCaseSummary(files []string) string {
total := 0
for range files {
total++
}
return fmt.Sprintf("%d case files", total)
}
1 change: 1 addition & 0 deletions integration/testdata/cases/expansion_inline.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
{
"name": "unbounded traversal filtering every traversed edge by a property",
"skip_drivers": ["neo4j"],
"cypher": "match (n)-[r*..]->(e:NodeKind1) where n.name = 'n1' and r.prop = 'a' return e",
"fixture": {
"nodes": [
Expand Down
3 changes: 3 additions & 0 deletions integration/testdata/cases/nodes.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
},
{
"name": "filter typed node where array property overlaps a literal list",
"skip_drivers": ["neo4j"],
"cypher": "match (n:NodeKind1) where ['DES-CBC-CRC', 'DES-CBC-MD5', 'RC4-HMAC-MD5'] in n.arrayProperty return n",
"assert": "non_empty"
},
Expand Down Expand Up @@ -218,6 +219,7 @@
},
{
"name": "filter typed node where toInt of a property appears in a literal integer list",
"skip_drivers": ["neo4j"],
"cypher": "match (n:NodeKind1) where toInt(n.value) in [1, 2, 3, 4] return n",
"assert": "non_empty"
},
Expand All @@ -238,6 +240,7 @@
},
{
"name": "filter node where a property equals date plus a duration string",
"skip_drivers": ["neo4j"],
"cypher": "match (s) where s.created_at = date() + duration('4 hours') return s",
"assert": "no_error"
},
Expand Down
4 changes: 2 additions & 2 deletions integration/testdata/cases/nodes_inline.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
{
"name": "cross-product filter where two nodes match different typed properties",
"skip": "PG type inference bug: mixed string/int cross-product properties (see zinic/testing fork)",
"skip_drivers": ["pg"],
"cypher": "match (s), (e) where s.name = '1234' and e.other = 1234 return s",
"fixture": {
"nodes": [
Expand Down Expand Up @@ -97,7 +97,7 @@
},
{
"name": "filter cross-product where either node satisfies a different property predicate",
"skip": "PG type inference bug: mixed string/int cross-product properties (see zinic/testing fork)",
"skip_drivers": ["pg"],
"cypher": "match (s), (e) where s.name = '1234' or e.other = 1234 return s",
"fixture": {
"nodes": [
Expand Down
1 change: 1 addition & 0 deletions integration/testdata/cases/shortest_paths.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
{
"name": "shortest path to self returns empty",
"skip_drivers": ["neo4j"],
"cypher": "MATCH p = allShortestPaths((s)-[*1..]->(e)) WHERE s.name = 'SOME NAME' AND e.name = 'SOME NAME' RETURN p",
"assert": "empty"
}
Expand Down
Loading