You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kvrocks.apache.org by ti...@apache.org on 2022/09/27 15:31:12 UTC
[incubator-kvrocks] branch unstable updated: Move TCL test unit/type/hash to Go case (#903)
This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/incubator-kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new da0d776 Move TCL test unit/type/hash to Go case (#903)
da0d776 is described below
commit da0d77680a8cf0ef678c1e1c8debea0f7dffdee3
Author: IoCing <39...@users.noreply.github.com>
AuthorDate: Tue Sep 27 23:31:07 2022 +0800
Move TCL test unit/type/hash to Go case (#903)
Co-authored-by: hulk <hu...@gmail.com>
Co-authored-by: tison <wa...@gmail.com>
---
tests/gocase/unit/type/hash/hash_test.go | 654 +++++++++++++++++++++++++++++--
tests/gocase/util/random.go | 4 +-
tests/tcl/tests/test_helper.tcl | 1 -
tests/tcl/tests/unit/type/hash.tcl | 528 -------------------------
4 files changed, 619 insertions(+), 568 deletions(-)
diff --git a/tests/gocase/unit/type/hash/hash_test.go b/tests/gocase/unit/type/hash/hash_test.go
index 349f88b..8ffb6a8 100644
--- a/tests/gocase/unit/type/hash/hash_test.go
+++ b/tests/gocase/unit/type/hash/hash_test.go
@@ -21,67 +21,647 @@ package hash
import (
"context"
+ "errors"
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
"testing"
+ "time"
"github.com/apache/incubator-kvrocks/tests/gocase/util"
"github.com/stretchr/testify/require"
)
+func getKeys(hash map[string]string) []string {
+ r := make([]string, 0)
+ for key := range hash {
+ r = append(r, key)
+ }
+ return r
+}
+
+func getVals(hash map[string]string) []string {
+ r := make([]string, 0)
+ for _, val := range hash {
+ r = append(r, val)
+ }
+ return r
+}
+
func TestHash(t *testing.T) {
srv := util.StartServer(t, map[string]string{})
defer srv.Close()
ctx := context.Background()
rdb := srv.NewClient()
defer func() { require.NoError(t, rdb.Close()) }()
- kvArray := []string{"a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "key1", "value1", "key2", "value2", "key3", "value3", "key10", "value10", "z", "z", "x", "x"}
- t.Run("HRange normal situation ", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.EqualValues(t, []interface{}{"key1", "value1", "key10", "value10"}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key2", "limit", 100).Val())
- require.EqualValues(t, []interface{}{"key1", "value1", "key10", "value10", "key2", "value2"}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key3", "limit", 100).Val())
+ smallhash := make(map[string]string)
+ bighash := make(map[string]string)
+
+ t.Run("HSET/HLEN - Small hash creation", func(t *testing.T) {
+ for i := 0; i < 8; i++ {
+ key := "__avoid_collisions__" + util.RandString(0, 8, util.Alpha)
+ val := "__avoid_collisions__" + util.RandString(0, 8, util.Alpha)
+ if _, ok := smallhash[key]; ok {
+ i--
+ }
+ rdb.HSet(ctx, "smallhash", key, val)
+ smallhash[key] = val
+ }
+ require.Equal(t, int64(8), rdb.HLen(ctx, "smallhash").Val())
+ })
+
+ t.Run("HSET/HLEN - Big hash creation", func(t *testing.T) {
+ for i := 0; i < 1024; i++ {
+ key := "__avoid_collisions__" + util.RandString(0, 8, util.Alpha)
+ val := "__avoid_collisions__" + util.RandString(0, 8, util.Alpha)
+ if _, ok := bighash[key]; ok {
+ i--
+ }
+ rdb.HSet(ctx, "bighash", key, val)
+ bighash[key] = val
+ }
+ require.Equal(t, int64(1024), rdb.HLen(ctx, "bighash").Val())
+ })
+
+ t.Run("HSET wrong number of args", func(t *testing.T) {
+ pattern := ".*wrong number.*"
+ util.ErrorRegexp(t, rdb.HSet(ctx, "hmsetmulti", "key1", "val1", "key2").Err(), pattern)
+ })
+
+ t.Run("HSET supports multiple fields", func(t *testing.T) {
+ require.Equal(t, int64(2), rdb.HSet(ctx, "hmsetmulti", "key1", "val1", "key2", "val2").Val())
+ require.Equal(t, int64(0), rdb.HSet(ctx, "hmsetmulti", "key1", "val1", "key2", "val2").Val())
+ require.Equal(t, int64(1), rdb.HSet(ctx, "hmsetmulti", "key1", "val1", "key3", "val3").Val())
+ })
+
+ t.Run("HGET against the small hash", func(t *testing.T) {
+ var err error
+ for key, val := range smallhash {
+ res := rdb.HGet(ctx, "smallhash", key)
+ if val != res.Val() {
+ err = res.Err()
+ break
+ }
+ }
+ require.NoError(t, err)
+ })
+
+ t.Run("HGET against the big hash", func(t *testing.T) {
+ var err error
+ for key, val := range bighash {
+ res := rdb.HGet(ctx, "bighash", key)
+ if val != res.Val() {
+ err = res.Err()
+ break
+ }
+ }
+ require.NoError(t, err)
+ })
+
+ t.Run("HGET against non existing key", func(t *testing.T) {
+ var rv []string
+ rv = append(rv, rdb.HGet(ctx, "samllhash", "__123123123__").Val())
+ rv = append(rv, rdb.HGet(ctx, "bighash", "__123123123__").Val())
+ require.Equal(t, []string{"", ""}, rv)
+ })
+
+ t.Run("HSET in update and insert mode", func(t *testing.T) {
+ var rv []string
+ k := getKeys(smallhash)[0]
+ rv = append(rv, fmt.Sprintf("%d", rdb.HSet(ctx, "smallhash", k, "newval1").Val()))
+ smallhash[k] = "newval1"
+ rv = append(rv, rdb.HGet(ctx, "smallhash", k).Val())
+ rv = append(rv, fmt.Sprintf("%d", rdb.HSet(ctx, "smallhash", "__foobar123__", "newval").Val()))
+ k = getKeys(bighash)[0]
+ rv = append(rv, fmt.Sprintf("%d", rdb.HSet(ctx, "bighash", k, "newval2").Val()))
+ bighash[k] = "newval2"
+ rv = append(rv, rdb.HGet(ctx, "bighash", k).Val())
+ rv = append(rv, fmt.Sprintf("%d", rdb.HSet(ctx, "bighash", "__foobar123__", "newval").Val()))
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "smallhash", "__foobar123__").Val()))
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "bighash", "__foobar123__").Val()))
+ require.Equal(t, []string{"0", "newval1", "1", "0", "newval2", "1", "1", "1"}, rv)
+ })
+
+ t.Run("HSETNX target key missing - small hash", func(t *testing.T) {
+ rdb.HSetNX(ctx, "smallhash", "__123123123__", "foo")
+ require.Equal(t, "foo", rdb.HGet(ctx, "smallhash", "__123123123__").Val())
+ })
+
+ t.Run("HSETNX target key exists - small hash", func(t *testing.T) {
+ rdb.HSetNX(ctx, "smallhash", "__123123123__", "bar")
+ res := rdb.HGet(ctx, "smallhash", "__123123123__").Val()
+ rdb.HDel(ctx, "smallhash", "__123123123__")
+ require.Equal(t, "foo", res)
+ })
+
+ t.Run("HSETNX target key missing - big hash", func(t *testing.T) {
+ rdb.HSetNX(ctx, "bighash", "__123123123__", "foo")
+ require.Equal(t, "foo", rdb.HGet(ctx, "bighash", "__123123123__").Val())
+ })
+
+ t.Run("HSETNX target key exists - big hash", func(t *testing.T) {
+ rdb.HSetNX(ctx, "bighash", "__123123123__", "bar")
+ res := rdb.HGet(ctx, "bighash", "__123123123__").Val()
+ rdb.HDel(ctx, "bighash", "__123123123__")
+ require.Equal(t, "foo", res)
+ })
+
+ t.Run("HMSET wrong number of args", func(t *testing.T) {
+ pattern := ".*wrong number.*"
+ util.ErrorRegexp(t, rdb.HMSet(ctx, "smallhash", "key1", "val1", "key2").Err(), pattern)
+ })
+
+ t.Run("HMSET - small hash", func(t *testing.T) {
+ var args []string
+ for key := range smallhash {
+ newval := util.RandString(0, 8, util.Alpha)
+ smallhash[key] = newval
+ args = append(args, key, newval)
+ }
+ require.Equal(t, true, rdb.HMSet(ctx, "smallhash", args).Val())
+ })
+
+ t.Run("HMSET - big hash", func(t *testing.T) {
+ var args []string
+ for key := range bighash {
+ newval := util.RandString(0, 8, util.Alpha)
+ bighash[key] = newval
+ args = append(args, key, newval)
+ }
+ require.Equal(t, true, rdb.HMSet(ctx, "bighash", args).Val())
+ })
+
+ t.Run("HMGET against non existing key and fields", func(t *testing.T) {
+ var rv [][]interface{}
+ cmd1 := rdb.HMGet(ctx, "doesntexist", "__123123123__", "__456456456__")
+ rv = append(rv, cmd1.Val())
+ cmd2 := rdb.HMGet(ctx, "smallhash", "__123123123__", "__456456456__")
+ rv = append(rv, cmd2.Val())
+ cmd3 := rdb.HMGet(ctx, "bighash", "__123123123__", "__456456456__")
+ rv = append(rv, cmd3.Val())
+ require.Equal(t, [][]interface{}{{interface{}(nil), interface{}(nil)}, {interface{}(nil), interface{}(nil)}, {interface{}(nil), interface{}(nil)}}, rv)
+ })
+
+ t.Run("HMGET against wrong type", func(t *testing.T) {
+ rdb.Set(ctx, "wrongtype", "somevalue", time.Millisecond*1000)
+ pattern := ".*wrong.*"
+ util.ErrorRegexp(t, rdb.HMGet(ctx, "wrongtype", "field1", "field2").Err(), pattern)
+ })
+
+ t.Run("HMGET - small hash", func(t *testing.T) {
+ var keys []string
+ var vals []string
+ for key, val := range smallhash {
+ keys = append(keys, key)
+ vals = append(vals, val)
+ }
+ var err error
+ res := rdb.HMGet(ctx, "smallhash", keys...).Val()
+ for i := range vals {
+ if vals[i] != res[i].(string) {
+ err = errors.New("$vals != $result")
+ break
+ }
+ }
+ require.NoError(t, err)
+ })
+
+ t.Run("HMGET - big hash", func(t *testing.T) {
+ var keys []string
+ var vals []string
+ for key, val := range bighash {
+ keys = append(keys, key)
+ vals = append(vals, val)
+ }
+ var err error
+ res := rdb.HMGet(ctx, "bighash", keys...).Val()
+ for i := range vals {
+ if vals[i] != res[i].(string) {
+ err = errors.New("$vals != $result")
+ break
+ }
+ }
+ require.NoError(t, err)
+ })
+
+ t.Run("HKEYS - small hash}", func(t *testing.T) {
+ expect := getKeys(smallhash)
+ sort.Strings(expect)
+ actual := rdb.HKeys(ctx, "smallhash").Val()
+ sort.Strings(actual)
+ require.Equal(t, expect, actual)
+ })
+
+ t.Run("HKEYS - big hash}", func(t *testing.T) {
+ expect := getKeys(bighash)
+ sort.Strings(expect)
+ actual := rdb.HKeys(ctx, "bighash").Val()
+ sort.Strings(actual)
+ require.Equal(t, expect, actual)
+ })
+
+ t.Run("HVALS - small hash}", func(t *testing.T) {
+ expect := getVals(smallhash)
+ sort.Strings(expect)
+ actual := rdb.HVals(ctx, "smallhash").Val()
+ sort.Strings(actual)
+ require.Equal(t, expect, actual)
+ })
+
+ t.Run("HVALS - big hash}", func(t *testing.T) {
+ expect := getVals(bighash)
+ sort.Strings(expect)
+ actual := rdb.HVals(ctx, "bighash").Val()
+ sort.Strings(actual)
+ require.Equal(t, expect, actual)
+ })
+
+ t.Run("HGETALL - small hash}", func(t *testing.T) {
+ res := rdb.Do(ctx, "hgetall", "smallhash").Val().([]interface{})
+ mid := make(map[string]string)
+ for i := 0; i < len(res); i += 2 {
+ if res[i+1] == nil {
+ mid[res[i].(string)] = ""
+ } else {
+ mid[res[i].(string)] = res[i+1].(string)
+ }
+ }
+ require.Equal(t, smallhash, mid)
+ })
+
+ t.Run("HGETALL - big hash}", func(t *testing.T) {
+ res := rdb.Do(ctx, "hgetall", "bighash").Val().([]interface{})
+ mid := make(map[string]string)
+ for i := 0; i < len(res); i += 2 {
+ if res[i+1] == nil {
+ mid[res[i].(string)] = ""
+ } else {
+ mid[res[i].(string)] = res[i+1].(string)
+ }
+ }
+ require.Equal(t, bighash, mid)
+ })
+
+ t.Run("HDEL and return value", func(t *testing.T) {
+ var rv []string
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "smallhash", "nokey").Val()))
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "bighash", "nokey").Val()))
+ k := getKeys(smallhash)[0]
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "smallhash", k).Val()))
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "smallhash", k).Val()))
+ rv = append(rv, rdb.HGet(ctx, "smallhash", k).Val())
+ delete(smallhash, k)
+ k = getKeys(bighash)[0]
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "bighash", k).Val()))
+ rv = append(rv, fmt.Sprintf("%d", rdb.HDel(ctx, "bighash", k).Val()))
+ rv = append(rv, rdb.HGet(ctx, "bighash", k).Val())
+ delete(bighash, k)
+ require.Equal(t, []string{"0", "0", "1", "0", "", "1", "0", ""}, rv)
+ })
+
+ t.Run("HDEL - more than a single value", func(t *testing.T) {
+ rdb.Del(ctx, "myhash")
+ rdb.HMSet(ctx, "myhash", []string{"a", "1", "b", "2", "c", "3"})
+ require.Equal(t, int64(0), rdb.HDel(ctx, "myhash", "x", "y").Val())
+ require.Equal(t, int64(2), rdb.HDel(ctx, "myhash", "a", "c", "f").Val())
+ require.Equal(t, map[string]string{"b": "2"}, rdb.HGetAll(ctx, "myhash").Val())
+ })
+
+ t.Run("HDEL - hash becomes empty before deleting all specified fields", func(t *testing.T) {
+ rdb.Del(ctx, "myhash")
+ rdb.HMSet(ctx, "myhash", []string{"a", "1", "b", "2", "c", "3"})
+ require.Equal(t, int64(3), rdb.HDel(ctx, "myhash", "a", "b", "c", "d", "e").Val())
+ require.Equal(t, int64(0), rdb.Exists(ctx, "myhash").Val())
+ })
+
+ t.Run("HEXISTS", func(t *testing.T) {
+ var rv []bool
+ k := getKeys(smallhash)[0]
+ rv = append(rv, rdb.HExists(ctx, "smallhash", k).Val())
+ rv = append(rv, rdb.HExists(ctx, "smallhash", "nokey").Val())
+ k = getKeys(bighash)[0]
+ rv = append(rv, rdb.HExists(ctx, "bighash", k).Val())
+ rv = append(rv, rdb.HExists(ctx, "bighash", "nokey").Val())
+ require.Equal(t, []bool{true, false, true, false}, rv)
+ })
+
+ t.Run("HINCRBY against non existing database key", func(t *testing.T) {
+ rdb.Del(ctx, "htest")
+ require.Equal(t, int64(2), rdb.HIncrBy(ctx, "htest", "foo", 2).Val())
+ })
+
+ t.Run("HINCRBY against non existing hash key", func(t *testing.T) {
+ var rv []string
+ rdb.HDel(ctx, "smallhash", "tmp")
+ rdb.HDel(ctx, "bighash", "tmp")
+ rv = append(rv, fmt.Sprintf("%d", rdb.HIncrBy(ctx, "smallhash", "tmp", 2).Val()))
+ rv = append(rv, rdb.HGet(ctx, "smallhash", "tmp").Val())
+ rv = append(rv, fmt.Sprintf("%d", rdb.HIncrBy(ctx, "bighash", "tmp", 2).Val()))
+ rv = append(rv, rdb.HGet(ctx, "bighash", "tmp").Val())
+ require.Equal(t, []string{"2", "2", "2", "2"}, rv)
+ })
+
+ t.Run("HINCRBY against hash key created by hincrby itself", func(t *testing.T) {
+ var rv []string
+ rv = append(rv, fmt.Sprintf("%d", rdb.HIncrBy(ctx, "smallhash", "tmp", 3).Val()))
+ rv = append(rv, rdb.HGet(ctx, "smallhash", "tmp").Val())
+ rv = append(rv, fmt.Sprintf("%d", rdb.HIncrBy(ctx, "bighash", "tmp", 3).Val()))
+ rv = append(rv, rdb.HGet(ctx, "bighash", "tmp").Val())
+ require.Equal(t, []string{"5", "5", "5", "5"}, rv)
+ })
+
+ t.Run("HINCRBY against hash key originally set with HSET", func(t *testing.T) {
+ rdb.HSet(ctx, "smallhash", "tmp", "100")
+ rdb.HSet(ctx, "bighash", "tmp", "100")
+ require.Equal(t, []int64{102, 102},
+ []int64{rdb.HIncrBy(ctx, "smallhash", "tmp", 2).Val(),
+ rdb.HIncrBy(ctx, "bighash", "tmp", 2).Val()})
+ })
+
+ t.Run("HINCRBY over 32bit value", func(t *testing.T) {
+ rdb.HSet(ctx, "smallhash", "tmp", "17179869184")
+ rdb.HSet(ctx, "bighash", "tmp", "17179869184")
+ require.Equal(t, []int64{17179869185, 17179869185},
+ []int64{rdb.HIncrBy(ctx, "smallhash", "tmp", 1).Val(),
+ rdb.HIncrBy(ctx, "bighash", "tmp", 1).Val()})
+ })
+
+ t.Run("HINCRBY over 32bit value with over 32bit increment", func(t *testing.T) {
+ rdb.HSet(ctx, "smallhash", "tmp", "17179869184")
+ rdb.HSet(ctx, "bighash", "tmp", "17179869184")
+ require.Equal(t, []int64{34359738368, 34359738368},
+ []int64{rdb.HIncrBy(ctx, "smallhash", "tmp", 17179869184).Val(),
+ rdb.HIncrBy(ctx, "bighash", "tmp", 17179869184).Val()})
+ })
+
+ t.Run("HINCRBY fails against hash value with spaces (left)", func(t *testing.T) {
+ rdb.HSet(ctx, "samllhash", "str", " 11")
+ rdb.HSet(ctx, "bighash", "str", " 11")
+ pattern := "ERR.*not an integer.*"
+ util.ErrorRegexp(t, rdb.HIncrBy(ctx, "samllhash", "str", 1).Err(), pattern)
+ util.ErrorRegexp(t, rdb.HIncrBy(ctx, "bighash", "str", 1).Err(), pattern)
+ })
+
+ t.Run("HINCRBY fails against hash value with spaces (right)", func(t *testing.T) {
+ rdb.HSet(ctx, "samllhash", "str", "11 ")
+ rdb.HSet(ctx, "bighash", "str", "11 ")
+ pattern := "ERR.*non-integer.*"
+ util.ErrorRegexp(t, rdb.HIncrBy(ctx, "samllhash", "str", 1).Err(), pattern)
+ util.ErrorRegexp(t, rdb.HIncrBy(ctx, "bighash", "str", 1).Err(), pattern)
+ })
+
+ t.Run("HINCRBY can detect overflows", func(t *testing.T) {
+ rdb.HSet(ctx, "hash", "n", "-9223372036854775484")
+ require.Equal(t, int64(-9223372036854775485), rdb.HIncrBy(ctx, "hash", "n", -1).Val())
+ pattern := ".*overflow.*"
+ util.ErrorRegexp(t, rdb.HIncrBy(ctx, "hash", "n", -10000).Err(), pattern)
+ })
+
+ t.Run("HINCRBYFLOAT against non existing database key", func(t *testing.T) {
+ rdb.Del(ctx, "htest")
+ require.Equal(t, 2.5, rdb.HIncrByFloat(ctx, "htest", "foo", 2.5).Val())
+ })
+
+ t.Run("HINCRBYFLOAT against non existing hash key", func(t *testing.T) {
+ var rv []float64
+ rdb.HDel(ctx, "smallhash", "tmp")
+ rdb.HDel(ctx, "bighash", "tmp")
+ rv = append(rv, rdb.HIncrByFloat(ctx, "smallhash", "tmp", 2.5).Val())
+ if res, err := strconv.ParseFloat(rdb.HGet(ctx, "smallhash", "tmp").Val(), strconv.IntSize); err == nil {
+ rv = append(rv, res)
+ }
+ rv = append(rv, rdb.HIncrByFloat(ctx, "bighash", "tmp", 2.5).Val())
+ if res, err := strconv.ParseFloat(rdb.HGet(ctx, "bighash", "tmp").Val(), strconv.IntSize); err == nil {
+ rv = append(rv, res)
+ }
+ require.Equal(t, []float64{2.5, 2.5, 2.5, 2.5}, rv)
+ })
+
+ t.Run("HINCRBYFLOAT against hash key created by hincrby itself", func(t *testing.T) {
+ var rv []float64
+ rv = append(rv, rdb.HIncrByFloat(ctx, "smallhash", "tmp", 3.5).Val())
+ if res, err := strconv.ParseFloat(rdb.HGet(ctx, "smallhash", "tmp").Val(), strconv.IntSize); err == nil {
+ rv = append(rv, res)
+ }
+ rv = append(rv, rdb.HIncrByFloat(ctx, "bighash", "tmp", 3.5).Val())
+ if res, err := strconv.ParseFloat(rdb.HGet(ctx, "bighash", "tmp").Val(), strconv.IntSize); err == nil {
+ rv = append(rv, res)
+ }
+ require.Equal(t, []float64{6, 6, 6, 6}, rv)
+ })
+
+ t.Run("HINCRBYFLOAT against hash key originally set with HSET", func(t *testing.T) {
+ var rv []float64
+ rdb.HSet(ctx, "smallhash", "tmp", 100)
+ rdb.HSet(ctx, "bighash", "tmp", 100)
+ rv = append(rv, rdb.HIncrByFloat(ctx, "smallhash", "tmp", 2.5).Val())
+ rv = append(rv, rdb.HIncrByFloat(ctx, "bighash", "tmp", 2.5).Val())
+ require.Equal(t, []float64{102.5, 102.5}, rv)
+ })
+
+ t.Run("HINCRBYFLOAT over 32bit value", func(t *testing.T) {
+ rdb.HSet(ctx, "smallhash", "tmp", "17179869184")
+ rdb.HSet(ctx, "bighash", "tmp", "17179869184")
+ require.Equal(t, []float64{17179869185, 17179869185},
+ []float64{rdb.HIncrByFloat(ctx, "smallhash", "tmp", 1).Val(),
+ rdb.HIncrByFloat(ctx, "bighash", "tmp", 1).Val()})
+ })
+
+ t.Run("HINCRBYFLOAT over 32bit value with over 32bit increment", func(t *testing.T) {
+ rdb.HSet(ctx, "smallhash", "tmp", "17179869184")
+ rdb.HSet(ctx, "bighash", "tmp", "17179869184")
+ require.Equal(t, []float64{34359738368, 34359738368},
+ []float64{rdb.HIncrByFloat(ctx, "smallhash", "tmp", 17179869184).Val(),
+ rdb.HIncrByFloat(ctx, "bighash", "tmp", 17179869184).Val()})
})
- t.Run("HRange stop <= start", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "key2", "key1", "limit", 100).Val())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key1", "limit", 100).Val())
+ t.Run("HINCRBYFLOAT fails against hash value with spaces (left)", func(t *testing.T) {
+ rdb.HSet(ctx, "samllhash", "str", " 11")
+ rdb.HSet(ctx, "bighash", "str", " 11")
+ pattern := "ERR.*not.*float.*"
+ util.ErrorRegexp(t, rdb.HIncrByFloat(ctx, "samllhash", "str", 1).Err(), pattern)
+ util.ErrorRegexp(t, rdb.HIncrByFloat(ctx, "bighash", "str", 1).Err(), pattern)
})
- t.Run("HRange limit", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.EqualValues(t, []interface{}{"a", "a", "b", "b"}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 2).Val())
- require.EqualValues(t, []interface{}{"a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "key1", "value1", "key10", "value10", "key2", "value2", "key3", "value3", "x", "x", "z", "z"}, rdb.Do(ctx, "HRange", "hashkey", "a", "zzz", "limit", 10000).Val())
+ t.Run("HINCRBYFLOAT fails against hash value with spaces (right)", func(t *testing.T) {
+ rdb.HSet(ctx, "samllhash", "str", "11 ")
+ rdb.HSet(ctx, "bighash", "str", "11 ")
+ pattern := "ERR.*not.*float.*"
+ util.ErrorRegexp(t, rdb.HIncrByFloat(ctx, "samllhash", "str", 1).Err(), pattern)
+ util.ErrorRegexp(t, rdb.HIncrByFloat(ctx, "bighash", "str", 1).Err(), pattern)
})
- t.Run("HRange limit is negative", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", -100).Val())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 0).Val())
+ t.Run("HSTRLEN against the small hash", func(t *testing.T) {
+ var err error
+ for _, k := range getKeys(smallhash) {
+ hlen := rdb.Do(ctx, "hstrlen", "smallhash", k).Val().(int64)
+ if int64(len(smallhash[k])) != hlen {
+ err = fmt.Errorf("[string length %d] != [r hstrlen %d]", len(smallhash[k]), hlen)
+ break
+ }
+ }
+ require.NoError(t, err)
})
- t.Run("HRange nonexistent key", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000).Val())
- require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000).Val())
+ t.Run("HSTRLEN against the big hash", func(t *testing.T) {
+ var err error
+ for _, k := range getKeys(bighash) {
+ hlen := rdb.Do(ctx, "hstrlen", "bighash", k).Val().(int64)
+ if int64(len(bighash[k])) != hlen {
+ err = fmt.Errorf("[string length %d] != [r hstrlen %d]", len(bighash[k]), hlen)
+ break
+ }
+ }
+ require.NoError(t, err)
})
- t.Run("HRange limit typo", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limitzz", 10000).Err(), "ERR syntax")
+ t.Run("HSTRLEN against non existing field", func(t *testing.T) {
+ var rv []int64
+ rv = append(rv, rdb.Do(ctx, "hstrlen", "smallhash", "__123123123__").Val().(int64))
+ rv = append(rv, rdb.Do(ctx, "hstrlen", "bighash", "__123123123__").Val().(int64))
+ require.Equal(t, []int64{0, 0}, rv)
})
- t.Run("HRange wrong number of arguments", func(t *testing.T) {
- require.NoError(t, rdb.Del(ctx, "hashkey").Err())
- require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
- require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000, "a").Err(), "wrong number of arguments")
- require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit").Err(), "wrong number of arguments")
- require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a").Err(), "wrong number of arguments")
- require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey").Err(), "wrong number of arguments")
- require.ErrorContains(t, rdb.Do(ctx, "HRange").Err(), "wrong number of arguments")
+ t.Run("HSTRLEN corner cases", func(t *testing.T) {
+ vals := []string{"-9223372036854775808", "9223372036854775807", "9223372036854775808", "", "0", "-1", "x"}
+ for _, v := range vals {
+ rdb.HMSet(ctx, "smallhash", "field", v)
+ rdb.HMSet(ctx, "bighash", "field", v)
+ len1 := int64(len(v))
+ len2 := rdb.Do(ctx, "hstrlen", "smallhash", "field").Val().(int64)
+ len3 := rdb.Do(ctx, "hstrlen", "bighash", "field").Val().(int64)
+ require.Equal(t, len1, len2)
+ require.Equal(t, len2, len3)
+ }
})
+ t.Run("Hash ziplist regression test for large keys", func(t *testing.T) {
+ rdb.HSet(ctx, "hash", strings.Repeat("k", 336), "a")
+ rdb.HSet(ctx, "hash", strings.Repeat("k", 336), "b")
+ require.Equal(t, "b", rdb.HGet(ctx, "hash", strings.Repeat("k", 336)).Val())
+ })
+
+ for _, size := range []int64{10, 512} {
+ t.Run(fmt.Sprintf("Hash fuzzing #1 - %d fields", size), func(t *testing.T) {
+ for times := 0; times < 10; times++ {
+ hash := make(map[string]string)
+ rdb.Del(ctx, "hash")
+
+ // Create
+ for j := 0; j < int(size); j++ {
+ field := util.RandomValue()
+ value := util.RandomValue()
+ rdb.HSet(ctx, "hash", field, value)
+ hash[field] = value
+ }
+
+ // Verify
+ for k, v := range hash {
+ require.Equal(t, v, rdb.HGet(ctx, "hash", k).Val())
+ }
+ require.Equal(t, int64(len(hash)), rdb.HLen(ctx, "hash").Val())
+ }
+ })
+
+ t.Run(fmt.Sprintf("Hash fuzzing #2 - %d fields", size), func(t *testing.T) {
+ for times := 0; times < 10; times++ {
+ hash := make(map[string]string)
+ rdb.Del(ctx, "hash")
+ var field string
+ var value string
+
+ // Create
+ for j := 0; j < int(size); j++ {
+ util.RandPath(
+ func() interface{} {
+ field = util.RandomValue()
+ value = util.RandomValue()
+ rdb.HSet(ctx, "hash", field, value)
+ hash[field] = value
+ return nil
+ },
+ func() interface{} {
+ field = strconv.Itoa(int(util.RandomSignedInt(512)))
+ value = strconv.Itoa(int(util.RandomSignedInt(512)))
+ rdb.HSet(ctx, "hash", field, value)
+ hash[field] = value
+ return nil
+ },
+ func() interface{} {
+ util.RandPath(
+ func() interface{} {
+ field = util.RandomValue()
+ return nil
+ },
+ func() interface{} {
+ field = strconv.Itoa(int(util.RandomSignedInt(512)))
+ return nil
+ },
+ )
+ rdb.HDel(ctx, "hash", field)
+ delete(hash, field)
+ return nil
+ },
+ )
+ }
+ // Verify
+ for k, v := range hash {
+ require.Equal(t, v, rdb.HGet(ctx, "hash", k).Val())
+ }
+ require.Equal(t, int64(len(hash)), rdb.HLen(ctx, "hash").Val())
+ }
+ })
+
+ kvArray := []string{"a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "key1", "value1", "key2", "value2", "key3", "value3", "key10", "value10", "z", "z", "x", "x"}
+ t.Run("HRange normal situation ", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.EqualValues(t, []interface{}{"key1", "value1", "key10", "value10"}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key2", "limit", 100).Val())
+ require.EqualValues(t, []interface{}{"key1", "value1", "key10", "value10", "key2", "value2"}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key3", "limit", 100).Val())
+ })
+
+ t.Run("HRange stop <= start", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "key2", "key1", "limit", 100).Val())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "key1", "key1", "limit", 100).Val())
+ })
+
+ t.Run("HRange limit", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.EqualValues(t, []interface{}{"a", "a", "b", "b"}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 2).Val())
+ require.EqualValues(t, []interface{}{"a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "key1", "value1", "key10", "value10", "key2", "value2", "key3", "value3", "x", "x", "z", "z"}, rdb.Do(ctx, "HRange", "hashkey", "a", "zzz", "limit", 10000).Val())
+ })
+
+ t.Run("HRange limit is negative", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", -100).Val())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 0).Val())
+ })
+
+ t.Run("HRange nonexistent key", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000).Val())
+ require.EqualValues(t, []interface{}{}, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000).Val())
+ })
+
+ t.Run("HRange limit typo", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limitzz", 10000).Err(), "ERR syntax")
+ })
+
+ t.Run("HRange wrong number of arguments", func(t *testing.T) {
+ require.NoError(t, rdb.Del(ctx, "hashkey").Err())
+ require.NoError(t, rdb.HMSet(ctx, "hashkey", kvArray).Err())
+ require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit", 10000, "a").Err(), "wrong number of arguments")
+ require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a", "z", "limit").Err(), "wrong number of arguments")
+ require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey", "a").Err(), "wrong number of arguments")
+ require.ErrorContains(t, rdb.Do(ctx, "HRange", "hashkey").Err(), "wrong number of arguments")
+ require.ErrorContains(t, rdb.Do(ctx, "HRange").Err(), "wrong number of arguments")
+ })
+ }
}
diff --git a/tests/gocase/util/random.go b/tests/gocase/util/random.go
index c8b949b..bb114aa 100644
--- a/tests/gocase/util/random.go
+++ b/tests/gocase/util/random.go
@@ -36,7 +36,7 @@ func RandPathNoResult(funcs ...func()) {
}
// Random signed integer in (-max, max)
-func randomSignedInt(max int32) int64 {
+func RandomSignedInt(max int32) int64 {
return rand.Int63n(int64(max)*2-1) - int64(max) + 1
}
@@ -78,7 +78,7 @@ func RandomValue() string {
return RandPath(
// Small enough to likely collide
func() string {
- return fmt.Sprintf("%d", randomSignedInt(1000))
+ return fmt.Sprintf("%d", RandomSignedInt(1000))
},
// 32 bit compressible signed/unsigned
func() string {
diff --git a/tests/tcl/tests/test_helper.tcl b/tests/tcl/tests/test_helper.tcl
index d16a59c..0596bf7 100644
--- a/tests/tcl/tests/test_helper.tcl
+++ b/tests/tcl/tests/test_helper.tcl
@@ -37,7 +37,6 @@ set ::all_tests {
unit/type/string
unit/type/list
unit/type/zset
- unit/type/hash
unit/type/stream
unit/multi
unit/expire
diff --git a/tests/tcl/tests/unit/type/hash.tcl b/tests/tcl/tests/unit/type/hash.tcl
deleted file mode 100644
index 0352eae..0000000
--- a/tests/tcl/tests/unit/type/hash.tcl
+++ /dev/null
@@ -1,528 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# Copyright (c) 2006-2020, Salvatore Sanfilippo
-# See bundled license file licenses/LICENSE.redis for details.
-
-# This file is copied and modified from the Redis project,
-# which started out as: https://github.com/redis/redis/blob/dbcc0a8/tests/unit/type/hash.tcl
-
-start_server {tags {"hash"}} {
- test {HSET/HLEN - Small hash creation} {
- array set smallhash {}
- for {set i 0} {$i < 8} {incr i} {
- set key __avoid_collisions__[randstring 0 8 alpha]
- set val __avoid_collisions__[randstring 0 8 alpha]
- if {[info exists smallhash($key)]} {
- incr i -1
- continue
- }
- r hset smallhash $key $val
- set smallhash($key) $val
- }
- list [r hlen smallhash]
- } {8}
-
- test {HSET/HLEN - Big hash creation} {
- array set bighash {}
- for {set i 0} {$i < 1024} {incr i} {
- set key __avoid_collisions__[randstring 0 8 alpha]
- set val __avoid_collisions__[randstring 0 8 alpha]
- if {[info exists bighash($key)]} {
- incr i -1
- continue
- }
- r hset bighash $key $val
- set bighash($key) $val
- }
- list [r hlen bighash]
- } {1024}
-
- test {HSET wrong number of args} {
- catch {r hset hmsetmulti key1 val1 key2} err
- format $err
- } {*wrong number*}
-
- test {HSET supports multiple fields} {
- assert_equal "2" [r hset hmsetmulti key1 val1 key2 val2]
- assert_equal "0" [r hset hmsetmulti key1 val1 key2 val2]
- assert_equal "1" [r hset hmsetmulti key1 val1 key3 val3]
- }
-
- test {HGET against the small hash} {
- set err {}
- foreach k [array names smallhash *] {
- if {$smallhash($k) ne [r hget smallhash $k]} {
- set err "$smallhash($k) != [r hget smallhash $k]"
- break
- }
- }
- set _ $err
- } {}
-
- test {HGET against the big hash} {
- set err {}
- foreach k [array names bighash *] {
- if {$bighash($k) ne [r hget bighash $k]} {
- set err "$bighash($k) != [r hget bighash $k]"
- break
- }
- }
- set _ $err
- } {}
-
- test {HGET against non existing key} {
- set rv {}
- lappend rv [r hget smallhash __123123123__]
- lappend rv [r hget bighash __123123123__]
- set _ $rv
- } {{} {}}
-
- test {HSET in update and insert mode} {
- set rv {}
- set k [lindex [array names smallhash *] 0]
- lappend rv [r hset smallhash $k newval1]
- set smallhash($k) newval1
- lappend rv [r hget smallhash $k]
- lappend rv [r hset smallhash __foobar123__ newval]
- set k [lindex [array names bighash *] 0]
- lappend rv [r hset bighash $k newval2]
- set bighash($k) newval2
- lappend rv [r hget bighash $k]
- lappend rv [r hset bighash __foobar123__ newval]
- lappend rv [r hdel smallhash __foobar123__]
- lappend rv [r hdel bighash __foobar123__]
- set _ $rv
- } {0 newval1 1 0 newval2 1 1 1}
-
- test {HSETNX target key missing - small hash} {
- r hsetnx smallhash __123123123__ foo
- r hget smallhash __123123123__
- } {foo}
-
- test {HSETNX target key exists - small hash} {
- r hsetnx smallhash __123123123__ bar
- set result [r hget smallhash __123123123__]
- r hdel smallhash __123123123__
- set _ $result
- } {foo}
-
- test {HSETNX target key missing - big hash} {
- r hsetnx bighash __123123123__ foo
- r hget bighash __123123123__
- } {foo}
-
- test {HSETNX target key exists - big hash} {
- r hsetnx bighash __123123123__ bar
- set result [r hget bighash __123123123__]
- r hdel bighash __123123123__
- set _ $result
- } {foo}
-
- test {HMSET wrong number of args} {
- catch {r hmset smallhash key1 val1 key2} err
- format $err
- } {*wrong number*}
-
- test {HMSET - small hash} {
- set args {}
- foreach {k v} [array get smallhash] {
- set newval [randstring 0 8 alpha]
- set smallhash($k) $newval
- lappend args $k $newval
- }
- r hmset smallhash {*}$args
- } {OK}
-
- test {HMSET - big hash} {
- set args {}
- foreach {k v} [array get bighash] {
- set newval [randstring 0 8 alpha]
- set bighash($k) $newval
- lappend args $k $newval
- }
- r hmset bighash {*}$args
- } {OK}
-
- test {HMGET against non existing key and fields} {
- set rv {}
- lappend rv [r hmget doesntexist __123123123__ __456456456__]
- lappend rv [r hmget smallhash __123123123__ __456456456__]
- lappend rv [r hmget bighash __123123123__ __456456456__]
- set _ $rv
- } {{{} {}} {{} {}} {{} {}}}
-
- test {HMGET against wrong type} {
- r set wrongtype somevalue
- assert_error "*wrong*" {r hmget wrongtype field1 field2}
- }
-
- test {HMGET - small hash} {
- set keys {}
- set vals {}
- foreach {k v} [array get smallhash] {
- lappend keys $k
- lappend vals $v
- }
- set err {}
- set result [r hmget smallhash {*}$keys]
- if {$vals ne $result} {
- set err "$vals != $result"
- break
- }
- set _ $err
- } {}
-
- test {HMGET - big hash} {
- set keys {}
- set vals {}
- foreach {k v} [array get bighash] {
- lappend keys $k
- lappend vals $v
- }
- set err {}
- set result [r hmget bighash {*}$keys]
- if {$vals ne $result} {
- set err "$vals != $result"
- break
- }
- set _ $err
- } {}
-
- test {HKEYS - small hash} {
- lsort [r hkeys smallhash]
- } [lsort [array names smallhash *]]
-
- test {HKEYS - big hash} {
- lsort [r hkeys bighash]
- } [lsort [array names bighash *]]
-
- test {HVALS - small hash} {
- set vals {}
- foreach {k v} [array get smallhash] {
- lappend vals $v
- }
- set _ [lsort $vals]
- } [lsort [r hvals smallhash]]
-
- test {HVALS - big hash} {
- set vals {}
- foreach {k v} [array get bighash] {
- lappend vals $v
- }
- set _ [lsort $vals]
- } [lsort [r hvals bighash]]
-
- test {HGETALL - small hash} {
- lsort [r hgetall smallhash]
- } [lsort [array get smallhash]]
-
- test {HGETALL - big hash} {
- lsort [r hgetall bighash]
- } [lsort [array get bighash]]
-
- test {HDEL and return value} {
- set rv {}
- lappend rv [r hdel smallhash nokey]
- lappend rv [r hdel bighash nokey]
- set k [lindex [array names smallhash *] 0]
- lappend rv [r hdel smallhash $k]
- lappend rv [r hdel smallhash $k]
- lappend rv [r hget smallhash $k]
- unset smallhash($k)
- set k [lindex [array names bighash *] 0]
- lappend rv [r hdel bighash $k]
- lappend rv [r hdel bighash $k]
- lappend rv [r hget bighash $k]
- unset bighash($k)
- set _ $rv
- } {0 0 1 0 {} 1 0 {}}
-
- test {HDEL - more than a single value} {
- set rv {}
- r del myhash
- r hmset myhash a 1 b 2 c 3
- assert_equal 0 [r hdel myhash x y]
- assert_equal 2 [r hdel myhash a c f]
- r hgetall myhash
- } {b 2}
-
- test {HDEL - hash becomes empty before deleting all specified fields} {
- r del myhash
- r hmset myhash a 1 b 2 c 3
- assert_equal 3 [r hdel myhash a b c d e]
- assert_equal 0 [r exists myhash]
- }
-
- test {HEXISTS} {
- set rv {}
- set k [lindex [array names smallhash *] 0]
- lappend rv [r hexists smallhash $k]
- lappend rv [r hexists smallhash nokey]
- set k [lindex [array names bighash *] 0]
- lappend rv [r hexists bighash $k]
- lappend rv [r hexists bighash nokey]
- } {1 0 1 0}
-
- test {HINCRBY against non existing database key} {
- r del htest
- list [r hincrby htest foo 2]
- } {2}
-
- test {HINCRBY against non existing hash key} {
- set rv {}
- r hdel smallhash tmp
- r hdel bighash tmp
- lappend rv [r hincrby smallhash tmp 2]
- lappend rv [r hget smallhash tmp]
- lappend rv [r hincrby bighash tmp 2]
- lappend rv [r hget bighash tmp]
- } {2 2 2 2}
-
- test {HINCRBY against hash key created by hincrby itself} {
- set rv {}
- lappend rv [r hincrby smallhash tmp 3]
- lappend rv [r hget smallhash tmp]
- lappend rv [r hincrby bighash tmp 3]
- lappend rv [r hget bighash tmp]
- } {5 5 5 5}
-
- test {HINCRBY against hash key originally set with HSET} {
- r hset smallhash tmp 100
- r hset bighash tmp 100
- list [r hincrby smallhash tmp 2] [r hincrby bighash tmp 2]
- } {102 102}
-
- test {HINCRBY over 32bit value} {
- r hset smallhash tmp 17179869184
- r hset bighash tmp 17179869184
- list [r hincrby smallhash tmp 1] [r hincrby bighash tmp 1]
- } {17179869185 17179869185}
-
- test {HINCRBY over 32bit value with over 32bit increment} {
- r hset smallhash tmp 17179869184
- r hset bighash tmp 17179869184
- list [r hincrby smallhash tmp 17179869184] [r hincrby bighash tmp 17179869184]
- } {34359738368 34359738368}
-
- test {HINCRBY fails against hash value with spaces (left)} {
- r hset smallhash str " 11"
- r hset bighash str " 11"
- catch {r hincrby smallhash str 1} smallerr
- catch {r hincrby smallhash str 1} bigerr
- set rv {}
- lappend rv [string match "ERR*not an integer*" $smallerr]
- lappend rv [string match "ERR*not an integer*" $bigerr]
- } {1 1}
-
- test {HINCRBY fails against hash value with spaces (right)} {
- r hset smallhash str "11 "
- r hset bighash str "11 "
- catch {r hincrby smallhash str 1} smallerr
- catch {r hincrby smallhash str 1} bigerr
- set rv {}
- lappend rv [string match "ERR*non-integer*" $smallerr]
- lappend rv [string match "ERR*non-integer*" $bigerr]
- } {1 1}
-
- test {HINCRBY can detect overflows} {
- set e {}
- r hset hash n -9223372036854775484
- assert {[r hincrby hash n -1] == -9223372036854775485}
- catch {r hincrby hash n -10000} e
- set e
- } {*overflow*}
-
- test {HINCRBYFLOAT against non existing database key} {
- r del htest
- list [r hincrbyfloat htest foo 2.5]
- } {2.5}
-
- test {HINCRBYFLOAT against non existing hash key} {
- set rv {}
- r hdel smallhash tmp
- r hdel bighash tmp
- lappend rv [roundFloat [r hincrbyfloat smallhash tmp 2.5]]
- lappend rv [roundFloat [r hget smallhash tmp]]
- lappend rv [roundFloat [r hincrbyfloat bighash tmp 2.5]]
- lappend rv [roundFloat [r hget bighash tmp]]
- } {2.5 2.5 2.5 2.5}
-
- test {HINCRBYFLOAT against hash key created by hincrby itself} {
- set rv {}
- lappend rv [roundFloat [r hincrbyfloat smallhash tmp 3.5]]
- lappend rv [roundFloat [r hget smallhash tmp]]
- lappend rv [roundFloat [r hincrbyfloat bighash tmp 3.5]]
- lappend rv [roundFloat [r hget bighash tmp]]
- } {6 6 6 6}
-
- test {HINCRBYFLOAT against hash key originally set with HSET} {
- r hset smallhash tmp 100
- r hset bighash tmp 100
- list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \
- [roundFloat [r hincrbyfloat bighash tmp 2.5]]
- } {102.5 102.5}
-
- test {HINCRBYFLOAT over 32bit value} {
- r hset smallhash tmp 17179869184
- r hset bighash tmp 17179869184
- list [r hincrbyfloat smallhash tmp 1] \
- [r hincrbyfloat bighash tmp 1]
- } {17179869185 17179869185}
-
- test {HINCRBYFLOAT over 32bit value with over 32bit increment} {
- r hset smallhash tmp 17179869184
- r hset bighash tmp 17179869184
- list [r hincrbyfloat smallhash tmp 17179869184] \
- [r hincrbyfloat bighash tmp 17179869184]
- } {34359738368 34359738368}
-
- test {HINCRBYFLOAT fails against hash value with spaces (left)} {
- r hset smallhash str " 11"
- r hset bighash str " 11"
- catch {r hincrbyfloat smallhash str 1} smallerr
- catch {r hincrbyfloat smallhash str 1} bigerr
- set rv {}
- lappend rv [string match "ERR*not*float*" $smallerr]
- lappend rv [string match "ERR*not*float*" $bigerr]
- } {1 1}
-
- test {HINCRBYFLOAT fails against hash value with spaces (right)} {
- r hset smallhash str "11 "
- r hset bighash str "11 "
- catch {r hincrbyfloat smallhash str 1} smallerr
- catch {r hincrbyfloat smallhash str 1} bigerr
- set rv {}
- lappend rv [string match "ERR*not*float*" $smallerr]
- lappend rv [string match "ERR*not*float*" $bigerr]
- } {1 1}
-
- test {HSTRLEN against the small hash} {
- set err {}
- foreach k [array names smallhash *] {
- if {[string length $smallhash($k)] ne [r hstrlen smallhash $k]} {
- set err "[string length $smallhash($k)] != [r hstrlen smallhash $k]"
- break
- }
- }
- set _ $err
- } {}
-
- test {HSTRLEN against the big hash} {
- set err {}
- foreach k [array names bighash *] {
- if {[string length $bighash($k)] ne [r hstrlen bighash $k]} {
- set err "[string length $bighash($k)] != [r hstrlen bighash $k]"
- puts "HSTRLEN and logical length mismatch:"
- puts "key: $k"
- puts "Logical content: $bighash($k)"
- puts "Server content: [r hget bighash $k]"
- }
- }
- set _ $err
- } {}
-
- test {HSTRLEN against non existing field} {
- set rv {}
- lappend rv [r hstrlen smallhash __123123123__]
- lappend rv [r hstrlen bighash __123123123__]
- set _ $rv
- } {0 0}
-
- test {HSTRLEN corner cases} {
- set vals {
- -9223372036854775808 9223372036854775807 9223372036854775808
- {} 0 -1 x
- }
- foreach v $vals {
- r hmset smallhash field $v
- r hmset bighash field $v
- set len1 [string length $v]
- set len2 [r hstrlen smallhash field]
- set len3 [r hstrlen bighash field]
- assert {$len1 == $len2}
- assert {$len2 == $len3}
- }
- }
-
- test {Hash ziplist regression test for large keys} {
- r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a
- r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b
- r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
- } {b}
-
- foreach size {10 512} {
- test "Hash fuzzing #1 - $size fields" {
- for {set times 0} {$times < 10} {incr times} {
- catch {unset hash}
- array set hash {}
- r del hash
-
- # Create
- for {set j 0} {$j < $size} {incr j} {
- set field [randomValue]
- set value [randomValue]
- r hset hash $field $value
- set hash($field) $value
- }
-
- # Verify
- foreach {k v} [array get hash] {
- assert_equal $v [r hget hash $k]
- }
- assert_equal [array size hash] [r hlen hash]
- }
- }
-
- test "Hash fuzzing #2 - $size fields" {
- for {set times 0} {$times < 10} {incr times} {
- catch {unset hash}
- array set hash {}
- r del hash
-
- # Create
- for {set j 0} {$j < $size} {incr j} {
- randpath {
- set field [randomValue]
- set value [randomValue]
- r hset hash $field $value
- set hash($field) $value
- } {
- set field [randomSignedInt 512]
- set value [randomSignedInt 512]
- r hset hash $field $value
- set hash($field) $value
- } {
- randpath {
- set field [randomValue]
- } {
- set field [randomSignedInt 512]
- }
- r hdel hash $field
- unset -nocomplain hash($field)
- }
- }
-
- # Verify
- foreach {k v} [array get hash] {
- assert_equal $v [r hget hash $k]
- }
- assert_equal [array size hash] [r hlen hash]
- }
- }
- }
-}