Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CC-1299: Update RESP framework to accomodate Transaction tests elegantly #153

Merged
merged 41 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
39df651
feat: Add ordered array assertion for RESP values
ryan-gang Jun 12, 2024
fa84532
feat:
ryan-gang Jun 12, 2024
08ac41d
feat: Add transaction test cases for transaction execution
ryan-gang Jun 12, 2024
5f7be75
feat: Add testTxMulti function for executing multiple transactions
ryan-gang Jun 12, 2024
af0e0d9
feat: Add bytes field to Value struct for Ints and Nils
ryan-gang Jun 12, 2024
7087489
feat: Refactor testTxMulti function to use MultiCommandTestCase
ryan-gang Jun 12, 2024
9e28d76
feat: Add `ErrorAssertion` for comparing error values in tests
ryan-gang Jun 12, 2024
d82bbb6
feat: refactor testTxDiscard function to use MultiCommandTestCase
ryan-gang Jun 12, 2024
cf7e938
fix: revert tester definition update
ryan-gang Jun 12, 2024
67b14ec
docs: update module level docstring
ryan-gang Jun 12, 2024
fecf766
feat: add tests for stages 1 - 3
ryan-gang Jun 13, 2024
fb6e805
feat: Add testTxMulti function to internal package
ryan-gang Jun 13, 2024
11c4a5c
feat: Add testTxEmpty function to internal package
ryan-gang Jun 13, 2024
2c4393a
feat: Add testTxQueue function for testing transaction queue
ryan-gang Jun 13, 2024
2003c23
feat: Add testTxExec function
ryan-gang Jun 13, 2024
c1e381f
feat: update TransactionTestCase to even run with empty results array
ryan-gang Jun 13, 2024
a5de8c0
feat: Add multiple clients to testTxErr, testTxSuccess, and testTxDis…
ryan-gang Jun 13, 2024
983add3
feat: Add `spawnClients` function
ryan-gang Jun 13, 2024
035058f
feat: Update function name and add documentation for spawning clients
ryan-gang Jun 13, 2024
b0e7962
feat: update tester_definition with new test cases for transactions
ryan-gang Jun 13, 2024
0bd8bac
tests: add fixtures for transaction stages
ryan-gang Jun 13, 2024
28be476
refactor: Rename test stages from numbered stages to named stages
ryan-gang Jun 13, 2024
a3957c1
refactor: improve transaction test cases
ryan-gang Jun 13, 2024
f2c6762
feat: add placeholder stage descriptions
ryan-gang Jun 13, 2024
a764c12
feat: Add support for Transactions extension
ryan-gang Jun 13, 2024
7b04ff9
refactor: Update testTxMulti to use TransactionTestCase
ryan-gang Jun 14, 2024
715817c
feat: Refactor transaction test cases
ryan-gang Jun 14, 2024
571cdf7
feat: add randomness to test case for transaction failure
ryan-gang Jun 14, 2024
a37aa7b
feat: add randomness to test case for transaction success
ryan-gang Jun 14, 2024
af87ab5
feat: add random key generation for INCR test cases
ryan-gang Jun 14, 2024
4bf9120
fix: make sure all individual keys and values are always unique
ryan-gang Jun 14, 2024
63b9b01
feat: Add randomness to test cases for transaction discard
ryan-gang Jun 14, 2024
263a9cb
feat: add randomness to concurrent txn test
ryan-gang Jun 14, 2024
3f032d4
tests: update fixtures
ryan-gang Jun 14, 2024
6690867
Merge pull request #154 from codecrafters-io/CC-1299-txn-stages
ryan-gang Jun 14, 2024
634dcce
fix: update naming to match standards, update internal error codes
ryan-gang Jun 14, 2024
77a2189
refactor: refactor transaction test case to accept an array of assert…
ryan-gang Jun 14, 2024
a3b7777
tests: update fixtures
ryan-gang Jun 14, 2024
b665420
fix: use quoted values in error assertion failure logs
ryan-gang Jun 14, 2024
f89d1ff
fix: add test to make sure INCR stores string value and not int
ryan-gang Jun 14, 2024
b1bebb4
tests: update fixtures
ryan-gang Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 22 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@ build:
test:
go test -count=1 -p 1 -v ./internal/...

test_with_redis: build
CODECRAFTERS_SUBMISSION_DIR=./internal/test_helpers/pass_all \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"repl-wait\",\"tester_log_prefix\":\"stage-118\",\"title\":\"Stage #118: WAIT Command\"}]" \
dist/main.out


