interpreter_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package jmespath
  2. import (
  3. "encoding/json"
  4. "testing"
  5. "github.com/stretchr/testify/assert"
  6. )
  7. type scalars struct {
  8. Foo string
  9. Bar string
  10. }
  11. type sliceType struct {
  12. A string
  13. B []scalars
  14. C []*scalars
  15. }
  16. type benchmarkStruct struct {
  17. Fooasdfasdfasdfasdf string
  18. }
  19. type benchmarkNested struct {
  20. Fooasdfasdfasdfasdf nestedA
  21. }
  22. type nestedA struct {
  23. Fooasdfasdfasdfasdf nestedB
  24. }
  25. type nestedB struct {
  26. Fooasdfasdfasdfasdf nestedC
  27. }
  28. type nestedC struct {
  29. Fooasdfasdfasdfasdf string
  30. }
  31. type nestedSlice struct {
  32. A []sliceType
  33. }
  34. func TestCanSupportEmptyInterface(t *testing.T) {
  35. assert := assert.New(t)
  36. data := make(map[string]interface{})
  37. data["foo"] = "bar"
  38. result, err := Search("foo", data)
  39. assert.Nil(err)
  40. assert.Equal("bar", result)
  41. }
  42. func TestCanSupportUserDefinedStructsValue(t *testing.T) {
  43. assert := assert.New(t)
  44. s := scalars{Foo: "one", Bar: "bar"}
  45. result, err := Search("Foo", s)
  46. assert.Nil(err)
  47. assert.Equal("one", result)
  48. }
  49. func TestCanSupportUserDefinedStructsRef(t *testing.T) {
  50. assert := assert.New(t)
  51. s := scalars{Foo: "one", Bar: "bar"}
  52. result, err := Search("Foo", &s)
  53. assert.Nil(err)
  54. assert.Equal("one", result)
  55. }
  56. func TestCanSupportStructWithSliceAll(t *testing.T) {
  57. assert := assert.New(t)
  58. data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
  59. result, err := Search("B[].Foo", data)
  60. assert.Nil(err)
  61. assert.Equal([]interface{}{"f1", "correct"}, result)
  62. }
  63. func TestCanSupportStructWithSlicingExpression(t *testing.T) {
  64. assert := assert.New(t)
  65. data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
  66. result, err := Search("B[:].Foo", data)
  67. assert.Nil(err)
  68. assert.Equal([]interface{}{"f1", "correct"}, result)
  69. }
  70. func TestCanSupportStructWithFilterProjection(t *testing.T) {
  71. assert := assert.New(t)
  72. data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
  73. result, err := Search("B[? `true` ].Foo", data)
  74. assert.Nil(err)
  75. assert.Equal([]interface{}{"f1", "correct"}, result)
  76. }
  77. func TestCanSupportStructWithSlice(t *testing.T) {
  78. assert := assert.New(t)
  79. data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
  80. result, err := Search("B[-1].Foo", data)
  81. assert.Nil(err)
  82. assert.Equal("correct", result)
  83. }
  84. func TestCanSupportStructWithOrExpressions(t *testing.T) {
  85. assert := assert.New(t)
  86. data := sliceType{A: "foo", C: nil}
  87. result, err := Search("C || A", data)
  88. assert.Nil(err)
  89. assert.Equal("foo", result)
  90. }
  91. func TestCanSupportStructWithSlicePointer(t *testing.T) {
  92. assert := assert.New(t)
  93. data := sliceType{A: "foo", C: []*scalars{&scalars{"f1", "b1"}, &scalars{"correct", "b2"}}}
  94. result, err := Search("C[-1].Foo", data)
  95. assert.Nil(err)
  96. assert.Equal("correct", result)
  97. }
  98. func TestWillAutomaticallyCapitalizeFieldNames(t *testing.T) {
  99. assert := assert.New(t)
  100. s := scalars{Foo: "one", Bar: "bar"}
  101. // Note that there's a lower cased "foo" instead of "Foo",
  102. // but it should still correspond to the Foo field in the
  103. // scalars struct
  104. result, err := Search("foo", &s)
  105. assert.Nil(err)
  106. assert.Equal("one", result)
  107. }
  108. func TestCanSupportStructWithSliceLowerCased(t *testing.T) {
  109. assert := assert.New(t)
  110. data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
  111. result, err := Search("b[-1].foo", data)
  112. assert.Nil(err)
  113. assert.Equal("correct", result)
  114. }
  115. func TestCanSupportStructWithNestedPointers(t *testing.T) {
  116. assert := assert.New(t)
  117. data := struct{ A *struct{ B int } }{}
  118. result, err := Search("A.B", data)
  119. assert.Nil(err)
  120. assert.Nil(result)
  121. }
  122. func TestCanSupportFlattenNestedSlice(t *testing.T) {
  123. assert := assert.New(t)
  124. data := nestedSlice{A: []sliceType{
  125. {B: []scalars{{Foo: "f1a"}, {Foo: "f1b"}}},
  126. {B: []scalars{{Foo: "f2a"}, {Foo: "f2b"}}},
  127. }}
  128. result, err := Search("A[].B[].Foo", data)
  129. assert.Nil(err)
  130. assert.Equal([]interface{}{"f1a", "f1b", "f2a", "f2b"}, result)
  131. }
  132. func TestCanSupportFlattenNestedEmptySlice(t *testing.T) {
  133. assert := assert.New(t)
  134. data := nestedSlice{A: []sliceType{
  135. {}, {B: []scalars{{Foo: "a"}}},
  136. }}
  137. result, err := Search("A[].B[].Foo", data)
  138. assert.Nil(err)
  139. assert.Equal([]interface{}{"a"}, result)
  140. }
  141. func TestCanSupportProjectionsWithStructs(t *testing.T) {
  142. assert := assert.New(t)
  143. data := nestedSlice{A: []sliceType{
  144. {A: "first"}, {A: "second"}, {A: "third"},
  145. }}
  146. result, err := Search("A[*].A", data)
  147. assert.Nil(err)
  148. assert.Equal([]interface{}{"first", "second", "third"}, result)
  149. }
  150. func BenchmarkInterpretSingleFieldStruct(b *testing.B) {
  151. intr := newInterpreter()
  152. parser := NewParser()
  153. ast, _ := parser.Parse("fooasdfasdfasdfasdf")
  154. data := benchmarkStruct{"foobarbazqux"}
  155. for i := 0; i < b.N; i++ {
  156. intr.Execute(ast, &data)
  157. }
  158. }
  159. func BenchmarkInterpretNestedStruct(b *testing.B) {
  160. intr := newInterpreter()
  161. parser := NewParser()
  162. ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
  163. data := benchmarkNested{
  164. nestedA{
  165. nestedB{
  166. nestedC{"foobarbazqux"},
  167. },
  168. },
  169. }
  170. for i := 0; i < b.N; i++ {
  171. intr.Execute(ast, &data)
  172. }
  173. }
  174. func BenchmarkInterpretNestedMaps(b *testing.B) {
  175. jsonData := []byte(`{"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": "foobarbazqux"}}}}`)
  176. var data interface{}
  177. json.Unmarshal(jsonData, &data)
  178. intr := newInterpreter()
  179. parser := NewParser()
  180. ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
  181. for i := 0; i < b.N; i++ {
  182. intr.Execute(ast, data)
  183. }
  184. }