a60e466129
* Fix index and slice expressions for query Support negative step for slice expressions
214 lines
3.8 KiB
Go
214 lines
3.8 KiB
Go
package query
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/pelletier/go-toml"
|
|
)
|
|
|
|
// dump path tree to a string
|
|
func pathString(root pathFn) string {
|
|
result := fmt.Sprintf("%T:", root)
|
|
switch fn := root.(type) {
|
|
case *terminatingFn:
|
|
result += "{}"
|
|
case *matchKeyFn:
|
|
result += fmt.Sprintf("{%s}", fn.Name)
|
|
result += pathString(fn.next)
|
|
case *matchIndexFn:
|
|
result += fmt.Sprintf("{%d}", fn.Idx)
|
|
result += pathString(fn.next)
|
|
case *matchSliceFn:
|
|
startString, endString, stepString := "nil", "nil", "nil"
|
|
if fn.Start != nil {
|
|
startString = strconv.Itoa(*fn.Start)
|
|
}
|
|
if fn.End != nil {
|
|
endString = strconv.Itoa(*fn.End)
|
|
}
|
|
if fn.Step != nil {
|
|
stepString = strconv.Itoa(*fn.Step)
|
|
}
|
|
result += fmt.Sprintf("{%s:%s:%s}", startString, endString, stepString)
|
|
result += pathString(fn.next)
|
|
case *matchAnyFn:
|
|
result += "{}"
|
|
result += pathString(fn.next)
|
|
case *matchUnionFn:
|
|
result += "{["
|
|
for _, v := range fn.Union {
|
|
result += pathString(v) + ", "
|
|
}
|
|
result += "]}"
|
|
case *matchRecursiveFn:
|
|
result += "{}"
|
|
result += pathString(fn.next)
|
|
case *matchFilterFn:
|
|
result += fmt.Sprintf("{%s}", fn.Name)
|
|
result += pathString(fn.next)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func assertPathMatch(t *testing.T, path, ref *Query) bool {
|
|
pathStr := pathString(path.root)
|
|
refStr := pathString(ref.root)
|
|
if pathStr != refStr {
|
|
t.Errorf("paths do not match")
|
|
t.Log("test:", pathStr)
|
|
t.Log("ref: ", refStr)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func assertPath(t *testing.T, query string, ref *Query) {
|
|
path, _ := parseQuery(lexQuery(query))
|
|
assertPathMatch(t, path, ref)
|
|
}
|
|
|
|
func buildPath(parts ...pathFn) *Query {
|
|
query := newQuery()
|
|
for _, v := range parts {
|
|
query.appendPath(v)
|
|
}
|
|
return query
|
|
}
|
|
|
|
func TestPathRoot(t *testing.T) {
|
|
assertPath(t,
|
|
"$",
|
|
buildPath(
|
|
// empty
|
|
))
|
|
}
|
|
|
|
func TestPathKey(t *testing.T) {
|
|
assertPath(t,
|
|
"$.foo",
|
|
buildPath(
|
|
newMatchKeyFn("foo"),
|
|
))
|
|
}
|
|
|
|
func TestPathBracketKey(t *testing.T) {
|
|
assertPath(t,
|
|
"$[foo]",
|
|
buildPath(
|
|
newMatchKeyFn("foo"),
|
|
))
|
|
}
|
|
|
|
func TestPathBracketStringKey(t *testing.T) {
|
|
assertPath(t,
|
|
"$['foo']",
|
|
buildPath(
|
|
newMatchKeyFn("foo"),
|
|
))
|
|
}
|
|
|
|
func TestPathIndex(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123]",
|
|
buildPath(
|
|
newMatchIndexFn(123),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceStart(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123:]",
|
|
buildPath(
|
|
newMatchSliceFn().setStart(123),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceStartEnd(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123:456]",
|
|
buildPath(
|
|
newMatchSliceFn().setStart(123).setEnd(456),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceStartEndColon(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123:456:]",
|
|
buildPath(
|
|
newMatchSliceFn().setStart(123).setEnd(456),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceStartStep(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123::7]",
|
|
buildPath(
|
|
newMatchSliceFn().setStart(123).setStep(7),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceEndStep(t *testing.T) {
|
|
assertPath(t,
|
|
"$[:456:7]",
|
|
buildPath(
|
|
newMatchSliceFn().setEnd(456).setStep(7),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceStep(t *testing.T) {
|
|
assertPath(t,
|
|
"$[::7]",
|
|
buildPath(
|
|
newMatchSliceFn().setStep(7),
|
|
))
|
|
}
|
|
|
|
func TestPathSliceAll(t *testing.T) {
|
|
assertPath(t,
|
|
"$[123:456:7]",
|
|
buildPath(
|
|
newMatchSliceFn().setStart(123).setEnd(456).setStep(7),
|
|
))
|
|
}
|
|
|
|
func TestPathAny(t *testing.T) {
|
|
assertPath(t,
|
|
"$.*",
|
|
buildPath(
|
|
newMatchAnyFn(),
|
|
))
|
|
}
|
|
|
|
func TestPathUnion(t *testing.T) {
|
|
assertPath(t,
|
|
"$[foo, bar, baz]",
|
|
buildPath(
|
|
&matchUnionFn{[]pathFn{
|
|
newMatchKeyFn("foo"),
|
|
newMatchKeyFn("bar"),
|
|
newMatchKeyFn("baz"),
|
|
}},
|
|
))
|
|
}
|
|
|
|
func TestPathRecurse(t *testing.T) {
|
|
assertPath(t,
|
|
"$..*",
|
|
buildPath(
|
|
newMatchRecursiveFn(),
|
|
))
|
|
}
|
|
|
|
func TestPathFilterExpr(t *testing.T) {
|
|
assertPath(t,
|
|
"$[?('foo'),?(bar)]",
|
|
buildPath(
|
|
&matchUnionFn{[]pathFn{
|
|
newMatchFilterFn("foo", toml.Position{}),
|
|
newMatchFilterFn("bar", toml.Position{}),
|
|
}},
|
|
))
|
|
}
|