package query import ( "fmt" "github.com/pelletier/go-toml" "testing" ) // 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: result += fmt.Sprintf("{%d:%d:%d}", fn.Start, fn.End, fn.Step) 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(123, maxInt, 1), )) } func TestPathSliceStartEnd(t *testing.T) { assertPath(t, "$[123:456]", buildPath( newMatchSliceFn(123, 456, 1), )) } func TestPathSliceStartEndColon(t *testing.T) { assertPath(t, "$[123:456:]", buildPath( newMatchSliceFn(123, 456, 1), )) } func TestPathSliceStartStep(t *testing.T) { assertPath(t, "$[123::7]", buildPath( newMatchSliceFn(123, maxInt, 7), )) } func TestPathSliceEndStep(t *testing.T) { assertPath(t, "$[:456:7]", buildPath( newMatchSliceFn(0, 456, 7), )) } func TestPathSliceStep(t *testing.T) { assertPath(t, "$[::7]", buildPath( newMatchSliceFn(0, maxInt, 7), )) } func TestPathSliceAll(t *testing.T) { assertPath(t, "$[123:456:7]", buildPath( newMatchSliceFn(123, 456, 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{}), }}, )) }