rclone/vendor/github.com/jmespath/go-jmespath/interpreter_test.go

213 lines
5.4 KiB
Go

package jmespath
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
type scalars struct {
Foo string
Bar string
}
type sliceType struct {
A string
B []scalars
C []*scalars
}
type benchmarkStruct struct {
Fooasdfasdfasdfasdf string
}
type benchmarkNested struct {
Fooasdfasdfasdfasdf nestedA
}
type nestedA struct {
Fooasdfasdfasdfasdf nestedB
}
type nestedB struct {
Fooasdfasdfasdfasdf nestedC
}
type nestedC struct {
Fooasdfasdfasdfasdf string
}
type nestedSlice struct {
A []sliceType
}
func TestCanSupportEmptyInterface(t *testing.T) {
assert := assert.New(t)
data := make(map[string]interface{})
data["foo"] = "bar"
result, err := Search("foo", data)
assert.Nil(err)
assert.Equal("bar", result)
}
func TestCanSupportUserDefinedStructsValue(t *testing.T) {
assert := assert.New(t)
s := scalars{Foo: "one", Bar: "bar"}
result, err := Search("Foo", s)
assert.Nil(err)
assert.Equal("one", result)
}
func TestCanSupportUserDefinedStructsRef(t *testing.T) {
assert := assert.New(t)
s := scalars{Foo: "one", Bar: "bar"}
result, err := Search("Foo", &s)
assert.Nil(err)
assert.Equal("one", result)
}
func TestCanSupportStructWithSliceAll(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
result, err := Search("B[].Foo", data)
assert.Nil(err)
assert.Equal([]interface{}{"f1", "correct"}, result)
}
func TestCanSupportStructWithSlicingExpression(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
result, err := Search("B[:].Foo", data)
assert.Nil(err)
assert.Equal([]interface{}{"f1", "correct"}, result)
}
func TestCanSupportStructWithFilterProjection(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
result, err := Search("B[? `true` ].Foo", data)
assert.Nil(err)
assert.Equal([]interface{}{"f1", "correct"}, result)
}
func TestCanSupportStructWithSlice(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
result, err := Search("B[-1].Foo", data)
assert.Nil(err)
assert.Equal("correct", result)
}
func TestCanSupportStructWithOrExpressions(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", C: nil}
result, err := Search("C || A", data)
assert.Nil(err)
assert.Equal("foo", result)
}
func TestCanSupportStructWithSlicePointer(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", C: []*scalars{&scalars{"f1", "b1"}, &scalars{"correct", "b2"}}}
result, err := Search("C[-1].Foo", data)
assert.Nil(err)
assert.Equal("correct", result)
}
func TestWillAutomaticallyCapitalizeFieldNames(t *testing.T) {
assert := assert.New(t)
s := scalars{Foo: "one", Bar: "bar"}
// Note that there's a lower cased "foo" instead of "Foo",
// but it should still correspond to the Foo field in the
// scalars struct
result, err := Search("foo", &s)
assert.Nil(err)
assert.Equal("one", result)
}
func TestCanSupportStructWithSliceLowerCased(t *testing.T) {
assert := assert.New(t)
data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}}
result, err := Search("b[-1].foo", data)
assert.Nil(err)
assert.Equal("correct", result)
}
func TestCanSupportStructWithNestedPointers(t *testing.T) {
assert := assert.New(t)
data := struct{ A *struct{ B int } }{}
result, err := Search("A.B", data)
assert.Nil(err)
assert.Nil(result)
}
func TestCanSupportFlattenNestedSlice(t *testing.T) {
assert := assert.New(t)
data := nestedSlice{A: []sliceType{
{B: []scalars{{Foo: "f1a"}, {Foo: "f1b"}}},
{B: []scalars{{Foo: "f2a"}, {Foo: "f2b"}}},
}}
result, err := Search("A[].B[].Foo", data)
assert.Nil(err)
assert.Equal([]interface{}{"f1a", "f1b", "f2a", "f2b"}, result)
}
func TestCanSupportFlattenNestedEmptySlice(t *testing.T) {
assert := assert.New(t)
data := nestedSlice{A: []sliceType{
{}, {B: []scalars{{Foo: "a"}}},
}}
result, err := Search("A[].B[].Foo", data)
assert.Nil(err)
assert.Equal([]interface{}{"a"}, result)
}
func TestCanSupportProjectionsWithStructs(t *testing.T) {
assert := assert.New(t)
data := nestedSlice{A: []sliceType{
{A: "first"}, {A: "second"}, {A: "third"},
}}
result, err := Search("A[*].A", data)
assert.Nil(err)
assert.Equal([]interface{}{"first", "second", "third"}, result)
}
func BenchmarkInterpretSingleFieldStruct(b *testing.B) {
intr := newInterpreter()
parser := NewParser()
ast, _ := parser.Parse("fooasdfasdfasdfasdf")
data := benchmarkStruct{"foobarbazqux"}
for i := 0; i < b.N; i++ {
intr.Execute(ast, &data)
}
}
func BenchmarkInterpretNestedStruct(b *testing.B) {
intr := newInterpreter()
parser := NewParser()
ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
data := benchmarkNested{
nestedA{
nestedB{
nestedC{"foobarbazqux"},
},
},
}
for i := 0; i < b.N; i++ {
intr.Execute(ast, &data)
}
}
func BenchmarkInterpretNestedMaps(b *testing.B) {
jsonData := []byte(`{"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": "foobarbazqux"}}}}`)
var data interface{}
json.Unmarshal(jsonData, &data)
intr := newInterpreter()
parser := NewParser()
ast, _ := parser.Parse("fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf.fooasdfasdfasdfasdf")
for i := 0; i < b.N; i++ {
intr.Execute(ast, data)
}
}