func testPipe2(t *testing.T, fileName string) { r, w, f := openPipe(t, fileName) defer f.Close() c := 1024 * 128 s := "Hello world!!" go func() { for i := 0; i < c; i++ { m := fmt.Sprintf("[%d]%s ", i, s) n, err := w.Write([]byte(m)) assert.MustNoError(err) assert.Must(n == len(m)) } assert.MustNoError(w.Close()) }() time.Sleep(time.Millisecond * 10) buf := make([]byte, len(s)*c*2) n, err := io.ReadFull(r, buf) assert.Must(errors.Equal(err, io.EOF)) buf = buf[:n] for i := 0; i < c; i++ { m := fmt.Sprintf("[%d]%s ", i, s) assert.Must(len(buf) >= len(m)) assert.Must(string(buf[:len(m)]) == m) buf = buf[len(m):] } assert.Must(len(buf) == 0) assert.MustNoError(r.Close()) }
func TestDecodeSimpleRequest1(t *testing.T) { resp, err := DecodeFromBytes([]byte("\r\n")) assert.MustNoError(err) x, ok := resp.(*Array) assert.Must(ok) assert.Must(len(x.Value) == 0) }
func TestItos(t *testing.T) { for i := 0; i < len(imap)*2; i++ { n, p := -i, i assert.Must(strconv.Itoa(n) == itos(int64(n))) assert.Must(strconv.Itoa(p) == itos(int64(p))) } }
func TestWriteAfterWriterClose(t *testing.T) { r, w := New() s := "hello" errs := make(chan error) go func() { n, err := w.Write([]byte(s)) assert.MustNoError(err) assert.Must(n == len(s)) assert.MustNoError(w.Close()) _, err = w.Write([]byte("world")) errs <- err }() buf := make([]byte, 4096) n, err := io.ReadFull(r, buf) assert.Must(errors.Equal(err, io.EOF)) assert.Must(string(buf[:n]) == s) err = <-errs assert.Must(errors.Equal(err, io.ErrClosedPipe)) assert.MustNoError(r.Close()) }
func checkHash(t *testing.T, o interface{}, m map[string]string) { x, ok := o.(Hash) assert.Must(ok) assert.Must(len(x) == len(m)) for _, e := range x { assert.Must(m[string(e.Field)] == string(e.Value)) } }
func checkList(t *testing.T, o interface{}, list []string) { x, ok := o.(List) assert.Must(ok) assert.Must(len(x) == len(list)) for i, e := range x { assert.Must(string(e) == list[i]) } }
func checkSet(t *testing.T, o interface{}, set []string) { x, ok := o.(Set) assert.Must(ok) assert.Must(len(x) == len(set)) for i, e := range x { assert.Must(string(e) == set[i]) } }
func TestBytesizeError(t *testing.T) { var err error _, err = Parse("--1") assert.Must(errors.Equal(err, ErrBadBytesize)) _, err = Parse("hello world") assert.Must(errors.Equal(err, ErrBadBytesize)) _, err = Parse("123.132.32") assert.Must(errors.Equal(err, ErrBadBytesize)) }
/* #!/bin/bash for ((i=0;i<32;i++)); do ./redis-cli rpush list $i done ./redis-cli dump list */ func TestDecodeList(t *testing.T) { s := ` 0120c000c001c002c003c004c005c006c007c008c009c00ac00bc00cc00dc00e c00fc010c011c012c013c014c015c016c017c018c019c01ac01bc01cc01dc01e c01f0600e87781cbebc997f5 ` val := hexStringToObject(t, s).(List) assert.Must(len(val) == 32) for i := 0; i < len(val); i++ { assert.Must(string(val[i]) == strconv.Itoa(i)) } }
/* #!/bin/bash for ((i=0;i<32;i++)); do ./redis-cli rpush list $i done ./redis-cli dump list */ func TestDecodeListZipmap(t *testing.T) { s := ` 0a405e5e0000005a000000200000f102f202f302f402f502f602f702f802f902 fa02fb02fc02fd02fe0d03fe0e03fe0f03fe1003fe1103fe1203fe1303fe1403 fe1503fe1603fe1703fe1803fe1903fe1a03fe1b03fe1c03fe1d03fe1e03fe1f ff060052f7f617938b332a ` val := hexStringToObject(t, s).(List) assert.Must(len(val) == 32) for i := 0; i < len(val); i++ { assert.Must(string(val[i]) == strconv.Itoa(i)) } }
func TestPipeReadClose2(t *testing.T) { r, w := New() c := make(chan int, 1) go delayClose(t, r, c, pipeTest{}) n, err := r.Read(make([]byte, 64)) <-c assert.Must(errors.Equal(err, io.ErrClosedPipe)) assert.Must(n == 0) assert.MustNoError(w.Close()) }
/* #!/bin/bash ./redis-cli flushall for ((i=0;i<32;i++)); do ./redis-cli rpush list ${i} done ./redis-cli save && xxd -p -c 32 dump.rdb */ func TestLoadList(t *testing.T) { s := ` 524544495330303036fe0001046c69737420c000c001c002c003c004c005c006 c007c008c009c00ac00bc00cc00dc00ec00fc010c011c012c013c014c015c016 c017c018c019c01ac01bc01cc01dc01ec01fff756ea1fa90adefe3 ` entries := DecodeHexRdb(t, s, 1) _, obj := getobj(t, entries, "list") val := obj.(List) assert.Must(len(val) == 32) for i := 0; i < 32; i++ { assert.Must(string(val[i]) == strconv.Itoa(i)) } }
func TestDecodeSimpleRequest3(t *testing.T) { test := []string{"\r", "\n", " \n"} for _, s := range test { _, err := DecodeFromBytes([]byte(s)) assert.Must(err != nil) } }
func getobj(t *testing.T, entries map[string]*BinEntry, key string) (*BinEntry, interface{}) { e := entries[key] assert.Must(e != nil) o, err := DecodeDump(e.Value) assert.MustNoError(err) return e, o }
func TestDecodeInvalidRequests(t *testing.T) { test := []string{ "*hello\r\n", "*-100\r\n", "*3\r\nhi", "*3\r\nhi\r\n", "*4\r\n$1", "*4\r\n$1\r", "*4\r\n$1\n", "*2\r\n$3\r\nget\r\n$what?\r\nx\r\n", "*4\r\n$3\r\nget\r\n$1\r\nx\r\n", "*2\r\n$3\r\nget\r\n$1\r\nx", "*2\r\n$3\r\nget\r\n$1\r\nx\r", "*2\r\n$3\r\nget\r\n$100\r\nx\r\n", "$6\r\nfoobar\r", "$0\rn\r\n", "$-1\n", "*0", "*2n$3\r\nfoo\r\n$3\r\nbar\r\n", "*-\r\n", "+OK\n", "-Error message\r", } for _, s := range test { _, err := DecodeFromBytes([]byte(s)) assert.Must(err != nil) } }
/* #!/bin/bash ./redis-cli flushall ./redis-cli set string_ttls string_ttls ./redis-cli expireat string_ttls 1500000000 ./redis-cli set string_ttlms string_ttlms ./redis-cli pexpireat string_ttlms 1500000000000 ./redis-cli save && xxd -p -c 32 dump.rdb */ func TestLoadStringTTL(t *testing.T) { s := ` 524544495330303036fe00fc0098f73e5d010000000c737472696e675f74746c 6d730c737472696e675f74746c6d73fc0098f73e5d010000000b737472696e67 5f74746c730b737472696e675f74746c73ffd15acd935a3fe949 ` expireat := uint64(1500000000000) entries := DecodeHexRdb(t, s, 2) keys := []string{"string_ttls", "string_ttlms"} for _, key := range keys { e, obj := getobj(t, entries, key) val := obj.(String) assert.Must(bytes.Equal([]byte(val), []byte(key))) assert.Must(e.ExpireAt == expireat) } }
func hexStringToObject(t *testing.T, s string) interface{} { p, err := hex.DecodeString(strings.NewReplacer("\t", "", "\r", "", "\n", "", " ", "").Replace(s)) assert.MustNoError(err) o, err := DecodeDump(p) assert.MustNoError(err) assert.Must(o != nil) return o }
func testPipe3(t *testing.T, fileName string) { r, w, f := openPipe(t, fileName) defer f.Close() c := make(chan int) size := 4096 go func() { buf := make([]byte, size) for { n, err := r.Read(buf) if errors.Equal(err, io.EOF) { break } assert.MustNoError(err) c <- n } assert.MustNoError(r.Close()) c <- 0 }() go func() { buf := make([]byte, size) for i := 1; i < size; i++ { n, err := w.Write(buf[:i]) assert.MustNoError(err) assert.Must(n == i) } assert.MustNoError(w.Close()) }() sum := 0 for i := 1; i < size; i++ { sum += i } for { n := <-c if n == 0 { break } sum -= n } assert.Must(sum == 0) }
/* #!/bin/bash for ((i=0;i<32;i++)); do ./redis-cli sadd set $i done ./redis-cli dump set */ func TestDecodeSet(t *testing.T) { s := ` 0220c016c00dc01bc012c01ac004c014c002c017c01dc01cc013c019c01ec008 c006c000c001c007c00fc009c01fc00ec003c00ac015c010c00bc018c011c00c c00506007bd0a89270890016 ` val := hexStringToObject(t, s).(Set) assert.Must(len(val) == 32) set := make(map[string]bool) for _, mem := range val { set[string(mem)] = true } assert.Must(len(val) == len(set)) for i := 0; i < 32; i++ { _, ok := set[strconv.Itoa(i)] assert.Must(ok) } }
func TestWriteNil(t *testing.T) { r, w := New() go func() { n, err := w.Write(nil) assert.MustNoError(err) assert.Must(n == 0) assert.MustNoError(w.Close()) }() time.Sleep(time.Millisecond * 10) buf := make([]byte, 4096) n, err := io.ReadFull(r, buf) assert.Must(errors.Equal(err, io.EOF)) assert.Must(n == 0) assert.MustNoError(r.Close()) }
/* #!/bin/bash ./redis-cli flushall for ((i=0;i<256;i++)); do ./redis-cli rpush list_lzf 0 ./redis-cli rpush list_lzf 1 done ./redis-cli save && xxd -p -c 32 dump.rdb */ func TestLoadListZipmap(t *testing.T) { s := ` 524544495330303036fe000a086c6973745f6c7a66c31f440b040b0400000820 0306000200f102f202e0ff03e1ff07e1ff07e1d90701f2ffff6a1c2d51c02301 16 ` entries := DecodeHexRdb(t, s, 1) _, obj := getobj(t, entries, "list_lzf") val := obj.(List) assert.Must(len(val) == 512) for i := 0; i < 256; i++ { var s string = "0" if i%2 != 0 { s = "1" } assert.Must(string(val[i]) == s) } }
func testPipe4(t *testing.T, fileName string) { r, w, f := openPipe(t, fileName) defer f.Close() key := []byte("spinlock aes-128") block := aes.BlockSize count := 1024 * 1024 * 128 / block go func() { buf := make([]byte, count*block) m, err := aes.NewCipher(key) assert.MustNoError(err) for i := 0; i < len(buf); i++ { buf[i] = byte(i) } e := cipher.NewCBCEncrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) n, err := w.Write(buf) assert.MustNoError(err) assert.MustNoError(w.Close()) assert.Must(n == len(buf)) }() buf := make([]byte, count*block) m, err := aes.NewCipher(key) assert.MustNoError(err) n, err := io.ReadFull(r, buf) assert.MustNoError(err) assert.Must(n == len(buf)) e := cipher.NewCBCDecrypter(m, make([]byte, block)) e.CryptBlocks(buf, buf) for i := 0; i < len(buf); i++ { assert.Must(buf[i] == byte(i)) } _, err = io.ReadFull(r, buf) assert.Must(errors.Equal(err, io.EOF)) assert.MustNoError(r.Close()) }
func testBacklog(t *testing.T, bl *Backlog, size int) { input := randSlice(32) r1, err := bl.NewReader() assert.MustNoError(err) checkWriter(bl, input) checkReader(r1, input) checkReader(r1, []byte{}) input = randSlice(size) checkWriter(bl, input) checkReader(r1, input) checkWriter(bl, randSlice(size)) assert.Must(r1.IsValid() == true) r2, err := bl.NewReader() assert.MustNoError(err) input = []byte{0xde, 0xad, 0xbe, 0xef} checkWriter(bl, input) assert.Must(r1.IsValid() == false) _, err = r1.Read([]byte{0}) assert.Must(errors.Equal(err, ErrInvalidOffset)) b := make([]byte, len(input)) n, err := io.ReadFull(r2, b) assert.MustNoError(err) assert.Must(n == len(b) && bytes.Equal(b, input)) bl.Close() assert.Must(r1.IsValid() == false) assert.Must(r2.IsValid() == false) _, err = r1.Read([]byte{0}) assert.Must(errors.Equal(err, ErrClosedBacklog)) _, err = r2.Read([]byte{0}) assert.Must(errors.Equal(err, ErrClosedBacklog)) _, err = bl.Write([]byte{0}) assert.Must(errors.Equal(err, ErrClosedBacklog)) }
func TestDecodeSimpleRequest2(t *testing.T) { test := []string{ "hello world\r\n", "hello world \r\n", " hello world \r\n", " hello world\r\n", " hello world \r\n", } for _, s := range test { resp, err := DecodeFromBytes([]byte(s)) assert.MustNoError(err) x, ok := resp.(*Array) assert.Must(ok) assert.Must(len(x.Value) == 2) s1, ok := x.Value[0].(*BulkBytes) assert.Must(ok && bytes.Equal(s1.Value, []byte("hello"))) s2, ok := x.Value[1].(*BulkBytes) assert.Must(ok && bytes.Equal(s2.Value, []byte("world"))) } }
func testPipe1(t *testing.T, fileName string) { r, w, f := openPipe(t, fileName) defer f.Close() s := "Hello world!!" go func(data []byte) { n, err := w.Write(data) assert.MustNoError(err) assert.Must(n == len(data)) assert.MustNoError(w.Close()) }([]byte(s)) buf := make([]byte, 64) n, err := io.ReadFull(r, buf) assert.Must(errors.Equal(err, io.EOF)) assert.Must(n == len(s)) assert.Must(string(buf[:n]) == s) assert.MustNoError(r.Close()) }
/* #!/bin/bash for ((i=0;i<32;i++)); do let j="$i*$i" ./redis-cli hset hash $i $j done ./redis-cli dump hash */ func TestDecodeHash(t *testing.T) { s := ` 0420c016c1e401c00dc1a900c01bc1d902c012c14401c01ac1a402c004c010c0 02c004c014c19001c017c11102c01dc14903c01cc11003c013c16901c019c171 02c01ec18403c008c040c006c024c000c000c001c001c007c031c009c051c00f c1e100c01fc1c103c00ec1c400c003c009c00ac064c015c1b901c010c10001c0 0bc079c018c14002c011c12101c00cc19000c005c019060072320e870e10799d ` val := hexStringToObject(t, s).(Hash) assert.Must(len(val) == 32) hash := make(map[string]string) for _, ent := range val { hash[string(ent.Field)] = string(ent.Value) } assert.Must(len(val) == len(hash)) for i := 0; i < 32; i++ { s := strconv.Itoa(i) assert.Must(hash[s] == strconv.Itoa(i*i)) } }
func TestPipeWriteClose(t *testing.T) { for _, u := range pipeTests { r, w := New() c := make(chan int, 1) if u.async { go delayClose(t, r, c, u) } else { delayClose(t, r, c, u) } <-c n, err := w.Write([]byte("hello, world")) expect := u.err if expect == nil { expect = io.ErrClosedPipe } assert.Must(errors.Equal(err, expect)) assert.Must(n == 0) assert.MustNoError(w.Close()) } }
func DecodeHexRdb(t *testing.T, s string, n int) map[string]*BinEntry { p, err := hex.DecodeString(strings.NewReplacer("\t", "", "\r", "", "\n", "", " ", "").Replace(s)) assert.MustNoError(err) r := bytes.NewReader(p) l := NewLoader(r) assert.MustNoError(l.Header()) entries := make(map[string]*BinEntry) var i int = 0 for { e, err := l.NextBinEntry() assert.MustNoError(err) if e == nil { break } assert.Must(e.DB == 0) entries[string(e.Key)] = e i++ } assert.MustNoError(l.Footer()) assert.Must(r.Len() == 0) assert.Must(len(entries) == i && i == n) return entries }
func TestWriteRead(t *testing.T) { r, w := New() p := make(chan []byte, 1) go func() { var x []byte for { b := make([]byte, 23) n, err := r.Read(b) if n != 0 { x = append(x, b[:n]...) } if err != nil { p <- x return } } }() b := make([]byte, 1024*1024*128) for i := 0; i < len(b); i++ { b[i] = byte(i) } n, err := w.Write(b) assert.MustNoError(err) assert.Must(n == len(b)) w.Close() x := <-p assert.Must(len(x) == len(b)) assert.Must(bytes.Equal(b, x)) n, err = r.Read(b) assert.Must(err != nil && n == 0) }
/* #!/bin/bash for ((i=0;i<32;i++)); do ./redis-cli zadd zset -$i $i done ./redis-cli dump zset */ func TestDecodeZSet(t *testing.T) { s := ` 0320c016032d3232c00d032d3133c01b032d3237c012032d3138c01a032d3236 c004022d34c014032d3230c002022d32c017032d3233c01d032d3239c01c032d 3238c013032d3139c019032d3235c01e032d3330c008022d38c006022d36c000 0130c001022d31c007022d37c009022d39c00f032d3135c01f032d3331c00e03 2d3134c003022d33c00a032d3130c015032d3231c010032d3136c00b032d3131 c018032d3234c011032d3137c00c032d3132c005022d35060046177397f6688b 16 ` val := hexStringToObject(t, s).(ZSet) assert.Must(len(val) == 32) zset := make(map[string]float64) for _, ent := range val { zset[string(ent.Member)] = ent.Score } assert.Must(len(val) == len(zset)) for i := 0; i < 32; i++ { s := strconv.Itoa(i) score, ok := zset[s] assert.Must(ok) assert.Must(math.Abs(score+float64(i)) < 1e-10) } }