ledisdb/vendor/github.com/siddontang/rdb/loader_test.go

374 lines
11 KiB
Go

// Copyright 2014 Wandoujia Inc. All Rights Reserved.
// Licensed under the MIT (MIT-LICENSE.txt) license.
package rdb
import (
"bytes"
"encoding/hex"
"fmt"
"math"
"strconv"
"strings"
"testing"
)
func AssertNoError(t *testing.T, err error) {
if err == nil {
return
}
t.Fatal(err)
}
func Assert(t *testing.T, b bool) {
if b {
return
}
t.Fatal("assertion failed")
}
func DecodeHexRdb(t *testing.T, s string, n int) map[string]*Entry {
p, err := hex.DecodeString(strings.NewReplacer("\t", "", "\r", "", "\n", "", " ", "").Replace(s))
AssertNoError(t, err)
r := bytes.NewReader(p)
l := NewLoader(r)
AssertNoError(t, l.LoadHeader())
entries := make(map[string]*Entry)
var i int = 0
for {
e, err := l.LoadEntry()
AssertNoError(t, err)
if e == nil {
break
}
Assert(t, e.DB == 0)
entries[string(e.Key)] = e
i++
}
AssertNoError(t, l.LoadChecksum())
Assert(t, r.Len() == 0)
Assert(t, len(entries) == i && i == n)
return entries
}
func getobj(t *testing.T, entries map[string]*Entry, key string) (*Entry, interface{}) {
e := entries[key]
Assert(t, e != nil)
val, err := DecodeDump(e.ValDump)
AssertNoError(t, err)
return e, val
}
/*
#!/bin/bash
./redis-cli flushall
for i in 1 255 256 65535 65536 2147483647 2147483648 4294967295 4294967296 -2147483648; do
./redis-cli set string_${i} ${i}
done
./redis-cli save && xxd -p -c 32 dump.rdb
*/
func TestLoadIntString(t *testing.T) {
s := `
524544495330303036fe00000a737472696e675f323535c1ff00000873747269
6e675f31c0010011737472696e675f343239343936373239360a343239343936
373239360011737472696e675f343239343936373239350a3432393439363732
39350012737472696e675f2d32313437343833363438c200000080000c737472
696e675f3635353335c2ffff00000011737472696e675f323134373438333634
380a32313437343833363438000c737472696e675f3635353336c20000010000
0a737472696e675f323536c100010011737472696e675f323134373438333634
37c2ffffff7fffe49d9f131fb5c3b5
`
values := []int{1, 255, 256, 65535, 65536, 2147483647, 2147483648, 4294967295, 4294967296, -2147483648}
entries := DecodeHexRdb(t, s, len(values))
for _, value := range values {
key := fmt.Sprintf("string_%d", value)
_, obj := getobj(t, entries, key)
val := obj.(String)
Assert(t, bytes.Equal([]byte(val), []byte(strconv.Itoa(value))))
}
}
/*
#!/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(t, bytes.Equal([]byte(val), []byte(key)))
Assert(t, e.ExpireAt == expireat)
}
}
/*
#!/bin/bash
s="01"
for ((i=0;i<15;i++)); do
s=$s$s
done
./redis-cli flushall
./redis-cli set string_long $s
./redis-cli save && xxd -p -c 32 dump.rdb
*/
func TestLoadLongString(t *testing.T) {
s := `
524544495330303036fe00000b737472696e675f6c6f6e67c342f28000010000
02303130e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff
01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0
ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01e0ff01
e0ff01e0ff01e0ff01e0ff01e03201013031ffdfdb02bd6d5da5e6
`
entries := DecodeHexRdb(t, s, 1)
_, obj := getobj(t, entries, "string_long")
val := []byte(obj.(String))
for i := 0; i < (1 << 15); i++ {
var c uint8 = '0'
if i%2 != 0 {
c = '1'
}
Assert(t, val[i] == c)
}
}
/*
#!/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(t, len(val) == 512)
for i := 0; i < 256; i++ {
var s string = "0"
if i%2 != 0 {
s = "1"
}
Assert(t, string(val[i]) == s)
}
}
/*
#!/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(t, len(val) == 32)
for i := 0; i < 32; i++ {
Assert(t, string(val[i]) == strconv.Itoa(i))
}
}
/*
#!/bin/bash
./redis-cli flushall
for ((i=0;i<16;i++)); do
./redis-cli sadd set1 ${i}
done
for ((i=0;i<32;i++)); do
./redis-cli sadd set2 ${i}
done
./redis-cli save && xxd -p -c 32 dump.rdb
*/
func TestLoadSetAndSetIntset(t *testing.T) {
s := `
524544495330303036fe0002047365743220c016c00dc01bc012c01ac004c014
c002c017c01dc01cc013c019c01ec008c006c000c001c007c00fc009c01fc00e
c003c00ac015c010c00bc018c011c00cc0050b04736574312802000000100000
0000000100020003000400050006000700080009000a000b000c000d000e000f
00ff3a0a9697324d19c3
`
entries := DecodeHexRdb(t, s, 2)
_, obj1 := getobj(t, entries, "set1")
val1 := obj1.(Set)
set1 := make(map[string]bool)
for _, mem := range val1 {
set1[string(mem)] = true
}
Assert(t, len(set1) == 16)
Assert(t, len(set1) == len(val1))
for i := 0; i < 16; i++ {
_, ok := set1[strconv.Itoa(i)]
Assert(t, ok)
}
_, obj2 := getobj(t, entries, "set2")
val2 := obj2.(Set)
set2 := make(map[string]bool)
for _, mem := range val2 {
set2[string(mem)] = true
}
Assert(t, len(set2) == 32)
Assert(t, len(set2) == len(val2))
for i := 0; i < 32; i++ {
_, ok := set2[strconv.Itoa(i)]
Assert(t, ok)
}
}
/*
#!/bin/bash
./redis-cli flushall
for ((i=0;i<16;i++)); do
./redis-cli hset hash1 ${i}
done
for ((i=-16;i<16;i++)); do
./redis-cli hset hash2 ${i}
done
./redis-cli save && xxd -p -c 32 dump.rdb
*/
func TestLoadHashAndHashZiplist(t *testing.T) {
s := `
524544495330303036fe000405686173683220c00dc00dc0fcc0fcc0ffc0ffc0
04c004c002c002c0fbc0fbc0f0c0f0c0f9c0f9c008c008c0fac0fac006c006c0
00c000c001c001c0fec0fec007c007c0f6c0f6c00fc00fc009c009c0f7c0f7c0
fdc0fdc0f1c0f1c0f2c0f2c0f3c0f3c00ec00ec003c003c00ac00ac00bc00bc0
f8c0f8c00cc00cc0f5c0f5c0f4c0f4c005c0050d056861736831405151000000
4d000000200000f102f102f202f202f302f302f402f402f502f502f602f602f7
02f702f802f802f902f902fa02fa02fb02fb02fc02fc02fd02fd02fe0d03fe0d
03fe0e03fe0e03fe0f03fe0fffffa423d3036c15e534
`
entries := DecodeHexRdb(t, s, 2)
_, obj1 := getobj(t, entries, "hash1")
val1 := obj1.(Hash)
hash1 := make(map[string]string)
for _, ent := range val1 {
hash1[string(ent.Field)] = string(ent.Value)
}
Assert(t, len(hash1) == 16)
Assert(t, len(hash1) == len(val1))
for i := 0; i < 16; i++ {
s := strconv.Itoa(i)
Assert(t, hash1[s] == s)
}
_, obj2 := getobj(t, entries, "hash2")
val2 := obj2.(Hash)
hash2 := make(map[string]string)
for _, ent := range val2 {
hash2[string(ent.Field)] = string(ent.Value)
}
Assert(t, len(hash2) == 32)
Assert(t, len(hash2) == len(val2))
for i := -16; i < 16; i++ {
s := strconv.Itoa(i)
Assert(t, hash2[s] == s)
}
}
/*
#!/bin/bash
./redis-cli flushall
for ((i=0;i<16;i++)); do
./redis-cli zadd zset1 ${i} ${i}
done
for ((i=0;i<32;i++)); do
./redis-cli zadd zset2 -${i} ${i}
done
./redis-cli save && xxd -p -c 32 dump.rdb
*/
func TestLoadZSetAndZSetZiplist(t *testing.T) {
s := `
524544495330303036fe0003057a7365743220c016032d3232c00d032d3133c0
1b032d3237c012032d3138c01a032d3236c004022d34c014032d3230c002022d
32c017032d3233c01d032d3239c01c032d3238c013032d3139c019032d3235c0
1e032d3330c008022d38c006022d36c000022d30c001022d31c007022d37c009
022d39c00f032d3135c01f032d3331c00e032d3134c003022d33c00a032d3130
c015032d3231c010032d3136c00b032d3131c018032d3234c011032d3137c00c
032d3132c005022d350c057a736574314051510000004d000000200000f102f1
02f202f202f302f302f402f402f502f502f602f602f702f702f802f802f902f9
02fa02fa02fb02fb02fc02fc02fd02fd02fe0d03fe0d03fe0e03fe0e03fe0f03
fe0fffff2addedbf4f5a8f93
`
entries := DecodeHexRdb(t, s, 2)
_, obj1 := getobj(t, entries, "zset1")
val1 := obj1.(ZSet)
zset1 := make(map[string]float64)
for _, ent := range val1 {
zset1[string(ent.Member)] = ent.Score
}
Assert(t, len(zset1) == 16)
Assert(t, len(zset1) == len(val1))
for i := 0; i < 16; i++ {
s := strconv.Itoa(i)
score, ok := zset1[s]
Assert(t, ok)
Assert(t, math.Abs(score-float64(i)) < 1e-10)
}
_, obj2 := getobj(t, entries, "zset2")
val2 := obj2.(ZSet)
zset2 := make(map[string]float64)
for _, ent := range val2 {
zset2[string(ent.Member)] = ent.Score
}
Assert(t, len(zset2) == 32)
Assert(t, len(zset2) == len(val2))
for i := 0; i < 32; i++ {
s := strconv.Itoa(i)
score, ok := zset2[s]
Assert(t, ok)
Assert(t, math.Abs(score+float64(i)) < 1e-10)
}
}