diff --git a/tests/fence_tests.go b/tests/fence_tests.go new file mode 100644 index 00000000..bde0084b --- /dev/null +++ b/tests/fence_tests.go @@ -0,0 +1,154 @@ +package tests + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "strconv" + "testing" + "time" + + "github.com/garyburd/redigo/redis" + "github.com/tidwall/gjson" +) + +func subTestFence(t *testing.T, mc *mockServer) { + runStep(t, mc, "basic", json_FENCE_basic_test) +} + +type fenceReader struct { + conn net.Conn + rd *bufio.Reader +} + +func (fr *fenceReader) receive() (string, error) { + if err := fr.conn.SetReadDeadline(time.Now().Add(time.Second)); err != nil { + return "", err + } + line, err := fr.rd.ReadBytes('\n') + if err != nil { + return "", err + } + if len(line) < 4 || line[0] != '$' || line[len(line)-2] != '\r' || line[len(line)-1] != '\n' { + return "", errors.New("invalid message") + } + n, err := strconv.ParseUint(string(line[1:len(line)-2]), 10, 64) + if err != nil { + return "", err + } + buf := make([]byte, int(n)+2) + _, err = io.ReadFull(fr.rd, buf) + if err != nil { + return "", err + } + if buf[len(buf)-2] != '\r' || buf[len(buf)-1] != '\n' { + return "", errors.New("invalid message") + } + js := buf[:len(buf)-2] + var m interface{} + if err := json.Unmarshal(js, &m); err != nil { + return "", err + } + return string(js), nil +} + +func (fr *fenceReader) receiveExpect(valex ...string) error { + s, err := fr.receive() + if err != nil { + return err + } + for i := 0; i < len(valex); i += 2 { + if gjson.Get(s, valex[i]).String() != valex[i+1] { + return fmt.Errorf("expected '%s'='%s', got '%s'", valex[i], valex[i+1], gjson.Get(s, valex[i]).String()) + } + } + return nil +} + +func json_FENCE_basic_test(mc *mockServer) error { + conn, err := net.Dial("tcp", fmt.Sprintf(":%d", mc.port)) + if err != nil { + return err + } + defer conn.Close() + _, err = fmt.Fprintf(conn, "NEARBY mykey FENCE POINT 33 -115 5000\r\n") + if err != nil { + return err + } + + buf := make([]byte, 4096) + n, err := conn.Read(buf) + if err != nil { + return err + } + res := string(buf[:n]) + if res != "+OK\r\n" { + return fmt.Errorf("expected OK, got '%v'", res) + } + rd := &fenceReader{conn, bufio.NewReader(conn)} + + // send a point + c, err := redis.Dial("tcp", fmt.Sprintf(":%d", mc.port)) + if err != nil { + return err + } + defer c.Close() + + res, err = redis.String(c.Do("SET", "mykey", "myid1", "POINT", 33, -115)) + if err != nil { + return err + } + if res != "OK" { + return fmt.Errorf("expected OK, got '%v'", res) + } + + // receive the message + if err := rd.receiveExpect("command", "set", + "detect", "enter", + "key", "mykey", + "id", "myid1", + "object.type", "Point", + "object.coordinates", "[-115,33]"); err != nil { + return err + } + + if err := rd.receiveExpect("command", "set", + "detect", "inside", + "key", "mykey", + "id", "myid1", + "object.type", "Point", + "object.coordinates", "[-115,33]"); err != nil { + return err + } + + res, err = redis.String(c.Do("SET", "mykey", "myid1", "POINT", 34, -115)) + if err != nil { + return err + } + if res != "OK" { + return fmt.Errorf("expected OK, got '%v'", res) + } + + // receive the message + if err := rd.receiveExpect("command", "set", + "detect", "exit", + "key", "mykey", + "id", "myid1", + "object.type", "Point", + "object.coordinates", "[-115,34]"); err != nil { + return err + } + + if err := rd.receiveExpect("command", "set", + "detect", "outside", + "key", "mykey", + "id", "myid1", + "object.type", "Point", + "object.coordinates", "[-115,34]"); err != nil { + return err + } + return nil +} diff --git a/tests/tests_test.go b/tests/tests_test.go index 0abf1334..85853da9 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -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, "fence", mc, subTestFence) } func runSubTest(t *testing.T, name string, mc *mockServer, test func(t *testing.T, mc *mockServer)) {