1 package query
2
3 import (
4 "fmt"
5 "strconv"
6 "testing"
7
8 "github.com/pelletier/go-toml"
9 )
10
11
12 func pathString(root pathFn) string {
13 result := fmt.Sprintf("%T:", root)
14 switch fn := root.(type) {
15 case *terminatingFn:
16 result += "{}"
17 case *matchKeyFn:
18 result += fmt.Sprintf("{%s}", fn.Name)
19 result += pathString(fn.next)
20 case *matchIndexFn:
21 result += fmt.Sprintf("{%d}", fn.Idx)
22 result += pathString(fn.next)
23 case *matchSliceFn:
24 startString, endString, stepString := "nil", "nil", "nil"
25 if fn.Start != nil {
26 startString = strconv.Itoa(*fn.Start)
27 }
28 if fn.End != nil {
29 endString = strconv.Itoa(*fn.End)
30 }
31 if fn.Step != nil {
32 stepString = strconv.Itoa(*fn.Step)
33 }
34 result += fmt.Sprintf("{%s:%s:%s}", startString, endString, stepString)
35 result += pathString(fn.next)
36 case *matchAnyFn:
37 result += "{}"
38 result += pathString(fn.next)
39 case *matchUnionFn:
40 result += "{["
41 for _, v := range fn.Union {
42 result += pathString(v) + ", "
43 }
44 result += "]}"
45 case *matchRecursiveFn:
46 result += "{}"
47 result += pathString(fn.next)
48 case *matchFilterFn:
49 result += fmt.Sprintf("{%s}", fn.Name)
50 result += pathString(fn.next)
51 }
52 return result
53 }
54
55 func assertPathMatch(t *testing.T, path, ref *Query) bool {
56 pathStr := pathString(path.root)
57 refStr := pathString(ref.root)
58 if pathStr != refStr {
59 t.Errorf("paths do not match")
60 t.Log("test:", pathStr)
61 t.Log("ref: ", refStr)
62 return false
63 }
64 return true
65 }
66
67 func assertPath(t *testing.T, query string, ref *Query) {
68 path, _ := parseQuery(lexQuery(query))
69 assertPathMatch(t, path, ref)
70 }
71
72 func buildPath(parts ...pathFn) *Query {
73 query := newQuery()
74 for _, v := range parts {
75 query.appendPath(v)
76 }
77 return query
78 }
79
80 func TestPathRoot(t *testing.T) {
81 assertPath(t,
82 "$",
83 buildPath(
84
85 ))
86 }
87
88 func TestPathKey(t *testing.T) {
89 assertPath(t,
90 "$.foo",
91 buildPath(
92 newMatchKeyFn("foo"),
93 ))
94 }
95
96 func TestPathBracketKey(t *testing.T) {
97 assertPath(t,
98 "$[foo]",
99 buildPath(
100 newMatchKeyFn("foo"),
101 ))
102 }
103
104 func TestPathBracketStringKey(t *testing.T) {
105 assertPath(t,
106 "$['foo']",
107 buildPath(
108 newMatchKeyFn("foo"),
109 ))
110 }
111
112 func TestPathIndex(t *testing.T) {
113 assertPath(t,
114 "$[123]",
115 buildPath(
116 newMatchIndexFn(123),
117 ))
118 }
119
120 func TestPathSliceStart(t *testing.T) {
121 assertPath(t,
122 "$[123:]",
123 buildPath(
124 newMatchSliceFn().setStart(123),
125 ))
126 }
127
128 func TestPathSliceStartEnd(t *testing.T) {
129 assertPath(t,
130 "$[123:456]",
131 buildPath(
132 newMatchSliceFn().setStart(123).setEnd(456),
133 ))
134 }
135
136 func TestPathSliceStartEndColon(t *testing.T) {
137 assertPath(t,
138 "$[123:456:]",
139 buildPath(
140 newMatchSliceFn().setStart(123).setEnd(456),
141 ))
142 }
143
144 func TestPathSliceStartStep(t *testing.T) {
145 assertPath(t,
146 "$[123::7]",
147 buildPath(
148 newMatchSliceFn().setStart(123).setStep(7),
149 ))
150 }
151
152 func TestPathSliceEndStep(t *testing.T) {
153 assertPath(t,
154 "$[:456:7]",
155 buildPath(
156 newMatchSliceFn().setEnd(456).setStep(7),
157 ))
158 }
159
160 func TestPathSliceStep(t *testing.T) {
161 assertPath(t,
162 "$[::7]",
163 buildPath(
164 newMatchSliceFn().setStep(7),
165 ))
166 }
167
168 func TestPathSliceAll(t *testing.T) {
169 assertPath(t,
170 "$[123:456:7]",
171 buildPath(
172 newMatchSliceFn().setStart(123).setEnd(456).setStep(7),
173 ))
174 }
175
176 func TestPathAny(t *testing.T) {
177 assertPath(t,
178 "$.*",
179 buildPath(
180 newMatchAnyFn(),
181 ))
182 }
183
184 func TestPathUnion(t *testing.T) {
185 assertPath(t,
186 "$[foo, bar, baz]",
187 buildPath(
188 &matchUnionFn{[]pathFn{
189 newMatchKeyFn("foo"),
190 newMatchKeyFn("bar"),
191 newMatchKeyFn("baz"),
192 }},
193 ))
194 }
195
196 func TestPathRecurse(t *testing.T) {
197 assertPath(t,
198 "$..*",
199 buildPath(
200 newMatchRecursiveFn(),
201 ))
202 }
203
204 func TestPathFilterExpr(t *testing.T) {
205 assertPath(t,
206 "$[?('foo'),?(bar)]",
207 buildPath(
208 &matchUnionFn{[]pathFn{
209 newMatchFilterFn("foo", toml.Position{}),
210 newMatchFilterFn("bar", toml.Position{}),
211 }},
212 ))
213 }
214
View as plain text