1package proto_test
2
3import (
4	"bytes"
5	"io"
6	"testing"
7
8	"github.com/go-redis/redis/v8/internal/proto"
9)
10
11func BenchmarkReader_ParseReply_Status(b *testing.B) {
12	benchmarkParseReply(b, "+OK\r\n", nil, false)
13}
14
15func BenchmarkReader_ParseReply_Int(b *testing.B) {
16	benchmarkParseReply(b, ":1\r\n", nil, false)
17}
18
19func BenchmarkReader_ParseReply_Error(b *testing.B) {
20	benchmarkParseReply(b, "-Error message\r\n", nil, true)
21}
22
23func BenchmarkReader_ParseReply_String(b *testing.B) {
24	benchmarkParseReply(b, "$5\r\nhello\r\n", nil, false)
25}
26
27func BenchmarkReader_ParseReply_Slice(b *testing.B) {
28	benchmarkParseReply(b, "*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n", multiBulkParse, false)
29}
30
31func TestReader_ReadLine(t *testing.T) {
32	original := bytes.Repeat([]byte("a"), 8192)
33	original[len(original)-2] = '\r'
34	original[len(original)-1] = '\n'
35	r := proto.NewReader(bytes.NewReader(original))
36	read, err := r.ReadLine()
37	if err != nil && err != io.EOF {
38		t.Errorf("Should be able to read the full buffer: %v", err)
39	}
40
41	if bytes.Compare(read, original[:len(original)-2]) != 0 {
42		t.Errorf("Values must be equal: %d expected %d", len(read), len(original[:len(original)-2]))
43	}
44}
45
46func benchmarkParseReply(b *testing.B, reply string, m proto.MultiBulkParse, wanterr bool) {
47	buf := new(bytes.Buffer)
48	for i := 0; i < b.N; i++ {
49		buf.WriteString(reply)
50	}
51	p := proto.NewReader(buf)
52	b.ResetTimer()
53
54	for i := 0; i < b.N; i++ {
55		_, err := p.ReadReply(m)
56		if !wanterr && err != nil {
57			b.Fatal(err)
58		}
59	}
60}
61
62func multiBulkParse(p *proto.Reader, n int64) (interface{}, error) {
63	vv := make([]interface{}, 0, n)
64	for i := int64(0); i < n; i++ {
65		v, err := p.ReadReply(multiBulkParse)
66		if err != nil {
67			return nil, err
68		}
69		vv = append(vv, v)
70	}
71	return vv, nil
72}
73