test_tmp: build
cd /Users/ryang/Developer/byox/build-your-own-redis && \
CODECRAFTERS_SUBMISSION_DIR=/Users/ryang/Developer/byox/build-your-own-redis \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"zg5\",\"tester_log_prefix\":\"stage-201\",\"title\":\"Stage #1: RDB Config\"}, {\"slug\":\"jz6\",\"tester_log_prefix\":\"stage-202\",\"title\":\"Stage #2: RDB Read Key\"}, {\"slug\":\"gc6\",\"tester_log_prefix\":\"stage-203\",\"title\":\"Stage #3: RDB String Value\"}, {\"slug\":\"jw4\",\"tester_log_prefix\":\"stage-204\",\"title\":\"Stage #4: RDB Read Multiple Keys\"}, {\"slug\":\"dq3\",\"tester_log_prefix\":\"stage-205\",\"title\":\"Stage #5: RDB Read Multiple String Values\"}, {\"slug\":\"sm4\",\"tester_log_prefix\":\"stage-206\",\"title\":\"Stage #6: RDB Read Value With Expiry\"}]" \
$(shell pwd)/dist/main.out

copy_course_file:
gh api repos/codecrafters-io/build-your-own-redis/contents/course-definition.yml \
| jq -r .content \
Expand All @@ -41,9 +29,20 @@ record_fixtures:
update_tester_utils:
go get -u github.com/codecrafters-io/tester-utils

test_all_with_redis: build
test_dev: build
cd /Users/ryang/Developer/byox/build-your-own-redis && \
CODECRAFTERS_SUBMISSION_DIR=/Users/ryang/Developer/byox/build-your-own-redis \
CODECRAFTERS_TEST_CASES_JSON="[]" \
$(shell pwd)/dist/main.out

test_base_with_redis: build
CODECRAFTERS_SUBMISSION_DIR=./internal/test_helpers/pass_all \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"jm1\",\"tester_log_prefix\":\"stage-1\",\"title\":\"Stage #1: Bind to a port\"},{\"slug\":\"rg2\",\"tester_log_prefix\":\"stage-2\",\"title\":\"Stage #2: Respond to PING\"},{\"slug\":\"wy1\",\"tester_log_prefix\":\"stage-3\",\"title\":\"Stage #3: Respond to multiple PINGs\"},{\"slug\":\"zu2\",\"tester_log_prefix\":\"stage-4\",\"title\":\"Stage #4: Handle concurrent clients\"},{\"slug\":\"qq0\",\"tester_log_prefix\":\"stage-5\",\"title\":\"Stage #5: Implement the ECHO command\"},{\"slug\":\"la7\",\"tester_log_prefix\":\"stage-6\",\"title\":\"Stage #6: Implement the SET \u0026 GET commands\"},{\"slug\":\"yz1\",\"tester_log_prefix\":\"stage-7\",\"title\":\"Stage #7: Expiry\"},{\"slug\":\"bw1\",\"tester_log_prefix\":\"stage-101\",\"title\":\"Stage #101: Replication - Custom Port\"}, {\"slug\":\"ye5\",\"tester_log_prefix\":\"stage-102\",\"title\":\"Stage #102: Replication - Info on Master\"},{\"slug\":\"hc6\",\"tester_log_prefix\":\"stage-103\",\"title\":\"Stage #103: Replication - Info on Replica\"}, {\"slug\":\"xc1\",\"tester_log_prefix\":\"stage-104\",\"title\":\"Stage #104: Replication - Replication ID and Offset\"}, {\"slug\":\"gl7\",\"tester_log_prefix\":\"stage-105\",\"title\":\"Stage #105: Replication - Handshake 1\"},{\"slug\":\"eh4\",\"tester_log_prefix\":\"stage-106\",\"title\":\"Stage #106: Replication - Handshake 2\"},{\"slug\":\"ju6\",\"tester_log_prefix\":\"stage-107\",\"title\":\"Stage #107: Replication - Handshake 3\"},{\"slug\":\"fj0\",\"tester_log_prefix\":\"stage-108\",\"title\":\"Stage #108: Replication - REPLCONF\"},{\"slug\":\"vm3\",\"tester_log_prefix\":\"stage-109\",\"title\":\"Stage #109: Replication - PSYNC\"},{\"slug\":\"cf8\",\"tester_log_prefix\":\"stage-110\",\"title\":\"Stage #110: Replication - PSYNC w RDB file\"},{\"slug\":\"zn8\",\"tester_log_prefix\":\"stage-111\",\"title\":\"Stage #111: Command Propagation\"},{\"slug\":\"hd5\",\"tester_log_prefix\":\"stage-112\",\"title\":\"Stage #112: Command Propagation to multiple Replicas\"},{\"slug\":\"yg4\",\"tester_log_prefix\":\"stage-113\",\"title\":\"Stage #113: Command Processing\"},{\"slug\":\"xv6\",\"tester_log_prefix\":\"stage-114\",\"title\":\"Stage #114: GetAck with 0 offset\"},{\"slug\":\"yd3\",\"tester_log_prefix\":\"stage-115\",\"title\":\"Stage #115: GetAck with non-0 offset\"},{\"slug\":\"my8\",\"tester_log_prefix\":\"stage-116\",\"title\":\"Stage #116: WAIT with 0 replicas\"},{\"slug\":\"tu8\",\"tester_log_prefix\":\"stage-117\",\"title\":\"Stage #117: WAIT with 0 offset\"},{\"slug\":\"na2\",\"tester_log_prefix\":\"stage-118\",\"title\":\"Stage #118: WAIT Command\"}]" \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"jm1\",\"tester_log_prefix\":\"stage-1\",\"title\":\"Stage #1: Bind to a port\"},{\"slug\":\"rg2\",\"tester_log_prefix\":\"stage-2\",\"title\":\"Stage #2: Respond to PING\"},{\"slug\":\"wy1\",\"tester_log_prefix\":\"stage-3\",\"title\":\"Stage #3: Respond to multiple PINGs\"},{\"slug\":\"zu2\",\"tester_log_prefix\":\"stage-4\",\"title\":\"Stage #4: Handle concurrent clients\"},{\"slug\":\"qq0\",\"tester_log_prefix\":\"stage-5\",\"title\":\"Stage #5: Implement the ECHO command\"},{\"slug\":\"la7\",\"tester_log_prefix\":\"stage-6\",\"title\":\"Stage #6: Implement the SET \u0026 GET commands\"},{\"slug\":\"yz1\",\"tester_log_prefix\":\"stage-7\",\"title\":\"Stage #7: Expiry\"}]" \
dist/main.out

