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

     1  package database
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  
     7  	"github.com/hdt3213/godis/lib/utils"
     8  	"github.com/hdt3213/godis/redis/protocol"
     9  	"github.com/hdt3213/godis/redis/protocol/asserts"
    10  )
    11  
    12  func TestPush(t *testing.T) {
    13  	testDB.Flush()
    14  	size := 100
    15  
    16  	// rpush single
    17  	key := utils.RandString(10)
    18  	values := make([][]byte, size)
    19  	for i := 0; i < size; i++ {
    20  		value := utils.RandString(10)
    21  		values[i] = []byte(value)
    22  		result := testDB.Exec(nil, utils.ToCmdLine("rpush", key, value))
    23  		if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(i+1) {
    24  			t.Errorf("expected %d, actually %d", i+1, intResult.Code)
    25  		}
    26  	}
    27  	actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
    28  	expected := protocol.MakeMultiBulkReply(values)
    29  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
    30  		t.Error("push error")
    31  	}
    32  	testDB.Remove(key)
    33  
    34  	// rpush multi
    35  	key = utils.RandString(10)
    36  	args := make([]string, size+1)
    37  	args[0] = key
    38  	values = make([][]byte, size)
    39  	for i := 0; i < size; i++ {
    40  		value := utils.RandString(10)
    41  		values[i] = []byte(value)
    42  		args[i+1] = value
    43  	}
    44  	result := testDB.Exec(nil, utils.ToCmdLine2("rpush", args...))
    45  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
    46  		t.Errorf("expected %d, actually %d", size, intResult.Code)
    47  	}
    48  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
    49  	expected = protocol.MakeMultiBulkReply(values)
    50  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
    51  		t.Error("push error")
    52  	}
    53  	testDB.Remove(key)
    54  
    55  	// left push single
    56  	key = utils.RandString(10)
    57  	values = make([][]byte, size)
    58  	for i := 0; i < size; i++ {
    59  		value := utils.RandString(10)
    60  		values[size-i-1] = []byte(value)
    61  		result = testDB.Exec(nil, utils.ToCmdLine("lpush", key, value))
    62  		if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(i+1) {
    63  			t.Errorf("expected %d, actually %d", i+1, intResult.Code)
    64  		}
    65  	}
    66  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
    67  	expected = protocol.MakeMultiBulkReply(values)
    68  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
    69  		t.Error("push error")
    70  	}
    71  	testDB.Remove(key)
    72  
    73  	// left push multi
    74  	key = utils.RandString(10)
    75  	args = make([]string, size+1)
    76  	args[0] = key
    77  	expectedValues := make([][]byte, size)
    78  	for i := 0; i < size; i++ {
    79  		value := utils.RandString(10)
    80  		args[i+1] = value
    81  		expectedValues[size-i-1] = []byte(value)
    82  	}
    83  	// result = execLPush(testDB, values)
    84  	result = testDB.Exec(nil, utils.ToCmdLine2("lpush", args...))
    85  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
    86  		t.Errorf("expected %d, actually %d", size, intResult.Code)
    87  	}
    88  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
    89  	expected = protocol.MakeMultiBulkReply(expectedValues)
    90  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
    91  		t.Error("push error")
    92  	}
    93  	testDB.Remove(key)
    94  }
    95  
    96  func TestLRange(t *testing.T) {
    97  	// prepare list
    98  	testDB.Flush()
    99  	size := 100
   100  	key := utils.RandString(10)
   101  	values := make([][]byte, size)
   102  	for i := 0; i < size; i++ {
   103  		value := utils.RandString(10)
   104  		testDB.Exec(nil, utils.ToCmdLine("rpush", key, value))
   105  		values[i] = []byte(value)
   106  	}
   107  
   108  	start := "0"
   109  	end := "9"
   110  	actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
   111  	expected := protocol.MakeMultiBulkReply(values[0:10])
   112  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   113  		t.Errorf("range error [%s, %s]", start, end)
   114  	}
   115  
   116  	start = "0"
   117  	end = "200"
   118  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
   119  	expected = protocol.MakeMultiBulkReply(values)
   120  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   121  		t.Errorf("range error [%s, %s]", start, end)
   122  	}
   123  
   124  	start = "0"
   125  	end = "-10"
   126  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
   127  	expected = protocol.MakeMultiBulkReply(values[0 : size-10+1])
   128  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   129  		t.Errorf("range error [%s, %s]", start, end)
   130  	}
   131  
   132  	start = "0"
   133  	end = "-200"
   134  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
   135  	expected = protocol.MakeMultiBulkReply(values[0:0])
   136  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   137  		t.Errorf("range error [%s, %s]", start, end)
   138  	}
   139  
   140  	start = "-10"
   141  	end = "-1"
   142  	actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
   143  	expected = protocol.MakeMultiBulkReply(values[90:])
   144  	if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
   145  		t.Errorf("range error [%s, %s]", start, end)
   146  	}
   147  }
   148  
   149  func TestLIndex(t *testing.T) {
   150  	// prepare list
   151  	testDB.Flush()
   152  	size := 100
   153  	key := utils.RandString(10)
   154  	values := make([][]byte, size)
   155  	for i := 0; i < size; i++ {
   156  		value := utils.RandString(10)
   157  		testDB.Exec(nil, utils.ToCmdLine("rpush", key, value))
   158  		values[i] = []byte(value)
   159  	}
   160  
   161  	result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
   162  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
   163  		t.Errorf("expected %d, actually %d", size, intResult.Code)
   164  	}
   165  
   166  	for i := 0; i < size; i++ {
   167  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(i)))
   168  		expected := protocol.MakeBulkReply(values[i])
   169  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   170  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   171  		}
   172  	}
   173  
   174  	for i := 1; i <= size; i++ {
   175  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(-i)))
   176  		expected := protocol.MakeBulkReply(values[size-i])
   177  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   178  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   179  		}
   180  	}
   181  }
   182  
   183  func TestLRem(t *testing.T) {
   184  	// prepare list
   185  	testDB.Flush()
   186  	key := utils.RandString(10)
   187  	values := []string{key, "a", "b", "a", "a", "c", "a", "a"}
   188  	testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
   189  
   190  	result := testDB.Exec(nil, utils.ToCmdLine("lrem", key, "1", "a"))
   191  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 1 {
   192  		t.Errorf("expected %d, actually %d", 1, intResult.Code)
   193  	}
   194  	result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
   195  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 6 {
   196  		t.Errorf("expected %d, actually %d", 6, intResult.Code)
   197  	}
   198  
   199  	result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "-2", "a"))
   200  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
   201  		t.Errorf("expected %d, actually %d", 2, intResult.Code)
   202  	}
   203  	result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
   204  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 4 {
   205  		t.Errorf("expected %d, actually %d", 4, intResult.Code)
   206  	}
   207  
   208  	result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "0", "a"))
   209  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
   210  		t.Errorf("expected %d, actually %d", 2, intResult.Code)
   211  	}
   212  	result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
   213  	if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
   214  		t.Errorf("expected %d, actually %d", 2, intResult.Code)
   215  	}
   216  }
   217  
   218  func TestLSet(t *testing.T) {
   219  	testDB.Flush()
   220  	key := utils.RandString(10)
   221  	values := []string{key, "a", "b", "c", "d", "e", "f"}
   222  	testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
   223  
   224  	// test positive index
   225  	size := len(values) - 1
   226  	for i := 0; i < size; i++ {
   227  		indexStr := strconv.Itoa(i)
   228  		value := utils.RandString(10)
   229  		result := testDB.Exec(nil, utils.ToCmdLine("lset", key, indexStr, value))
   230  		if _, ok := result.(*protocol.OkReply); !ok {
   231  			t.Errorf("expected OK, actually %s", string(result.ToBytes()))
   232  		}
   233  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, indexStr))
   234  		expected := protocol.MakeBulkReply([]byte(value))
   235  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   236  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   237  		}
   238  	}
   239  	// test negative index
   240  	for i := 1; i <= size; i++ {
   241  		value := utils.RandString(10)
   242  		result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-i), value))
   243  		if _, ok := result.(*protocol.OkReply); !ok {
   244  			t.Errorf("expected OK, actually %s", string(result.ToBytes()))
   245  		}
   246  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(len(values)-i-1)))
   247  		expected := protocol.MakeBulkReply([]byte(value))
   248  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   249  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   250  		}
   251  	}
   252  
   253  	// test illegal index
   254  	value := utils.RandString(10)
   255  	result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-len(values)-1), value))
   256  	expected := protocol.MakeErrReply("ERR index out of range")
   257  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   258  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   259  	}
   260  	result = testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(len(values)), value))
   261  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   262  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   263  	}
   264  	result = testDB.Exec(nil, utils.ToCmdLine("lset", key, "a", value))
   265  	expected = protocol.MakeErrReply("ERR value is not an integer or out of range")
   266  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   267  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   268  	}
   269  }
   270  
   271  func TestLPop(t *testing.T) {
   272  	testDB.Flush()
   273  	key := utils.RandString(10)
   274  	values := []string{key, "a", "b", "c", "d", "e", "f"}
   275  	testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
   276  	size := len(values) - 1
   277  
   278  	for i := 0; i < size; i++ {
   279  		result := testDB.Exec(nil, utils.ToCmdLine("lpop", key))
   280  		expected := protocol.MakeBulkReply([]byte(values[i+1]))
   281  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   282  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   283  		}
   284  	}
   285  	result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
   286  	expected := &protocol.NullBulkReply{}
   287  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   288  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   289  	}
   290  }
   291  
   292  func TestRPop(t *testing.T) {
   293  	testDB.Flush()
   294  	key := utils.RandString(10)
   295  	values := []string{key, "a", "b", "c", "d", "e", "f"}
   296  	testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
   297  	size := len(values) - 1
   298  
   299  	for i := 0; i < size; i++ {
   300  		result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
   301  		expected := protocol.MakeBulkReply([]byte(values[len(values)-i-1]))
   302  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   303  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   304  		}
   305  	}
   306  	result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
   307  	expected := &protocol.NullBulkReply{}
   308  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   309  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   310  	}
   311  }
   312  
   313  func TestRPopLPush(t *testing.T) {
   314  	testDB.Flush()
   315  	key1 := utils.RandString(10)
   316  	key2 := utils.RandString(10)
   317  	values := []string{key1, "a", "b", "c", "d", "e", "f"}
   318  	testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
   319  	size := len(values) - 1
   320  
   321  	for i := 0; i < size; i++ {
   322  		result := testDB.Exec(nil, utils.ToCmdLine("rpoplpush", key1, key2))
   323  		expected := protocol.MakeBulkReply([]byte(values[len(values)-i-1]))
   324  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   325  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   326  		}
   327  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key2, "0"))
   328  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   329  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   330  		}
   331  	}
   332  	result := testDB.Exec(nil, utils.ToCmdLine("rpop", key1))
   333  	expected := &protocol.NullBulkReply{}
   334  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   335  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   336  	}
   337  }
   338  
   339  func TestRPushX(t *testing.T) {
   340  	testDB.Flush()
   341  	key := utils.RandString(10)
   342  	result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
   343  	expected := protocol.MakeIntReply(int64(0))
   344  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   345  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   346  	}
   347  
   348  	testDB.Exec(nil, utils.ToCmdLine("rpush", key, "1"))
   349  	for i := 0; i < 10; i++ {
   350  		value := utils.RandString(10)
   351  		result = testDB.Exec(nil, utils.ToCmdLine("rpushx", key, value))
   352  		expected := protocol.MakeIntReply(int64(i + 2))
   353  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   354  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   355  		}
   356  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "-1"))
   357  		expected2 := protocol.MakeBulkReply([]byte(value))
   358  		if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
   359  			t.Errorf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes()))
   360  		}
   361  	}
   362  }
   363  
   364  func TestLPushX(t *testing.T) {
   365  	testDB.Flush()
   366  	key := utils.RandString(10)
   367  	result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
   368  	expected := protocol.MakeIntReply(int64(0))
   369  	if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   370  		t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   371  	}
   372  
   373  	testDB.Exec(nil, utils.ToCmdLine("lpush", key, "1"))
   374  	for i := 0; i < 10; i++ {
   375  		value := utils.RandString(10)
   376  		result = testDB.Exec(nil, utils.ToCmdLine("lpushx", key, value))
   377  		expected := protocol.MakeIntReply(int64(i + 2))
   378  		if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
   379  			t.Errorf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes()))
   380  		}
   381  		result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "0"))
   382  		expected2 := protocol.MakeBulkReply([]byte(value))
   383  		if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
   384  			t.Errorf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes()))
   385  		}
   386  	}
   387  }
   388  
   389  func TestLTrim(t *testing.T) {
   390  	testDB.Flush()
   391  	key := utils.RandString(10)
   392  	values := []string{"a", "b", "c", "d", "e", "f"}
   393  	result := testDB.Exec(nil, utils.ToCmdLine("rpush", key, "a", "b", "c", "d", "e", "f"))
   394  	asserts.AssertIntReply(t, result, 6)
   395  
   396  	// case1
   397  	result1 := testDB.Exec(nil, utils.ToCmdLine("ltrim", key, "1", "-2"))
   398  	asserts.AssertStatusReply(t, result1, "OK")
   399  
   400  	actualValue1 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
   401  	asserts.AssertMultiBulkReply(t, actualValue1, values[1:5])
   402  
   403  	// case2
   404  	result2 := testDB.Exec(nil, utils.ToCmdLine("ltrim", key, "-3", "-2"))
   405  	asserts.AssertStatusReply(t, result2, "OK")
   406  
   407  	actualValue2 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
   408  	asserts.AssertMultiBulkReply(t, actualValue2, values[2:4])
   409  
   410  	// case3
   411  	result3 := testDB.Exec(nil, utils.ToCmdLine("ltrim", key, "1", "0"))
   412  	asserts.AssertStatusReply(t, result3, "OK")
   413  
   414  	actualValue3 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
   415  	asserts.AssertMultiBulkReplySize(t, actualValue3, 0)
   416  }
   417  
   418  func TestLInsert(t *testing.T) {
   419  	testDB.Flush()
   420  	key := utils.RandString(10)
   421  	result := testDB.Exec(nil, utils.ToCmdLine("rpush", key, "a", "b", "c", "d", "e", "f"))
   422  	asserts.AssertIntReply(t, result, 6)
   423  
   424  	// case1
   425  	result = testDB.Exec(nil, utils.ToCmdLine("linsert", key, "before", "d", "0"))
   426  	asserts.AssertIntReply(t, result, 7)
   427  
   428  	values1 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
   429  	asserts.AssertMultiBulkReply(t, values1, []string{"a", "b", "c", "0", "d", "e", "f"})
   430  
   431  	// case2
   432  	result = testDB.Exec(nil, utils.ToCmdLine("linsert", key, "after", "d", "1"))
   433  	asserts.AssertIntReply(t, result, 8)
   434  
   435  	values2 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
   436  	asserts.AssertMultiBulkReply(t, values2, []string{"a", "b", "c", "0", "d", "1", "e", "f"})
   437  
   438  	// case3
   439  	result3 := testDB.Exec(nil, utils.ToCmdLine("linsert", key, "test", "d", "1"))
   440  	asserts.AssertErrReply(t, result3, "ERR syntax error")
   441  
   442  	// case4
   443  	result4 := testDB.Exec(nil, utils.ToCmdLine("linsert", key, "test", "d"))
   444  	asserts.AssertErrReply(t, result4, "ERR wrong number of arguments for 'linsert' command")
   445  
   446  	// case5
   447  	result5 := testDB.Exec(nil, utils.ToCmdLine("linsert", key, "before", "z", "2"))
   448  	asserts.AssertIntReply(t, result5, -1)
   449  }
   450  
   451  func TestUndoLPush(t *testing.T) {
   452  	testDB.Flush()
   453  	key := utils.RandString(10)
   454  	value := utils.RandString(10)
   455  	cmdLine := utils.ToCmdLine("lpush", key, value)
   456  	testDB.Exec(nil, cmdLine)
   457  	undoCmdLines := undoLPush(testDB, cmdLine[1:])
   458  	testDB.Exec(nil, cmdLine)
   459  	for _, cmdLine := range undoCmdLines {
   460  		testDB.Exec(nil, cmdLine)
   461  	}
   462  	result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
   463  	asserts.AssertIntReply(t, result, 1)
   464  }
   465  
   466  func TestUndoLPop(t *testing.T) {
   467  	testDB.Flush()
   468  	key := utils.RandString(10)
   469  	value := utils.RandString(10)
   470  	testDB.Exec(nil, utils.ToCmdLine("lpush", key, value, value))
   471  	cmdLine := utils.ToCmdLine("lpop", key)
   472  	undoCmdLines := undoLPop(testDB, cmdLine[1:])
   473  	testDB.Exec(nil, cmdLine)
   474  	for _, cmdLine := range undoCmdLines {
   475  		testDB.Exec(nil, cmdLine)
   476  	}
   477  	result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
   478  	asserts.AssertIntReply(t, result, 2)
   479  }
   480  
   481  func TestUndoLSet(t *testing.T) {
   482  	testDB.Flush()
   483  	key := utils.RandString(10)
   484  	value := utils.RandString(10)
   485  	value2 := utils.RandString(10)
   486  	testDB.Exec(nil, utils.ToCmdLine("lpush", key, value, value))
   487  	cmdLine := utils.ToCmdLine("lset", key, "1", value2)
   488  	undoCmdLines := undoLSet(testDB, cmdLine[1:])
   489  	testDB.Exec(nil, cmdLine)
   490  	for _, cmdLine := range undoCmdLines {
   491  		testDB.Exec(nil, cmdLine)
   492  	}
   493  	result := testDB.Exec(nil, utils.ToCmdLine("lindex", key, "1"))
   494  	asserts.AssertBulkReply(t, result, value)
   495  }
   496  
   497  func TestUndoRPop(t *testing.T) {
   498  	testDB.Flush()
   499  	key := utils.RandString(10)
   500  	value := utils.RandString(10)
   501  	testDB.Exec(nil, utils.ToCmdLine("rpush", key, value, value))
   502  	cmdLine := utils.ToCmdLine("rpop", key)
   503  	undoCmdLines := undoRPop(testDB, cmdLine[1:])
   504  	testDB.Exec(nil, cmdLine)
   505  	for _, cmdLine := range undoCmdLines {
   506  		testDB.Exec(nil, cmdLine)
   507  	}
   508  	result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
   509  	asserts.AssertIntReply(t, result, 2)
   510  }
   511  
   512  func TestUndoRPopLPush(t *testing.T) {
   513  	testDB.Flush()
   514  	key1 := utils.RandString(10)
   515  	key2 := utils.RandString(10)
   516  	value := utils.RandString(10)
   517  	testDB.Exec(nil, utils.ToCmdLine("lpush", key1, value))
   518  
   519  	cmdLine := utils.ToCmdLine("rpoplpush", key1, key2)
   520  	undoCmdLines := undoRPopLPush(testDB, cmdLine[1:])
   521  	testDB.Exec(nil, cmdLine)
   522  	for _, cmdLine := range undoCmdLines {
   523  		testDB.Exec(nil, cmdLine)
   524  	}
   525  	result := testDB.Exec(nil, utils.ToCmdLine("llen", key1))
   526  	asserts.AssertIntReply(t, result, 1)
   527  	result = testDB.Exec(nil, utils.ToCmdLine("llen", key2))
   528  	asserts.AssertIntReply(t, result, 0)
   529  }