github.com/hdt3213/godis@v1.2.9/database/hash_test.go (about)

     1  package database
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/hdt3213/godis/lib/utils"
     6  	"github.com/hdt3213/godis/redis/protocol"
     7  	"github.com/hdt3213/godis/redis/protocol/asserts"
     8  	"strconv"
     9  	"testing"
    10  )
    11  
    12  func TestHSet(t *testing.T) {
    13  	testDB.Flush()
    14  	size := 100
    15  
    16  	// test hset
    17  	key := utils.RandString(10)
    18  	values := make(map[string][]byte, size)
    19  	for i := 0; i < size; i++ {
    20  		value := utils.RandString(10)
    21  		field := strconv.Itoa(i)
    22  		values[field] = []byte(value)
    23  		result := testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
    24  		if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(1) {
    25  			t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
    26  		}
    27  	}
    28  
    29  	// test hget, hexists and hstrlen
    30  	for field, v := range values {
    31  		actual := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
    32  		expected := protocol.MakeBulkReply(v)
    33  		if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
    34  			t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
    35  		}
    36  		actual = testDB.Exec(nil, utils.ToCmdLine("hexists", key, field))
    37  		if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(1) {
    38  			t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
    39  		}
    40  
    41  		actual = testDB.Exec(nil, utils.ToCmdLine("hstrlen", key, field))
    42  		if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(v)) {
    43  			t.Error(fmt.Sprintf("expected %d, actually %d", int64(len(v)), intResult.Code))
    44  		}
    45  	}
    46  
    47  	// test hlen
    48  	actual := testDB.Exec(nil, utils.ToCmdLine("hlen", key))
    49  	if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(values)) {
    50  		t.Error(fmt.Sprintf("expected %d, actually %d", len(values), intResult.Code))
    51  	}
    52  }
    53  
    54  func TestHDel(t *testing.T) {
    55  	testDB.Flush()
    56  	size := 100
    57  
    58  	// set values
    59  	key := utils.RandString(10)
    60  	fields := make([]string, size)
    61  	for i := 0; i < size; i++ {
    62  		value := utils.RandString(10)
    63  		field := strconv.Itoa(i)
    64  		fields[i] = field
    65  		testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
    66  	}
    67  
    68  	// test HDel
    69  	args := []string{key}
    70  	args = append(args, fields...)
    71  	actual := testDB.Exec(nil, utils.ToCmdLine2("hdel", args...))
    72  	if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(fields)) {
    73  		t.Error(fmt.Sprintf("expected %d, actually %d", len(fields), intResult.Code))
    74  	}
    75  
    76  	actual = testDB.Exec(nil, utils.ToCmdLine("hlen", key))
    77  	if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(0) {
    78  		t.Error(fmt.Sprintf("expected %d, actually %d", 0, intResult.Code))
    79  	}
    80  }
    81  
    82  func TestHMSet(t *testing.T) {
    83  	testDB.Flush()
    84  	size := 100
    85  
    86  	// test hset
    87  	key := utils.RandString(10)
    88  	fields := make([]string, size)
    89  	values := make([]string, size)
    90  	setArgs := []string{key}
    91  	for i := 0; i < size; i++ {
    92  		fields[i] = utils.RandString(10)
    93  		values[i] = utils.RandString(10)
    94  		setArgs = append(setArgs, fields[i], values[i])
    95  	}
    96  	result := testDB.Exec(nil, utils.ToCmdLine2("hmset", setArgs...))
    97  	if _, ok := result.(*protocol.OkReply); !ok {
    98  		t.Error(fmt.Sprintf("expected ok, actually %s", string(result.ToBytes())))
    99  	}
   100  
   101  	// test HMGet
   102  	getArgs := []string{key}
   103  	getArgs = append(getArgs, fields...)
   104  	actual := testDB.Exec(nil, utils.ToCmdLine2("hmget", getArgs...))
   105  	expected := protocol.MakeMultiBulkReply(utils.ToCmdLine(values...))
   106  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   107  		t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
   108  	}
   109  }
   110  
   111  func TestHGetAll(t *testing.T) {
   112  	testDB.Flush()
   113  	size := 100
   114  	key := utils.RandString(10)
   115  	fields := make([]string, size)
   116  	valueSet := make(map[string]bool, size)
   117  	valueMap := make(map[string]string)
   118  	all := make([]string, 0)
   119  	for i := 0; i < size; i++ {
   120  		fields[i] = utils.RandString(10)
   121  		value := utils.RandString(10)
   122  		all = append(all, fields[i], value)
   123  		valueMap[fields[i]] = value
   124  		valueSet[value] = true
   125  		execHSet(testDB, utils.ToCmdLine(key, fields[i], value))
   126  	}
   127  
   128  	// test HGetAll
   129  	result := testDB.Exec(nil, utils.ToCmdLine("hgetall", key))
   130  	multiBulk, ok := result.(*protocol.MultiBulkReply)
   131  	if !ok {
   132  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   133  	}
   134  	if 2*len(fields) != len(multiBulk.Args) {
   135  		t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*len(fields), len(multiBulk.Args)))
   136  	}
   137  	for i := range fields {
   138  		field := string(multiBulk.Args[2*i])
   139  		actual := string(multiBulk.Args[2*i+1])
   140  		expected, ok := valueMap[field]
   141  		if !ok {
   142  			t.Error(fmt.Sprintf("unexpected field %s", field))
   143  			continue
   144  		}
   145  		if actual != expected {
   146  			t.Error(fmt.Sprintf("expected %s, actually %s", expected, actual))
   147  		}
   148  	}
   149  
   150  	// test HKeys
   151  	result = testDB.Exec(nil, utils.ToCmdLine("hkeys", key))
   152  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   153  	if !ok {
   154  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   155  	}
   156  	if len(fields) != len(multiBulk.Args) {
   157  		t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args)))
   158  	}
   159  	for _, v := range multiBulk.Args {
   160  		field := string(v)
   161  		if _, ok := valueMap[field]; !ok {
   162  			t.Error(fmt.Sprintf("unexpected field %s", field))
   163  		}
   164  	}
   165  
   166  	// test HVals
   167  	result = testDB.Exec(nil, utils.ToCmdLine("hvals", key))
   168  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   169  	if !ok {
   170  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   171  	}
   172  	if len(fields) != len(multiBulk.Args) {
   173  		t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args)))
   174  	}
   175  	for _, v := range multiBulk.Args {
   176  		value := string(v)
   177  		_, ok := valueSet[value]
   178  		if !ok {
   179  			t.Error(fmt.Sprintf("unexpected value %s", value))
   180  		}
   181  	}
   182  
   183  	// test HRandField
   184  	// test HRandField count of 0 is handled correctly -- "emptyarray"
   185  	result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, "0"))
   186  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   187  	if !ok {
   188  		resultBytes := string(result.ToBytes())
   189  		if resultBytes != "*0\r\n" {
   190  			t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", resultBytes))
   191  		}
   192  	}
   193  
   194  	// test HRandField count > size
   195  	result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(size+100)))
   196  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   197  	if !ok {
   198  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   199  	}
   200  	if len(fields) != len(multiBulk.Args) {
   201  		t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields), len(multiBulk.Args)))
   202  	}
   203  
   204  	// test HRandField count > size withvalues
   205  	result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(size+100), "withvalues"))
   206  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   207  	if !ok {
   208  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   209  	}
   210  	if 2*len(fields) != len(multiBulk.Args) {
   211  		t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*len(fields), len(multiBulk.Args)))
   212  	}
   213  
   214  	// test HRandField count < size
   215  	result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(-size-10)))
   216  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   217  	if !ok {
   218  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   219  	}
   220  	if len(fields)+10 != len(multiBulk.Args) {
   221  		t.Error(fmt.Sprintf("expected %d items , actually %d ", len(fields)+10, len(multiBulk.Args)))
   222  	}
   223  
   224  	// test HRandField count < size withvalues
   225  	result = testDB.Exec(nil, utils.ToCmdLine("hrandfield", key, strconv.Itoa(-size-10), "withvalues"))
   226  	multiBulk, ok = result.(*protocol.MultiBulkReply)
   227  	if !ok {
   228  		t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
   229  	}
   230  	if 2*(len(fields)+10) != len(multiBulk.Args) {
   231  		t.Error(fmt.Sprintf("expected %d items , actually %d ", 2*(len(fields)+10), len(multiBulk.Args)))
   232  	}
   233  }
   234  
   235  func TestHIncrBy(t *testing.T) {
   236  	testDB.Flush()
   237  
   238  	key := utils.RandString(10)
   239  	result := testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
   240  	if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1" {
   241  		t.Error(fmt.Sprintf("expected %s, actually %s", "1", string(bulkResult.Arg)))
   242  	}
   243  	result = testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
   244  	if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2" {
   245  		t.Error(fmt.Sprintf("expected %s, actually %s", "2", string(bulkResult.Arg)))
   246  	}
   247  
   248  	result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
   249  	if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1.2" {
   250  		t.Error(fmt.Sprintf("expected %s, actually %s", "1.2", string(bulkResult.Arg)))
   251  	}
   252  	result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
   253  	if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2.4" {
   254  		t.Error(fmt.Sprintf("expected %s, actually %s", "2.4", string(bulkResult.Arg)))
   255  	}
   256  }
   257  
   258  func TestHSetNX(t *testing.T) {
   259  	testDB.Flush()
   260  	key := utils.RandString(10)
   261  	field := utils.RandString(10)
   262  	value := utils.RandString(10)
   263  	result := testDB.Exec(nil, utils.ToCmdLine("hsetnx", key, field, value))
   264  	asserts.AssertIntReply(t, result, 1)
   265  	value2 := utils.RandString(10)
   266  	result = testDB.Exec(nil, utils.ToCmdLine("hsetnx", key, field, value2))
   267  	asserts.AssertIntReply(t, result, 0)
   268  	result = testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
   269  	asserts.AssertBulkReply(t, result, value)
   270  }
   271  
   272  func TestUndoHDel(t *testing.T) {
   273  	testDB.Flush()
   274  	key := utils.RandString(10)
   275  	field := utils.RandString(10)
   276  	value := utils.RandString(10)
   277  
   278  	testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
   279  	cmdLine := utils.ToCmdLine("hdel", key, field)
   280  	undoCmdLines := undoHDel(testDB, cmdLine[1:])
   281  	testDB.Exec(nil, cmdLine)
   282  	for _, cmdLine := range undoCmdLines {
   283  		testDB.Exec(nil, cmdLine)
   284  	}
   285  	result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
   286  	asserts.AssertBulkReply(t, result, value)
   287  }
   288  
   289  func TestUndoHSet(t *testing.T) {
   290  	testDB.Flush()
   291  	key := utils.RandString(10)
   292  	field := utils.RandString(10)
   293  	value := utils.RandString(10)
   294  	value2 := utils.RandString(10)
   295  
   296  	testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
   297  	cmdLine := utils.ToCmdLine("hset", key, field, value2)
   298  	undoCmdLines := undoHSet(testDB, cmdLine[1:])
   299  	testDB.Exec(nil, cmdLine)
   300  	for _, cmdLine := range undoCmdLines {
   301  		testDB.Exec(nil, cmdLine)
   302  	}
   303  	result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
   304  	asserts.AssertBulkReply(t, result, value)
   305  }
   306  
   307  func TestUndoHMSet(t *testing.T) {
   308  	testDB.Flush()
   309  	key := utils.RandString(10)
   310  	field1 := utils.RandString(10)
   311  	field2 := utils.RandString(10)
   312  	value := utils.RandString(10)
   313  	value2 := utils.RandString(10)
   314  
   315  	testDB.Exec(nil, utils.ToCmdLine("hmset", key, field1, value, field2, value))
   316  	cmdLine := utils.ToCmdLine("hmset", key, field1, value2, field2, value2)
   317  	undoCmdLines := undoHMSet(testDB, cmdLine[1:])
   318  	testDB.Exec(nil, cmdLine)
   319  	for _, cmdLine := range undoCmdLines {
   320  		testDB.Exec(nil, cmdLine)
   321  	}
   322  	result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field1))
   323  	asserts.AssertBulkReply(t, result, value)
   324  	result = testDB.Exec(nil, utils.ToCmdLine("hget", key, field2))
   325  	asserts.AssertBulkReply(t, result, value)
   326  }
   327  
   328  func TestUndoHIncr(t *testing.T) {
   329  	testDB.Flush()
   330  	key := utils.RandString(10)
   331  	field := utils.RandString(10)
   332  
   333  	testDB.Exec(nil, utils.ToCmdLine("hset", key, field, "1"))
   334  	cmdLine := utils.ToCmdLine("hinctby", key, field, "2")
   335  	undoCmdLines := undoHIncr(testDB, cmdLine[1:])
   336  	testDB.Exec(nil, cmdLine)
   337  	for _, cmdLine := range undoCmdLines {
   338  		testDB.Exec(nil, cmdLine)
   339  	}
   340  	result := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
   341  	asserts.AssertBulkReply(t, result, "1")
   342  }