Skip to content

Commit

Permalink
feat: Add transaction test cases for transaction execution
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-gang committed Jun 12, 2024
1 parent fa84532 commit 08ac41d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 100 deletions.
78 changes: 78 additions & 0 deletions internal/test_cases/transaction_test_case.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package test_cases

import (
resp_client "github.com/codecrafters-io/redis-tester/internal/resp/connection"
resp_value "github.com/codecrafters-io/redis-tester/internal/resp/value"
"github.com/codecrafters-io/redis-tester/internal/resp_assertions"
"github.com/codecrafters-io/tester-utils/logger"
)

// TransactionTestCase is a test case where we connect to a master
// as a replica and perform either all or a subset of the replication handshake.
//
// RunAll will run all the steps in the replication handshake. Alternatively, you
// can run each step individually.
type TransactionTestCase struct {
// All the CommandQueue will be sent in order to client
// And a string "QUEUED" will be expected
CommandQueue [][]string

// After queueing all the commands,
// if ResultArray is not empty, "EXEC" is sent
// And the response is compared with this ResultArray
ResultArray []resp_value.Value
}

func (t TransactionTestCase) RunAll(client *resp_client.RespConnection, logger *logger.Logger) error {
if err := t.RunMulti(client, logger); err != nil {
return err
}

if err := t.RunQueueAll(client, logger); err != nil {
return err
}

if len(t.ResultArray) > 0 {
if err := t.RunExec(client, logger); err != nil {
return err
}
}

return nil
}

func (t TransactionTestCase) RunMulti(client *resp_client.RespConnection, logger *logger.Logger) error {
commandTest := SendCommandTestCase{
Command: "MULTI",
Args: []string{},
Assertion: resp_assertions.NewStringAssertion("OK"),
}

return commandTest.Run(client, logger)
}

func (t TransactionTestCase) RunQueueAll(client *resp_client.RespConnection, logger *logger.Logger) error {
for i, v := range t.CommandQueue {
logger.Debugf("Sent #%d command", i)
commandTest := SendCommandTestCase{
Command: v[0],
Args: v[1:],
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}
if err := commandTest.Run(client, logger); err != nil {
return err
}
}

return nil
}

func (t TransactionTestCase) RunExec(client *resp_client.RespConnection, logger *logger.Logger) error {
setCommandTestCase := SendCommandTestCase{
Command: "EXEC",
Args: []string{},
Assertion: resp_assertions.NewOrderedArrayAssertion(t.ResultArray),
}

return setCommandTestCase.Run(client, logger)
}
48 changes: 8 additions & 40 deletions internal/test_txn_10.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,46 +45,14 @@ func testTxErr(stageHarness *test_case_harness.TestCaseHarness) error {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "MULTI",
Args: []string{},
Assertion: resp_assertions.NewStringAssertion("OK"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "INCR",
Args: []string{"foo"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "INCR",
Args: []string{"bar"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "EXEC",
Args: []string{},
Assertion: resp_assertions.NewOrderedArrayAssertion([]resp_value.Value{
resp_value.NewErrorValue("ERR value is not an integer or out of range"), resp_value.NewIntegerValue(8)}),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
transactionTestCase := test_cases.TransactionTestCase{
CommandQueue: [][]string{
{"INCR", "foo"},
{"INCR", "bar"},
},
ResultArray: []resp_value.Value{
resp_value.NewErrorValue("ERR value is not an integer or out of range"), resp_value.NewIntegerValue(8)},
}

return nil
return transactionTestCase.RunAll(client, logger)
}
69 changes: 9 additions & 60 deletions internal/test_txn_8.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
resp_value "github.com/codecrafters-io/redis-tester/internal/resp/value"

"github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection"
"github.com/codecrafters-io/redis-tester/internal/resp_assertions"
"github.com/codecrafters-io/redis-tester/internal/test_cases"
"github.com/codecrafters-io/tester-utils/test_case_harness"
)
Expand All @@ -25,65 +24,15 @@ func testTxSuccess(stageHarness *test_case_harness.TestCaseHarness) error {
}
defer client.Close()

setCommandTestCase := test_cases.SendCommandTestCase{
Command: "MULTI",
Args: []string{},
Assertion: resp_assertions.NewStringAssertion("OK"),
transactionTestCase := test_cases.TransactionTestCase{
CommandQueue: [][]string{
{"SET", "foo", "6"},
{"INCR", "foo"},
{"INCR", "bar"},
{"GET", "bar"},
},
ResultArray: []resp_value.Value{resp_value.NewSimpleStringValue("OK"), resp_value.NewIntegerValue(7), resp_value.NewIntegerValue(1), resp_value.NewBulkStringValue("1")},
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "SET",
Args: []string{"foo", "6"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "INCR",
Args: []string{"foo"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "INCR",
Args: []string{"bar"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "GET",
Args: []string{"bar"},
Assertion: resp_assertions.NewStringAssertion("QUEUED"),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

setCommandTestCase = test_cases.SendCommandTestCase{
Command: "EXEC",
Args: []string{},
Assertion: resp_assertions.NewOrderedArrayAssertion([]resp_value.Value{resp_value.NewSimpleStringValue("OK"), resp_value.NewIntegerValue(7), resp_value.NewIntegerValue(1), resp_value.NewBulkStringValue("1")}),
}

if err := setCommandTestCase.Run(client, logger); err != nil {
return err
}

return nil
return transactionTestCase.RunAll(client, logger)
}

0 comments on commit 08ac41d

Please sign in to comment.