test_repl_with_redis: build
CODECRAFTERS_SUBMISSION_DIR=./internal/test_helpers/pass_all \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"bw1\",\"tester_log_prefix\":\"stage-101\",\"title\":\"Stage #101: Replication - Custom Port\"}, {\"slug\":\"ye5\",\"tester_log_prefix\":\"stage-102\",\"title\":\"Stage #102: Replication - Info on Master\"},{\"slug\":\"hc6\",\"tester_log_prefix\":\"stage-103\",\"title\":\"Stage #103: Replication - Info on Replica\"}, {\"slug\":\"xc1\",\"tester_log_prefix\":\"stage-104\",\"title\":\"Stage #104: Replication - Replication ID and Offset\"}, {\"slug\":\"gl7\",\"tester_log_prefix\":\"stage-105\",\"title\":\"Stage #105: Replication - Handshake 1\"},{\"slug\":\"eh4\",\"tester_log_prefix\":\"stage-106\",\"title\":\"Stage #106: Replication - Handshake 2\"},{\"slug\":\"ju6\",\"tester_log_prefix\":\"stage-107\",\"title\":\"Stage #107: Replication - Handshake 3\"},{\"slug\":\"fj0\",\"tester_log_prefix\":\"stage-108\",\"title\":\"Stage #108: Replication - REPLCONF\"},{\"slug\":\"vm3\",\"tester_log_prefix\":\"stage-109\",\"title\":\"Stage #109: Replication - PSYNC\"},{\"slug\":\"cf8\",\"tester_log_prefix\":\"stage-110\",\"title\":\"Stage #110: Replication - PSYNC w RDB file\"},{\"slug\":\"zn8\",\"tester_log_prefix\":\"stage-111\",\"title\":\"Stage #111: Command Propagation\"},{\"slug\":\"hd5\",\"tester_log_prefix\":\"stage-112\",\"title\":\"Stage #112: Command Propagation to multiple Replicas\"},{\"slug\":\"yg4\",\"tester_log_prefix\":\"stage-113\",\"title\":\"Stage #113: Command Processing\"},{\"slug\":\"xv6\",\"tester_log_prefix\":\"stage-114\",\"title\":\"Stage #114: GetAck with 0 offset\"},{\"slug\":\"yd3\",\"tester_log_prefix\":\"stage-115\",\"title\":\"Stage #115: GetAck with non-0 offset\"},{\"slug\":\"my8\",\"tester_log_prefix\":\"stage-116\",\"title\":\"Stage #116: WAIT with 0 replicas\"},{\"slug\":\"tu8\",\"tester_log_prefix\":\"stage-117\",\"title\":\"Stage #117: WAIT with 0 offset\"},{\"slug\":\"na2\",\"tester_log_prefix\":\"stage-118\",\"title\":\"Stage #118: WAIT Command\"}]" \
dist/main.out

