1 package jmespath
2
3 import (
4 "encoding/json"
5 "testing"
6
7 "github.com/jmespath/go-jmespath/internal/testify/assert"
8 )
9
10 type scalars struct {
11 Foo string
12 Bar string
13 }
14
15 type sliceType struct {
16 A string
17 B []scalars
18 C []*scalars
19 }
20
21 type benchmarkStruct struct {
22 Fooasdfasdfasdfasdf string
23 }
24
25 type benchmarkNested struct {
26 Fooasdfasdfasdfasdf nestedA
27 }
28
29 type nestedA struct {
30 Fooasdfasdfasdfasdf nestedB
31 }
32
33 type nestedB struct {
34 Fooasdfasdfasdfasdf nestedC
35 }
36
37 type nestedC struct {
38 Fooasdfasdfasdfasdf string
39 }
40
41 type nestedSlice struct {
42 A []sliceType
43 }
44
45 func TestCanSupportEmptyInterface(t *testing.T) {
46 assert := assert.New(t)
47 data := make(map[string]interface{})
48 data["foo"] = "bar"
49 result, err := Search("foo", data)
50 assert.Nil(err)
51 assert.Equal("bar", result)
52 }
53
54 func TestCanSupportUserDefinedStructsValue(t *testing.T) {
55 assert := assert.New(t)
56 s := scalars{Foo: "one", Bar: "bar"}
57 result, err := Search("Foo", s)
58 assert.Nil(err)
59 assert.Equal("one", result)
60 }
61
62 func TestCanSupportUserDefinedStructsRef(t *testing.T) {
63 assert := assert.New(t)
64 s := scalars{Foo: "one", Bar: "bar"}
65 result, err := Search("Foo", &s)
66 assert.Nil(err)
67 assert.Equal("one", result)
68 }
69
70 func TestCanSupportStructWithSliceAll(t *testing.T) {
71 assert := assert.New(t)
72 data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}}
73 result, err := Search("B[].Foo", data)
74 assert.Nil(err)
75 assert.Equal([]interface{}{"f1", "correct"}, result)
76 }
77
78 func TestCanSupportStructWithSlicingExpression(t *testing.T) {
79 assert := assert.New(t)
80 data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}}
81 result, err := Search("B[:].Foo", data)
82 assert.Nil(err)
83 assert.Equal([]interface{}{"f1", "correct"}, result)
84 }
85
86 func TestCanSupportStructWithFilterProjection(t *testing.T) {
87 assert := assert.New(t)
88 data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}}
89 result, err := Search("B[? `true` ].Foo", data)
90 assert.Nil(err)
91 assert.Equal([]interface{}{"f1", "correct"}, result)
92 }
93
94 func TestCanSupportStructWithSlice(t *testing.T) {
95 assert := assert.New(t)
96 data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}}
97 result, err := Search("B[-1].Foo", data)
98 assert.Nil(err)
99 assert.Equal("correct", result)
100 }
101
102 func TestCanSupportStructWithOrExpressions(t *testing.T) {
103 assert := assert.New(t)
104 data := sliceType{A: "foo", C: nil}
105 result, err := Search("C || A", data)
106 assert.Nil(err)
107 assert.Equal("foo", result)
108 }
109
110 func TestCanSupportStructWithSlicePointer(t *testing.T) {
111 assert := assert.New(t)
112 data := sliceType{A: "foo", C: []*scalars{{"f1", "b1"}, {"correct", "b2"}}}
113 result, err := Search("C[-1].Foo", data)
114 assert.Nil(err)
115 assert.Equal("correct", result)
116 }
117
118 func TestWillAutomaticallyCapitalizeFieldNames(t *testing.T) {
119 assert := assert.New(t)
120 s := scalars{Foo: "one", Bar: "bar"}
121
122
123
124 result, err := Search("foo", &s)
125 assert.Nil(err)
126 assert.Equal("one", result)
127 }
128
129 func TestCanSupportStructWithSliceLowerCased(t *testing.T) {
130 assert := assert.New(t)
131 data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}}
132 result, err := Search("b[-1].foo", data)
133 assert.Nil(err)
134 assert.Equal("correct", result)
135 }
136
137 func TestCanSupportStructWithNestedPointers(t *testing.T) {
138 assert := assert.New(t)
139 data := struct{ A *struct{ B int } }{}
140 result, err := Search("A.B", data)
141 assert.Nil(err)
142 assert.Nil(result)
143 }
144
145 func TestCanSupportFlattenNestedSlice(t *testing.T) {
146 assert := assert.New(t)
147 data := nestedSlice{A: []sliceType{
148 {B: []scalars{{Foo: "f1a"}, {Foo: "f1b"}}},
149 {B: []scalars{{Foo: "f2a"}, {Foo: "f2b"}}},
150 }}
151 result, err := Search("A[].B[].Foo", data)
152 assert.Nil(err)
153 assert.Equal([]interface{}{"f1a", "f1b", "f2a", "f2b"}, result)
154 }
155
156 func TestCanSupportFlattenNestedEmptySlice(t *testing.T) {
157 assert := assert.New(t)
158 data := nestedSlice{A: []sliceType{
159 {}, {B: []scalars{{Foo: "a"}}},
160 }}
161 result, err := Search("A[].B[].Foo", data)
162 assert.Nil(err)
163 assert.Equal([]interface{}{"a"}, result)
164 }
165
166 func TestCanSupportProjectionsWithStructs(t *testing.T) {
167 assert := assert.New(t)
168 data := nestedSlice{A: []sliceType{
169 {A: "first"}, {A: "second"}, {A: "third"},
170 }}
171 result, err := Search("A[*].A", data)
172 assert.Nil(err)
173 assert.Equal([]interface{}{"first", "second", "third"}, result)
174 }
175
176 func TestCanSupportSliceOfStructsWithFunctions(t *testing.T) {
177 assert := assert.New(t)
178 data := []scalars{scalars{"a1", "b1"}, scalars{"a2", "b2"}}
179 result, err := Search("length(@)", data)
180 assert.Nil(err)
181 assert.Equal(result.(float64), 2.0)
182 }
183
184 func BenchmarkInterpretSingleFieldStruct(b *testing.B) {
185 assert := assert.New(b)
186 intr := newInterpreter()
187 parser := NewParser()
188 ast, _ := parser.Parse("fooasdfasdfasdfasdf")
189 data := benchmarkStruct{"foobarbazqux"}
190 for i := 0; i < b.N; i++ {
191 _, err := intr.Execute(ast, data)
192 if err != nil {
193 assert.Fail("Received error from interpreter")
194 }
195 }
196 }
197
198 func BenchmarkInterpretNestedStruct(b *testing.B) {
199 assert := assert.New(b)
200 intr := newInterpreter()
201 parser := NewParser()
202 ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
203 data := benchmarkNested{
204 nestedA{
205 nestedB{
206 nestedC{"foobarbazqux"},
207 },
208 },
209 }
210 for i := 0; i < b.N; i++ {
211 _, err := intr.Execute(ast, data)
212 if err != nil {
213 assert.Fail("Received error from interpreter")
214 }
215 }
216 }
217
218 func BenchmarkInterpretNestedMaps(b *testing.B) {
219 assert := assert.New(b)
220 jsonData := []byte(`{"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": "foobarbazqux"}}}}`)
221 var data interface{}
222 err := json.Unmarshal(jsonData, &data)
223 assert.Nil(err)
224
225 intr := newInterpreter()
226 parser := NewParser()
227 ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
228 for i := 0; i < b.N; i++ {
229 _, err := intr.Execute(ast, data)
230 if err != nil {
231 assert.Fail("Received error from interpreter")
232 }
233 }
234 }
235
View as plain text