diff --git a/database/list.go b/database/list.go index 4360a53..7d239db 100644 --- a/database/list.go +++ b/database/list.go @@ -152,16 +152,14 @@ func undoLPop(db *DB, args [][]byte) []CmdLine { if count > list.Len() { count = list.Len() } + elements := make([][]byte, count) vals := list.Range(0, count) - var cmds []CmdLine - for i := len(vals) - 1; i >= 0; i-- { - cmds = append(cmds, CmdLine{ - lPushCmd, - args[0], - vals[i].([]byte), - }) + for i := 0; i < count; i++ { + elements[count-i-1] = vals[i].([]byte) } - return cmds + cmd := CmdLine{lPushCmd, args[0]} + cmd = append(cmd, elements...) + return []CmdLine{cmd} } element, _ := list.Get(0).([]byte) return []CmdLine{ @@ -456,16 +454,14 @@ func undoRPop(db *DB, args [][]byte) []CmdLine { if count > list.Len() { count = list.Len() } + elements := make([][]byte, count) vals := list.Range(list.Len()-count, list.Len()) - var cmds []CmdLine for i := 0; i < count; i++ { - cmds = append(cmds, CmdLine{ - rPushCmd, - args[0], - vals[i].([]byte), - }) + elements[i] = vals[i].([]byte) } - return cmds + cmd := CmdLine{rPushCmd, args[0]} + cmd = append(cmd, elements...) + return []CmdLine{cmd} } element, _ := list.Get(list.Len() - 1).([]byte) return []CmdLine{ diff --git a/database/list_test.go b/database/list_test.go index 14e8501..c7ac4e4 100644 --- a/database/list_test.go +++ b/database/list_test.go @@ -496,24 +496,47 @@ func TestUndoLPush(t *testing.T) { func TestUndoLPop(t *testing.T) { testDB.Flush() key := utils.RandString(10) - value := utils.RandString(10) - testDB.Exec(nil, utils.ToCmdLine("lpush", key, value, value)) + size := 10 + values := make([]string, size) + pushArgs := []string{key} + for i := 0; i < size; i++ { + values[i] = utils.RandString(10) + pushArgs = append(pushArgs, values[i]) + } + testDB.Exec(nil, utils.ToCmdLine2("lpush", pushArgs...)) + result0 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + + // test single lpop cmdLine := utils.ToCmdLine("lpop", key) undoCmdLines := undoLPop(testDB, cmdLine[1:]) testDB.Exec(nil, cmdLine) - for _, cmdLine := range undoCmdLines { - testDB.Exec(nil, cmdLine) - } result := testDB.Exec(nil, utils.ToCmdLine("llen", key)) - asserts.AssertIntReply(t, result, 2) - cmdLine = utils.ToCmdLine("lpop", key, strconv.Itoa(2)) - undoCmdLines = undoRPop(testDB, cmdLine[1:]) - testDB.Exec(nil, cmdLine) + asserts.AssertIntReply(t, result, 9) for _, cmdLine := range undoCmdLines { testDB.Exec(nil, cmdLine) } result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) - asserts.AssertIntReply(t, result, 2) + asserts.AssertIntReply(t, result, size) + result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + if !utils.Equals(result0.ToBytes(), result.ToBytes()) { + t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes()) + } + + // test multi lpop + cmdLine = utils.ToCmdLine("lpop", key, strconv.Itoa(size)) + undoCmdLines = undoLPop(testDB, cmdLine[1:]) + testDB.Exec(nil, cmdLine) + result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) + asserts.AssertIntReply(t, result, 0) + for _, cmdLine := range undoCmdLines { + testDB.Exec(nil, cmdLine) + } + result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) + asserts.AssertIntReply(t, result, size) + result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + if !utils.Equals(result0.ToBytes(), result.ToBytes()) { + t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes()) + } } func TestUndoLSet(t *testing.T) { @@ -535,24 +558,47 @@ func TestUndoLSet(t *testing.T) { func TestUndoRPop(t *testing.T) { testDB.Flush() key := utils.RandString(10) - value := utils.RandString(10) - testDB.Exec(nil, utils.ToCmdLine("rpush", key, value, value)) + size := 10 + values := make([]string, size) + pushArgs := []string{key} + for i := 0; i < size; i++ { + values[i] = utils.RandString(10) + pushArgs = append(pushArgs, values[i]) + } + testDB.Exec(nil, utils.ToCmdLine2("rpush", pushArgs...)) + result0 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + + // test single rpop cmdLine := utils.ToCmdLine("rpop", key) undoCmdLines := undoRPop(testDB, cmdLine[1:]) testDB.Exec(nil, cmdLine) - for _, cmdLine := range undoCmdLines { - testDB.Exec(nil, cmdLine) - } result := testDB.Exec(nil, utils.ToCmdLine("llen", key)) - asserts.AssertIntReply(t, result, 2) - cmdLine = utils.ToCmdLine("rpop", key, strconv.Itoa(2)) - undoCmdLines = undoRPop(testDB, cmdLine[1:]) - testDB.Exec(nil, cmdLine) + asserts.AssertIntReply(t, result, 9) for _, cmdLine := range undoCmdLines { testDB.Exec(nil, cmdLine) } result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) - asserts.AssertIntReply(t, result, 2) + asserts.AssertIntReply(t, result, size) + result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + if !utils.Equals(result0.ToBytes(), result.ToBytes()) { + t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes()) + } + + // test multi rpop + cmdLine = utils.ToCmdLine("rpop", key, strconv.Itoa(size)) + undoCmdLines = undoRPop(testDB, cmdLine[1:]) + testDB.Exec(nil, cmdLine) + result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) + asserts.AssertIntReply(t, result, 0) + for _, cmdLine := range undoCmdLines { + testDB.Exec(nil, cmdLine) + } + result = testDB.Exec(nil, utils.ToCmdLine("llen", key)) + asserts.AssertIntReply(t, result, size) + result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size))) + if !utils.Equals(result0.ToBytes(), result.ToBytes()) { + t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes()) + } } func TestUndoRPopLPush(t *testing.T) {