mirror of https://github.com/tidwall/tile38.git
wip - better tests
This commit is contained in:
parent
a824d58419
commit
d61f0bc6c8
|
@ -5,10 +5,11 @@ cd $(dirname "${BASH_SOURCE[0]}")/..
|
||||||
|
|
||||||
export CGO_ENABLED=0
|
export CGO_ENABLED=0
|
||||||
|
|
||||||
# if [ "$NOMODULES" != "1" ]; then
|
cd tests
|
||||||
# export GO111MODULE=on
|
go test -coverpkg=../internal/server -coverprofile=/tmp/coverage.out
|
||||||
# export GOFLAGS=-mod=vendor
|
go tool cover -html=/tmp/coverage.out -o /tmp/coverage.html
|
||||||
# fi
|
echo "details: file:///tmp/coverage.html"
|
||||||
|
cd ..
|
||||||
|
|
||||||
cd tests && go test && cd ..
|
# go test -coverpkg=internal/ \
|
||||||
go test $(go list ./... | grep -v /vendor/ | grep -v /tests)
|
# $(go list ./... | grep -v /vendor/ | grep -v /tests)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -29,7 +29,7 @@ func fence_roaming_webhook_test(mc *mockServer) error {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
// Read the request body
|
// Read the request body
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -115,8 +115,10 @@ func fence_roaming_live_test(mc *mockServer) error {
|
||||||
liveReady.Add(1)
|
liveReady.Add(1)
|
||||||
return goMultiFunc(mc,
|
return goMultiFunc(mc,
|
||||||
func() error {
|
func() error {
|
||||||
sc, err := redis.DialTimeout("tcp", fmt.Sprintf(":%d", mc.port),
|
sc, err := redis.Dial("tcp", fmt.Sprintf(":%d", mc.port),
|
||||||
0, time.Second*5, time.Second*5)
|
redis.DialConnectTimeout(0),
|
||||||
|
redis.DialReadTimeout(time.Second*5),
|
||||||
|
redis.DialWriteTimeout(time.Second*5))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
liveReady.Done()
|
liveReady.Done()
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -205,7 +205,7 @@ func fence_channel_message_order_test(mc *mockServer) error {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case error:
|
case error:
|
||||||
fmt.Printf(err.Error())
|
fmt.Printf("%s\n", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,10 +230,10 @@ func fence_channel_message_order_test(mc *mockServer) error {
|
||||||
// Fire all setup commands on the base client
|
// Fire all setup commands on the base client
|
||||||
for _, cmd := range []string{
|
for _, cmd := range []string{
|
||||||
"SET points point POINT 33.412529053733444 -111.93368911743164",
|
"SET points point POINT 33.412529053733444 -111.93368911743164",
|
||||||
fmt.Sprintf(`SETCHAN A WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.95205688476562,33.400491820565236],[-111.92630767822266,33.400491820565236],[-111.92630767822266,33.422272258866045],[-111.95205688476562,33.422272258866045],[-111.95205688476562,33.400491820565236]]]}`),
|
`SETCHAN A WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.95205688476562,33.400491820565236],[-111.92630767822266,33.400491820565236],[-111.92630767822266,33.422272258866045],[-111.95205688476562,33.422272258866045],[-111.95205688476562,33.400491820565236]]]}`,
|
||||||
fmt.Sprintf(`SETCHAN B WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.93952560424803,33.403501285221594],[-111.92630767822266,33.403501285221594],[-111.92630767822266,33.41997983836345],[-111.93952560424803,33.41997983836345],[-111.93952560424803,33.403501285221594]]]}`),
|
`SETCHAN B WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.93952560424803,33.403501285221594],[-111.92630767822266,33.403501285221594],[-111.92630767822266,33.41997983836345],[-111.93952560424803,33.41997983836345],[-111.93952560424803,33.403501285221594]]]}`,
|
||||||
fmt.Sprintf(`SETCHAN C WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.9255781173706,33.40342963251261],[-111.91201686859131,33.40342963251261],[-111.91201686859131,33.41994401881284],[-111.9255781173706,33.41994401881284],[-111.9255781173706,33.40342963251261]]]}`),
|
`SETCHAN C WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.9255781173706,33.40342963251261],[-111.91201686859131,33.40342963251261],[-111.91201686859131,33.41994401881284],[-111.9255781173706,33.41994401881284],[-111.9255781173706,33.40342963251261]]]}`,
|
||||||
fmt.Sprintf(`SETCHAN D WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.92562103271484,33.40063513076968],[-111.90021514892578,33.40063513076968],[-111.90021514892578,33.42212898435788],[-111.92562103271484,33.42212898435788],[-111.92562103271484,33.40063513076968]]]}`),
|
`SETCHAN D WITHIN points FENCE OBJECT {"type":"Polygon","coordinates":[[[-111.92562103271484,33.40063513076968],[-111.90021514892578,33.40063513076968],[-111.90021514892578,33.42212898435788],[-111.92562103271484,33.42212898435788],[-111.92562103271484,33.40063513076968]]]}`,
|
||||||
"SET points point POINT 33.412529053733444 -111.91909790039062",
|
"SET points point POINT 33.412529053733444 -111.91909790039062",
|
||||||
} {
|
} {
|
||||||
if _, err := do(bc, cmd); err != nil {
|
if _, err := do(bc, cmd); err != nil {
|
||||||
|
|
|
@ -4,9 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -36,18 +33,19 @@ func subTestKeys(t *testing.T, mc *mockServer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func keys_BOUNDS_test(mc *mockServer) error {
|
func keys_BOUNDS_test(mc *mockServer) error {
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch(
|
||||||
{"SET", "mykey", "myid1", "POINT", 33, -115}, {"OK"},
|
Do("SET", "mykey", "myid1", "POINT", 33, -115).OK(),
|
||||||
{"BOUNDS", "mykey"}, {"[[-115 33] [-115 33]]"},
|
Do("BOUNDS", "mykey").String("[[-115 33] [-115 33]]"),
|
||||||
{"SET", "mykey", "myid2", "POINT", 34, -112}, {"OK"},
|
Do("SET", "mykey", "myid2", "POINT", 34, -112).OK(),
|
||||||
{"BOUNDS", "mykey"}, {"[[-115 33] [-112 34]]"},
|
Do("BOUNDS", "mykey").String("[[-115 33] [-112 34]]"),
|
||||||
{"DEL", "mykey", "myid2"}, {1},
|
Do("DEL", "mykey", "myid2").String("1"),
|
||||||
{"BOUNDS", "mykey"}, {"[[-115 33] [-115 33]]"},
|
Do("BOUNDS", "mykey").String("[[-115 33] [-115 33]]"),
|
||||||
{"SET", "mykey", "myid3", "OBJECT", `{"type":"Point","coordinates":[-130,38,10]}`}, {"OK"},
|
Do("SET", "mykey", "myid3", "OBJECT", `{"type":"Point","coordinates":[-130,38,10]}`).OK(),
|
||||||
{"SET", "mykey", "myid4", "OBJECT", `{"type":"Point","coordinates":[-110,25,-8]}`}, {"OK"},
|
Do("SET", "mykey", "myid4", "OBJECT", `{"type":"Point","coordinates":[-110,25,-8]}`).OK(),
|
||||||
{"BOUNDS", "mykey"}, {"[[-130 25] [-110 38]]"},
|
Do("BOUNDS", "mykey").String("[[-130 25] [-110 38]]"),
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func keys_DEL_test(mc *mockServer) error {
|
func keys_DEL_test(mc *mockServer) error {
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SET", "mykey", "myid", "POINT", 33, -115}, {"OK"},
|
{"SET", "mykey", "myid", "POINT", 33, -115}, {"OK"},
|
||||||
|
@ -256,62 +254,6 @@ func keys_TTL_test(mc *mockServer) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type PSAUX struct {
|
|
||||||
User string
|
|
||||||
PID int
|
|
||||||
CPU float64
|
|
||||||
Mem float64
|
|
||||||
VSZ int
|
|
||||||
RSS int
|
|
||||||
TTY string
|
|
||||||
Stat string
|
|
||||||
Start string
|
|
||||||
Time string
|
|
||||||
Command string
|
|
||||||
}
|
|
||||||
|
|
||||||
func atoi(s string) int {
|
|
||||||
n, _ := strconv.ParseInt(s, 10, 64)
|
|
||||||
return int(n)
|
|
||||||
}
|
|
||||||
func atof(s string) float64 {
|
|
||||||
n, _ := strconv.ParseFloat(s, 64)
|
|
||||||
return float64(n)
|
|
||||||
}
|
|
||||||
func psaux(pid int) PSAUX {
|
|
||||||
var res []byte
|
|
||||||
res, err := exec.Command("ps", "aux").CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return PSAUX{}
|
|
||||||
}
|
|
||||||
pids := strconv.FormatInt(int64(pid), 10)
|
|
||||||
for _, line := range strings.Split(string(res), "\n") {
|
|
||||||
var words []string
|
|
||||||
for _, word := range strings.Split(line, " ") {
|
|
||||||
if word != "" {
|
|
||||||
words = append(words, word)
|
|
||||||
}
|
|
||||||
if len(words) > 11 {
|
|
||||||
if words[1] == pids {
|
|
||||||
return PSAUX{
|
|
||||||
User: words[0],
|
|
||||||
PID: atoi(words[1]),
|
|
||||||
CPU: atof(words[2]),
|
|
||||||
Mem: atof(words[3]),
|
|
||||||
VSZ: atoi(words[4]),
|
|
||||||
RSS: atoi(words[5]),
|
|
||||||
TTY: words[6],
|
|
||||||
Stat: words[7],
|
|
||||||
Start: words[8],
|
|
||||||
Time: words[9],
|
|
||||||
Command: words[10],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PSAUX{}
|
|
||||||
}
|
|
||||||
func keys_SET_EX_test(mc *mockServer) (err error) {
|
func keys_SET_EX_test(mc *mockServer) (err error) {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package tests
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -13,7 +13,7 @@ func downloadURLWithStatusCode(t *testing.T, u string) (int, string) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IO struct {
|
||||||
|
args []any
|
||||||
|
json bool
|
||||||
|
out any
|
||||||
|
}
|
||||||
|
|
||||||
|
func Do(args ...any) *IO {
|
||||||
|
return &IO{args: args}
|
||||||
|
}
|
||||||
|
func (cmd *IO) JSON() *IO {
|
||||||
|
cmd.json = true
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
func (cmd *IO) String(s string) *IO {
|
||||||
|
cmd.out = s
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
func (cmd *IO) Custom(fn func(s string) error) *IO {
|
||||||
|
cmd.out = func(s string) error {
|
||||||
|
if cmd.json {
|
||||||
|
if !gjson.Valid(s) {
|
||||||
|
return errors.New("invalid json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fn(s)
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *IO) OK() *IO {
|
||||||
|
return cmd.Custom(func(s string) error {
|
||||||
|
if cmd.json {
|
||||||
|
if gjson.Get(s, "ok").Type != gjson.True {
|
||||||
|
return errors.New("not ok")
|
||||||
|
}
|
||||||
|
} else if s != "OK" {
|
||||||
|
return errors.New("not ok")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ioVisitor struct {
|
||||||
|
fset *token.FileSet
|
||||||
|
ln int
|
||||||
|
pos int
|
||||||
|
got bool
|
||||||
|
data string
|
||||||
|
end int
|
||||||
|
done bool
|
||||||
|
index int
|
||||||
|
nidx int
|
||||||
|
frag string
|
||||||
|
fpos int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *ioVisitor) Visit(n ast.Node) ast.Visitor {
|
||||||
|
if n == nil || v.done {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.got {
|
||||||
|
if int(n.Pos()) > v.end {
|
||||||
|
v.done = true
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
if n, ok := n.(*ast.CallExpr); ok {
|
||||||
|
frag := strings.TrimSpace(v.data[int(n.Pos())-1 : int(n.End())])
|
||||||
|
if _, ok := n.Fun.(*ast.Ident); ok {
|
||||||
|
if v.index == v.nidx {
|
||||||
|
frag = strings.TrimSpace(strings.TrimSuffix(frag, "."))
|
||||||
|
idx := strings.IndexByte(frag, '(')
|
||||||
|
if idx != -1 {
|
||||||
|
frag = frag[idx:]
|
||||||
|
}
|
||||||
|
v.frag = frag
|
||||||
|
v.done = true
|
||||||
|
v.fpos = int(n.Pos())
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
v.nidx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
if int(n.Pos()) == v.pos {
|
||||||
|
if n, ok := n.(*ast.CallExpr); ok {
|
||||||
|
v.end = int(n.Rparen)
|
||||||
|
v.got = true
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *IO) deepError(index int, err error) error {
|
||||||
|
oerr := err
|
||||||
|
werr := func(err error) error {
|
||||||
|
return fmt.Errorf("batch[%d]: %v: %v", index, oerr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// analyse stack
|
||||||
|
_, file, ln, ok := runtime.Caller(3)
|
||||||
|
if !ok {
|
||||||
|
return werr(errors.New("runtime.Caller failed"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the character position from line
|
||||||
|
bdata, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return werr(err)
|
||||||
|
}
|
||||||
|
data := string(bdata)
|
||||||
|
|
||||||
|
var pos int
|
||||||
|
var iln int
|
||||||
|
var pln int
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
if data[i] == '\n' {
|
||||||
|
j := pln
|
||||||
|
line := data[pln:i]
|
||||||
|
pln = i + 1
|
||||||
|
iln++
|
||||||
|
if iln == ln {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if !strings.HasPrefix(line, "return mc.DoBatch(") {
|
||||||
|
return oerr
|
||||||
|
}
|
||||||
|
for ; j < len(data); j++ {
|
||||||
|
if data[j] == 'm' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos = j + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pos == 0 {
|
||||||
|
return oerr
|
||||||
|
}
|
||||||
|
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
pfile, err := parser.ParseFile(fset, file, nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
return werr(err)
|
||||||
|
}
|
||||||
|
v := &ioVisitor{
|
||||||
|
fset: fset,
|
||||||
|
ln: ln,
|
||||||
|
pos: pos,
|
||||||
|
data: string(data),
|
||||||
|
index: index,
|
||||||
|
}
|
||||||
|
ast.Walk(v, pfile)
|
||||||
|
|
||||||
|
if v.fpos == 0 {
|
||||||
|
return oerr
|
||||||
|
}
|
||||||
|
|
||||||
|
pln = 1
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
if data[i] == '\n' {
|
||||||
|
if i > v.fpos {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pln++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fsig := fmt.Sprintf("%s:%d", filepath.Base(file), pln)
|
||||||
|
emsg := oerr.Error()
|
||||||
|
if strings.HasPrefix(emsg, "expected ") &&
|
||||||
|
strings.Contains(emsg, ", got ") {
|
||||||
|
emsg = "" +
|
||||||
|
" EXPECTED: " + strings.Split(emsg, ", got ")[0][9:] + "\n" +
|
||||||
|
" GOT: " +
|
||||||
|
strings.Split(emsg, ", got ")[1]
|
||||||
|
} else {
|
||||||
|
emsg = "" +
|
||||||
|
" ERROR: " + emsg
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("\n%s: entry[%d]\n COMMAND: %s\n%s",
|
||||||
|
fsig, index+1, v.frag, emsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *mockServer) doIOTest(index int, cmd *IO) error {
|
||||||
|
// switch json mode if desired
|
||||||
|
if cmd.json {
|
||||||
|
if !mc.ioJSON {
|
||||||
|
if _, err := mc.Do("OUTPUT", "json"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mc.ioJSON = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if mc.ioJSON {
|
||||||
|
if _, err := mc.Do("OUTPUT", "resp"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mc.ioJSON = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mc.DoExpect(cmd.out, cmd.args[0].(string), cmd.args[1:]...)
|
||||||
|
if err != nil {
|
||||||
|
return cmd.deepError(index, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -3,11 +3,10 @@ package tests
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ func mockCleanup(silent bool) {
|
||||||
if !silent {
|
if !silent {
|
||||||
fmt.Printf("Cleanup: may take some time... ")
|
fmt.Printf("Cleanup: may take some time... ")
|
||||||
}
|
}
|
||||||
files, _ := ioutil.ReadDir(".")
|
files, _ := os.ReadDir(".")
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if strings.HasPrefix(file.Name(), "data-mock-") {
|
if strings.HasPrefix(file.Name(), "data-mock-") {
|
||||||
os.RemoveAll(file.Name())
|
os.RemoveAll(file.Name())
|
||||||
|
@ -36,11 +35,9 @@ func mockCleanup(silent bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockServer struct {
|
type mockServer struct {
|
||||||
port int
|
port int
|
||||||
//join string
|
conn redis.Conn
|
||||||
//n *finn.Node
|
ioJSON bool
|
||||||
//m *Machine
|
|
||||||
conn redis.Conn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockOpenServer(silent bool) (*mockServer, error) {
|
func mockOpenServer(silent bool) (*mockServer, error) {
|
||||||
|
@ -50,7 +47,7 @@ func mockOpenServer(silent bool) (*mockServer, error) {
|
||||||
if !silent {
|
if !silent {
|
||||||
fmt.Printf("Starting test server at port %d\n", port)
|
fmt.Printf("Starting test server at port %d\n", port)
|
||||||
}
|
}
|
||||||
logOutput := ioutil.Discard
|
logOutput := io.Discard
|
||||||
if os.Getenv("PRINTLOG") == "1" {
|
if os.Getenv("PRINTLOG") == "1" {
|
||||||
logOutput = os.Stderr
|
logOutput = os.Stderr
|
||||||
}
|
}
|
||||||
|
@ -80,7 +77,7 @@ func (s *mockServer) waitForStartup() error {
|
||||||
var lerr error
|
var lerr error
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
for {
|
for {
|
||||||
if time.Now().Sub(start) > time.Second*5 {
|
if time.Since(start) > time.Second*5 {
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
return lerr
|
return lerr
|
||||||
}
|
}
|
||||||
|
@ -159,7 +156,28 @@ func (s *mockServer) Do(commandName string, args ...interface{}) (interface{}, e
|
||||||
return resps[0], nil
|
return resps[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *mockServer) DoBatch(commands ...interface{}) error { //[][]interface{}) error {
|
func (mc *mockServer) DoBatch(commands ...interface{}) error {
|
||||||
|
// Probe for I/O tests
|
||||||
|
if len(commands) > 0 {
|
||||||
|
if _, ok := commands[0].(*IO); ok {
|
||||||
|
var cmds []*IO
|
||||||
|
// If the first is an I/O test then all must be
|
||||||
|
for _, cmd := range commands {
|
||||||
|
if cmd, ok := cmd.(*IO); ok {
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
} else {
|
||||||
|
return errors.New("DoBatch cannot mix I/O tests with other kinds")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, cmd := range cmds {
|
||||||
|
if err := mc.doIOTest(i, cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var tag string
|
var tag string
|
||||||
for _, commands := range commands {
|
for _, commands := range commands {
|
||||||
switch commands := commands.(type) {
|
switch commands := commands.(type) {
|
||||||
|
@ -181,6 +199,10 @@ func (mc *mockServer) DoBatch(commands ...interface{}) error { //[][]interface{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tag = ""
|
tag = ""
|
||||||
|
case *IO:
|
||||||
|
return errors.New("DoBatch cannot mix I/O tests with other kinds")
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown command input")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -281,27 +303,3 @@ func (mc *mockServer) DoExpect(expect interface{}, commandName string, args ...i
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func round(v float64, decimals int) float64 {
|
|
||||||
var pow float64 = 1
|
|
||||||
for i := 0; i < decimals; i++ {
|
|
||||||
pow *= 10
|
|
||||||
}
|
|
||||||
return float64(int((v*pow)+0.5)) / pow
|
|
||||||
}
|
|
||||||
|
|
||||||
func exfloat(v float64, decimals int) func(v interface{}) (resp, expect interface{}) {
|
|
||||||
ex := round(v, decimals)
|
|
||||||
return func(v interface{}) (resp, expect interface{}) {
|
|
||||||
var s string
|
|
||||||
if b, ok := v.([]uint8); ok {
|
|
||||||
s = string(b)
|
|
||||||
} else {
|
|
||||||
s = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
n, err := strconv.ParseFloat(s, 64)
|
|
||||||
if err != nil {
|
|
||||||
return v, ex
|
|
||||||
}
|
|
||||||
return round(n, decimals), ex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestAll(t *testing.T) {
|
||||||
mockCleanup(false)
|
mockCleanup(false)
|
||||||
defer mockCleanup(false)
|
defer mockCleanup(false)
|
||||||
|
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||||
go func() {
|
go func() {
|
||||||
<-ch
|
<-ch
|
||||||
|
@ -82,8 +82,9 @@ func runStep(t *testing.T, mc *mockServer, name string, step func(mc *mockServer
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
fmt.Printf("["+red+"fail"+clear+"]: %s\n", name)
|
fmt.Fprintf(os.Stderr, "["+red+"fail"+clear+"]: %s\n", name)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
// t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("["+green+"ok"+clear+"]: %s\n", name)
|
fmt.Printf("["+green+"ok"+clear+"]: %s\n", name)
|
||||||
})
|
})
|
||||||
|
@ -93,7 +94,7 @@ func BenchmarkAll(b *testing.B) {
|
||||||
mockCleanup(true)
|
mockCleanup(true)
|
||||||
defer mockCleanup(true)
|
defer mockCleanup(true)
|
||||||
|
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||||
go func() {
|
go func() {
|
||||||
<-ch
|
<-ch
|
||||||
|
|
|
@ -56,6 +56,9 @@ func setup(mc *mockServer, count int, points bool) (err error) {
|
||||||
|
|
||||||
func timeout_spatial_test(mc *mockServer) (err error) {
|
func timeout_spatial_test(mc *mockServer) (err error) {
|
||||||
err = setup(mc, 10000, true)
|
err = setup(mc, 10000, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SCAN", "mykey", "WHERE", "foo", -1, 2, "COUNT"}, {"10000"},
|
{"SCAN", "mykey", "WHERE", "foo", -1, 2, "COUNT"}, {"10000"},
|
||||||
|
@ -70,6 +73,9 @@ func timeout_spatial_test(mc *mockServer) (err error) {
|
||||||
|
|
||||||
func timeout_search_test(mc *mockServer) (err error) {
|
func timeout_search_test(mc *mockServer) (err error) {
|
||||||
err = setup(mc, 10000, false)
|
err = setup(mc, 10000, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SEARCH", "mykey", "MATCH", "val:*", "COUNT"}, {"10000"},
|
{"SEARCH", "mykey", "MATCH", "val:*", "COUNT"}, {"10000"},
|
||||||
|
@ -122,6 +128,9 @@ func scriptTimeoutErr(v interface{}) (resp, expect interface{}) {
|
||||||
|
|
||||||
func timeout_within_scripts_test(mc *mockServer) (err error) {
|
func timeout_within_scripts_test(mc *mockServer) (err error) {
|
||||||
err = setup(mc, 10000, true)
|
err = setup(mc, 10000, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
script1 := "return tile38.call('timeout', 10, 'SCAN', 'mykey', 'WHERE', 'foo', -1, 2, 'COUNT')"
|
script1 := "return tile38.call('timeout', 10, 'SCAN', 'mykey', 'WHERE', 'foo', -1, 2, 'COUNT')"
|
||||||
script2 := "return tile38.call('timeout', 0.000001, 'SCAN', 'mykey', 'WHERE', 'foo', -1, 2, 'COUNT')"
|
script2 := "return tile38.call('timeout', 0.000001, 'SCAN', 'mykey', 'WHERE', 'foo', -1, 2, 'COUNT')"
|
||||||
|
|
Loading…
Reference in New Issue