test_rdb_with_redis: build
Expand All @@ -56,7 +55,14 @@ test_streams_with_redis: build
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\": \"cc3\", \"tester_log_prefix\": \"stage-301\", \"title\": \"stage #01: StreamsType\"},{\"slug\": \"cf6\", \"tester_log_prefix\": \"stage-302\", \"title\": \"stage #02: StreamsXadd\"},{\"slug\": \"hq8\", \"tester_log_prefix\": \"stage-303\", \"title\": \"stage #03: StreamsXaddValidateID\"},{\"slug\": \"yh3\", \"tester_log_prefix\": \"stage-304\", \"title\": \"stage #04: StreamsXaddPartialAutoid\"},{\"slug\": \"xu6\", \"tester_log_prefix\": \"stage-305\", \"title\": \"stage #05: StreamsXaddFullAutoid\"},{\"slug\": \"zx1\", \"tester_log_prefix\": \"stage-306\", \"title\": \"stage #06: StreamsXrange\"},{\"slug\": \"yp1\", \"tester_log_prefix\": \"stage-307\", \"title\": \"stage #07: StreamsXrangeMinID\"},{\"slug\": \"fs1\", \"tester_log_prefix\": \"stage-308\", \"title\": \"stage #08: StreamsXrangeMaxID\"},{\"slug\": \"um0\", \"tester_log_prefix\": \"stage-309\", \"title\": \"stage #09: StreamsXread\"},{\"slug\": \"ru9\", \"tester_log_prefix\": \"stage-310\", \"title\": \"stage #10: StreamsXreadMultiple\"},{\"slug\": \"bs1\", \"tester_log_prefix\": \"stage-311\", \"title\": \"stage #11: StreamsXreadBlock\"},{\"slug\": \"hw1\", \"tester_log_prefix\": \"stage-312\", \"title\": \"stage #12: StreamsXreadBlockNoTimeout\"},{\"slug\": \"xu1\", \"tester_log_prefix\": \"stage-313\", \"title\": \"stage #13: StreamsXreadBlockMaxID\"}]" \
dist/main.out

test_dev: build
test_txn_with_redis: build
CODECRAFTERS_SUBMISSION_DIR=./internal/test_helpers/pass_all \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"yg4\",\"tester_log_prefix\":\"stage-113\",\"title\":\"Stage #113: Command Processing\"}]" \
CODECRAFTERS_TEST_CASES_JSON="[{\"slug\":\"si4\",\"tester_log_prefix\":\"stage-401\",\"title\":\"Stage #401: INCR-1\"},{\"slug\":\"lz8\",\"tester_log_prefix\":\"stage-402\",\"title\":\"Stage #402: INCR-2\"}, {\"slug\":\"mk1\",\"tester_log_prefix\":\"stage-403\",\"title\":\"Stage #403: INCR-3\"}, {\"slug\":\"pn0\",\"tester_log_prefix\":\"stage-404\",\"title\":\"Stage #404: MULTI\"}, {\"slug\":\"lo4\",\"tester_log_prefix\":\"stage-405\",\"title\":\"Stage #405: EXEC\"}, {\"slug\":\"we1\",\"tester_log_prefix\":\"stage-406\",\"title\":\"Stage #406: Empty Transaction\"}, {\"slug\":\"rs9\",\"tester_log_prefix\":\"stage-407\",\"title\":\"Stage #407: Queueing Commands\"}, {\"slug\":\"fy6\",\"tester_log_prefix\":\"stage-408\",\"title\":\"Stage #408: Executing a transaction\"}, {\"slug\":\"rl9\",\"tester_log_prefix\":\"stage-409\",\"title\":\"Stage #409: Discarding a transaction\"}, {\"slug\":\"sg9\",\"tester_log_prefix\":\"stage-410\",\"title\":\"Stage #410: Executing a failed transaction\"}, {\"slug\":\"jf8\",\"tester_log_prefix\":\"stage-411\",\"title\":\"Stage #411: Executing concurrent transactions\"}]" \
dist/main.out

test_all_with_redis:
make test_base_with_redis || true
make test_repl_with_redis || true
make test_rdb_with_redis || true
make test_streams_with_redis || true
make test_txn_with_redis || true
7 changes: 7 additions & 0 deletions internal/resp/value/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ func (v *Value) Integer() int {
return v.integer
}

func (v *Value) Error() string {
if v.Type == ERROR {
return string(v.String())
}
return ""
}

