package jpath import ( "fmt" "math" "testing" ) func pathString(path QueryPath) string { result := "[" for _, v := range path { result += fmt.Sprintf("%T:%v, ", v, v) } return result + "]" } func assertPathMatch(t *testing.T, path, ref QueryPath) bool { if len(path) != len(ref) { t.Errorf("lengths do not match: %v vs %v", pathString(path), pathString(ref)) return false } else { for i, v := range ref { pass := false node := path[i] // compare by value switch refNode := v.(type) { case *matchKeyFn: castNode, ok := node.(*matchKeyFn) pass = ok && (*refNode == *castNode) case *matchIndexFn: castNode, ok := node.(*matchIndexFn) pass = ok && (*refNode == *castNode) case *matchSliceFn: castNode, ok := node.(*matchSliceFn) pass = ok && (*refNode == *castNode) case *matchAnyFn: castNode, ok := node.(*matchAnyFn) pass = ok && (*refNode == *castNode) case *matchUnionFn: castNode, ok := node.(*matchUnionFn) // special case - comapre all contents pass = ok && assertPathMatch(t, castNode.Union, refNode.Union) case *matchRecursiveFn: castNode, ok := node.(*matchRecursiveFn) pass = ok && (*refNode == *castNode) } if !pass { t.Errorf("paths do not match at index %d: %v vs %v", i, pathString(path), pathString(ref)) return false } } } return true } func assertPath(t *testing.T, query string, ref QueryPath) { _, flow := lex(query) path := parse(flow) assertPathMatch(t, path, ref) } func TestPathRoot(t *testing.T) { assertPath(t, "$", QueryPath{ // empty }) } func TestPathKey(t *testing.T) { assertPath(t, "$.foo", QueryPath{ &matchKeyFn{ "foo" }, }) } func TestPathBracketKey(t *testing.T) { assertPath(t, "$[foo]", QueryPath{ &matchKeyFn{ "foo" }, }) } func TestPathBracketStringKey(t *testing.T) { assertPath(t, "$['foo']", QueryPath{ &matchKeyFn{ "foo" }, }) } func TestPathIndex(t *testing.T) { assertPath(t, "$[123]", QueryPath{ &matchIndexFn{ 123 }, }) } func TestPathSliceStart(t *testing.T) { assertPath(t, "$[123:]", QueryPath{ &matchSliceFn{ 123, math.MaxInt64, 1 }, }) } func TestPathSliceStartEnd(t *testing.T) { assertPath(t, "$[123:456]", QueryPath{ &matchSliceFn{ 123, 456, 1 }, }) } func TestPathSliceStartEndColon(t *testing.T) { assertPath(t, "$[123:456:]", QueryPath{ &matchSliceFn{ 123, 456, 1 }, }) } func TestPathSliceStartStep(t *testing.T) { assertPath(t, "$[123::7]", QueryPath{ &matchSliceFn{ 123, math.MaxInt64, 7 }, }) } func TestPathSliceEndStep(t *testing.T) { assertPath(t, "$[:456:7]", QueryPath{ &matchSliceFn{ 0, 456, 7 }, }) } func TestPathSliceStep(t *testing.T) { assertPath(t, "$[::7]", QueryPath{ &matchSliceFn{ 0, math.MaxInt64, 7 }, }) } func TestPathSliceAll(t *testing.T) { assertPath(t, "$[123:456:7]", QueryPath{ &matchSliceFn{ 123, 456, 7 }, }) } func TestPathAny(t *testing.T) { assertPath(t, "$.*", QueryPath{ &matchAnyFn{}, }) } func TestPathUnion(t *testing.T) { assertPath(t, "$[foo, bar, baz]", QueryPath{ &matchUnionFn{ []PathFn { &matchKeyFn{ "foo" }, &matchKeyFn{ "bar" }, &matchKeyFn{ "baz" }, }}, }) } func TestPathRecurse(t *testing.T) { assertPath(t, "$..*", QueryPath{ &matchRecursiveFn{}, }) }