add unittests and bug fix

This commit is contained in:
hdt3213
2021-05-05 20:51:53 +08:00
parent f1ab47bd83
commit 18d2cbb29b
30 changed files with 704 additions and 446 deletions

View File

@@ -2,6 +2,7 @@ package parser
import (
"bufio"
"bytes"
"errors"
"github.com/hdt3213/godis/interface/redis"
"github.com/hdt3213/godis/lib/logger"
@@ -17,19 +18,25 @@ type Payload struct {
Err error
}
func Parse(reader io.Reader) <-chan *Payload {
// ParseStream reads data from io.Reader and send payloads through channel
func ParseStream(reader io.Reader) <-chan *Payload {
ch := make(chan *Payload)
go func() {
defer func() {
if err := recover(); err != nil {
logger.Error(debug.Stack())
}
}()
parse0(reader, ch)
}()
go parse0(reader, ch)
return ch
}
// ParseOne reads data from []byte and return the first payload
func ParseOne(data []byte) (redis.Reply, error) {
ch := make(chan *Payload)
reader := bytes.NewReader(data)
go parse0(reader, ch)
payload := <-ch // parse0 will close the channel
if payload == nil {
return nil, errors.New("no reply")
}
return payload.Data, payload.Err
}
type readState struct {
downloading bool
expectedArgsCount int
@@ -44,6 +51,11 @@ func (s *readState) finished() bool {
}
func parse0(reader io.Reader, ch chan<- *Payload) {
defer func() {
if err := recover(); err != nil {
logger.Error(string(debug.Stack()))
}
}()
bufReader := bufio.NewReader(reader)
var state readState
var err error

View File

@@ -9,7 +9,7 @@ import (
"testing"
)
func TestParse(t *testing.T) {
func TestParseStream(t *testing.T) {
replies := []redis.Reply{
reply.MakeIntReply(1),
reply.MakeStatusReply("OK"),
@@ -33,7 +33,7 @@ func TestParse(t *testing.T) {
[]byte("set"), []byte("a"), []byte("a"),
}))
ch := Parse(bytes.NewReader(reqs.Bytes()))
ch := ParseStream(bytes.NewReader(reqs.Bytes()))
i := 0
for payload := range ch {
if payload.Err != nil {
@@ -54,3 +54,28 @@ func TestParse(t *testing.T) {
}
}
}
func TestParseOne(t *testing.T) {
replies := []redis.Reply{
reply.MakeIntReply(1),
reply.MakeStatusReply("OK"),
reply.MakeErrReply("ERR unknown"),
reply.MakeBulkReply([]byte("a\r\nb")), // test binary safe
reply.MakeNullBulkReply(),
reply.MakeMultiBulkReply([][]byte{
[]byte("a"),
[]byte("\r\n"),
}),
reply.MakeEmptyMultiBulkReply(),
}
for _, re := range replies {
result, err := ParseOne(re.ToBytes())
if err != nil {
t.Error(err)
continue
}
if !utils.BytesEquals(result.ToBytes(), re.ToBytes()) {
t.Error("parse failed: " + string(re.ToBytes()))
}
}
}