Merge pull request #409 from rshura/test_cmd

Test command
This commit is contained in:
Josh Baker 2019-02-12 05:05:50 -07:00 committed by GitHub
commit 6fffa75b58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 930 additions and 7 deletions

View File

@ -1785,5 +1785,256 @@
"complexity": "O(1)",
"since": "1.10.0",
"group": "scripting"
},
"TEST":{
"summary": "Performs spatial test",
"complexity": "One test per command, complexity depends on the test",
"arguments": [
{
"name": "area1",
"enumargs": [
{
"name": "POINT",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
}
]
},
{
"name": "GET",
"arguments": [
{
"name": "key",
"type": "string"
},
{
"name": "id",
"type": "string"
}
]
},
{
"name": "BOUNDS",
"arguments":[
{
"name": "minlat",
"type": "double"
},
{
"name": "minlon",
"type": "double"
},
{
"name": "maxlat",
"type": "double"
},
{
"name": "maxlon",
"type": "double"
}
]
},
{
"name": "OBJECT",
"arguments":[
{
"name": "geojson",
"type": "geojson"
}
]
},
{
"name": "CIRCLE",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "meters",
"type": "double"
}
]
},
{
"name": "TILE",
"arguments":[
{
"name": "x",
"type": "double"
},
{
"name": "y",
"type": "double"
},
{
"name": "z",
"type": "double"
}
]
},
{
"name": "QUADKEY",
"arguments":[
{
"name": "quadkey",
"type": "string"
}
]
},
{
"name": "HASH",
"arguments": [
{
"name": "geohash",
"type": "geohash"
}
]
}
]
},
{
"name": "test",
"enumargs": [
{
"name": "INTERSECTS"
},
{
"name": "WITHIN"
}
]
},
{
"command": "CLIP",
"name": [],
"type": [],
"optional": true
},
{
"name": "area2",
"enumargs": [
{
"name": "POINT",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
}
]
},
{
"name": "GET",
"arguments": [
{
"name": "key",
"type": "string"
},
{
"name": "id",
"type": "string"
}
]
},
{
"name": "BOUNDS",
"arguments":[
{
"name": "minlat",
"type": "double"
},
{
"name": "minlon",
"type": "double"
},
{
"name": "maxlat",
"type": "double"
},
{
"name": "maxlon",
"type": "double"
}
]
},
{
"name": "OBJECT",
"arguments":[
{
"name": "geojson",
"type": "geojson"
}
]
},
{
"name": "CIRCLE",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "meters",
"type": "double"
}
]
},
{
"name": "TILE",
"arguments":[
{
"name": "x",
"type": "double"
},
{
"name": "y",
"type": "double"
},
{
"name": "z",
"type": "double"
}
]
},
{
"name": "QUADKEY",
"arguments":[
{
"name": "quadkey",
"type": "string"
}
]
},
{
"name": "HASH",
"arguments": [
{
"name": "geohash",
"type": "geohash"
}
]
}
]
}
],
"since": "1.16.0",
"group": "tests"
}
}

View File

