Skip to content

Commit 98f4e94

Browse files
committed
test(query/v2): cover legacy query parity
1 parent 480486d commit 98f4e94

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

query/v2/legacy_parity_test.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package v2_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/specterops/dawgs/cypher/models/cypher"
7+
"github.com/specterops/dawgs/graph"
8+
legacyquery "github.com/specterops/dawgs/query"
9+
"github.com/specterops/dawgs/query/neo4j"
10+
v2 "github.com/specterops/dawgs/query/v2"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func renderNeo4jQuery(t *testing.T, regularQuery *cypher.RegularQuery, prepareAllShortestPaths bool) (string, map[string]any) {
15+
t.Helper()
16+
17+
queryBuilder := neo4j.NewQueryBuilder(regularQuery)
18+
19+
if prepareAllShortestPaths {
20+
require.NoError(t, queryBuilder.PrepareAllShortestPaths())
21+
} else {
22+
require.NoError(t, queryBuilder.Prepare())
23+
}
24+
25+
rendered, err := queryBuilder.Render()
26+
require.NoError(t, err)
27+
28+
return rendered, queryBuilder.Parameters
29+
}
30+
31+
func assertLegacyNeo4jParity(t *testing.T, legacyQuery *cypher.RegularQuery, v2Builder v2.QueryBuilder, prepareLegacyAllShortestPaths bool) {
32+
t.Helper()
33+
34+
preparedQuery, err := v2Builder.Build()
35+
require.NoError(t, err)
36+
37+
legacyRendered, legacyParameters := renderNeo4jQuery(t, legacyQuery, prepareLegacyAllShortestPaths)
38+
v2Rendered, v2Parameters := renderNeo4jQuery(t, preparedQuery.Query, false)
39+
40+
require.Equal(t, legacyRendered, v2Rendered)
41+
require.Equal(t, legacyParameters, v2Parameters)
42+
}
43+
44+
func TestLegacyNeo4jParity(t *testing.T) {
45+
userKind := graph.StringKind("User")
46+
edgeKind := graph.StringKind("MemberOf")
47+
48+
t.Run("node count by kind", func(t *testing.T) {
49+
assertLegacyNeo4jParity(t,
50+
legacyquery.SinglePartQuery(
51+
legacyquery.Where(
52+
legacyquery.KindIn(legacyquery.Node(), userKind),
53+
),
54+
legacyquery.Returning(
55+
legacyquery.Count(legacyquery.Node()),
56+
),
57+
),
58+
v2.New().Where(
59+
v2.Node().Kinds().Has(userKind),
60+
).Return(
61+
v2.Node().Count(),
62+
),
63+
false,
64+
)
65+
})
66+
67+
t.Run("node read with pagination", func(t *testing.T) {
68+
assertLegacyNeo4jParity(t,
69+
legacyquery.SinglePartQuery(
70+
legacyquery.Where(
71+
legacyquery.And(
72+
legacyquery.StringContains(legacyquery.NodeProperty("name"), "admin"),
73+
legacyquery.IsNotNull(legacyquery.NodeProperty("enabled")),
74+
),
75+
),
76+
legacyquery.Returning(
77+
legacyquery.Node(),
78+
legacyquery.OrderBy(legacyquery.Order(legacyquery.NodeProperty("name"), legacyquery.Ascending())),
79+
legacyquery.Offset(0),
80+
legacyquery.Limit(0),
81+
),
82+
),
83+
v2.New().Where(
84+
v2.And(
85+
v2.Node().Property("name").Contains("admin"),
86+
v2.Node().Property("enabled").IsNotNull(),
87+
),
88+
).Return(
89+
v2.Node(),
90+
).OrderBy(
91+
v2.Asc(v2.Node().Property("name")),
92+
).Skip(0).Limit(0),
93+
false,
94+
)
95+
})
96+
97+
t.Run("relationship read", func(t *testing.T) {
98+
assertLegacyNeo4jParity(t,
99+
legacyquery.SinglePartQuery(
100+
legacyquery.Where(
101+
legacyquery.And(
102+
legacyquery.KindIn(legacyquery.Relationship(), edgeKind),
103+
legacyquery.Equals(legacyquery.StartID(), 1),
104+
legacyquery.Equals(legacyquery.EndID(), 2),
105+
),
106+
),
107+
legacyquery.Returning(
108+
legacyquery.StartID(),
109+
legacyquery.RelationshipID(),
110+
legacyquery.EndID(),
111+
),
112+
),
113+
v2.New().Where(
114+
v2.Relationship().Kind().Is(edgeKind),
115+
v2.Start().ID().Equals(1),
116+
v2.End().ID().Equals(2),
117+
).Return(
118+
v2.Start().ID(),
119+
v2.Relationship().ID(),
120+
v2.End().ID(),
121+
),
122+
false,
123+
)
124+
})
125+
126+
t.Run("create relationship with matched endpoints", func(t *testing.T) {
127+
properties := map[string]any{"name": "rel"}
128+
129+
assertLegacyNeo4jParity(t,
130+
legacyquery.SinglePartQuery(
131+
legacyquery.Where(
132+
legacyquery.And(
133+
legacyquery.Equals(legacyquery.StartID(), 1),
134+
legacyquery.Equals(legacyquery.EndID(), 2),
135+
),
136+
),
137+
legacyquery.Create(
138+
legacyquery.Start(),
139+
legacyquery.RelationshipPattern(edgeKind, legacyquery.Parameter(properties), graph.DirectionOutbound),
140+
legacyquery.End(),
141+
),
142+
legacyquery.Returning(
143+
legacyquery.RelationshipID(),
144+
),
145+
),
146+
v2.New().Where(
147+
v2.Start().ID().Equals(1),
148+
v2.End().ID().Equals(2),
149+
).Create(
150+
v2.Start(),
151+
v2.RelationshipPattern(edgeKind, v2.Parameter(properties), graph.DirectionOutbound),
152+
v2.End(),
153+
).Return(
154+
v2.Relationship().ID(),
155+
),
156+
false,
157+
)
158+
})
159+
160+
t.Run("all shortest paths", func(t *testing.T) {
161+
assertLegacyNeo4jParity(t,
162+
legacyquery.SinglePartQuery(
163+
legacyquery.Where(
164+
legacyquery.And(
165+
legacyquery.KindIn(legacyquery.Relationship(), edgeKind),
166+
legacyquery.Equals(legacyquery.StartID(), 1),
167+
legacyquery.Equals(legacyquery.EndID(), 2),
168+
),
169+
),
170+
legacyquery.Returning(
171+
legacyquery.Path(),
172+
),
173+
),
174+
v2.New().WithAllShortestPaths().Where(
175+
v2.Relationship().Kind().Is(edgeKind),
176+
v2.Start().ID().Equals(1),
177+
v2.End().ID().Equals(2),
178+
).Return(
179+
v2.Path(),
180+
),
181+
true,
182+
)
183+
})
184+
}

0 commit comments

Comments
 (0)