Add expression errors test. Make parser stricter.

This commit is contained in:
Alex Roitman 2019-06-13 13:10:47 -07:00
parent 0c3a5d02ca
commit 2d83e18934
2 changed files with 52 additions and 9 deletions

View File

@ -712,7 +712,7 @@ func (ps *parentStack) pop() (e *areaExpression, empty bool) {
func (s *Server) parseAreaExpression(vsin []string, doClip bool) (vsout []string, ae *areaExpression, err error) {
ps := &parentStack{}
vsout = vsin[:]
var negate bool
var negate, needObj bool
loop:
for {
nvs, wtok, ok := tokenval(vsout)
@ -723,6 +723,7 @@ loop:
case tokenLParen:
newExpr := &areaExpression{negate: negate, op: NOOP}
negate = false
needObj = false
if ae != nil {
ae.children = append(ae.children, newExpr)
}
@ -730,8 +731,8 @@ loop:
ps.push(ae)
vsout = nvs
case tokenRParen:
if negate {
err = errInvalidArgument(tokenNOT)
if needObj {
err = errInvalidArgument(tokenRParen)
return
}
if parent, empty := ps.pop(); empty {
@ -743,12 +744,14 @@ loop:
vsout = nvs
case tokenNOT:
negate = true
needObj = true
vsout = nvs
case tokenAND:
if negate {
err = errInvalidArgument(tokenNOT)
if needObj {
err = errInvalidArgument(tokenAND)
return
}
needObj = true
if ae == nil {
err = errInvalidArgument(tokenAND)
return
@ -774,10 +777,11 @@ loop:
}
vsout = nvs
case tokenOR:
if negate {
err = errInvalidArgument(tokenNOT)
if needObj {
err = errInvalidArgument(tokenOR)
return
}
needObj = true
if ae == nil {
err = errInvalidArgument(tokenOR)
return
@ -804,6 +808,7 @@ loop:
} else {
newExpr := &areaExpression{negate: negate, obj: parsedObj, op: NOOP}
negate = false
needObj = false
if ae == nil {
ae = newExpr
} else {
@ -812,12 +817,15 @@ loop:
vsout = parsedVs
}
default:
if negate {
err = errInvalidArgument(tokenNOT)
if needObj {
err = errInvalidArgument(wtok)
return
}
break loop
}
}
if !ps.isEmpty() || needObj || ae == nil || (ae.obj == nil && len(ae.children) == 0) {
err = errInvalidNumberOfArguments
}
return
}

View File

@ -8,6 +8,7 @@ func subTestTestCmd(t *testing.T, mc *mockServer) {
runStep(t, mc, "WITHIN", testcmd_WITHIN_test)
runStep(t, mc, "INTERSECTS", testcmd_INTERSECTS_test)
runStep(t, mc, "INTERSECTS_CLIP", testcmd_INTERSECTS_CLIP_test)
runStep(t, mc, "ExpressionErrors", testcmd_expressionErrors_test)
runStep(t, mc, "Expressions", testcmd_expression_test)
}
@ -117,6 +118,40 @@ func testcmd_INTERSECTS_CLIP_test(mc *mockServer) error {
})
}
func testcmd_expressionErrors_test(mc *mockServer) error {
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "foo", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "bar", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "baz", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "(", "GET", "mykey", "bar"}, {
"ERR wrong number of arguments for 'test' command"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", ")"}, {
"ERR invalid argument ')'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "OR", "GET", "mykey", "bar"}, {
"ERR invalid argument 'or'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "AND", "GET", "mykey", "bar"}, {
"ERR invalid argument 'and'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "OR", "AND", "GET", "mykey", "baz"}, {
"ERR invalid argument 'and'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "AND", "OR", "GET", "mykey", "baz"}, {
"ERR invalid argument 'or'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "OR", "OR", "GET", "mykey", "baz"}, {
"ERR invalid argument 'or'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "AND", "AND", "GET", "mykey", "baz"}, {
"ERR invalid argument 'and'"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "OR"}, {
"ERR wrong number of arguments for 'test' command"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "AND"}, {
"ERR wrong number of arguments for 'test' command"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "NOT"}, {
"ERR wrong number of arguments for 'test' command"},
{"TEST", "GET", "mykey", "foo", "INTERSECTS", "GET", "mykey", "bar", "NOT", "AND", "GET", "mykey", "baz"}, {
"ERR invalid argument 'and'"},
})
}
func testcmd_expression_test(mc *mockServer) error {
poly := `{
"type": "Polygon",