func (v *Value) FormattedString() string {
switch v.Type {
case SIMPLE_STRING:
Expand Down
27 changes: 27 additions & 0 deletions internal/resp_assertions/error_assertion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package resp_assertions

import (
"fmt"

resp_value "github.com/codecrafters-io/redis-tester/internal/resp/value"
)

type ErrorAssertion struct {
ExpectedValue string
}

func NewErrorAssertion(expectedValue string) RESPAssertion {
return ErrorAssertion{ExpectedValue: expectedValue}
}

func (a ErrorAssertion) Run(value resp_value.Value) error {
if value.Type != resp_value.ERROR {
return fmt.Errorf("Expected error, got %s", value.Type)
}

if value.Error() != a.ExpectedValue {
return fmt.Errorf("Expected %q, got %q", a.ExpectedValue, value.Error())
}

return nil
}
39 changes: 39 additions & 0 deletions internal/resp_assertions/ordered_array_assertion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package resp_assertions

import (
"fmt"

resp_value "github.com/codecrafters-io/redis-tester/internal/resp/value"
)

// OrderedArrayAssertion : Order of the actual and expected values matters.
// All RESP values are accepted as elements in this array.
// We don't alter the ordering.
// For each element in the array, we run the corresponding assertion.
type OrderedArrayAssertion struct {
ExpectedValue []RESPAssertion
}

func NewOrderedArrayAssertion(expectedValue []RESPAssertion) RESPAssertion {
return OrderedArrayAssertion{ExpectedValue: expectedValue}
}

func (a OrderedArrayAssertion) Run(value resp_value.Value) error {
if value.Type != resp_value.ARRAY {
return fmt.Errorf("Expected an array, got %s", value.Type)
}

if len(value.Array()) != len(a.ExpectedValue) {
return fmt.Errorf("Expected %d elements in array, got %d (%s)", len(a.ExpectedValue), len(value.Array()), value.FormattedString())
}

for i, assertion := range a.ExpectedValue {
actualElement := value.Array()[i]

if err := assertion.Run(actualElement); err != nil {
return err
}
}

return nil
}
7 changes: 7 additions & 0 deletions internal/stages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ func TestStages(t *testing.T) {
StdoutFixturePath: "./test_helpers/fixtures/streams/pass",
NormalizeOutputFunc: normalizeTesterOutput,
},
"transactions_pass": {
UntilStageSlug: "jf8",
CodePath: "./test_helpers/pass_all",
ExpectedExitCode: 0,
StdoutFixturePath: "./test_helpers/fixtures/transactions/pass",
NormalizeOutputFunc: normalizeTesterOutput,
},
}

tester_utils_testing.TestTesterOutput(t, testerDefinition, testCases)
Expand Down
35 changes: 35 additions & 0 deletions internal/test_cases/multi_command_test_case.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package test_cases

import (
"fmt"

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

// MultiCommandTestCase is a concise & easier way to define & run multiple SendCommandTestCase
type MultiCommandTestCase struct {
Commands [][]string
Assertions []resp_assertions.RESPAssertion
}

func (t *MultiCommandTestCase) RunAll(client *resp_client.RespConnection, logger *logger.Logger) error {
if len(t.Assertions) != len(t.Commands) {
return fmt.Errorf("CodeCrafters internal error. Number of commands and assertions should be equal in MultiCommandTestCase")
}

for i, command := range t.Commands {
setCommandTestCase := SendCommandTestCase{
Command: command[0],
Args: command[1:],
Assertion: t.Assertions[i],
}

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

return nil
}
89 changes: 89 additions & 0 deletions internal/test_cases/transaction_test_case.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package test_cases

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

// TransactionTestCase is a test case where we initiate a transaction by sending "MULTI" command
// Send a series of commands to the server expected back "QUEUED" for each command
// Finally send "EXEC" command and expect the response to be the same as ExpectedResponseArray
//
// RunAll will run all the steps in the Transaction execution. 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 "EXEC" is sent (based on which function is called)
// The elements in the response array are asserted based on the
// assertions in the ExpectedResponseArray
ExpectedResponseArray []resp_assertions.RESPAssertion
}

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 err := t.RunExec(client, logger); err != nil {
return err
}

return nil
}

func (t TransactionTestCase) RunWithoutExec(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
}

return nil
}

func (t TransactionTestCase) RunMulti(client *resp_client.RespConnection, logger *logger.Logger) error {
rohitpaulk marked this conversation as resolved.
Show resolved Hide resolved
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("Sending command: #%d/#%d", i+1, len(t.CommandQueue))
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.ExpectedResponseArray),
}

return setCommandTestCase.Run(client, logger)
}