2016-04-03 00:46:39 +03:00
|
|
|
package resp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/binary"
|
2016-09-09 02:11:53 +03:00
|
|
|
"errors"
|
2016-04-03 00:46:39 +03:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestIntegers(t *testing.T) {
|
|
|
|
var n, rn int
|
|
|
|
var v Value
|
|
|
|
var err error
|
|
|
|
data := []byte(":1234567\r\n:-90898\r\n:0\r\n")
|
|
|
|
r := NewReader(bytes.NewBuffer(data))
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Integer() != 1234567 {
|
|
|
|
t.Fatalf("invalid integer: expected %d, got %d", 1234567, v.Integer())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Integer() != -90898 {
|
|
|
|
t.Fatalf("invalid integer: expected %d, got %d", -90898, v.Integer())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Integer() != 0 {
|
|
|
|
t.Fatalf("invalid integer: expected %d, got %d", 0, v.Integer())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != io.EOF {
|
|
|
|
t.Fatalf("invalid error: expected %v, got %v", io.EOF, err)
|
|
|
|
}
|
|
|
|
if n != len(data) {
|
|
|
|
t.Fatalf("invalid read count: expected %d, got %d", len(data), n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFloats(t *testing.T) {
|
|
|
|
var n, rn int
|
|
|
|
var v Value
|
|
|
|
var err error
|
|
|
|
data := []byte(":1234567\r\n+-90898\r\n$6\r\n12.345\r\n-90284.987\r\n")
|
|
|
|
r := NewReader(bytes.NewBuffer(data))
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Float() != 1234567 {
|
|
|
|
t.Fatalf("invalid integer: expected %v, got %v", 1234567, v.Float())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Float() != -90898 {
|
|
|
|
t.Fatalf("invalid integer: expected %v, got %v", -90898, v.Float())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Float() != 12.345 {
|
|
|
|
t.Fatalf("invalid integer: expected %v, got %v", 12.345, v.Float())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if v.Float() != 90284.987 {
|
|
|
|
t.Fatalf("invalid integer: expected %v, got %v", 90284.987, v.Float())
|
|
|
|
}
|
|
|
|
v, rn, err = r.ReadValue()
|
|
|
|
n += rn
|
|
|
|
if err != io.EOF {
|
|
|
|
t.Fatalf("invalid error: expected %v, got %v", io.EOF, err)
|
|
|
|
}
|
|
|
|
if n != len(data) {
|
|
|
|
t.Fatalf("invalid read count: expected %d, got %d", len(data), n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestLotsaRandomness does generates N resp messages and reads the values though a Reader.
|
|
|
|
// It then marshals the values back to strings and compares to the original.
|
|
|
|
// All data and resp types are random.
|
|
|
|
|
|
|
|
func TestLotsaRandomness(t *testing.T) {
|
|
|
|
n := 10000
|
|
|
|
var anys []string
|
|
|
|
var buf bytes.Buffer
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
any := randRESPAny()
|
|
|
|
anys = append(anys, any)
|
|
|
|
buf.WriteString(any)
|
|
|
|
}
|
|
|
|
r := NewReader(bytes.NewBuffer(buf.Bytes()))
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v, _, err := r.ReadValue()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-09-09 02:11:53 +03:00
|
|
|
ts := fmt.Sprintf("%v", v.Type())
|
|
|
|
if ts == "Unknown" {
|
|
|
|
t.Fatal("got 'Unknown'")
|
|
|
|
}
|
|
|
|
tvs := fmt.Sprintf("%v %v %v %v %v %v %v %v",
|
|
|
|
v.String(), v.Float(), v.Integer(), v.Array(),
|
|
|
|
v.Bool(), v.Bytes(), v.IsNull(), v.Error(),
|
|
|
|
)
|
|
|
|
if len(tvs) < 10 {
|
|
|
|
t.Fatal("conversion error")
|
|
|
|
}
|
|
|
|
if !v.Equals(v) {
|
|
|
|
t.Fatal("equals failed")
|
|
|
|
}
|
2016-04-03 00:46:39 +03:00
|
|
|
resp, err := v.MarshalRESP()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if string(resp) != anys[i] {
|
|
|
|
t.Fatalf("resp failed to remarshal #%d\n-- original --\n%s\n-- remarshalled --\n%s\n-- done --", i, anys[i], string(resp))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-09 02:11:53 +03:00
|
|
|
func TestBigFragmented(t *testing.T) {
|
|
|
|
b := make([]byte, 10*1024*1024)
|
|
|
|
if _, err := rand.Read(b); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
cmd := []byte("*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$" + strconv.FormatInt(int64(len(b)), 10) + "\r\n" + string(b) + "\r\n")
|
|
|
|
cmdlen := len(cmd)
|
|
|
|
pr, pw := io.Pipe()
|
|
|
|
frag := 1024
|
|
|
|
go func() {
|
|
|
|
defer pw.Close()
|
|
|
|
for len(cmd) >= frag {
|
|
|
|
if _, err := pw.Write(cmd[:frag]); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
cmd = cmd[frag:]
|
|
|
|
}
|
|
|
|
if len(cmd) > 0 {
|
|
|
|
if _, err := pw.Write(cmd); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
r := NewReader(pr)
|
|
|
|
value, telnet, n, err := r.ReadMultiBulk()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if n != cmdlen {
|
|
|
|
t.Fatalf("expected %v, got %v", cmdlen, n)
|
|
|
|
}
|
|
|
|
if telnet {
|
|
|
|
t.Fatalf("expected false, got true")
|
|
|
|
}
|
|
|
|
arr := value.Array()
|
|
|
|
if len(arr) != 3 {
|
|
|
|
t.Fatalf("expected 3, got %v", len(arr))
|
|
|
|
}
|
|
|
|
if arr[0].String() != "SET" {
|
|
|
|
t.Fatalf("expected 'SET', got %v", arr[0].String())
|
|
|
|
}
|
|
|
|
if arr[1].String() != "KEY" {
|
|
|
|
t.Fatalf("expected 'KEY', got %v", arr[0].String())
|
|
|
|
}
|
|
|
|
if bytes.Compare(arr[2].Bytes(), b) != 0 {
|
|
|
|
t.Fatal("bytes not equal")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAnyValues(t *testing.T) {
|
|
|
|
var vs = []interface{}{
|
|
|
|
nil,
|
|
|
|
int(10), uint(10), int8(10),
|
|
|
|
uint8(10), int16(10), uint16(10),
|
|
|
|
int32(10), uint32(10), int64(10),
|
|
|
|
uint64(10), bool(true), bool(false),
|
|
|
|
float32(10), float64(10),
|
|
|
|
[]byte("hello"), string("hello"),
|
|
|
|
}
|
|
|
|
for i, v := range vs {
|
|
|
|
if AnyValue(v).String() == "" && v != nil {
|
|
|
|
t.Fatalf("missing string value for #%d: '%v'", i, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshalStrangeValue(t *testing.T) {
|
|
|
|
var v Value
|
|
|
|
v.null = true
|
|
|
|
b, err := marshalAnyRESP(v)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if string(b) != "$-1\r\n" {
|
|
|
|
t.Fatalf("expected '%v', got '%v'", "$-1\r\n", string(b))
|
|
|
|
}
|
|
|
|
v.null = false
|
|
|
|
|
|
|
|
_, err = marshalAnyRESP(v)
|
|
|