mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-05 08:46:56 +08:00
add unittests and bug fix
This commit is contained in:
@@ -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
|
||||
|
@@ -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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user