@ -1951,5 +1951,256 @@ var commandsJSON = `{
"complexity": "O(1)",
"since": "1.10.0",
"group": "scripting"
},
"TEST":{
"summary": "Performs spatial test",
"complexity": "One test per command, complexity depends on the test",
"arguments": [
{
"name": "area1",
"enumargs": [
{
"name": "POINT",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
}
]
},
{
"name": "GET",
"arguments": [
{
"name": "key",
"type": "string"
},
{
"name": "id",
"type": "string"
}
]
},
{
"name": "BOUNDS",
"arguments":[
{
"name": "minlat",
"type": "double"
},
{
"name": "minlon",
"type": "double"
},
{
"name": "maxlat",
"type": "double"
},
{
"name": "maxlon",
"type": "double"
}
]
},
{
"name": "OBJECT",
"arguments":[
{
"name": "geojson",
"type": "geojson"
}
]
},
{
"name": "CIRCLE",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "meters",
"type": "double"
}
]
},
{
"name": "TILE",
"arguments":[
{
"name": "x",
"type": "double"
},
{
"name": "y",
"type": "double"
},
{
"name": "z",
"type": "double"
}
]
},
{
"name": "QUADKEY",
"arguments":[
{
"name": "quadkey",
"type": "string"
}
]
},
{
"name": "HASH",
"arguments": [
{
"name": "geohash",
"type": "geohash"
}
]
}
]
},
{
"name": "test",
"enumargs": [
{
"name": "INTERSECTS"
},
{
"name": "WITHIN"
}
]
},
{
"command": "CLIP",
"name": [],
"type": [],
"optional": true
},
{
"name": "area2",
"enumargs": [
{
"name": "POINT",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
}
]
},
{
"name": "GET",
"arguments": [
{
"name": "key",
"type": "string"
},
{
"name": "id",
"type": "string"
}
]
},
{
"name": "BOUNDS",
"arguments":[
{
"name": "minlat",
"type": "double"
},
{
"name": "minlon",
"type": "double"
},
{
"name": "maxlat",
"type": "double"
},
{
"name": "maxlon",
"type": "double"
}
]
},
{
"name": "OBJECT",
"arguments":[
{
"name": "geojson",
"type": "geojson"
}
]
},
{
"name": "CIRCLE",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "meters",
"type": "double"
}
]
},
{
"name": "TILE",
"arguments":[
{
"name": "x",
"type": "double"
},
{
"name": "y",
"type": "double"
},
{
"name": "z",
"type": "double"
}
]
},
{
"name": "QUADKEY",
"arguments":[
{
"name": "quadkey",
"type": "string"
}
]
},
{
"name": "HASH",
"arguments": [
{
"name": "geohash",
"type": "geohash"
}
]
}
]
}
],
"since": "1.16.0",
"group": "tests"
}
}`

View File

@ -35,5 +35,5 @@ func clipPolygon(
if newPoly.Empty() {
return geojson.NewMultiPolygon(nil)
}
return polygon
return newPoly
}

View File

@ -620,6 +620,8 @@ func (c *Server) commandInScript(msg *Message) (
res, err = c.cmdType(msg)
case "keys":
res, err = c.cmdKeys(msg)
case "test":
res, err = c.cmdTest(msg)
}
return
}
@ -668,7 +670,7 @@ func (c *Server) luaTile38AtomicRW(msg *Message) (resp.Value, error) {
return resp.NullValue(), errReadOnly
}
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
"ttl", "bounds", "server", "info", "type", "jget":
"ttl", "bounds", "server", "info", "type", "jget", "test":
// read operations
if c.config.followHost() != "" && !c.fcuponce {
return resp.NullValue(), errCatchingUp
@ -700,7 +702,7 @@ func (c *Server) luaTile38AtomicRO(msg *Message) (resp.Value, error) {
return resp.NullValue(), errReadOnly
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
"ttl", "bounds", "server", "info", "type", "jget":
"ttl", "bounds", "server", "info", "type", "jget", "test":
// read operations
if c.config.followHost() != "" && !c.fcuponce {
return resp.NullValue(), errCatchingUp
@ -735,7 +737,7 @@ func (c *Server) luaTile38NonAtomic(msg *Message) (resp.Value, error) {
return resp.NullValue(), errReadOnly
}
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
"ttl", "bounds", "server", "info", "type", "jget":
"ttl", "bounds", "server", "info", "type", "jget", "test":
// read operations
c.mu.RLock()
defer c.mu.RUnlock()

View File

@ -106,7 +106,7 @@ func (server *Server) cmdSearchArgs(
fallthrough
case "circle":
if s.clip {
err = errInvalidArgument("cannnot clip with " + ltyp)
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var slat, slon, smeters string
@ -158,7 +158,7 @@ func (server *Server) cmdSearchArgs(
s.obj = geojson.NewCircle(geometry.Point{X: lon, Y: lat}, meters, defaultCircleSteps)
case "object":
if s.clip {
err = errInvalidArgument("cannnot clip with object")
err = errInvalidArgument("cannot clip with object")
return
}
var obj string
@ -272,7 +272,7 @@ func (server *Server) cmdSearchArgs(
})
case "get":
if s.clip {
err = errInvalidArgument("cannnot clip with get")
err = errInvalidArgument("cannot clip with get")
}
var key, id string
if vs, key, ok = tokenval(vs); !ok || key == "" {

View File

@ -1203,6 +1203,8 @@ func (server *Server) command(msg *Message, client *Client) (
res, err = server.cmdPsubscribe(msg)
case "publish":
res, err = server.cmdPublish(msg)
case "test":
res, err = server.cmdTest(msg)
}
return
}

300
internal/server/test.go Normal file
View File

@ -0,0 +1,300 @@
// TEST command: spatial tests without walking the tree.
package server
import (
"bytes"
"fmt"
"strconv"
"strings"
"time"
"github.com/mmcloughlin/geohash"
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
"github.com/tidwall/resp"
"github.com/tidwall/tile38/internal/bing"
"github.com/tidwall/tile38/internal/clip"
)
func (s * Server) parseArea(ovs[]string, doClip bool) (vs []string, o geojson.Object, err error) {
var ok bool
var typ string
vs = ovs[:]
if vs, typ, ok = tokenval(vs); !ok || typ == "" {
err = errInvalidNumberOfArguments
return
}
ltyp := strings.ToLower(typ)
switch ltyp {
case "point":
var slat, slon string
if vs, slat, ok = tokenval(vs); !ok || slat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, slon, ok = tokenval(vs); !ok || slon == "" {
err = errInvalidNumberOfArguments
return
}
var lat, lon float64
if lat, err = strconv.ParseFloat(slat, 64); err != nil {
err = errInvalidArgument(slat)
return
}
if lon, err = strconv.ParseFloat(slon, 64); err != nil {
err = errInvalidArgument(slon)
return
}
o = geojson.NewPoint(geometry.Point{X: lon, Y: lat})
case "circle":
if doClip {
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var slat, slon, smeters string
if vs, slat, ok = tokenval(vs); !ok || slat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, slon, ok = tokenval(vs); !ok || slon == "" {
err = errInvalidNumberOfArguments
return
}
var lat, lon, meters float64
if lat, err = strconv.ParseFloat(slat, 64); err != nil {
err = errInvalidArgument(slat)
return
}
if lon, err = strconv.ParseFloat(slon, 64); err != nil {
err = errInvalidArgument(slon)
return
}
if vs, smeters, ok = tokenval(vs); !ok || smeters == "" {
err = errInvalidNumberOfArguments
return
}
if meters, err = strconv.ParseFloat(smeters, 64); err != nil {
err = errInvalidArgument(smeters)
return
}
if meters < 0 {
err = errInvalidArgument(smeters)
return
}
o = geojson.NewCircle(geometry.Point{X: lon, Y: lat}, meters, defaultCircleSteps)
case "object":
if doClip {
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var obj string
if vs, obj, ok = tokenval(vs); !ok || obj == "" {
err = errInvalidNumberOfArguments
return
}
o, err = geojson.Parse(obj, &s.geomParseOpts)
if err != nil {
return
}
case "bounds":
var sminLat, sminLon, smaxlat, smaxlon string
if vs, sminLat, ok = tokenval(vs); !ok || sminLat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sminLon, ok = tokenval(vs); !ok || sminLon == "" {
err = errInvalidNumberOfArguments
return
}
if vs, smaxlat, ok = tokenval(vs); !ok || smaxlat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, smaxlon, ok = tokenval(vs); !ok || smaxlon == "" {
err = errInvalidNumberOfArguments
return
}
var minLat, minLon, maxLat, maxLon float64
if minLat, err = strconv.ParseFloat(sminLat, 64); err != nil {
err = errInvalidArgument(sminLat)
return
}
if minLon, err = strconv.ParseFloat(sminLon, 64); err != nil {
err = errInvalidArgument(sminLon)
return
}
if maxLat, err = strconv.ParseFloat(smaxlat, 64); err != nil {
err = errInvalidArgument(smaxlat)
return
}
if maxLon, err = strconv.ParseFloat(smaxlon, 64); err != nil {
err = errInvalidArgument(smaxlon)
return
}
o = geojson.NewRect(geometry.Rect{
Min: geometry.Point{X: minLon, Y: minLat},
Max: geometry.Point{X: maxLon, Y: maxLat},
})
case "hash":
var hash string
if vs, hash, ok = tokenval(vs); !ok || hash == "" {
err = errInvalidNumberOfArguments
return
}
box := geohash.BoundingBox(hash)
o = geojson.NewRect(geometry.Rect{
Min: geometry.Point{X: box.MinLng, Y: box.MinLat},
Max: geometry.Point{X: box.MaxLng, Y: box.MaxLat},
})
case "quadkey":
var key string
if vs, key, ok = tokenval(vs); !ok || key == "" {
err = errInvalidNumberOfArguments
return
}
var minLat, minLon, maxLat, maxLon float64
minLat, minLon, maxLat, maxLon, err = bing.QuadKeyToBounds(key)
if err != nil {
err = errInvalidArgument(key)
return
}
o = geojson.NewRect(geometry.Rect{
Min: geometry.Point{X: minLon, Y: minLat},
Max: geometry.Point{X: maxLon, Y: maxLat},
})
case "tile":
var sx, sy, sz string
if vs, sx, ok = tokenval(vs); !ok || sx == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sy, ok = tokenval(vs); !ok || sy == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sz, ok = tokenval(vs); !ok || sz == "" {
err = errInvalidNumberOfArguments
return
}
var x, y int64
var z uint64
if x, err = strconv.ParseInt(sx, 10, 64); err != nil {
err = errInvalidArgument(sx)
return
}
if y, err = strconv.ParseInt(sy, 10, 64); err != nil {
err = errInvalidArgument(sy)
return
}
if z, err = strconv.ParseUint(sz, 10, 64); err != nil {
err = errInvalidArgument(sz)
return
}
var minLat, minLon, maxLat, maxLon float64
minLat, minLon, maxLat, maxLon = bing.TileXYToBounds(x, y, z)
o = geojson.NewRect(geometry.Rect{
Min: geometry.Point{X: minLon, Y: minLat},
Max: geometry.Point{X: maxLon, Y: maxLat},
})
case "get":
if doClip {
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var key, id string
if vs, key, ok = tokenval(vs); !ok || key == "" {
err = errInvalidNumberOfArguments
return
}
if vs, id, ok = tokenval(vs); !ok || id == "" {
err = errInvalidNumberOfArguments
return
}
col := s.getCol(key)
if col == nil {
err = errKeyNotFound
return
}
o, _, ok = col.Get(id)
if !ok {
err = errIDNotFound
return
}
}
return
}
func (s *Server) cmdTest (msg *Message) (res resp.Value, err error) {
start := time.Now()
vs := msg.Args[1:]
var ok bool
var test string
var obj1, obj2, clipped geojson.Object
if vs, obj1, err = s.parseArea(vs, false); err != nil {
return
}
if vs, test, ok = tokenval(vs); !ok || test == "" {
err = errInvalidNumberOfArguments
return
}
lTest := strings.ToLower(test)
if lTest != "within" && lTest != "intersects" {
err = errInvalidArgument(test)
return
}
var wtok string
var nvs []string
var doClip bool
nvs, wtok, ok = tokenval(vs)
if ok && len(wtok) > 0 {
switch strings.ToLower(wtok) {
case "clip":
vs = nvs
if lTest != "intersects" {
err = errInvalidArgument("cannot clip with" + wtok)
return
}
doClip = true
}
}
if vs, obj2, err = s.parseArea(vs, doClip); err != nil {
return
}
if len(vs) != 0 {
err = errInvalidNumberOfArguments
}
var result int
if lTest == "within" {
if obj1.Within(obj2) {
result = 1
}
} else if lTest == "intersects" {
if obj1.Intersects(obj2) {
result = 1
if doClip {
clipped = clip.Clip(obj1, obj2)
}
}
}
switch msg.OutputType {
case JSON:
var buf bytes.Buffer
buf.WriteString(`{"ok":true`)
buf.WriteString(fmt.Sprintf(`,"result":%d`, result))
if clipped != nil {
buf.WriteString(`,"object":` + clipped.JSON())
}
buf.WriteString(`,"elapsed":"` + time.Now().Sub(start).String() + "\"}")
return resp.StringValue(buf.String()), nil
case RESP:
if clipped != nil {
return resp.ArrayValue([]resp.Value{
resp.IntegerValue(result),
resp.StringValue(clipped.JSON())}), nil
}
return resp.IntegerValue(result), nil
}
return NOMessage, nil
}

116
tests/testcmd_test.go Normal file
View File

@ -0,0 +1,116 @@
package tests
import (
"testing"
)
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)
}
func testcmd_WITHIN_test(mc *mockServer) error {
poly := `{
"type": "Polygon",
"coordinates": [
[
[-122.44126439094543,37.72906137107],
[-122.43980526924135,37.72906137107],
[-122.43980526924135,37.73421283683962],
[-122.44126439094543,37.73421283683962],
[-122.44126439094543,37.72906137107]
]
]
}`
poly8 := `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]],[[-122.44060993194579,37.73345766902749],[-122.44044363498686,37.73345766902749],[-122.44044363498686,37.73355524732416],[-122.44060993194579,37.73355524732416],[-122.44060993194579,37.73345766902749]],[[-122.44060724973677,37.7336888869566],[-122.4402102828026,37.7336888869566],[-122.4402102828026,37.7339752567853],[-122.44060724973677,37.7339752567853],[-122.44060724973677,37.7336888869566]]]}`
poly9 := `{"type":"Polygon","coordinates":[[[-122.44037926197052,37.73313523548048],[-122.44017541408539,37.73313523548048],[-122.44017541408539,37.73336857568778],[-122.44037926197052,37.73336857568778],[-122.44037926197052,37.73313523548048]]]}`
poly10 := `{"type":"Polygon","coordinates":[[[-122.44040071964262,37.73359343010089],[-122.4402666091919,37.73359343010089],[-122.4402666091919,37.73373767596864],[-122.44040071964262,37.73373767596864],[-122.44040071964262,37.73359343010089]]]}`
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
{"SET", "mykey", "point2", "POINT", 37.7335, -122.44121}, {"OK"},
{"SET", "mykey", "line3", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "poly4", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
{"SET", "mykey", "multipoly5", "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]],[[[-122.44091033935547,37.731981251280985],[-122.43994474411011,37.731981251280985],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.731981251280985]]]]}`}, {"OK"},
{"SET", "mykey", "point6", "POINT", -5, 5}, {"OK"},
{"SET", "mykey", "point7", "POINT", 33, 21}, {"OK"},
{"SET", "mykey", "poly8", "OBJECT", poly8}, {"OK"},
{"TEST", "GET", "mykey", "point1", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "line3", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly4", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "multipoly5", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly8", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "point6", "WITHIN", "OBJECT", poly}, {"0"},
{"TEST", "GET", "mykey", "point7", "WITHIN", "OBJECT", poly}, {"0"},
{"TEST", "OBJECT", poly9, "WITHIN", "OBJECT", poly8}, {"1"},
{"TEST", "OBJECT", poly10, "WITHIN", "OBJECT", poly8}, {"0"},
})
}
func testcmd_INTERSECTS_test(mc *mockServer) error {
poly := `{
"type": "Polygon",
"coordinates": [
[
[-122.44126439094543,37.732906137107],
[-122.43980526924135,37.732906137107],
[-122.43980526924135,37.73421283683962],
[-122.44126439094543,37.73421283683962],
[-122.44126439094543,37.732906137107]
]
]
}`
poly8 := `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]],[[-122.44060993194579,37.73345766902749],[-122.44044363498686,37.73345766902749],[-122.44044363498686,37.73355524732416],[-122.44060993194579,37.73355524732416],[-122.44060993194579,37.73345766902749]],[[-122.44060724973677,37.7336888869566],[-122.4402102828026,37.7336888869566],[-122.4402102828026,37.7339752567853],[-122.44060724973677,37.7339752567853],[-122.44060724973677,37.7336888869566]]]}`
poly9 := `{"type": "Polygon","coordinates": [[[-122.44037926197052,37.73313523548048],[-122.44017541408539,37.73313523548048],[-122.44017541408539,37.73336857568778],[-122.44037926197052,37.73336857568778],[-122.44037926197052,37.73313523548048]]]}`
poly10 := `{"type": "Polygon","coordinates": [[[-122.44040071964262,37.73359343010089],[-122.4402666091919,37.73359343010089],[-122.4402666091919,37.73373767596864],[-122.44040071964262,37.73373767596864],[-122.44040071964262,37.73359343010089]]]}`
poly101 := `{"type":"Polygon","coordinates":[[[-122.44051605463028,37.73375464605226],[-122.44028002023695,37.73375464605226],[-122.44028002023695,37.733903134117966],[-122.44051605463028,37.733903134117966],[-122.44051605463028,37.73375464605226]]]}`
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
{"SET", "mykey", "point2", "POINT", 37.7335, -122.44121}, {"OK"},
{"SET", "mykey", "line3", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "poly4", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
{"SET", "mykey", "multipoly5", "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]],[[[-122.44091033935547,37.731981251280985],[-122.43994474411011,37.731981251280985],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.731981251280985]]]]}`}, {"OK"},
{"SET", "mykey", "point6", "POINT", -5, 5}, {"OK"},
{"SET", "mykey", "point7", "POINT", 33, 21}, {"OK"},
{"SET", "mykey", "poly8", "OBJECT", poly8}, {"OK"},
{"TEST", "GET", "mykey", "point1", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "point2", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "line3", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly4", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "multipoly5", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly8", "INTERSECTS", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "point6", "INTERSECTS", "OBJECT", poly}, {"0"},
{"TEST", "GET", "mykey", "point7", "INTERSECTS", "OBJECT", poly}, {"0"},
{"TEST", "OBJECT", poly9, "INTERSECTS", "OBJECT", poly8}, {"1"},
{"TEST", "OBJECT", poly10, "INTERSECTS", "OBJECT", poly8}, {"1"},
{"TEST", "OBJECT", poly101, "INTERSECTS", "OBJECT", poly8}, {"0"},
})
}
func testcmd_INTERSECTS_CLIP_test(mc *mockServer) error {
poly8 := `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]],[[-122.44060993194579,37.73345766902749],[-122.44044363498686,37.73345766902749],[-122.44044363498686,37.73355524732416],[-122.44060993194579,37.73355524732416],[-122.44060993194579,37.73345766902749]],[[-122.44060724973677,37.7336888869566],[-122.4402102828026,37.7336888869566],[-122.4402102828026,37.7339752567853],[-122.44060724973677,37.7339752567853],[-122.44060724973677,37.7336888869566]]]}`
poly9 := `{"type":"Polygon","coordinates":[[[-122.44037926197052,37.73313523548048],[-122.44017541408539,37.73313523548048],[-122.44017541408539,37.73336857568778],[-122.44037926197052,37.73336857568778],[-122.44037926197052,37.73313523548048]]]}`
multipoly5 := `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]],[[[-122.44091033935547,37.731981251280985],[-122.43994474411011,37.731981251280985],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.731981251280985]]]]}`
poly101 := `{"type":"Polygon","coordinates":[[[-122.44051605463028,37.73375464605226],[-122.44028002023695,37.73375464605226],[-122.44028002023695,37.733903134117966],[-122.44051605463028,37.733903134117966],[-122.44051605463028,37.73375464605226]]]}`
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
{"TEST", "OBJECT", poly9, "INTERSECTS", "CLIP", "OBJECT", "{}"}, {"ERR invalid argument 'cannot clip with object'"},
{"TEST", "OBJECT", poly9, "INTERSECTS", "CLIP", "CIRCLE", "1", "2", "3"}, {"ERR invalid argument 'cannot clip with circle'"},
{"TEST", "OBJECT", poly9, "INTERSECTS", "CLIP", "GET", "mykey", "point1"}, {"ERR invalid argument 'cannot clip with get'"},
{"TEST", "OBJECT", poly9, "INTERSECTS", "CLIP", "BOUNDS", 37.732906137107, -122.44126439094543, 37.73421283683962, -122.43980526924135}, {"[1 " + poly9 + "]"},
{"TEST", "OBJECT", poly8, "INTERSECTS", "CLIP", "BOUNDS", 37.733, -122.4408378, 37.7341129, -122.44}, {"[1 " + poly8 + "]"},
{"TEST", "OBJECT", multipoly5, "INTERSECTS", "CLIP", "BOUNDS", 37.73227823422744, -122.44120001792908, 37.73319038868677, -122.43955314159392}, {"[1 " + `{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-122.4408378,37.73319038868677],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.73319038868677],[-122.4408378,37.73319038868677]]]}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-122.44091033935547,37.73227823422744],[-122.43994474411011,37.73227823422744],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.73227823422744]]]}}]}` + "]"},
{"TEST", "OBJECT", poly101, "INTERSECTS", "CLIP", "BOUNDS", 37.73315644825698, -122.44054287672043, 37.73349585185455, -122.44008690118788}, {"0"},
})
}

View File

@ -42,6 +42,7 @@ func TestAll(t *testing.T) {
runSubTest(t, "keys", mc, subTestKeys)
runSubTest(t, "json", mc, subTestJSON)
runSubTest(t, "search", mc, subTestSearch)
runSubTest(t, "testcmd", mc, subTestTestCmd)
runSubTest(t, "fence", mc, subTestFence)
runSubTest(t, "scripts", mc, subTestScripts)
runSubTest(t, "info", mc, subTestInfo)