diff --git a/Makefile b/Makefile index 0cb0f9d5..412dd0a2 100644 --- a/Makefile +++ b/Makefile @@ -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 \ @@ -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 @@ -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 diff --git a/internal/resp/value/value.go b/internal/resp/value/value.go index e1ff45a5..854f07ed 100644 --- a/internal/resp/value/value.go +++ b/internal/resp/value/value.go @@ -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: diff --git a/internal/resp_assertions/error_assertion.go b/internal/resp_assertions/error_assertion.go new file mode 100644 index 00000000..3ab6038a --- /dev/null +++ b/internal/resp_assertions/error_assertion.go @@ -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 +} diff --git a/internal/resp_assertions/ordered_array_assertion.go b/internal/resp_assertions/ordered_array_assertion.go new file mode 100644 index 00000000..ed642ed4 --- /dev/null +++ b/internal/resp_assertions/ordered_array_assertion.go @@ -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 +} diff --git a/internal/stages_test.go b/internal/stages_test.go index ccd68693..da7f4348 100644 --- a/internal/stages_test.go +++ b/internal/stages_test.go @@ -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) diff --git a/internal/test_cases/multi_command_test_case.go b/internal/test_cases/multi_command_test_case.go new file mode 100644 index 00000000..bf73b59c --- /dev/null +++ b/internal/test_cases/multi_command_test_case.go @@ -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 +} diff --git a/internal/test_cases/transaction_test_case.go b/internal/test_cases/transaction_test_case.go new file mode 100644 index 00000000..c562cca7 --- /dev/null +++ b/internal/test_cases/transaction_test_case.go @@ -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 { + 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) +} diff --git a/internal/test_helpers/course_definition.yml b/internal/test_helpers/course_definition.yml index 1151a765..79835f3b 100644 --- a/internal/test_helpers/course_definition.yml +++ b/internal/test_helpers/course_definition.yml @@ -89,9 +89,20 @@ extensions: [xadd-command]: https://redis.io/commands/xadd/ [xrange-command]: https://redis.io/commands/xrange/ + - slug: "transactions" + name: "Transactions" + description_markdown: |- + In this challenge extension you'll add support for [Transactions][redis-transactions] to your Redis implementation. + + Along the way, you'll learn about the [MULTI][multi-command], [EXEC][exec-command], and [DISCARD][discard-command] commands, as well as how Redis handles transactions atomically. + + [redis-transactions]: https://redis.io/docs/latest/develop/interact/transactions/ + [multi-command]: https://redis.io/commands/multi/ + [exec-command]: https://redis.io/commands/exec/ + [discard-command]: https://redis.io/commands/discard/ + stages: - - legacy_slug: "init" - slug: "jm1" + - slug: "jm1" concept_slugs: [ "network-protocols", @@ -130,8 +141,7 @@ stages: default port that Redis uses. tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_bind.go#L11" - - legacy_slug: "ping-pong" - slug: "rg2" + - slug: "rg2" concept_slugs: [ "network-protocols", @@ -183,8 +193,7 @@ stages: protocol](https://redis.io/topics/protocol) to encode the reply. tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_ping_pong.go#L9" - - legacy_slug: "ping-pong-multiple" - slug: "wy1" + - slug: "wy1" concept_slugs: [ "network-protocols", @@ -240,8 +249,7 @@ stages: [PING](https://redis.io/commands/ping) commands sent by the same client. tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_ping_pong.go#L35" - - legacy_slug: "concurrent-clients" - slug: "zu2" + - slug: "zu2" concept_slugs: [ "network-protocols", @@ -301,8 +309,7 @@ stages: like the official Redis implementation does. tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_ping_pong.go#L56" - - legacy_slug: "echo" - slug: "qq0" + - slug: "qq0" name: "Implement the ECHO command" difficulty: medium description_md: |- @@ -349,9 +356,7 @@ stages: specification](https://redis.io/topics/protocol). tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_echo.go#L11" - # TODO: Change this to use hyphens - - legacy_slug: "set_get" - slug: "la7" + - slug: "la7" name: "Implement the SET & GET commands" difficulty: medium description_md: |- @@ -405,8 +410,7 @@ stages: [GET](https://redis.io/commands/get) commands. tester_source_code_url: "https://github.com/codecrafters-io/redis-tester/blob/a58b9d58b33870fe26a164c0e323f809275a7250/internal/test_get_set.go#L11" - - legacy_slug: "expiry" - slug: "yz1" + - slug: "yz1" name: "Expiry" difficulty: medium description_md: |- @@ -468,8 +472,7 @@ stages: # Persistence - - legacy_slug: "rdb-config" - slug: "zg5" + - slug: "zg5" primary_extension_slug: "persistence-rdb" name: "RDB file config" difficulty: easy @@ -482,14 +485,14 @@ stages: An RDB file is a point-in-time snapshot of a Redis dataset. When RDB persistence is enabled, the Redis server syncs its in-memory state with an RDB file, by doing the following: - 1. On startup, the Redis server loads the data from the RDB file. - 2. While running, the Redis server periodically takes new snapshots of the dataset, in order to update the RDB file. + 1. On startup, the Redis server loads the data from the RDB file. + 2. While running, the Redis server periodically takes new snapshots of the dataset, in order to update the RDB file. - ### `dir` and `dbfilename` + ### `dir` and `dbfilename` The configuration parameters `dir` and `dbfilename` specify where an RDB file is stored: - - `dir` - the path to the directory where the RDB file is stored (example: `/tmp/redis-data`) - - `dbfilename` - the name of the RDB file (example: `rdbfile`) + - `dir` - the path to the directory where the RDB file is stored (example: `/tmp/redis-data`) + - `dbfilename` - the name of the RDB file (example: `rdbfile`) ### The `CONFIG GET` command @@ -522,8 +525,8 @@ stages: Your server must respond to each `CONFIG GET` command with a RESP array containing two elements: - 1. The parameter **name**, encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings) - 2. The parameter **value**, encoded as a RESP Bulk string + 1. The parameter **name**, encoded as a [RESP Bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings) + 2. The parameter **value**, encoded as a RESP Bulk string For example, if the value of `dir` is `/tmp/redis-files`, then the expected response to `CONFIG GET dir` is: @@ -533,57 +536,236 @@ stages: ### Notes - 1. You don't need to read the RDB file in this stage, you only need to store `dir` and `dbfilename`. Reading from the file will be covered in later stages. - 2. If your repository was created before 5th Oct 2023, it's possible that your `./spawn_redis_server.sh` script is not passing arguments to your program. To fix this, you'll need to edit `./spawn_redis_server.sh`. Check the [update CLI args PR](https://github.com/codecrafters-io/build-your-own-redis/pull/89/files) for details on how to do this. + - You don't need to read the RDB file in this stage, you only need to store `dir` and `dbfilename`. Reading from the file will be covered in later stages. + - If your repository was created before 5th Oct 2023, it's possible that your `./spawn_redis_server.sh` script is not passing arguments to your program. To fix this, you'll need to edit `./spawn_redis_server.sh`. Check the [update CLI args PR](https://github.com/codecrafters-io/build-your-own-redis/pull/89/files) for details on how to do this. marketing_md: | In this stage, you'll add support for reading the config values related to where RDB files are stored. You'll implement the `CONFIG GET` command. - - legacy_slug: "rdb-read-key" - slug: "jz6" + - slug: "jz6" primary_extension_slug: "persistence-rdb" name: "Read a key" difficulty: medium description_md: | - In this stage, you'll add support for reading a key from an RDB file. + In this stage, you'll add support for reading a single key from an RDB file. + + ### RDB file format + +
+ Click to expand/collapse + #### RDB file format overview - To keep things simple, we'll start out by supporting RDB files that contain a single key. + Here are the different sections of the RDB file, in order: - Jan-Erik Rediger (author of [rdb-rs](https://rdb.fnordig.de/)) has a great [write-up](https://rdb.fnordig.de/file_format.html) - that explains the RDB file format in detail. We recommend using it as a reference when working on this stage. + 1. Header section + 2. Metadata section + 3. Database section + 4. End of file section - The tester will create an RDB file with a single key and execute your program like this: + RDB files use special encodings to store different types of data. The ones relevant to this stage are "size encoding" and "string encoding." These are explained near the end of this page. + + The following breakdown of the RDB file format is based on [Redis RDB File Format](https://rdb.fnordig.de/file_format.html) by Jan-Erik Rediger. We’ve only included the parts that are relevant to this stage. + + #### Header section + RDB files begin with a header section, which looks something like this: ``` - ./spawn_redis_server.sh --dir --dbfilename + 52 45 44 49 53 30 30 30 37 // Magic string + version number (ASCII): "REDIS0007". ``` - It'll then send a `KEYS *` command to your server. + The header contains the magic string `REDIS`, followed by a four-character RDB version number. In this challenge, the test RDB files all use version 7. So, the header is always `REDIS0007`. - ```bash + #### Metadata section + + Next is the metadata section. It contains zero or more "metadata subsections," which each specify a single metadata attribute. Here's an example of a metadata subsection that specifies `redis-ver`: + ``` + FA // Indicates the start of a metadata subsection. + 09 72 65 64 69 73 2D 76 65 72 // The name of the metadata attribute (string encoded): "redis-ver". + 06 36 2E 30 2E 31 36 // The value of the metadata attribute (string encoded): "6.0.16". + ``` + + The metadata name and value are always string encoded. + + #### Database section + + Next is the database section. It contains zero or more "database subsections," which each describe a single database. Here's an example of a database subsection: + ``` + FE // Indicates the start of a database subsection. + 00 /* The index of the database (size encoded). + Here, the index is 0. */ + + FB // Indicates that hash table size information follows. + 02 /* The size of the hash table that stores the keys and values (size encoded). + Here, the key-value hash table size is 2. */ + 01 /* The size of the hash table that stores the expires of the keys (size encoded). + Here, the expire hash table size is 1. */ + + 00 /* The 1-byte flag that specifies the value’s type and encoding. + Here, the flag is 0, which means "string." */ + 06 66 6F 6F 62 61 72 // The name of the key (string encoded). Here, it's "foobar". + 06 62 61 7A 71 75 78 // The value (string encoded). Here, it's "bazqux". + + FC /* Indicates that this key has an expire, + and that the expire timestamp is expressed in milliseconds. */ + 15 72 E7 07 8F 01 00 00 /* The expire timestamp, expressed in Unix time, + stored as an 8-byte unsigned long, in little-endian (read right-to-left). + Here, the expire timestamp is 1713824559637. */ + 00 // Value type is string. + 03 66 6F 6F // Key name is "foo". + 03 62 61 72 // Value is "bar". + + FD /* Indicates that this key has an expire, + and that the expire timestamp is expressed in seconds. */ + 52 ED 2A 66 /* The expire timestamp, expressed in Unix time, + stored as an 4-byte unsigned integer, in little-endian (read right-to-left). + Here, the expire timestamp is 1714089298. */ + 00 // Value type is string. + 03 62 61 7A // Key name is "baz". + 03 71 75 78 // Value is "qux". + ``` + + Here's a more formal description of how each key-value pair is stored: + + 1. Optional expire information (one of the following): + * Timestamp in seconds: + 1. `FD` + 2. Expire timestamp in seconds (4-byte unsigned integer) + * Timestamp in milliseconds: + 1. `FC` + 2. Expire timestamp in milliseconds (8-byte unsigned long) + 2. Value type (1-byte flag) + 3. Key (string encoded) + 4. Value (encoding depends on value type) + + #### End of file section + + This section marks the end of the file. It looks something like this: + ``` + FF /* Indicates that the file is ending, + and that the checksum follows. */ + 89 3b b7 4e f8 0f 77 19 // An 8-byte CRC64 checksum of the entire file. + ``` + + #### Size encoding + + Size-encoded values specify the size of something. Here are some examples: + - The database indexes and hash table sizes are size encoded. + - String encoding begins with a size-encoded value that specifies the number of characters in the string. + - List encoding begins with a size-encoded value that specifies the number of elements in the list. + + The first two bits of a size-encoded value indicate how the value should be parsed. Here's a guide (bits are shown in both hexadecimal and binary): + ``` + /* If the first two bits are 0b00: + The size is the remaining 6 bits of the byte. + In this example, the size is 10: */ + 0A + 00001010 + + /* If the first two bits are 0b01: + The size is the next 14 bits + (remaining 6 bits in the first byte, combined with the next byte), + in big-endian (read left-to-right). + In this example, the size is 700: */ + 42 BC + 01000010 10111100 + + /* If the first two bits are 0b10: + Ignore the remaining 6 bits of the first byte. + The size is the next 4 bytes, in big-endian (read left-to-right). + In this example, the size is 17000: */ + 80 00 00 42 68 + 10000000 00000000 00000000 01000010 01101000 + + /* If the first two bits are 0b11: + The remaining 6 bits specify a type of string encoding. + See string encoding section. */ + ``` + + #### String encoding + + A string-encoded value consists of two parts: + 1. The size of the string (size encoded). + 2. The string. + + Here's an example: + ``` + /* The 0x0D size specifies that the string is 13 characters long. + The remaining characters spell out "Hello, World!". */ + 0D 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 + ``` + + For sizes that begin with `0b11`, the remaining 6 bits indicate a type of string format: + ``` + /* The 0xC0 size indicates the string is an 8-bit integer. + In this example, the string is "123". */ + C0 7B + + /* The 0xC1 size indicates the string is a 16-bit integer. + The remaining bytes are in little-endian (read right-to-left). + In this example, the string is "12345". */ + C1 39 30 + + /* The 0xC2 size indicates the string is a 32-bit integer. + The remaining bytes are in little-endian (read right-to-left), + In this example, the string is "1234567". */ + C2 87 D6 12 00 + + /* The 0xC3 size indicates that the string is compressed with the LZF algorithm. + You will not encounter LZF-compressed strings in this challenge. */ + C3 ... + ``` +
+ + + ### The `KEYS` command +
+ Click to expand/collapse + + The [`KEYS command`](https://redis.io/docs/latest/commands/keys/) returns all the keys that match a given pattern, as a RESP array: + ``` + $ redis-cli SET foo bar + OK + $ redis-cli SET baz qux + OK + $ redis-cli KEYS "f*" + 1) "foo" + ``` + + When the pattern is `*`, the command returns all the keys in the database: + ``` $ redis-cli KEYS "*" + 1) "baz" + 2) "foo" ``` - The response to `KEYS *` should be a RESP array with one element: the key. + In this stage, you must add support for the `KEYS` command. However, you only need to support the `*` pattern. +
+ + ### Tests - For example, let's say the RDB file contains a key called `foo`. The expected response will be: + The tester will create an RDB file with a single key and execute your program like this: + ``` + $ ./spawn_redis_server.sh --dir --dbfilename + ``` + It'll then send a `KEYS "*"` command to your server. ``` - *1\r\n$3\r\nfoo\r\n + $ redis-cli KEYS "*" ``` - - `*1\r\n` indicates that the array has one element - - `$3\r\nfoo\r\n` indicates that the first element is a bulk string with the value `foo` + Your server must respond with a RESP array that contains the key from the RDB file: + ``` + *1\r\n$3\r\nfoo\r\n + ``` - **Note**: Remember, in this stage you only need to support RDB files that contain a single key, and you can ignore the value of the key. We'll - get to handling multiple keys and reading values in later stages. + ### Notes - **Note**: The `.rdb` file provided via `--dir`/`--dbfilename` might not exist. If the file doesn't exist, your program must treat it as if the database - is currently empty. + - The RDB file provided by `--dir` and `--dbfilename` might not exist. If the file doesn't exist, your program must treat the database as empty. + - RDB files use both little-endian and big-endian to store numbers. See the [MDN article on endianness](https://developer.mozilla.org/en-US/docs/Glossary/Endianness) to learn more. + - To generate an RDB file, use the [`SAVE` command](https://redis.io/docs/latest/commands/save/). marketing_md: | In this stage, you'll add support for reading a key from an RDB file that contains a single key-value pair. You'll do this by implementing the `KEYS *` command. - - legacy_slug: "rdb-read-string-value" - slug: "gc6" + - slug: "gc6" primary_extension_slug: "persistence-rdb" name: "Read a string value" difficulty: medium @@ -620,8 +802,7 @@ stages: marketing_md: | In this stage, you'll add support for reading the value of a key from an RDB file that contains a single key-value pair. - - legacy_slug: "rdb-read-multiple-keys" - slug: "jw4" + - slug: "jw4" primary_extension_slug: "persistence-rdb" name: "Read multiple keys" difficulty: medium @@ -654,8 +835,7 @@ stages: marketing_md: | In this stage, you'll add support for reading multiple keys from an RDB file. You'll do this by extending the `KEYS *` command to support multiple keys. - - legacy_slug: "rdb-read-multiple-string-values" - slug: "dq3" + - slug: "dq3" primary_extension_slug: "persistence-rdb" name: "Read multiple string values" difficulty: medium @@ -679,8 +859,7 @@ stages: marketing_md: | In this stage, you'll add support for reading multiple string values from an RDB file. - - legacy_slug: "rdb-read-value-with-expiry" - slug: "sm4" + - slug: "sm4" primary_extension_slug: "persistence-rdb" name: "Read value with expiry" difficulty: medium @@ -711,8 +890,7 @@ stages: # Replication - - legacy_slug: "repl-custom-port" - slug: "bw1" + - slug: "bw1" primary_extension_slug: "replication" name: "Configure listening port" difficulty: easy @@ -746,8 +924,7 @@ stages: marketing_md: | In this stage, you'll add support for parsing the `--port` flag and starting Redis on a custom port. - - legacy_slug: "repl-info" - slug: "ye5" + - slug: "ye5" primary_extension_slug: "replication" name: "The INFO command" difficulty: easy @@ -814,8 +991,7 @@ stages: marketing_md: | In this stage, you'll add support for the INFO command on the master. - - legacy_slug: "repl-info-replica" - slug: "hc6" + - slug: "hc6" primary_extension_slug: "replication" name: "The INFO command on a replica" difficulty: medium @@ -863,8 +1039,7 @@ stages: marketing_md: | In this stage, you'll add support for the --replicaof arg and INFO command on the replica. - - legacy_slug: "repl-id" - slug: "xc1" + - slug: "xc1" primary_extension_slug: "replication" name: "Initial Replication ID and Offset" difficulty: easy @@ -915,8 +1090,7 @@ stages: marketing_md: | In this stage, you'll add support for reading a key from an RDB file that contains a single key-value pair. You'll do this by implementing the `KEYS *` command. - - legacy_slug: "repl-replica-ping" - slug: "gl7" + - slug: "gl7" primary_extension_slug: "replication" name: "Send handshake (1/3)" difficulty: easy @@ -951,8 +1125,7 @@ stages: marketing_md: | In this stage, you'll add support for starting the handshake from the Replica side. - - legacy_slug: "repl-replica-replconf" - slug: "eh4" + - slug: "eh4" primary_extension_slug: "replication" name: "Send handshake (2/3)" difficulty: easy @@ -1009,8 +1182,7 @@ stages: marketing_md: | In this stage, you'll add support for continuing the handshake from the Replica side, by sending REPLCONF. - - legacy_slug: "repl-replica-psync" - slug: "ju6" + - slug: "ju6" primary_extension_slug: "replication" name: "Send handshake (3/3)" difficulty: medium @@ -1067,8 +1239,7 @@ stages: marketing_md: | In this stage, you'll add support for finishing the handshake from the Replica side, by sending PSYNC. - - legacy_slug: "repl-master-replconf" - slug: "fj0" + - slug: "fj0" primary_extension_slug: "replication" name: "Receive handshake (1/2)" difficulty: easy @@ -1107,8 +1278,7 @@ stages: marketing_md: | In this stage, you'll add support for starting the handshake from the master side, by accepting REPLCONF. - - legacy_slug: "repl-master-psync" - slug: "vm3" + - slug: "vm3" primary_extension_slug: "replication" name: "Receive handshake (2/2)" difficulty: easy @@ -1167,8 +1337,7 @@ stages: marketing_md: | In this stage, you'll add support for accepting PSYNC, and starting a FULLRESYNC. - - legacy_slug: "repl-master-psync-rdb" - slug: "cf8" + - slug: "cf8" primary_extension_slug: "replication" name: "Empty RDB Transfer" difficulty: easy @@ -1229,8 +1398,7 @@ stages: marketing_md: | In this stage, you'll add support for sending an empty RDB file to the replica. This is part of the "full resynchronization" process. - - legacy_slug: "repl-master-cmd-prop" - slug: "zn8" + - slug: "zn8" primary_extension_slug: "replication" name: "Single-replica propagation" difficulty: medium @@ -1300,8 +1468,7 @@ stages: marketing_md: | In this stage, you'll add support for finishing the sync handshake from the master side, by sending a RDB file. - - legacy_slug: "repl-multiple-replicas" - slug: "hd5" + - slug: "hd5" primary_extension_slug: "replication" name: "Multi Replica Command Propagation" difficulty: hard @@ -1337,8 +1504,7 @@ stages: marketing_md: | In this stage, you'll complete your implementation of Redis replication. - - legacy_slug: "repl-cmd-processing" - slug: "yg4" + - slug: "yg4" primary_extension_slug: "replication" name: "Command Processing" difficulty: hard @@ -1387,8 +1553,7 @@ stages: marketing_md: | In this stage, you'll add support for processing commands received by the replica from the master. - - legacy_slug: "repl-replica-getack" - slug: "xv6" + - slug: "xv6" primary_extension_slug: "replication" name: "ACKs with no commands" difficulty: easy @@ -1455,8 +1620,7 @@ stages: marketing_md: | In this stage, you'll add support for returning an ACK back to master as a response to GETACK. - - legacy_slug: "repl-replica-getack-nonzero" - slug: "yd3" + - slug: "yd3" primary_extension_slug: "replication" name: "ACKs with commands" difficulty: medium @@ -1531,8 +1695,7 @@ stages: marketing_md: | In this stage, you'll add support for returning an ACK back to master as a response to GETACK. - - legacy_slug: "repl-wait-zero-replicas" - slug: "my8" + - slug: "my8" primary_extension_slug: "replication" name: "WAIT with no replicas" difficulty: medium @@ -1569,8 +1732,7 @@ stages: marketing_md: | In this stage, you'll start implementing the WAIT command on your master. - - legacy_slug: "repl-wait-zero-offset" - slug: "tu8" + - slug: "tu8" primary_extension_slug: "replication" name: "WAIT with no commands" difficulty: medium @@ -1611,8 +1773,7 @@ stages: marketing_md: | In this stage, you'll continue implementing the WAIT command on your master. - - legacy_slug: "repl-wait" - slug: "na2" + - slug: "na2" primary_extension_slug: "replication" name: "WAIT with multiple commands" difficulty: hard @@ -1654,8 +1815,8 @@ stages: In this stage, you'll finish implementing the WAIT command on your master. # Streams - - legacy_slug: "streams-type" - slug: "cc3" + + - slug: "cc3" primary_extension_slug: "streams" name: "The TYPE command" difficulty: easy @@ -1722,8 +1883,7 @@ stages: marketing_md: | In this stage, you'll add support for the `TYPE` command. - - legacy_slug: "streams-xadd" - slug: "cf6" + - slug: "cf6" primary_extension_slug: "streams" name: "Create a stream" difficulty: medium @@ -1803,8 +1963,7 @@ stages: marketing_md: | In this stage, you'll add support for creating a [Redis stream](https://redis.io/docs/data-types/streams/) using the `XADD` command. - - legacy_slug: "streams-xadd-validate-id" - slug: "hq8" + - slug: "hq8" primary_extension_slug: "streams" name: "Validating entry IDs" difficulty: easy @@ -1923,8 +2082,7 @@ stages: marketing_md: | In this stage, you'll enhance the `XADD` command by extending support for explicit IDs. - - legacy_slug: "streams-xadd-partial-autoid" - slug: "yh3" + - slug: "yh3" primary_extension_slug: "streams" name: "Partially auto-generated IDs" difficulty: medium @@ -1995,8 +2153,7 @@ stages: marketing_md: | In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the sequence number. - - legacy_slug: "streams-xadd-full-autoid" - slug: "xu6" + - slug: "xu6" primary_extension_slug: "streams" name: "Fully auto-generated IDs" difficulty: medium @@ -2042,8 +2199,7 @@ stages: marketing_md: | In this stage, you'll enhance the `XADD` command by adding the option to use `*` as the entry ID. - - legacy_slug: "streams-xrange" - slug: "zx1" + - slug: "zx1" primary_extension_slug: "streams" name: "Query entries from stream" difficulty: medium @@ -2186,8 +2342,7 @@ stages: marketing_md: | In this stage, you'll add support for querying data from a stream using the `XRANGE` command. - - legacy_slug: "streams-xrange-min-id" - slug: "yp1" + - slug: "yp1" primary_extension_slug: "streams" name: "Query with -" difficulty: easy @@ -2276,8 +2431,7 @@ stages: marketing_md: | In this stage, you'll extend support for `XRANGE` to allow querying using `-`. - - legacy_slug: "streams-xrange-max-id" - slug: "fs1" + - slug: "fs1" primary_extension_slug: "streams" name: "Query with +" difficulty: easy @@ -2376,8 +2530,7 @@ stages: marketing_md: | In this stage, you'll extend support for `XRANGE` to allow querying using `+`. - - legacy_slug: "streams-xread" - slug: "um0" + - slug: "um0" primary_extension_slug: "streams" name: "Query single stream using XREAD" difficulty: medium @@ -2524,8 +2677,7 @@ stages: marketing_md: | In this stage, you'll add support to querying a stream using the `XREAD` command. - - legacy_slug: "streams-xread-multiple" - slug: "ru9" + - slug: "ru9" primary_extension_slug: "streams" name: "Query multiple streams using XREAD" difficulty: medium @@ -2611,8 +2763,7 @@ stages: marketing_md: | In this stage, you'll add extend support to `XREAD` to allow querying multiple streams. - - legacy_slug: "streams-xread-block" - slug: "bs1" + - slug: "bs1" primary_extension_slug: "streams" name: "Blocking reads" difficulty: hard @@ -2752,8 +2903,7 @@ stages: marketing_md: | In this stage, you'll add extend support to `XREAD` to allow querying multiple streams. - - legacy_slug: "streams-xread-block-no-timeout" - slug: "hw1" + - slug: "hw1" primary_extension_slug: "streams" name: "Blocking reads without timeout" difficulty: medium @@ -2870,8 +3020,7 @@ stages: marketing_md: | In this stage, you'll add extend support to `XREAD` to allow for the blocking command not timing out. - - legacy_slug: "streams-xread-block-max-id" - slug: "xu1" + - slug: "xu1" primary_extension_slug: "streams" name: "Blocking reads using $" difficulty: easy @@ -3006,3 +3155,313 @@ stages: - In the response, the items are separated onto new lines for readability. The tester expects all of these to be in one line. marketing_md: | In this stage, you'll add extend support to `XREAD` to allow for passing in `$` as the ID for a blocking command. + + # Transactions + + - slug: "si4" + primary_extension_slug: "transactions" + name: "INCR Command (1/3)" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli SET foo 41 + > INCR foo + ``` + + marketing_md: | + In this stage, you'll start implementing the INCR command. + + - slug: "lz8" + primary_extension_slug: "transactions" + name: "INCR Command (2/3)" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli INCR foo + > INCR bar + ``` + + marketing_md: | + In this stage, you'll continue implementing the INCR command. + + - slug: "mk1" + primary_extension_slug: "transactions" + name: "INCR Command (3/3)" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli SET foo xyz + > INCR foo + ``` + + marketing_md: | + In this stage, you'll finish implementing the INCR command. + + - slug: "pn0" + primary_extension_slug: "transactions" + name: "MULTI Command" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli MULTI + ``` + + marketing_md: | + In this stage, you'll implement the MULTI command. + + - slug: "lo4" + primary_extension_slug: "transactions" + name: "EXEC Command" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli EXEC + ``` + + marketing_md: | + In this stage, you'll start implementing the EXEC command. + + - slug: "we1" + primary_extension_slug: "transactions" + name: "Empty transaction" + difficulty: hard + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli MULTI + > EXEC + > EXEC + ``` + + marketing_md: | + In this stage, you'll implement an empty transaction. + + - slug: "rs9" + primary_extension_slug: "transactions" + name: "Queueing Commands" + difficulty: medium + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli MULTI + > SET foo 41 + > INCR foo + ``` + + The tester will then create another connection to your master as a Redis client, and send a single command: + + ```bash + $ redis-cli GET foo + ``` + + marketing_md: | + In this stage, you'll implement queueing commands to a transaction. + + - slug: "fy6" + primary_extension_slug: "transactions" + name: "Executing a transaction" + difficulty: hard + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli MULTI + > SET foo 6 + > INCR foo + > INCR bar + > GET bar + > EXEC + ``` + + The tester will then create another connection to your master as a Redis client, and send a single command: + + ```bash + $ redis-cli GET foo + ``` + + marketing_md: | + In this stage, you'll implement executing a successful transaction. + + - slug: "rl9" + primary_extension_slug: "transactions" + name: "DISCARD Command" + difficulty: easy + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli MULTI + > SET foo 41 + > INCR foo + > DISCARD + > GET foo + > GET bar + > DISCARD + ``` + + marketing_md: | + In this stage, you'll implement the DISCARD command. + + - slug: "sg9" + primary_extension_slug: "transactions" + name: "Failures within transactions" + difficulty: medium + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as a Redis client, and send multiple commands using the same connection: + + ```bash + $ redis-cli SET foo abc + > SET bar 7 + > MULTI + > INCR foo + > INCR bar + > EXEC + ``` + + The tester will then create another connection to your master as a Redis client, and send a single command: + + ```bash + $ redis-cli GET foo + > GET bar + ``` + + marketing_md: | + In this stage, you'll implement handling failures while executing a transaction. + + - slug: "jf8" + primary_extension_slug: "transactions" + name: "Multiple transactions" + difficulty: medium + description_md: | + **🚧 We're still working on instructions for this stage**. You can find notes on how the tester works below. + + ### Tests + + The tester will execute your program as a master like this: + + ``` + ./spawn_redis_server.sh + ``` + + The tester will then connect to your master as multiple Redis clients, and send multiple commands from each connection: + + ```bash + $ redis-cli MULTI + > INCR foo + > EXEC + ``` + + marketing_md: | + In this stage, you'll implement multiple concurrent transactions. diff --git a/internal/test_helpers/fixtures/expiry/pass b/internal/test_helpers/fixtures/expiry/pass index c6c28831..50cac706 100644 --- a/internal/test_helpers/fixtures/expiry/pass +++ b/internal/test_helpers/fixtures/expiry/pass @@ -7,15 +7,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP simple string: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 20:00:25.321 -[stage-7] Fetching key "apple" at 20:00:25.321 (should not be expired) +[stage-7] Received OK at 13:28:48.453 +[stage-7] Fetching key "apple" at 13:28:48.454 (should not be expired) [stage-7] > GET apple [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" [stage-7] Received bytes: "$9\r\nblueberry\r\n" [stage-7] Received RESP bulk string: "blueberry" [stage-7] Received "blueberry" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "apple" at 20:00:25.425 (should be expired) +[stage-7] Fetching key "apple" at 13:28:48.557 (should be expired) [stage-7] > GET apple [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass b/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass index 92ee3ff4..b9030dd6 100644 --- a/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass +++ b/internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass @@ -1,7 +1,7 @@ Debug = true [stage-13] Running tests for Stage #13: sm4 -[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4019289137 --dbfilename pear.rdb +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2566692571 --dbfilename pear.rdb [stage-13] client: $ redis-cli GET orange [stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\norange\r\n" [stage-13] client: Received bytes: "$10\r\nstrawberry\r\n" @@ -23,7 +23,7 @@ Debug = true [stage-12] Running tests for Stage #12: dq3 [stage-12] Created RDB file with key-value pairs: "grape"="pineapple", "apple"="raspberry", "banana"="apple", "mango"="orange", "orange"="pear" -[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles117344466 --dbfilename raspberry.rdb +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3581289170 --dbfilename raspberry.rdb [stage-12] client: $ redis-cli GET grape [stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-12] client: Received bytes: "$9\r\npineapple\r\n" @@ -55,19 +55,19 @@ Debug = true [stage-11] Running tests for Stage #11: jw4 [stage-11] Created RDB file with 3 keys: ["banana" "apple" "blueberry"] -[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2161578068 --dbfilename blueberry.rdb +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2596974998 --dbfilename blueberry.rdb [stage-11] client: $ redis-cli KEYS * [stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" -[stage-11] client: Received bytes: "*3\r\n$9\r\nblueberry\r\n$6\r\nbanana\r\n$5\r\napple\r\n" -[stage-11] client: Received RESP array: ["blueberry", "banana", "apple"] -[stage-11] Received ["blueberry", "banana", "apple"] +[stage-11] client: Received bytes: "*3\r\n$9\r\nblueberry\r\n$5\r\napple\r\n$6\r\nbanana\r\n" +[stage-11] client: Received RESP array: ["blueberry", "apple", "banana"] +[stage-11] Received ["blueberry", "apple", "banana"] [stage-11] Test passed. [stage-11] Terminating program [stage-11] Program terminated successfully [stage-10] Running tests for Stage #10: gc6 [stage-10] Created RDB file with single key-value pair: grape="pineapple" -[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2004705524 --dbfilename orange.rdb +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles383736839 --dbfilename orange.rdb [stage-10] client: $ redis-cli GET grape [stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-10] client: Received bytes: "$9\r\npineapple\r\n" @@ -79,7 +79,7 @@ Debug = true [stage-9] Running tests for Stage #9: jz6 [stage-9] Created RDB file with single key: "mango" -[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1043361946 --dbfilename pear.rdb +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles142773913 --dbfilename pear.rdb [stage-9] client: $ redis-cli KEYS * [stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" [stage-9] client: Received bytes: "*1\r\n$5\r\nmango\r\n" @@ -90,12 +90,12 @@ Debug = true [stage-9] Program terminated successfully [stage-8] Running tests for Stage #8: zg5 -[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1967874176 --dbfilename blueberry.rdb +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1708726226 --dbfilename blueberry.rdb [stage-8] client: $ redis-cli CONFIG GET dir [stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" -[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1967874176\r\n" -[stage-8] client: Received RESP array: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1967874176"] -[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1967874176"] +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1708726226\r\n" +[stage-8] client: Received RESP array: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1708726226"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1708726226"] [stage-8] Test passed. [stage-8] Terminating program [stage-8] Program terminated successfully @@ -107,15 +107,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP simple string: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 20:00:45.594 -[stage-7] Fetching key "strawberry" at 20:00:45.594 (should not be expired) +[stage-7] Received OK at 13:28:51.062 +[stage-7] Fetching key "strawberry" at 13:28:51.062 (should not be expired) [stage-7] > GET strawberry [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" [stage-7] Received bytes: "$4\r\npear\r\n" [stage-7] Received RESP bulk string: "pear" [stage-7] Received "pear" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "strawberry" at 20:00:45.697 (should be expired) +[stage-7] Fetching key "strawberry" at 13:28:51.166 (should be expired) [stage-7] > GET strawberry [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_helpers/fixtures/streams/pass b/internal/test_helpers/fixtures/streams/pass index ae089d26..819ee990 100644 --- a/internal/test_helpers/fixtures/streams/pass +++ b/internal/test_helpers/fixtures/streams/pass @@ -215,7 +215,7 @@ Debug = true [stage-36] Running tests for Stage #36: xu6 [stage-36] $ ./spawn_redis_server.sh [stage-36] $ redis-cli xadd "mango" * foo bar -[stage-36] Received response: ""1718116262630-0"" +[stage-36] Received response: ""1718351938723-0"" [stage-36] The first part of the ID is a valid unix milliseconds timestamp [stage-36] The second part of the ID is a valid sequence number [stage-36] Test passed. @@ -293,11 +293,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-1: > PSYNC ? -1 [stage-31] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-1: Received bytes: "+FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0\r\n" -[stage-31] replica-1: Received RESP simple string: "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" -[stage-31] Received "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" +[stage-31] replica-1: Received bytes: "+FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0\r\n" +[stage-31] replica-1: Received RESP simple string: "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" +[stage-31] Received "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" [stage-31] Reading RDB file... -[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime§_hf\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(621d10f0c496c5a070d10141d7088a1cf31b9f78\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x8e̟\xd8\xe3\x80Z\xa3" +[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2C\xf8kf\xfa\bused-mem\xc2P\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8965bde70155f67b71a42d008e93f087ae062fcb\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\u0378V\x1f\xdd\x15\\\xff" [stage-31] Received RDB file [stage-31] Creating replica: 2 [stage-31] replica-2: $ redis-cli PING @@ -317,11 +317,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-2: > PSYNC ? -1 [stage-31] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-2: Received bytes: "+FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0\r\n" -[stage-31] replica-2: Received RESP simple string: "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" -[stage-31] Received "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" +[stage-31] replica-2: Received bytes: "+FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0\r\n" +[stage-31] replica-2: Received RESP simple string: "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" +[stage-31] Received "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" [stage-31] Reading RDB file... -[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime§_hf\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(621d10f0c496c5a070d10141d7088a1cf31b9f78\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff'\xd9\b\xdf\x1b-\x94\x16" +[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2C\xf8kf\xfa\bused-mem\xc2\xe0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8965bde70155f67b71a42d008e93f087ae062fcb\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x86K\xf1O\xbbq(\xa6" [stage-31] Received RDB file [stage-31] Creating replica: 3 [stage-31] replica-3: $ redis-cli PING @@ -341,11 +341,11 @@ Debug = true [stage-31] Received "OK" [stage-31] replica-3: > PSYNC ? -1 [stage-31] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-31] replica-3: Received bytes: "+FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0\r\n" -[stage-31] replica-3: Received RESP simple string: "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" -[stage-31] Received "FULLRESYNC 621d10f0c496c5a070d10141d7088a1cf31b9f78 0" +[stage-31] replica-3: Received bytes: "+FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0\r\n" +[stage-31] replica-3: Received RESP simple string: "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" +[stage-31] Received "FULLRESYNC 8965bde70155f67b71a42d008e93f087ae062fcb 0" [stage-31] Reading RDB file... -[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime§_hf\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(621d10f0c496c5a070d10141d7088a1cf31b9f78\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x1f\xfe\x90\x97\xf2\xe2\x038" +[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2C\xf8kf\xfa\bused-mem\xc2\xe0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(8965bde70155f67b71a42d008e93f087ae062fcb\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xbeli\aR\xbe\xbf\x88" [stage-31] Received RDB file [stage-31] client: $ redis-cli SET foo 123 [stage-31] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -438,7 +438,7 @@ Debug = true [stage-31] replica-3: Not sending ACK to Master [stage-31] client: Received bytes: ":2\r\n" [stage-31] client: Received RESP integer: 2 -[stage-31] WAIT command returned after 2094 ms +[stage-31] WAIT command returned after 2009 ms [stage-31] Test passed. [stage-31] Terminating program [stage-31] Program terminated successfully @@ -464,11 +464,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-1: > PSYNC ? -1 [stage-30] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-1: Received bytes: "+FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0\r\n" -[stage-30] replica-1: Received RESP simple string: "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" -[stage-30] Received "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" +[stage-30] replica-1: Received bytes: "+FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0\r\n" +[stage-30] replica-1: Received RESP simple string: "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" +[stage-30] Received "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" [stage-30] Reading RDB file... -[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime©_hf\xfa\bused-mem\xc2\x10\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(21b4727bf25bc40a9c76ad49d09596b6b035452d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xa9\xdd\xca\xd5Dp\xec*" +[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2E\xf8kf\xfa\bused-mem\xc2\xf0\r\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(6a4bad58bfdbc1ed46748a175209b2ec761524ed\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x19m^ \x0e\b-N" [stage-30] Received RDB file [stage-30] Creating replica: 2 [stage-30] replica-2: $ redis-cli PING @@ -488,11 +488,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-2: > PSYNC ? -1 [stage-30] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-2: Received bytes: "+FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0\r\n" -[stage-30] replica-2: Received RESP simple string: "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" -[stage-30] Received "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" +[stage-30] replica-2: Received bytes: "+FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0\r\n" +[stage-30] replica-2: Received RESP simple string: "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" +[stage-30] Received "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" [stage-30] Reading RDB file... -[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime©_hf\xfa\bused-mem\u00a0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(21b4727bf25bc40a9c76ad49d09596b6b035452d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe2.m\x85\"\x14\x98s" +[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2E\xf8kf\xfa\bused-mem\u0080\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(6a4bad58bfdbc1ed46748a175209b2ec761524ed\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff+\xc7%V_\xe3\x96s" [stage-30] Received RDB file [stage-30] Creating replica: 3 [stage-30] replica-3: $ redis-cli PING @@ -512,11 +512,11 @@ Debug = true [stage-30] Received "OK" [stage-30] replica-3: > PSYNC ? -1 [stage-30] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-30] replica-3: Received bytes: "+FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0\r\n" -[stage-30] replica-3: Received RESP simple string: "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" -[stage-30] Received "FULLRESYNC 21b4727bf25bc40a9c76ad49d09596b6b035452d 0" +[stage-30] replica-3: Received bytes: "+FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0\r\n" +[stage-30] replica-3: Received RESP simple string: "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" +[stage-30] Received "FULLRESYNC 6a4bad58bfdbc1ed46748a175209b2ec761524ed 0" [stage-30] Reading RDB file... -[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime©_hf\xfa\bused-mem\u00a0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(21b4727bf25bc40a9c76ad49d09596b6b035452d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xda\t\xf5\xcd\xcb\xdb\x0f]" +[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2E\xf8kf\xfa\bused-mem\u0080@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(6a4bad58bfdbc1ed46748a175209b2ec761524ed\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x13\xe0\xbd\x1e\xb6,\x01]" [stage-30] Received RDB file [stage-30] client: $ redis-cli WAIT 3 500 [stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n3\r\n$3\r\n500\r\n" @@ -720,11 +720,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-1: > PSYNC ? -1 [stage-25] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-1: Received bytes: "+FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0\r\n" -[stage-25] replica-1: Received RESP simple string: "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" -[stage-25] Received "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" +[stage-25] replica-1: Received bytes: "+FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0\r\n" +[stage-25] replica-1: Received RESP simple string: "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" +[stage-25] Received "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" [stage-25] Reading RDB file... -[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime¬_hf\xfa\bused-mem\xc2 S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(99c8652bed12063d6b0c3528c21ced60fe57d6c3\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xb8\xda\xe6\x91q\x8fk7" +[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2G\xf8kf\xfa\bused-mem\xc2\xc0S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(076f601d81e979b1530c70e56a413fe84ef9cc43\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffq\x14\xd3\xcco\xd7\x1d\x00" [stage-25] Received RDB file [stage-25] Creating replica: 2 [stage-25] replica-2: $ redis-cli PING @@ -744,11 +744,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-2: > PSYNC ? -1 [stage-25] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-2: Received bytes: "+FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0\r\n" -[stage-25] replica-2: Received RESP simple string: "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" -[stage-25] Received "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" +[stage-25] replica-2: Received bytes: "+FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0\r\n" +[stage-25] replica-2: Received RESP simple string: "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" +[stage-25] Received "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" [stage-25] Reading RDB file... -[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime¬_hf\xfa\bused-mem\u0090:\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(99c8652bed12063d6b0c3528c21ced60fe57d6c3\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\b\xaf\x18a`\x05\xdb\"" +[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2H\xf8kf\xfa\bused-mem\xc20;\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(076f601d81e979b1530c70e56a413fe84ef9cc43\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffقu\xa3\x1a\xdbgr" [stage-25] Received RDB file [stage-25] Creating replica: 3 [stage-25] replica-3: $ redis-cli PING @@ -768,11 +768,11 @@ Debug = true [stage-25] Received "OK" [stage-25] replica-3: > PSYNC ? -1 [stage-25] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-25] replica-3: Received bytes: "+FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0\r\n" -[stage-25] replica-3: Received RESP simple string: "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" -[stage-25] Received "FULLRESYNC 99c8652bed12063d6b0c3528c21ced60fe57d6c3 0" +[stage-25] replica-3: Received bytes: "+FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0\r\n" +[stage-25] replica-3: Received RESP simple string: "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" +[stage-25] Received "FULLRESYNC 076f601d81e979b1530c70e56a413fe84ef9cc43 0" [stage-25] Reading RDB file... -[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime¬_hf\xfa\bused-mem\u00a0I\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(99c8652bed12063d6b0c3528c21ced60fe57d6c3\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff-\xbdK\xa9\xc9i\x8cF" +[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2H\xf8kf\xfa\bused-mem\xc2@J\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(076f601d81e979b1530c70e56a413fe84ef9cc43\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x1f\xb9w\x0eg\xc1\xd3O" [stage-25] Received RDB file [stage-25] client: $ redis-cli SET foo 123 [stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -857,11 +857,11 @@ Debug = true [stage-24] Received "OK" [stage-24] replica: > PSYNC ? -1 [stage-24] replica: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-24] replica: Received bytes: "+FULLRESYNC 446bb4a75f064ae3e2b98b55674872078bf38b0a 0\r\n" -[stage-24] replica: Received RESP simple string: "FULLRESYNC 446bb4a75f064ae3e2b98b55674872078bf38b0a 0" -[stage-24] Received "FULLRESYNC 446bb4a75f064ae3e2b98b55674872078bf38b0a 0" +[stage-24] replica: Received bytes: "+FULLRESYNC 341d75e90ca30f190449cdbe9a77e95ac3baf3cc 0\r\n" +[stage-24] replica: Received RESP simple string: "FULLRESYNC 341d75e90ca30f190449cdbe9a77e95ac3baf3cc 0" +[stage-24] Received "FULLRESYNC 341d75e90ca30f190449cdbe9a77e95ac3baf3cc 0" [stage-24] Reading RDB file... -[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime¬_hf\xfa\bused-mem\xc2`S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(446bb4a75f064ae3e2b98b55674872078bf38b0a\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xfffc\xa3\x87[[&\x85" +[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2H\xf8kf\xfa\bused-mem\xc2`S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(341d75e90ca30f190449cdbe9a77e95ac3baf3cc\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x15)Jxƅg$" [stage-24] Received RDB file [stage-24] client: $ redis-cli SET foo 123 [stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" @@ -916,11 +916,11 @@ Debug = true [stage-23] Received "OK" [stage-23] client: > PSYNC ? -1 [stage-23] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-23] client: Received bytes: "+FULLRESYNC 528286689160f7bee2c769ca06019c0f899abb1d 0\r\n" -[stage-23] client: Received RESP simple string: "FULLRESYNC 528286689160f7bee2c769ca06019c0f899abb1d 0" -[stage-23] Received "FULLRESYNC 528286689160f7bee2c769ca06019c0f899abb1d 0" +[stage-23] client: Received bytes: "+FULLRESYNC bec7657fc36ac8fb2f6aeaa2ede91eea6a245b86 0\r\n" +[stage-23] client: Received RESP simple string: "FULLRESYNC bec7657fc36ac8fb2f6aeaa2ede91eea6a245b86 0" +[stage-23] Received "FULLRESYNC bec7657fc36ac8fb2f6aeaa2ede91eea6a245b86 0" [stage-23] Reading RDB file... -[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime¬_hf\xfa\bused-mem°\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(528286689160f7bee2c769ca06019c0f899abb1d\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x8e\xd5\\\xc9\xfbS\xde\x1b" +[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2H\xf8kf\xfa\bused-mem\xc2\xd0\r\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(bec7657fc36ac8fb2f6aeaa2ede91eea6a245b86\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x9a\x88\xa4\xf4èL^" [stage-23] Received RDB file [stage-23] Test passed. [stage-23] Terminating program @@ -945,9 +945,9 @@ Debug = true [stage-22] Received "OK" [stage-22] client: > PSYNC ? -1 [stage-22] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" -[stage-22] client: Received bytes: "+FULLRESYNC e3b1141657b2cc2ffa6f38dbee4e118e8479f1f4 0\r\n" -[stage-22] client: Received RESP simple string: "FULLRESYNC e3b1141657b2cc2ffa6f38dbee4e118e8479f1f4 0" -[stage-22] Received "FULLRESYNC e3b1141657b2cc2ffa6f38dbee4e118e8479f1f4 0" +[stage-22] client: Received bytes: "+FULLRESYNC 7a8142c02c705f559b35195392a38e09b9d7ccd9 0\r\n" +[stage-22] client: Received RESP simple string: "FULLRESYNC 7a8142c02c705f559b35195392a38e09b9d7ccd9 0" +[stage-22] Received "FULLRESYNC 7a8142c02c705f559b35195392a38e09b9d7ccd9 0" [stage-22] Test passed. [stage-22] Terminating program [stage-22] Program terminated successfully @@ -1046,9 +1046,9 @@ Debug = true [stage-17] $ ./spawn_redis_server.sh [stage-17] client: $ redis-cli INFO replication [stage-17] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:987bbfeeca4616af6d1291243f53e1a837a757d4\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-17] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:987bbfeeca4616af6d1291243f53e1a837a757d4\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:987bbfeeca4616af6d1291243f53e1a837a757d4\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:440193ba3ac20e968150152fb60781eb3631e128\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-17] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:440193ba3ac20e968150152fb60781eb3631e128\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:440193ba3ac20e968150152fb60781eb3631e128\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-17] Found master_replid:xxx in response. [stage-17] Found master_reploffset:0 in response. [stage-17] Test passed. @@ -1089,9 +1089,9 @@ Debug = true [stage-15] $ ./spawn_redis_server.sh [stage-15] client: $ redis-cli INFO replication [stage-15] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" -[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:898d6da3a136f5920e5ce78a71478a7b795ab380\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" -[stage-15] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:898d6da3a136f5920e5ce78a71478a7b795ab380\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" -[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:898d6da3a136f5920e5ce78a71478a7b795ab380\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:54df69f029f58da533312ef20853623a74aa0919\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-15] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:54df69f029f58da533312ef20853623a74aa0919\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:54df69f029f58da533312ef20853623a74aa0919\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" [stage-15] Found role:master in response. [stage-15] Test passed. [stage-15] Terminating program @@ -1106,7 +1106,7 @@ Debug = true [stage-14] Program terminated successfully [stage-13] Running tests for Stage #13: sm4 -[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1104761699 --dbfilename banana.rdb +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3464846617 --dbfilename banana.rdb [stage-13] client: $ redis-cli GET blueberry [stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" [stage-13] client: Received bytes: "$4\r\npear\r\n" @@ -1133,7 +1133,7 @@ Debug = true [stage-12] Running tests for Stage #12: dq3 [stage-12] Created RDB file with key-value pairs: "pineapple"="pear", "raspberry"="strawberry", "pear"="pineapple" -[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1757425797 --dbfilename strawberry.rdb +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1186933777 --dbfilename strawberry.rdb [stage-12] client: $ redis-cli GET pineapple [stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\npineapple\r\n" [stage-12] client: Received bytes: "$4\r\npear\r\n" @@ -1155,19 +1155,19 @@ Debug = true [stage-11] Running tests for Stage #11: jw4 [stage-11] Created RDB file with 4 keys: ["mango" "pineapple" "blueberry" "apple"] -[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2865505801 --dbfilename strawberry.rdb +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1436298453 --dbfilename strawberry.rdb [stage-11] client: $ redis-cli KEYS * [stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" -[stage-11] client: Received bytes: "*4\r\n$5\r\napple\r\n$9\r\npineapple\r\n$5\r\nmango\r\n$9\r\nblueberry\r\n" -[stage-11] client: Received RESP array: ["apple", "pineapple", "mango", "blueberry"] -[stage-11] Received ["apple", "pineapple", "mango", "blueberry"] +[stage-11] client: Received bytes: "*4\r\n$5\r\napple\r\n$9\r\nblueberry\r\n$9\r\npineapple\r\n$5\r\nmango\r\n" +[stage-11] client: Received RESP array: ["apple", "blueberry", "pineapple", "mango"] +[stage-11] Received ["apple", "blueberry", "pineapple", "mango"] [stage-11] Test passed. [stage-11] Terminating program [stage-11] Program terminated successfully [stage-10] Running tests for Stage #10: gc6 [stage-10] Created RDB file with single key-value pair: grape="raspberry" -[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3625740230 --dbfilename blueberry.rdb +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3560698957 --dbfilename blueberry.rdb [stage-10] client: $ redis-cli GET grape [stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" [stage-10] client: Received bytes: "$9\r\nraspberry\r\n" @@ -1179,7 +1179,7 @@ Debug = true [stage-9] Running tests for Stage #9: jz6 [stage-9] Created RDB file with single key: "orange" -[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles269673552 --dbfilename mango.rdb +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3889048063 --dbfilename mango.rdb [stage-9] client: $ redis-cli KEYS * [stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" [stage-9] client: Received bytes: "*1\r\n$6\r\norange\r\n" @@ -1190,12 +1190,12 @@ Debug = true [stage-9] Program terminated successfully [stage-8] Running tests for Stage #8: zg5 -[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3106879690 --dbfilename raspberry.rdb +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2176374416 --dbfilename raspberry.rdb [stage-8] client: $ redis-cli CONFIG GET dir [stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" -[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3106879690\r\n" -[stage-8] client: Received RESP array: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3106879690"] -[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3106879690"] +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2176374416\r\n" +[stage-8] client: Received RESP array: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2176374416"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2176374416"] [stage-8] Test passed. [stage-8] Terminating program [stage-8] Program terminated successfully @@ -1207,15 +1207,15 @@ Debug = true [stage-7] Received bytes: "+OK\r\n" [stage-7] Received RESP simple string: "OK" [stage-7] Received "OK" -[stage-7] Received OK at 20:01:11.910 -[stage-7] Fetching key "banana" at 20:01:11.910 (should not be expired) +[stage-7] Received OK at 13:29:07.724 +[stage-7] Fetching key "banana" at 13:29:07.724 (should not be expired) [stage-7] > GET banana [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\nbanana\r\n" [stage-7] Received bytes: "$6\r\norange\r\n" [stage-7] Received RESP bulk string: "orange" [stage-7] Received "orange" [stage-7] Sleeping for 101ms -[stage-7] Fetching key "banana" at 20:01:12.014 (should be expired) +[stage-7] Fetching key "banana" at 13:29:07.827 (should be expired) [stage-7] > GET banana [stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\nbanana\r\n" [stage-7] Received bytes: "$-1\r\n" diff --git a/internal/test_helpers/fixtures/transactions/pass b/internal/test_helpers/fixtures/transactions/pass new file mode 100644 index 00000000..aadea53a --- /dev/null +++ b/internal/test_helpers/fixtures/transactions/pass @@ -0,0 +1,1845 @@ +Debug = true + +[stage-55] Running tests for Stage #55: jf8 +[stage-55] $ ./spawn_redis_server.sh +[stage-55] client-1: $ redis-cli SET blueberry 80 +[stage-55] client-1: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$2\r\n80\r\n" +[stage-55] client-1: Received bytes: "+OK\r\n" +[stage-55] client-1: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] client-1: > INCR apple +[stage-55] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-1: Received bytes: ":1\r\n" +[stage-55] client-1: Received RESP integer: 1 +[stage-55] Received 1 +[stage-55] client-2: $ redis-cli SET blueberry 80 +[stage-55] client-2: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$2\r\n80\r\n" +[stage-55] client-2: Received bytes: "+OK\r\n" +[stage-55] client-2: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] client-2: > INCR apple +[stage-55] client-2: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-2: Received bytes: ":2\r\n" +[stage-55] client-2: Received RESP integer: 2 +[stage-55] Received 2 +[stage-55] client-3: $ redis-cli SET blueberry 80 +[stage-55] client-3: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$2\r\n80\r\n" +[stage-55] client-3: Received bytes: "+OK\r\n" +[stage-55] client-3: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] client-3: > INCR apple +[stage-55] client-3: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-3: Received bytes: ":3\r\n" +[stage-55] client-3: Received RESP integer: 3 +[stage-55] Received 3 +[stage-55] client-1: > MULTI +[stage-55] client-1: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-55] client-1: Received bytes: "+OK\r\n" +[stage-55] client-1: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] Sending command: #1/#2 +[stage-55] client-1: > INCR apple +[stage-55] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-1: Received bytes: "+QUEUED\r\n" +[stage-55] client-1: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] Sending command: #2/#2 +[stage-55] client-1: > INCR blueberry +[stage-55] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nblueberry\r\n" +[stage-55] client-1: Received bytes: "+QUEUED\r\n" +[stage-55] client-1: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] client-2: > MULTI +[stage-55] client-2: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-55] client-2: Received bytes: "+OK\r\n" +[stage-55] client-2: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] Sending command: #1/#2 +[stage-55] client-2: > INCR apple +[stage-55] client-2: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-2: Received bytes: "+QUEUED\r\n" +[stage-55] client-2: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] Sending command: #2/#2 +[stage-55] client-2: > INCR blueberry +[stage-55] client-2: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nblueberry\r\n" +[stage-55] client-2: Received bytes: "+QUEUED\r\n" +[stage-55] client-2: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] client-3: > MULTI +[stage-55] client-3: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-55] client-3: Received bytes: "+OK\r\n" +[stage-55] client-3: Received RESP simple string: "OK" +[stage-55] Received "OK" +[stage-55] Sending command: #1/#2 +[stage-55] client-3: > INCR apple +[stage-55] client-3: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-55] client-3: Received bytes: "+QUEUED\r\n" +[stage-55] client-3: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] Sending command: #2/#2 +[stage-55] client-3: > INCR blueberry +[stage-55] client-3: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nblueberry\r\n" +[stage-55] client-3: Received bytes: "+QUEUED\r\n" +[stage-55] client-3: Received RESP simple string: "QUEUED" +[stage-55] Received "QUEUED" +[stage-55] client-1: > EXEC +[stage-55] client-1: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-55] client-1: Received bytes: "*2\r\n:4\r\n:81\r\n" +[stage-55] client-1: Received RESP array: [4, 81] +[stage-55] Received [4, 81] +[stage-55] client-2: > EXEC +[stage-55] client-2: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-55] client-2: Received bytes: "*2\r\n:5\r\n:82\r\n" +[stage-55] client-2: Received RESP array: [5, 82] +[stage-55] Received [5, 82] +[stage-55] client-3: > EXEC +[stage-55] client-3: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-55] client-3: Received bytes: "*2\r\n:6\r\n:83\r\n" +[stage-55] client-3: Received RESP array: [6, 83] +[stage-55] Received [6, 83] +[stage-55] Test passed. +[stage-55] Terminating program +[stage-55] Program terminated successfully + +[stage-54] Running tests for Stage #54: sg9 +[stage-54] $ ./spawn_redis_server.sh +[stage-54] client-1: $ redis-cli SET pineapple pear +[stage-54] client-1: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\npineapple\r\n$4\r\npear\r\n" +[stage-54] client-1: Received bytes: "+OK\r\n" +[stage-54] client-1: Received RESP simple string: "OK" +[stage-54] Received "OK" +[stage-54] client-1: > SET grape 92 +[stage-54] client-1: Sent bytes: "*3\r\n$3\r\nSET\r\n$5\r\ngrape\r\n$2\r\n92\r\n" +[stage-54] client-1: Received bytes: "+OK\r\n" +[stage-54] client-1: Received RESP simple string: "OK" +[stage-54] Received "OK" +[stage-54] client-1: > MULTI +[stage-54] client-1: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-54] client-1: Received bytes: "+OK\r\n" +[stage-54] client-1: Received RESP simple string: "OK" +[stage-54] Received "OK" +[stage-54] Sending command: #1/#2 +[stage-54] client-1: > INCR pineapple +[stage-54] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\npineapple\r\n" +[stage-54] client-1: Received bytes: "+QUEUED\r\n" +[stage-54] client-1: Received RESP simple string: "QUEUED" +[stage-54] Received "QUEUED" +[stage-54] Sending command: #2/#2 +[stage-54] client-1: > INCR grape +[stage-54] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\ngrape\r\n" +[stage-54] client-1: Received bytes: "+QUEUED\r\n" +[stage-54] client-1: Received RESP simple string: "QUEUED" +[stage-54] Received "QUEUED" +[stage-54] client-1: > EXEC +[stage-54] client-1: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-54] client-1: Received bytes: "*2\r\n-ERR value is not an integer or out of range\r\n:93\r\n" +[stage-54] client-1: Received RESP array: ["ERR: ERR value is not an integer or out of range", 93] +[stage-54] Received ["ERR: ERR value is not an integer or out of range", 93] +[stage-54] client-2: $ redis-cli GET grape +[stage-54] client-2: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" +[stage-54] client-2: Received bytes: "$2\r\n93\r\n" +[stage-54] client-2: Received RESP bulk string: "93" +[stage-54] Received "93" +[stage-54] client-2: > GET pineapple +[stage-54] client-2: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\npineapple\r\n" +[stage-54] client-2: Received bytes: "$4\r\npear\r\n" +[stage-54] client-2: Received RESP bulk string: "pear" +[stage-54] Received "pear" +[stage-54] Test passed. +[stage-54] Terminating program +[stage-54] Program terminated successfully + +[stage-53] Running tests for Stage #53: rl9 +[stage-53] $ ./spawn_redis_server.sh +[stage-53] client: $ redis-cli SET grape 35 +[stage-53] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$5\r\ngrape\r\n$2\r\n35\r\n" +[stage-53] client: Received bytes: "+OK\r\n" +[stage-53] client: Received RESP simple string: "OK" +[stage-53] Received "OK" +[stage-53] client: > MULTI +[stage-53] client: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-53] client: Received bytes: "+OK\r\n" +[stage-53] client: Received RESP simple string: "OK" +[stage-53] Received "OK" +[stage-53] Sending command: #1/#2 +[stage-53] client: > SET raspberry 96 +[stage-53] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nraspberry\r\n$2\r\n96\r\n" +[stage-53] client: Received bytes: "+QUEUED\r\n" +[stage-53] client: Received RESP simple string: "QUEUED" +[stage-53] Received "QUEUED" +[stage-53] Sending command: #2/#2 +[stage-53] client: > INCR raspberry +[stage-53] client: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nraspberry\r\n" +[stage-53] client: Received bytes: "+QUEUED\r\n" +[stage-53] client: Received RESP simple string: "QUEUED" +[stage-53] Received "QUEUED" +[stage-53] client: > DISCARD +[stage-53] client: Sent bytes: "*1\r\n$7\r\nDISCARD\r\n" +[stage-53] client: Received bytes: "+OK\r\n" +[stage-53] client: Received RESP simple string: "OK" +[stage-53] Received "OK" +[stage-53] client: > GET raspberry +[stage-53] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nraspberry\r\n" +[stage-53] client: Received bytes: "$-1\r\n" +[stage-53] client: Received RESP null bulk string: "$-1\r\n" +[stage-53] Received "$-1\r\n" +[stage-53] client: > GET grape +[stage-53] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\ngrape\r\n" +[stage-53] client: Received bytes: "$2\r\n35\r\n" +[stage-53] client: Received RESP bulk string: "35" +[stage-53] Received "35" +[stage-53] client: > DISCARD +[stage-53] client: Sent bytes: "*1\r\n$7\r\nDISCARD\r\n" +[stage-53] client: Received bytes: "-ERR DISCARD without MULTI\r\n" +[stage-53] client: Received RESP error: "ERR: ERR DISCARD without MULTI" +[stage-53] Received "ERR: ERR DISCARD without MULTI" +[stage-53] Test passed. +[stage-53] Terminating program +[stage-53] Program terminated successfully + +[stage-52] Running tests for Stage #52: fy6 +[stage-52] $ ./spawn_redis_server.sh +[stage-52] client-1: $ redis-cli MULTI +[stage-52] client-1: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-52] client-1: Received bytes: "+OK\r\n" +[stage-52] client-1: Received RESP simple string: "OK" +[stage-52] Received "OK" +[stage-52] Sending command: #1/#4 +[stage-52] client-1: > SET blueberry 50 +[stage-52] client-1: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$2\r\n50\r\n" +[stage-52] client-1: Received bytes: "+QUEUED\r\n" +[stage-52] client-1: Received RESP simple string: "QUEUED" +[stage-52] Received "QUEUED" +[stage-52] Sending command: #2/#4 +[stage-52] client-1: > INCR blueberry +[stage-52] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nblueberry\r\n" +[stage-52] client-1: Received bytes: "+QUEUED\r\n" +[stage-52] client-1: Received RESP simple string: "QUEUED" +[stage-52] Received "QUEUED" +[stage-52] Sending command: #3/#4 +[stage-52] client-1: > INCR orange +[stage-52] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$6\r\norange\r\n" +[stage-52] client-1: Received bytes: "+QUEUED\r\n" +[stage-52] client-1: Received RESP simple string: "QUEUED" +[stage-52] Received "QUEUED" +[stage-52] Sending command: #4/#4 +[stage-52] client-1: > GET orange +[stage-52] client-1: Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\norange\r\n" +[stage-52] client-1: Received bytes: "+QUEUED\r\n" +[stage-52] client-1: Received RESP simple string: "QUEUED" +[stage-52] Received "QUEUED" +[stage-52] client-1: > EXEC +[stage-52] client-1: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-52] client-1: Received bytes: "*4\r\n+OK\r\n:51\r\n:1\r\n$1\r\n1\r\n" +[stage-52] client-1: Received RESP array: ["OK", 51, 1, "1"] +[stage-52] Received ["OK", 51, 1, "1"] +[stage-52] client-2: $ redis-cli GET blueberry +[stage-52] client-2: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" +[stage-52] client-2: Received bytes: "$2\r\n51\r\n" +[stage-52] client-2: Received RESP bulk string: "51" +[stage-52] Received "51" +[stage-52] Test passed. +[stage-52] Terminating program +[stage-52] Program terminated successfully + +[stage-51] Running tests for Stage #51: rs9 +[stage-51] $ ./spawn_redis_server.sh +[stage-51] client-1: $ redis-cli MULTI +[stage-51] client-1: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-51] client-1: Received bytes: "+OK\r\n" +[stage-51] client-1: Received RESP simple string: "OK" +[stage-51] Received "OK" +[stage-51] Sending command: #1/#2 +[stage-51] client-1: > SET blueberry 73 +[stage-51] client-1: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$2\r\n73\r\n" +[stage-51] client-1: Received bytes: "+QUEUED\r\n" +[stage-51] client-1: Received RESP simple string: "QUEUED" +[stage-51] Received "QUEUED" +[stage-51] Sending command: #2/#2 +[stage-51] client-1: > INCR blueberry +[stage-51] client-1: Sent bytes: "*2\r\n$4\r\nINCR\r\n$9\r\nblueberry\r\n" +[stage-51] client-1: Received bytes: "+QUEUED\r\n" +[stage-51] client-1: Received RESP simple string: "QUEUED" +[stage-51] Received "QUEUED" +[stage-51] client-2: $ redis-cli GET blueberry +[stage-51] client-2: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nblueberry\r\n" +[stage-51] client-2: Received bytes: "$-1\r\n" +[stage-51] client-2: Received RESP null bulk string: "$-1\r\n" +[stage-51] Received "$-1\r\n" +[stage-51] Test passed. +[stage-51] Terminating program +[stage-51] Program terminated successfully + +[stage-50] Running tests for Stage #50: we1 +[stage-50] $ ./spawn_redis_server.sh +[stage-50] client: $ redis-cli MULTI +[stage-50] client: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-50] client: Received bytes: "+OK\r\n" +[stage-50] client: Received RESP simple string: "OK" +[stage-50] Received "OK" +[stage-50] client: > EXEC +[stage-50] client: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-50] client: Received bytes: "*0\r\n" +[stage-50] client: Received RESP array: [] +[stage-50] Received [] +[stage-50] client: > EXEC +[stage-50] client: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-50] client: Received bytes: "-ERR EXEC without MULTI\r\n" +[stage-50] client: Received RESP error: "ERR: ERR EXEC without MULTI" +[stage-50] Received "ERR: ERR EXEC without MULTI" +[stage-50] Test passed. +[stage-50] Terminating program +[stage-50] Program terminated successfully + +[stage-49] Running tests for Stage #49: lo4 +[stage-49] $ ./spawn_redis_server.sh +[stage-49] client: $ redis-cli EXEC +[stage-49] client: Sent bytes: "*1\r\n$4\r\nEXEC\r\n" +[stage-49] client: Received bytes: "-ERR EXEC without MULTI\r\n" +[stage-49] client: Received RESP error: "ERR: ERR EXEC without MULTI" +[stage-49] Received "ERR: ERR EXEC without MULTI" +[stage-49] Test passed. +[stage-49] Terminating program +[stage-49] Program terminated successfully + +[stage-48] Running tests for Stage #48: pn0 +[stage-48] $ ./spawn_redis_server.sh +[stage-48] client: $ redis-cli MULTI +[stage-48] client: Sent bytes: "*1\r\n$5\r\nMULTI\r\n" +[stage-48] client: Received bytes: "+OK\r\n" +[stage-48] client: Received RESP simple string: "OK" +[stage-48] Received "OK" +[stage-48] Test passed. +[stage-48] Terminating program +[stage-48] Program terminated successfully + +[stage-47] Running tests for Stage #47: mk1 +[stage-47] $ ./spawn_redis_server.sh +[stage-47] client: $ redis-cli SET banana apple +[stage-47] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$6\r\nbanana\r\n$5\r\napple\r\n" +[stage-47] client: Received bytes: "+OK\r\n" +[stage-47] client: Received RESP simple string: "OK" +[stage-47] Received "OK" +[stage-47] client: > INCR banana +[stage-47] client: Sent bytes: "*2\r\n$4\r\nINCR\r\n$6\r\nbanana\r\n" +[stage-47] client: Received bytes: "-ERR value is not an integer or out of range\r\n" +[stage-47] client: Received RESP error: "ERR: ERR value is not an integer or out of range" +[stage-47] Received "ERR: ERR value is not an integer or out of range" +[stage-47] Test passed. +[stage-47] Terminating program +[stage-47] Program terminated successfully + +[stage-46] Running tests for Stage #46: lz8 +[stage-46] $ ./spawn_redis_server.sh +[stage-46] client: $ redis-cli INCR pear +[stage-46] client: Sent bytes: "*2\r\n$4\r\nINCR\r\n$4\r\npear\r\n" +[stage-46] client: Received bytes: ":1\r\n" +[stage-46] client: Received RESP integer: 1 +[stage-46] Received 1 +[stage-46] client: > INCR pear +[stage-46] client: Sent bytes: "*2\r\n$4\r\nINCR\r\n$4\r\npear\r\n" +[stage-46] client: Received bytes: ":2\r\n" +[stage-46] client: Received RESP integer: 2 +[stage-46] Received 2 +[stage-46] client: > GET pear +[stage-46] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$4\r\npear\r\n" +[stage-46] client: Received bytes: "$1\r\n2\r\n" +[stage-46] client: Received RESP bulk string: "2" +[stage-46] Received "2" +[stage-46] Test passed. +[stage-46] Terminating program +[stage-46] Program terminated successfully + +[stage-45] Running tests for Stage #45: si4 +[stage-45] $ ./spawn_redis_server.sh +[stage-45] client: $ redis-cli SET apple 35 +[stage-45] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$5\r\napple\r\n$2\r\n35\r\n" +[stage-45] client: Received bytes: "+OK\r\n" +[stage-45] client: Received RESP simple string: "OK" +[stage-45] Received "OK" +[stage-45] client: > INCR apple +[stage-45] client: Sent bytes: "*2\r\n$4\r\nINCR\r\n$5\r\napple\r\n" +[stage-45] client: Received bytes: ":36\r\n" +[stage-45] client: Received RESP integer: 36 +[stage-45] Received 36 +[stage-45] Test passed. +[stage-45] Terminating program +[stage-45] Program terminated successfully + +[stage-44] Running tests for Stage #44: xu1 +[stage-44] $ ./spawn_redis_server.sh +[stage-44] $ redis-cli xadd "apple" "0-1" "temperature 10" +[stage-44] Received response: ""0-1"" +[stage-44] $ redis-cli xread block '\x00' streams "apple 0-1" +[stage-44] $ redis-cli xadd "apple" "0-2" "temperature 10" +[stage-44] Received response: ""0-2"" +[stage-44] Received response: "[ +[stage-44]  { +[stage-44]  "Stream": "apple", +[stage-44]  "Messages": [ +[stage-44]  { +[stage-44]  "ID": "0-2", +[stage-44]  "Values": { +[stage-44]  "temperature": "10" +[stage-44]  } +[stage-44]  } +[stage-44]  ] +[stage-44]  } +[stage-44] ]" +[stage-44] Test passed. +[stage-44] Terminating program +[stage-44] Program terminated successfully + +[stage-43] Running tests for Stage #43: hw1 +[stage-43] $ ./spawn_redis_server.sh +[stage-43] $ redis-cli xadd "banana" "0-1" "temperature 91" +[stage-43] Received response: ""0-1"" +[stage-43] $ redis-cli xread block '\x00' streams "banana 0-1" +[stage-43] $ redis-cli xadd "banana" "0-2" "temperature 91" +[stage-43] Received response: ""0-2"" +[stage-43] Received response: "[ +[stage-43]  { +[stage-43]  "Stream": "banana", +[stage-43]  "Messages": [ +[stage-43]  { +[stage-43]  "ID": "0-2", +[stage-43]  "Values": { +[stage-43]  "temperature": "91" +[stage-43]  } +[stage-43]  } +[stage-43]  ] +[stage-43]  } +[stage-43] ]" +[stage-43] Test passed. +[stage-43] Terminating program +[stage-43] Program terminated successfully + +[stage-42] Running tests for Stage #42: bs1 +[stage-42] $ ./spawn_redis_server.sh +[stage-42] $ redis-cli xadd "orange" "0-1" "temperature 2" +[stage-42] Received response: ""0-1"" +[stage-42] $ redis-cli xread block 'Ϩ' streams "orange 0-1" +[stage-42] $ redis-cli xadd "orange" "0-2" "temperature 2" +[stage-42] Received response: ""0-2"" +[stage-42] Received response: "[ +[stage-42]  { +[stage-42]  "Stream": "orange", +[stage-42]  "Messages": [ +[stage-42]  { +[stage-42]  "ID": "0-2", +[stage-42]  "Values": { +[stage-42]  "temperature": "2" +[stage-42]  } +[stage-42]  } +[stage-42]  ] +[stage-42]  } +[stage-42] ]" +[stage-42] $ redis-cli xread block 'Ϩ' streams "orange 0-2" +[stage-42] Received nil response +[stage-42] Test passed. +[stage-42] Terminating program +[stage-42] Program terminated successfully + +[stage-41] Running tests for Stage #41: ru9 +[stage-41] $ ./spawn_redis_server.sh +[stage-41] $ redis-cli xadd "pineapple" "0-1" "temperature 99" +[stage-41] Received response: ""0-1"" +[stage-41] $ redis-cli xadd "orange" "0-2" "humidity 37" +[stage-41] Received response: ""0-2"" +[stage-41] $ redis-cli xread streams "pineapple orange 0-0 0-1" +[stage-41] Received response: "[ +[stage-41]  { +[stage-41]  "Stream": "pineapple", +[stage-41]  "Messages": [ +[stage-41]  { +[stage-41]  "ID": "0-1", +[stage-41]  "Values": { +[stage-41]  "temperature": "99" +[stage-41]  } +[stage-41]  } +[stage-41]  ] +[stage-41]  }, +[stage-41]  { +[stage-41]  "Stream": "orange", +[stage-41]  "Messages": [ +[stage-41]  { +[stage-41]  "ID": "0-2", +[stage-41]  "Values": { +[stage-41]  "humidity": "37" +[stage-41]  } +[stage-41]  } +[stage-41]  ] +[stage-41]  } +[stage-41] ]" +[stage-41] Test passed. +[stage-41] Terminating program +[stage-41] Program terminated successfully + +[stage-40] Running tests for Stage #40: um0 +[stage-40] $ ./spawn_redis_server.sh +[stage-40] $ redis-cli xadd "apple" "0-1" "temperature 88" +[stage-40] Received response: ""0-1"" +[stage-40] $ redis-cli xread streams "apple 0-0" +[stage-40] Received response: "[ +[stage-40]  { +[stage-40]  "Stream": "apple", +[stage-40]  "Messages": [ +[stage-40]  { +[stage-40]  "ID": "0-1", +[stage-40]  "Values": { +[stage-40]  "temperature": "88" +[stage-40]  } +[stage-40]  } +[stage-40]  ] +[stage-40]  } +[stage-40] ]" +[stage-40] Test passed. +[stage-40] Terminating program +[stage-40] Program terminated successfully + +[stage-39] Running tests for Stage #39: fs1 +[stage-39] $ ./spawn_redis_server.sh +[stage-39] $ redis-cli xadd "apple" "0-1" "foo bar" +[stage-39] Received response: ""0-1"" +[stage-39] $ redis-cli xadd "apple" "0-2" "foo bar" +[stage-39] Received response: ""0-2"" +[stage-39] $ redis-cli xadd "apple" "0-3" "foo bar" +[stage-39] Received response: ""0-3"" +[stage-39] $ redis-cli xadd "apple" "0-4" "foo bar" +[stage-39] Received response: ""0-4"" +[stage-39] $ redis-cli xrange "apple" 0-2 + +[stage-39] Received response: "[ +[stage-39]  { +[stage-39]  "ID": "0-2", +[stage-39]  "Values": { +[stage-39]  "foo": "bar" +[stage-39]  } +[stage-39]  }, +[stage-39]  { +[stage-39]  "ID": "0-3", +[stage-39]  "Values": { +[stage-39]  "foo": "bar" +[stage-39]  } +[stage-39]  }, +[stage-39]  { +[stage-39]  "ID": "0-4", +[stage-39]  "Values": { +[stage-39]  "foo": "bar" +[stage-39]  } +[stage-39]  } +[stage-39] ]" +[stage-39] Test passed. +[stage-39] Terminating program +[stage-39] Program terminated successfully + +[stage-38] Running tests for Stage #38: yp1 +[stage-38] $ ./spawn_redis_server.sh +[stage-38] $ redis-cli xadd "blueberry" "0-1" "foo bar" +[stage-38] Received response: ""0-1"" +[stage-38] $ redis-cli xadd "blueberry" "0-2" "foo bar" +[stage-38] Received response: ""0-2"" +[stage-38] $ redis-cli xadd "blueberry" "0-3" "foo bar" +[stage-38] Received response: ""0-3"" +[stage-38] $ redis-cli xadd "blueberry" "0-4" "foo bar" +[stage-38] Received response: ""0-4"" +[stage-38] $ redis-cli xrange "blueberry" - "0-3" +[stage-38] Received response: "[ +[stage-38]  { +[stage-38]  "ID": "0-1", +[stage-38]  "Values": { +[stage-38]  "foo": "bar" +[stage-38]  } +[stage-38]  }, +[stage-38]  { +[stage-38]  "ID": "0-2", +[stage-38]  "Values": { +[stage-38]  "foo": "bar" +[stage-38]  } +[stage-38]  }, +[stage-38]  { +[stage-38]  "ID": "0-3", +[stage-38]  "Values": { +[stage-38]  "foo": "bar" +[stage-38]  } +[stage-38]  } +[stage-38] ]" +[stage-38] Test passed. +[stage-38] Terminating program +[stage-38] Program terminated successfully + +[stage-37] Running tests for Stage #37: zx1 +[stage-37] $ ./spawn_redis_server.sh +[stage-37] $ redis-cli xadd "grape" "0-1" "foo bar" +[stage-37] Received response: ""0-1"" +[stage-37] $ redis-cli xadd "grape" "0-2" "foo bar" +[stage-37] Received response: ""0-2"" +[stage-37] $ redis-cli xadd "grape" "0-3" "foo bar" +[stage-37] Received response: ""0-3"" +[stage-37] $ redis-cli xadd "grape" "0-4" "foo bar" +[stage-37] Received response: ""0-4"" +[stage-37] $ redis-cli xrange "grape" 0-2 "0-4" +[stage-37] Received response: "[ +[stage-37]  { +[stage-37]  "ID": "0-2", +[stage-37]  "Values": { +[stage-37]  "foo": "bar" +[stage-37]  } +[stage-37]  }, +[stage-37]  { +[stage-37]  "ID": "0-3", +[stage-37]  "Values": { +[stage-37]  "foo": "bar" +[stage-37]  } +[stage-37]  }, +[stage-37]  { +[stage-37]  "ID": "0-4", +[stage-37]  "Values": { +[stage-37]  "foo": "bar" +[stage-37]  } +[stage-37]  } +[stage-37] ]" +[stage-37] Test passed. +[stage-37] Terminating program +[stage-37] Program terminated successfully + +[stage-36] Running tests for Stage #36: xu6 +[stage-36] $ ./spawn_redis_server.sh +[stage-36] $ redis-cli xadd "pear" * foo bar +[stage-36] Received response: ""1718383812190-0"" +[stage-36] The first part of the ID is a valid unix milliseconds timestamp +[stage-36] The second part of the ID is a valid sequence number +[stage-36] Test passed. +[stage-36] Terminating program +[stage-36] Program terminated successfully + +[stage-35] Running tests for Stage #35: yh3 +[stage-35] $ ./spawn_redis_server.sh +[stage-35] $ redis-cli xadd "raspberry" "0-*" "foo bar" +[stage-35] Received response: ""0-1"" +[stage-35] $ redis-cli xadd "raspberry" "1-*" "foo bar" +[stage-35] Received response: ""1-0"" +[stage-35] $ redis-cli xadd "raspberry" "1-*" "bar baz" +[stage-35] Received response: ""1-1"" +[stage-35] Test passed. +[stage-35] Terminating program +[stage-35] Program terminated successfully + +[stage-34] Running tests for Stage #34: hq8 +[stage-34] $ ./spawn_redis_server.sh +[stage-34] $ redis-cli xadd "blueberry" "1-1" "foo bar" +[stage-34] Received response: ""1-1"" +[stage-34] $ redis-cli xadd "blueberry" "1-2" "bar baz" +[stage-34] Received response: ""1-2"" +[stage-34] $ redis-cli xadd "blueberry" "1-2" "baz foo" +[stage-34] Received error: ""ERR The ID specified in XADD is equal or smaller than the target stream top item"" +[stage-34] $ redis-cli xadd "blueberry" "0-3" "baz foo" +[stage-34] Received error: ""ERR The ID specified in XADD is equal or smaller than the target stream top item"" +[stage-34] $ redis-cli xadd "blueberry" "0-0" "baz foo" +[stage-34] Received error: ""ERR The ID specified in XADD must be greater than 0-0"" +[stage-34] Test passed. +[stage-34] Terminating program +[stage-34] Program terminated successfully + +[stage-33] Running tests for Stage #33: cf6 +[stage-33] $ ./spawn_redis_server.sh +[stage-33] $ redis-cli xadd "blueberry" "0-1" "foo bar" +[stage-33] Received response: ""0-1"" +[stage-33] $ redis-cli type "blueberry" +[stage-33] Type of "blueberry" is "stream" +[stage-33] Test passed. +[stage-33] Terminating program +[stage-33] Program terminated successfully + +[stage-32] Running tests for Stage #32: cc3 +[stage-32] $ ./spawn_redis_server.sh +[stage-32] $ redis-cli set "mango" "banana" +[stage-32] Received response: ""OK"" +[stage-32] $ redis-cli type "mango" +[stage-32] Type of "mango" is "string" +[stage-32] $ redis-cli type "missing_key_banana" +[stage-32] Type of missing_key_"banana" is "none" +[stage-32] Test passed. +[stage-32] Terminating program +[stage-32] Program terminated successfully + +[stage-31] Running tests for Stage #31: na2 +[stage-31] $ ./spawn_redis_server.sh --port 6379 +[stage-31] Proceeding to create 4 replicas. +[stage-31] Creating replica: 1 +[stage-31] replica-1: $ redis-cli PING +[stage-31] replica-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-31] replica-1: Received bytes: "+PONG\r\n" +[stage-31] replica-1: Received RESP simple string: "PONG" +[stage-31] Received "PONG" +[stage-31] replica-1: > REPLCONF listening-port 6380 +[stage-31] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-31] replica-1: Received bytes: "+OK\r\n" +[stage-31] replica-1: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-1: > REPLCONF capa psync2 +[stage-31] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-31] replica-1: Received bytes: "+OK\r\n" +[stage-31] replica-1: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-1: > PSYNC ? -1 +[stage-31] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-31] replica-1: Received bytes: "+FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0\r\n" +[stage-31] replica-1: Received RESP simple string: "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Received "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Reading RDB file... +[stage-31] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc4tlf\xfa\bused-mem\xc20\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xe4\x986i\xa6\x02\xe0\xc3" +[stage-31] Received RDB file +[stage-31] Creating replica: 2 +[stage-31] replica-2: $ redis-cli PING +[stage-31] replica-2: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-31] replica-2: Received bytes: "+PONG\r\n" +[stage-31] replica-2: Received RESP simple string: "PONG" +[stage-31] Received "PONG" +[stage-31] replica-2: > REPLCONF listening-port 6381 +[stage-31] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6381\r\n" +[stage-31] replica-2: Received bytes: "+OK\r\n" +[stage-31] replica-2: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-2: > REPLCONF capa psync2 +[stage-31] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-31] replica-2: Received bytes: "+OK\r\n" +[stage-31] replica-2: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-2: > PSYNC ? -1 +[stage-31] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-31] replica-2: Received bytes: "+FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0\r\n" +[stage-31] replica-2: Received RESP simple string: "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Received "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Reading RDB file... +[stage-31] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc4tlf\xfa\bused-mem\xc2\xc0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffM\x8d\xa1n^\xaf.v" +[stage-31] Received RDB file +[stage-31] Creating replica: 3 +[stage-31] replica-3: $ redis-cli PING +[stage-31] replica-3: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-31] replica-3: Received bytes: "+PONG\r\n" +[stage-31] replica-3: Received RESP simple string: "PONG" +[stage-31] Received "PONG" +[stage-31] replica-3: > REPLCONF listening-port 6382 +[stage-31] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6382\r\n" +[stage-31] replica-3: Received bytes: "+OK\r\n" +[stage-31] replica-3: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-3: > REPLCONF capa psync2 +[stage-31] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-31] replica-3: Received bytes: "+OK\r\n" +[stage-31] replica-3: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-3: > PSYNC ? -1 +[stage-31] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-31] replica-3: Received bytes: "+FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0\r\n" +[stage-31] replica-3: Received RESP simple string: "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Received "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Reading RDB file... +[stage-31] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc4tlf\xfa\bused-mem\xc2\xc0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffu\xaa9&\xb7`\xb9X" +[stage-31] Received RDB file +[stage-31] Creating replica: 4 +[stage-31] replica-4: $ redis-cli PING +[stage-31] replica-4: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-31] replica-4: Received bytes: "+PONG\r\n" +[stage-31] replica-4: Received RESP simple string: "PONG" +[stage-31] Received "PONG" +[stage-31] replica-4: > REPLCONF listening-port 6383 +[stage-31] replica-4: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6383\r\n" +[stage-31] replica-4: Received bytes: "+OK\r\n" +[stage-31] replica-4: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-4: > REPLCONF capa psync2 +[stage-31] replica-4: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-31] replica-4: Received bytes: "+OK\r\n" +[stage-31] replica-4: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] replica-4: > PSYNC ? -1 +[stage-31] replica-4: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-31] replica-4: Received bytes: "+FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0\r\n" +[stage-31] replica-4: Received RESP simple string: "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Received "FULLRESYNC 1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7 0" +[stage-31] Reading RDB file... +[stage-31] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc5tlf\xfa\bused-mem\xc2Ћ\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(1c06ed29c4a083a5302082fabaa3a0b91c9a3bf7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffDj\xe05Z\xab\xfa." +[stage-31] Received RDB file +[stage-31] client: $ redis-cli SET foo 123 +[stage-31] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-31] client: Received bytes: "+OK\r\n" +[stage-31] client: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] client: > WAIT 1 500 +[stage-31] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n1\r\n$3\r\n500\r\n" +[stage-31] Testing Replica : 1 +[stage-31] replica-1: Expecting "SET foo 123" to be propagated +[stage-31] replica-1: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-31] replica-1: Received RESP array: ["SELECT", "0"] +[stage-31] replica-1: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-31] replica-1: Received RESP array: ["SET", "foo", "123"] +[stage-31] Received ["SET", "foo", "123"] +[stage-31] replica-1: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-1: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-1: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-1: Sending ACK to Master +[stage-31] replica-1: $ redis-cli REPLCONF ACK 54 +[stage-31] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$2\r\n54\r\n" +[stage-31] Testing Replica : 2 +[stage-31] replica-2: Expecting "SET foo 123" to be propagated +[stage-31] replica-2: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-31] replica-2: Received RESP array: ["SELECT", "0"] +[stage-31] replica-2: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-31] replica-2: Received RESP array: ["SET", "foo", "123"] +[stage-31] Received ["SET", "foo", "123"] +[stage-31] replica-2: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-2: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-2: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-2: Not sending ACK to Master +[stage-31] Testing Replica : 3 +[stage-31] replica-3: Expecting "SET foo 123" to be propagated +[stage-31] replica-3: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-31] replica-3: Received RESP array: ["SELECT", "0"] +[stage-31] replica-3: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-31] replica-3: Received RESP array: ["SET", "foo", "123"] +[stage-31] Received ["SET", "foo", "123"] +[stage-31] replica-3: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-3: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-3: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-3: Not sending ACK to Master +[stage-31] Testing Replica : 4 +[stage-31] replica-4: Expecting "SET foo 123" to be propagated +[stage-31] replica-4: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-31] replica-4: Received RESP array: ["SELECT", "0"] +[stage-31] replica-4: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-31] replica-4: Received RESP array: ["SET", "foo", "123"] +[stage-31] Received ["SET", "foo", "123"] +[stage-31] replica-4: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-4: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-4: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-4: Not sending ACK to Master +[stage-31] client: Received bytes: ":1\r\n" +[stage-31] client: Received RESP integer: 1 +[stage-31] Passed first WAIT test. +[stage-31] client: > SET baz 789 +[stage-31] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-31] client: Received bytes: "+OK\r\n" +[stage-31] client: Received RESP simple string: "OK" +[stage-31] Received "OK" +[stage-31] client: > WAIT 3 2000 +[stage-31] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n3\r\n$4\r\n2000\r\n" +[stage-31] Testing Replica : 1 +[stage-31] replica-1: Expecting "SET baz 789" to be propagated +[stage-31] replica-1: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-31] replica-1: Received RESP array: ["SET", "baz", "789"] +[stage-31] Received ["SET", "baz", "789"] +[stage-31] replica-1: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-1: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-1: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-1: Sending ACK to Master +[stage-31] replica-1: > REPLCONF ACK 122 +[stage-31] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$3\r\n122\r\n" +[stage-31] Testing Replica : 2 +[stage-31] replica-2: Expecting "SET baz 789" to be propagated +[stage-31] replica-2: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-31] replica-2: Received RESP array: ["SET", "baz", "789"] +[stage-31] Received ["SET", "baz", "789"] +[stage-31] replica-2: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-2: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-2: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-2: Sending ACK to Master +[stage-31] replica-2: $ redis-cli REPLCONF ACK 122 +[stage-31] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$3\r\n122\r\n" +[stage-31] Testing Replica : 3 +[stage-31] replica-3: Expecting "SET baz 789" to be propagated +[stage-31] replica-3: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-31] replica-3: Received RESP array: ["SET", "baz", "789"] +[stage-31] Received ["SET", "baz", "789"] +[stage-31] replica-3: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-3: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-3: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-3: Not sending ACK to Master +[stage-31] Testing Replica : 4 +[stage-31] replica-4: Expecting "SET baz 789" to be propagated +[stage-31] replica-4: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-31] replica-4: Received RESP array: ["SET", "baz", "789"] +[stage-31] Received ["SET", "baz", "789"] +[stage-31] replica-4: Expecting "REPLCONF GETACK *" from Master +[stage-31] replica-4: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-31] replica-4: Received RESP array: ["REPLCONF", "GETACK", "*"] +[stage-31] Received ["REPLCONF", "GETACK", "*"] +[stage-31] replica-4: Not sending ACK to Master +[stage-31] client: Received bytes: ":2\r\n" +[stage-31] client: Received RESP integer: 2 +[stage-31] WAIT command returned after 2097 ms +[stage-31] Test passed. +[stage-31] Terminating program +[stage-31] Program terminated successfully + +[stage-30] Running tests for Stage #30: tu8 +[stage-30] $ ./spawn_redis_server.sh --port 6379 +[stage-30] Proceeding to create 6 replicas. +[stage-30] Creating replica: 1 +[stage-30] replica-1: $ redis-cli PING +[stage-30] replica-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-1: Received bytes: "+PONG\r\n" +[stage-30] replica-1: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-1: > REPLCONF listening-port 6380 +[stage-30] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-30] replica-1: Received bytes: "+OK\r\n" +[stage-30] replica-1: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-1: > REPLCONF capa psync2 +[stage-30] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-1: Received bytes: "+OK\r\n" +[stage-30] replica-1: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-1: > PSYNC ? -1 +[stage-30] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-1: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-1: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem\xc2\x10\x0e\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x00\xa4\x1fh\xdd\xc0\x9e\x9e" +[stage-30] Received RDB file +[stage-30] Creating replica: 2 +[stage-30] replica-2: $ redis-cli PING +[stage-30] replica-2: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-2: Received bytes: "+PONG\r\n" +[stage-30] replica-2: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-2: > REPLCONF listening-port 6381 +[stage-30] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6381\r\n" +[stage-30] replica-2: Received bytes: "+OK\r\n" +[stage-30] replica-2: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-2: > REPLCONF capa psync2 +[stage-30] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-2: Received bytes: "+OK\r\n" +[stage-30] replica-2: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-2: > PSYNC ? -1 +[stage-30] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-2: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-2: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem\u00a0\xf5\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffKW\xb88\xbb\xa4\xea\xc7" +[stage-30] Received RDB file +[stage-30] Creating replica: 3 +[stage-30] replica-3: $ redis-cli PING +[stage-30] replica-3: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-3: Received bytes: "+PONG\r\n" +[stage-30] replica-3: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-3: > REPLCONF listening-port 6382 +[stage-30] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6382\r\n" +[stage-30] replica-3: Received bytes: "+OK\r\n" +[stage-30] replica-3: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-3: > REPLCONF capa psync2 +[stage-30] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-3: Received bytes: "+OK\r\n" +[stage-30] replica-3: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-3: > PSYNC ? -1 +[stage-30] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-3: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-3: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem\u00a0@\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffsp pRk}\xe9" +[stage-30] Received RDB file +[stage-30] Creating replica: 4 +[stage-30] replica-4: $ redis-cli PING +[stage-30] replica-4: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-4: Received bytes: "+PONG\r\n" +[stage-30] replica-4: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-4: > REPLCONF listening-port 6383 +[stage-30] replica-4: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6383\r\n" +[stage-30] replica-4: Received bytes: "+OK\r\n" +[stage-30] replica-4: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-4: > REPLCONF capa psync2 +[stage-30] replica-4: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-4: Received bytes: "+OK\r\n" +[stage-30] replica-4: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-4: > PSYNC ? -1 +[stage-30] replica-4: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-4: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-4: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-4: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem°\x8b\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xb7E\xa1\aD\x11hA" +[stage-30] Received RDB file +[stage-30] Creating replica: 5 +[stage-30] replica-5: $ redis-cli PING +[stage-30] replica-5: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-5: Received bytes: "+PONG\r\n" +[stage-30] replica-5: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-5: > REPLCONF listening-port 6384 +[stage-30] replica-5: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6384\r\n" +[stage-30] replica-5: Received bytes: "+OK\r\n" +[stage-30] replica-5: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-5: > REPLCONF capa psync2 +[stage-30] replica-5: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-5: Received bytes: "+OK\r\n" +[stage-30] replica-5: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-5: > PSYNC ? -1 +[stage-30] replica-5: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-5: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-5: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-5: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem\xc2\xc0\xd6\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffT$н\xefh\x02\xe7" +[stage-30] Received RDB file +[stage-30] Creating replica: 6 +[stage-30] replica-6: $ redis-cli PING +[stage-30] replica-6: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-30] replica-6: Received bytes: "+PONG\r\n" +[stage-30] replica-6: Received RESP simple string: "PONG" +[stage-30] Received "PONG" +[stage-30] replica-6: > REPLCONF listening-port 6385 +[stage-30] replica-6: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6385\r\n" +[stage-30] replica-6: Received bytes: "+OK\r\n" +[stage-30] replica-6: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-6: > REPLCONF capa psync2 +[stage-30] replica-6: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-30] replica-6: Received bytes: "+OK\r\n" +[stage-30] replica-6: Received RESP simple string: "OK" +[stage-30] Received "OK" +[stage-30] replica-6: > PSYNC ? -1 +[stage-30] replica-6: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-30] replica-6: Received bytes: "+FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0\r\n" +[stage-30] replica-6: Received RESP simple string: "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Received "FULLRESYNC 5375b7c06be89997dbda6de1083a664bddf749a7 0" +[stage-30] Reading RDB file... +[stage-30] replica-6: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc7tlf\xfa\bused-mem\xc2\xc0!\x14\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(5375b7c06be89997dbda6de1083a664bddf749a7\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff8^pfO6R\xe7" +[stage-30] Received RDB file +[stage-30] client: $ redis-cli WAIT 3 500 +[stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n3\r\n$3\r\n500\r\n" +[stage-30] client: Received bytes: ":6\r\n" +[stage-30] client: Received RESP integer: 6 +[stage-30] Received 6 +[stage-30] client: > WAIT 5 500 +[stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n5\r\n$3\r\n500\r\n" +[stage-30] client: Received bytes: ":6\r\n" +[stage-30] client: Received RESP integer: 6 +[stage-30] Received 6 +[stage-30] client: > WAIT 7 500 +[stage-30] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n7\r\n$3\r\n500\r\n" +[stage-30] client: Received bytes: ":6\r\n" +[stage-30] client: Received RESP integer: 6 +[stage-30] Received 6 +[stage-30] Test passed. +[stage-30] Terminating program +[stage-30] Program terminated successfully + +[stage-29] Running tests for Stage #29: my8 +[stage-29] $ ./spawn_redis_server.sh --port 6379 +[stage-29] client: $ redis-cli WAIT 0 60000 +[stage-29] client: Sent bytes: "*3\r\n$4\r\nWAIT\r\n$1\r\n0\r\n$5\r\n60000\r\n" +[stage-29] client: Received bytes: ":0\r\n" +[stage-29] client: Received RESP integer: 0 +[stage-29] Received 0 +[stage-29] Test passed. +[stage-29] Terminating program +[stage-29] Program terminated successfully + +[stage-28] Running tests for Stage #28: yd3 +[stage-28] Master is running on port 6379 +[stage-28] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-28] master: Waiting for replica to initiate handshake with "PING" command +[stage-28] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-28] master: Received RESP array: ["PING"] +[stage-28] Received ["PING"] +[stage-28] master: Sent "PONG" +[stage-28] master: Sent bytes: "+PONG\r\n" +[stage-28] master: Waiting for replica to send "REPLCONF listening-port 6380" command +[stage-28] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-28] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-28] Received ["REPLCONF", "listening-port", "6380"] +[stage-28] master: Sent "OK" +[stage-28] master: Sent bytes: "+OK\r\n" +[stage-28] master: Waiting for replica to send "REPLCONF capa" command +[stage-28] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-28] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-28] Received ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-28] master: Sent "OK" +[stage-28] master: Sent bytes: "+OK\r\n" +[stage-28] master: Waiting for replica to send "PSYNC" command +[stage-28] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-28] master: Received RESP array: ["PSYNC", "?", "-1"] +[stage-28] Received ["PSYNC", "?", "-1"] +[stage-28] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0" +[stage-28] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n" +[stage-28] Sending RDB file... +[stage-28] master: Sent bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2" +[stage-28] Sent RDB file. +[stage-28] master: $ redis-cli REPLCONF GETACK * +[stage-28] master: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-28] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$1\r\n0\r\n" +[stage-28] master: Received RESP array: ["REPLCONF", "ACK", "0"] +[stage-28] Received ["REPLCONF", "ACK", "0"] +[stage-28] master: > PING +[stage-28] master: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-28] master: > REPLCONF GETACK * +[stage-28] master: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-28] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$2\r\n51\r\n" +[stage-28] master: Received RESP array: ["REPLCONF", "ACK", "51"] +[stage-28] Received ["REPLCONF", "ACK", "51"] +[stage-28] master: > SET banana banana +[stage-28] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$6\r\nbanana\r\n$6\r\nbanana\r\n" +[stage-28] master: > SET blueberry orange +[stage-28] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$9\r\nblueberry\r\n$6\r\norange\r\n" +[stage-28] master: > REPLCONF GETACK * +[stage-28] master: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-28] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$3\r\n165\r\n" +[stage-28] master: Received RESP array: ["REPLCONF", "ACK", "165"] +[stage-28] Received ["REPLCONF", "ACK", "165"] +[stage-28] Test passed. +[stage-28] Terminating program +[stage-28] Program terminated successfully + +[stage-27] Running tests for Stage #27: xv6 +[stage-27] Master is running on port 6379 +[stage-27] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-27] master: Waiting for replica to initiate handshake with "PING" command +[stage-27] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-27] master: Received RESP array: ["PING"] +[stage-27] Received ["PING"] +[stage-27] master: Sent "PONG" +[stage-27] master: Sent bytes: "+PONG\r\n" +[stage-27] master: Waiting for replica to send "REPLCONF listening-port 6380" command +[stage-27] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-27] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-27] Received ["REPLCONF", "listening-port", "6380"] +[stage-27] master: Sent "OK" +[stage-27] master: Sent bytes: "+OK\r\n" +[stage-27] master: Waiting for replica to send "REPLCONF capa" command +[stage-27] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-27] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-27] Received ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-27] master: Sent "OK" +[stage-27] master: Sent bytes: "+OK\r\n" +[stage-27] master: Waiting for replica to send "PSYNC" command +[stage-27] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-27] master: Received RESP array: ["PSYNC", "?", "-1"] +[stage-27] Received ["PSYNC", "?", "-1"] +[stage-27] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0" +[stage-27] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n" +[stage-27] Sending RDB file... +[stage-27] master: Sent bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2" +[stage-27] Sent RDB file. +[stage-27] master: > REPLCONF GETACK * +[stage-27] master: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$6\r\nGETACK\r\n$1\r\n*\r\n" +[stage-27] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$3\r\nACK\r\n$1\r\n0\r\n" +[stage-27] master: Received RESP array: ["REPLCONF", "ACK", "0"] +[stage-27] Received ["REPLCONF", "ACK", "0"] +[stage-27] Test passed. +[stage-27] Terminating program +[stage-27] Program terminated successfully + +[stage-26] Running tests for Stage #26: yg4 +[stage-26] Master is running on port 6379 +[stage-26] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-26] master: Waiting for replica to initiate handshake with "PING" command +[stage-26] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-26] master: Received RESP array: ["PING"] +[stage-26] Received ["PING"] +[stage-26] master: Sent "PONG" +[stage-26] master: Sent bytes: "+PONG\r\n" +[stage-26] master: Waiting for replica to send "REPLCONF listening-port 6380" command +[stage-26] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-26] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-26] Received ["REPLCONF", "listening-port", "6380"] +[stage-26] master: Sent "OK" +[stage-26] master: Sent bytes: "+OK\r\n" +[stage-26] master: Waiting for replica to send "REPLCONF capa" command +[stage-26] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-26] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-26] Received ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-26] master: Sent "OK" +[stage-26] master: Sent bytes: "+OK\r\n" +[stage-26] master: Waiting for replica to send "PSYNC" command +[stage-26] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-26] master: Received RESP array: ["PSYNC", "?", "-1"] +[stage-26] Received ["PSYNC", "?", "-1"] +[stage-26] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0" +[stage-26] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n" +[stage-26] Sending RDB file... +[stage-26] master: Sent bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2" +[stage-26] Sent RDB file. +[stage-26] master: > SET foo 123 +[stage-26] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-26] master: > SET bar 456 +[stage-26] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-26] master: > SET baz 789 +[stage-26] master: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-26] Getting key foo +[stage-26] client: $ redis-cli GET foo +[stage-26] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n" +[stage-26] client: Received bytes: "$3\r\n123\r\n" +[stage-26] client: Received RESP bulk string: "123" +[stage-26] Received "123" +[stage-26] Getting key bar +[stage-26] client: > GET bar +[stage-26] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$3\r\nbar\r\n" +[stage-26] client: Received bytes: "$3\r\n456\r\n" +[stage-26] client: Received RESP bulk string: "456" +[stage-26] Received "456" +[stage-26] Getting key baz +[stage-26] client: > GET baz +[stage-26] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$3\r\nbaz\r\n" +[stage-26] client: Received bytes: "$3\r\n789\r\n" +[stage-26] client: Received RESP bulk string: "789" +[stage-26] Received "789" +[stage-26] Test passed. +[stage-26] Terminating program +[stage-26] Program terminated successfully + +[stage-25] Running tests for Stage #25: hd5 +[stage-25] $ ./spawn_redis_server.sh --port 6379 +[stage-25] Creating replica: 1 +[stage-25] replica-1: $ redis-cli PING +[stage-25] replica-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-25] replica-1: Received bytes: "+PONG\r\n" +[stage-25] replica-1: Received RESP simple string: "PONG" +[stage-25] Received "PONG" +[stage-25] replica-1: > REPLCONF listening-port 6380 +[stage-25] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-25] replica-1: Received bytes: "+OK\r\n" +[stage-25] replica-1: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-1: > REPLCONF capa psync2 +[stage-25] replica-1: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-25] replica-1: Received bytes: "+OK\r\n" +[stage-25] replica-1: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-1: > PSYNC ? -1 +[stage-25] replica-1: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-25] replica-1: Received bytes: "+FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0\r\n" +[stage-25] replica-1: Received RESP simple string: "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Received "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Reading RDB file... +[stage-25] replica-1: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9tlf\xfa\bused-mem\u00a0S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(2e58128f42dc607c41d060c0144f89740dd79c29\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\xde0\xf4_xg\x18\xd1" +[stage-25] Received RDB file +[stage-25] Creating replica: 2 +[stage-25] replica-2: $ redis-cli PING +[stage-25] replica-2: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-25] replica-2: Received bytes: "+PONG\r\n" +[stage-25] replica-2: Received RESP simple string: "PONG" +[stage-25] Received "PONG" +[stage-25] replica-2: > REPLCONF listening-port 6381 +[stage-25] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6381\r\n" +[stage-25] replica-2: Received bytes: "+OK\r\n" +[stage-25] replica-2: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-2: > REPLCONF capa psync2 +[stage-25] replica-2: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-25] replica-2: Received bytes: "+OK\r\n" +[stage-25] replica-2: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-2: > PSYNC ? -1 +[stage-25] replica-2: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-25] replica-2: Received bytes: "+FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0\r\n" +[stage-25] replica-2: Received RESP simple string: "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Received "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Reading RDB file... +[stage-25] replica-2: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9tlf\xfa\bused-mem\xc2\x10;\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(2e58128f42dc607c41d060c0144f89740dd79c29\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff[kq\x1a塨\v" +[stage-25] Received RDB file +[stage-25] Creating replica: 3 +[stage-25] replica-3: $ redis-cli PING +[stage-25] replica-3: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-25] replica-3: Received bytes: "+PONG\r\n" +[stage-25] replica-3: Received RESP simple string: "PONG" +[stage-25] Received "PONG" +[stage-25] replica-3: > REPLCONF listening-port 6382 +[stage-25] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6382\r\n" +[stage-25] replica-3: Received bytes: "+OK\r\n" +[stage-25] replica-3: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-3: > REPLCONF capa psync2 +[stage-25] replica-3: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-25] replica-3: Received bytes: "+OK\r\n" +[stage-25] replica-3: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] replica-3: > PSYNC ? -1 +[stage-25] replica-3: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-25] replica-3: Received bytes: "+FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0\r\n" +[stage-25] replica-3: Received RESP simple string: "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Received "FULLRESYNC 2e58128f42dc607c41d060c0144f89740dd79c29 0" +[stage-25] Reading RDB file... +[stage-25] replica-3: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9tlf\xfa\bused-mem\xc2 J\x13\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(2e58128f42dc607c41d060c0144f89740dd79c29\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xff\x7f\xb6C\xe0\x06r\xa6\xda" +[stage-25] Received RDB file +[stage-25] client: $ redis-cli SET foo 123 +[stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-25] client: Received bytes: "+OK\r\n" +[stage-25] client: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] client: > SET bar 456 +[stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-25] client: Received bytes: "+OK\r\n" +[stage-25] client: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] client: > SET baz 789 +[stage-25] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-25] client: Received bytes: "+OK\r\n" +[stage-25] client: Received RESP simple string: "OK" +[stage-25] Received "OK" +[stage-25] Testing Replica: 1/3 +[stage-25] replica-1: Expecting "SET foo 123" to be propagated +[stage-25] replica-1: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-25] replica-1: Received RESP array: ["SELECT", "0"] +[stage-25] replica-1: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-25] replica-1: Received RESP array: ["SET", "foo", "123"] +[stage-25] Received ["SET", "foo", "123"] +[stage-25] replica-1: Expecting "SET bar 456" to be propagated +[stage-25] replica-1: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-25] replica-1: Received RESP array: ["SET", "bar", "456"] +[stage-25] Received ["SET", "bar", "456"] +[stage-25] replica-1: Expecting "SET baz 789" to be propagated +[stage-25] replica-1: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-25] replica-1: Received RESP array: ["SET", "baz", "789"] +[stage-25] Received ["SET", "baz", "789"] +[stage-25] Testing Replica: 2/3 +[stage-25] replica-2: Expecting "SET foo 123" to be propagated +[stage-25] replica-2: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-25] replica-2: Received RESP array: ["SELECT", "0"] +[stage-25] replica-2: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-25] replica-2: Received RESP array: ["SET", "foo", "123"] +[stage-25] Received ["SET", "foo", "123"] +[stage-25] replica-2: Expecting "SET bar 456" to be propagated +[stage-25] replica-2: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-25] replica-2: Received RESP array: ["SET", "bar", "456"] +[stage-25] Received ["SET", "bar", "456"] +[stage-25] replica-2: Expecting "SET baz 789" to be propagated +[stage-25] replica-2: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-25] replica-2: Received RESP array: ["SET", "baz", "789"] +[stage-25] Received ["SET", "baz", "789"] +[stage-25] Testing Replica: 3/3 +[stage-25] replica-3: Expecting "SET foo 123" to be propagated +[stage-25] replica-3: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-25] replica-3: Received RESP array: ["SELECT", "0"] +[stage-25] replica-3: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-25] replica-3: Received RESP array: ["SET", "foo", "123"] +[stage-25] Received ["SET", "foo", "123"] +[stage-25] replica-3: Expecting "SET bar 456" to be propagated +[stage-25] replica-3: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-25] replica-3: Received RESP array: ["SET", "bar", "456"] +[stage-25] Received ["SET", "bar", "456"] +[stage-25] replica-3: Expecting "SET baz 789" to be propagated +[stage-25] replica-3: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-25] replica-3: Received RESP array: ["SET", "baz", "789"] +[stage-25] Received ["SET", "baz", "789"] +[stage-25] Test passed. +[stage-25] Terminating program +[stage-25] Program terminated successfully + +[stage-24] Running tests for Stage #24: zn8 +[stage-24] $ ./spawn_redis_server.sh --port 6379 +[stage-24] replica: $ redis-cli PING +[stage-24] replica: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-24] replica: Received bytes: "+PONG\r\n" +[stage-24] replica: Received RESP simple string: "PONG" +[stage-24] Received "PONG" +[stage-24] replica: > REPLCONF listening-port 6380 +[stage-24] replica: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-24] replica: Received bytes: "+OK\r\n" +[stage-24] replica: Received RESP simple string: "OK" +[stage-24] Received "OK" +[stage-24] replica: > REPLCONF capa psync2 +[stage-24] replica: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-24] replica: Received bytes: "+OK\r\n" +[stage-24] replica: Received RESP simple string: "OK" +[stage-24] Received "OK" +[stage-24] replica: > PSYNC ? -1 +[stage-24] replica: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-24] replica: Received bytes: "+FULLRESYNC fb217523f2c9c301e3804564b643014400411d9b 0\r\n" +[stage-24] replica: Received RESP simple string: "FULLRESYNC fb217523f2c9c301e3804564b643014400411d9b 0" +[stage-24] Received "FULLRESYNC fb217523f2c9c301e3804564b643014400411d9b 0" +[stage-24] Reading RDB file... +[stage-24] replica: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xc9tlf\xfa\bused-mem\xc2\xc0S\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(fb217523f2c9c301e3804564b643014400411d9b\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffn\xff\b\xcdI\xcb\xc0a" +[stage-24] Received RDB file +[stage-24] client: $ redis-cli SET foo 123 +[stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-24] client: Received bytes: "+OK\r\n" +[stage-24] client: Received RESP simple string: "OK" +[stage-24] Received "OK" +[stage-24] client: > SET bar 456 +[stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-24] client: Received bytes: "+OK\r\n" +[stage-24] client: Received RESP simple string: "OK" +[stage-24] Received "OK" +[stage-24] client: > SET baz 789 +[stage-24] client: Sent bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-24] client: Received bytes: "+OK\r\n" +[stage-24] client: Received RESP simple string: "OK" +[stage-24] Received "OK" +[stage-24] Sent 3 SET commands to master successfully. +[stage-24] replica: Expecting "SET foo 123" to be propagated +[stage-24] replica: Received bytes: "*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n" +[stage-24] replica: Received RESP array: ["SELECT", "0"] +[stage-24] replica: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n" +[stage-24] replica: Received RESP array: ["SET", "foo", "123"] +[stage-24] Received ["SET", "foo", "123"] +[stage-24] replica: Expecting "SET bar 456" to be propagated +[stage-24] replica: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$3\r\n456\r\n" +[stage-24] replica: Received RESP array: ["SET", "bar", "456"] +[stage-24] Received ["SET", "bar", "456"] +[stage-24] replica: Expecting "SET baz 789" to be propagated +[stage-24] replica: Received bytes: "*3\r\n$3\r\nSET\r\n$3\r\nbaz\r\n$3\r\n789\r\n" +[stage-24] replica: Received RESP array: ["SET", "baz", "789"] +[stage-24] Received ["SET", "baz", "789"] +[stage-24] Test passed. +[stage-24] Terminating program +[stage-24] Program terminated successfully + +[stage-23] Running tests for Stage #23: cf8 +[stage-23] $ ./spawn_redis_server.sh --port 6379 +[stage-23] client: $ redis-cli PING +[stage-23] client: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-23] client: Received bytes: "+PONG\r\n" +[stage-23] client: Received RESP simple string: "PONG" +[stage-23] Received "PONG" +[stage-23] client: > REPLCONF listening-port 6380 +[stage-23] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-23] client: Received bytes: "+OK\r\n" +[stage-23] client: Received RESP simple string: "OK" +[stage-23] Received "OK" +[stage-23] client: > REPLCONF capa psync2 +[stage-23] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-23] client: Received bytes: "+OK\r\n" +[stage-23] client: Received RESP simple string: "OK" +[stage-23] Received "OK" +[stage-23] client: > PSYNC ? -1 +[stage-23] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-23] client: Received bytes: "+FULLRESYNC 4a683405a76db69b468112e12b5244236490dbac 0\r\n" +[stage-23] client: Received RESP simple string: "FULLRESYNC 4a683405a76db69b468112e12b5244236490dbac 0" +[stage-23] Received "FULLRESYNC 4a683405a76db69b468112e12b5244236490dbac 0" +[stage-23] Reading RDB file... +[stage-23] client: Received bytes: "$171\r\nREDIS0011\xfa\tredis-ver\x057.2.4\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2\xcatlf\xfa\bused-mem\xc2\xf0\r\x12\x00\xfa\x0erepl-stream-db\xc0\x00\xfa\arepl-id(4a683405a76db69b468112e12b5244236490dbac\xfa\vrepl-offset\xc0\x00\xfa\baof-base\xc0\x00\xffm\xdc\xf5\xc2b\xd08\xfb" +[stage-23] Received RDB file +[stage-23] Test passed. +[stage-23] Terminating program +[stage-23] Program terminated successfully + +[stage-22] Running tests for Stage #22: vm3 +[stage-22] $ ./spawn_redis_server.sh --port 6379 +[stage-22] client: $ redis-cli PING +[stage-22] client: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-22] client: Received bytes: "+PONG\r\n" +[stage-22] client: Received RESP simple string: "PONG" +[stage-22] Received "PONG" +[stage-22] client: > REPLCONF listening-port 6380 +[stage-22] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-22] client: Received bytes: "+OK\r\n" +[stage-22] client: Received RESP simple string: "OK" +[stage-22] Received "OK" +[stage-22] client: > REPLCONF capa psync2 +[stage-22] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-22] client: Received bytes: "+OK\r\n" +[stage-22] client: Received RESP simple string: "OK" +[stage-22] Received "OK" +[stage-22] client: > PSYNC ? -1 +[stage-22] client: Sent bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-22] client: Received bytes: "+FULLRESYNC 378cc0e01a8107822ffb083ff497644efb3d0d21 0\r\n" +[stage-22] client: Received RESP simple string: "FULLRESYNC 378cc0e01a8107822ffb083ff497644efb3d0d21 0" +[stage-22] Received "FULLRESYNC 378cc0e01a8107822ffb083ff497644efb3d0d21 0" +[stage-22] Test passed. +[stage-22] Terminating program +[stage-22] Program terminated successfully + +[stage-21] Running tests for Stage #21: fj0 +[stage-21] $ ./spawn_redis_server.sh --port 6379 +[stage-21] client: $ redis-cli PING +[stage-21] client: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-21] client: Received bytes: "+PONG\r\n" +[stage-21] client: Received RESP simple string: "PONG" +[stage-21] Received "PONG" +[stage-21] client: > REPLCONF listening-port 6380 +[stage-21] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-21] client: Received bytes: "+OK\r\n" +[stage-21] client: Received RESP simple string: "OK" +[stage-21] Received "OK" +[stage-21] client: > REPLCONF capa psync2 +[stage-21] client: Sent bytes: "*3\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-21] client: Received bytes: "+OK\r\n" +[stage-21] client: Received RESP simple string: "OK" +[stage-21] Received "OK" +[stage-21] Test passed. +[stage-21] Terminating program +[stage-21] Program terminated successfully + +[stage-20] Running tests for Stage #20: ju6 +[stage-20] Master is running on port 6379 +[stage-20] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-20] master: Waiting for replica to initiate handshake with "PING" command +[stage-20] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-20] master: Received RESP array: ["PING"] +[stage-20] Received ["PING"] +[stage-20] master: Sent "PONG" +[stage-20] master: Sent bytes: "+PONG\r\n" +[stage-20] master: Waiting for replica to send "REPLCONF listening-port 6380" command +[stage-20] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-20] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-20] Received ["REPLCONF", "listening-port", "6380"] +[stage-20] master: Sent "OK" +[stage-20] master: Sent bytes: "+OK\r\n" +[stage-20] master: Waiting for replica to send "REPLCONF capa" command +[stage-20] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-20] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-20] Received ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-20] master: Sent "OK" +[stage-20] master: Sent bytes: "+OK\r\n" +[stage-20] master: Waiting for replica to send "PSYNC" command +[stage-20] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-20] master: Received RESP array: ["PSYNC", "?", "-1"] +[stage-20] Received ["PSYNC", "?", "-1"] +[stage-20] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0" +[stage-20] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n" +[stage-20] Test passed. +[stage-20] Terminating program +[stage-20] Program terminated successfully + +[stage-19] Running tests for Stage #19: eh4 +[stage-19] Master is running on port 6379 +[stage-19] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-19] master: Waiting for replica to initiate handshake with "PING" command +[stage-19] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-19] master: Received RESP array: ["PING"] +[stage-19] Received ["PING"] +[stage-19] master: Sent "PONG" +[stage-19] master: Sent bytes: "+PONG\r\n" +[stage-19] master: Waiting for replica to send "REPLCONF listening-port 6380" command +[stage-19] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-19] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-19] Received ["REPLCONF", "listening-port", "6380"] +[stage-19] master: Sent "OK" +[stage-19] master: Sent bytes: "+OK\r\n" +[stage-19] master: Waiting for replica to send "REPLCONF capa" command +[stage-19] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-19] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-19] Received ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-19] master: Sent "OK" +[stage-19] master: Sent bytes: "+OK\r\n" +[stage-19] Test passed. +[stage-19] Terminating program +[stage-19] Program terminated successfully + +[stage-18] Running tests for Stage #18: gl7 +[stage-18] Master is running on port 6379. +[stage-18] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-18] master: Waiting for replica to initiate handshake with "PING" command +[stage-18] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-18] master: Received RESP array: ["PING"] +[stage-18] Received ["PING"] +[stage-18] master: Sent "PONG" +[stage-18] master: Sent bytes: "+PONG\r\n" +[stage-18] Test passed. +[stage-18] Terminating program +[stage-18] Program terminated successfully + +[stage-17] Running tests for Stage #17: xc1 +[stage-17] $ ./spawn_redis_server.sh +[stage-17] client: $ redis-cli INFO replication +[stage-17] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" +[stage-17] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9c5dddb64daca5c0a600308f4e3d66d424043344\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-17] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9c5dddb64daca5c0a600308f4e3d66d424043344\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:9c5dddb64daca5c0a600308f4e3d66d424043344\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-17] Found master_replid:xxx in response. +[stage-17] Found master_reploffset:0 in response. +[stage-17] Test passed. +[stage-17] Terminating program +[stage-17] Program terminated successfully + +[stage-16] Running tests for Stage #16: hc6 +[stage-16] Master is running on port 6379 +[stage-16] $ ./spawn_redis_server.sh --port 6380 --replicaof "localhost 6379" +[stage-16] master: Received bytes: "*1\r\n$4\r\nPING\r\n" +[stage-16] master: Received RESP array: ["PING"] +[stage-16] master: Sent "PONG" +[stage-16] master: Sent bytes: "+PONG\r\n" +[stage-16] master: Received bytes: "*3\r\n$8\r\nREPLCONF\r\n$14\r\nlistening-port\r\n$4\r\n6380\r\n" +[stage-16] master: Received RESP array: ["REPLCONF", "listening-port", "6380"] +[stage-16] master: Sent "OK" +[stage-16] master: Sent bytes: "+OK\r\n" +[stage-16] master: Received bytes: "*5\r\n$8\r\nREPLCONF\r\n$4\r\ncapa\r\n$3\r\neof\r\n$4\r\ncapa\r\n$6\r\npsync2\r\n" +[stage-16] master: Received RESP array: ["REPLCONF", "capa", "eof", "capa", "psync2"] +[stage-16] master: Sent "OK" +[stage-16] master: Sent bytes: "+OK\r\n" +[stage-16] master: Received bytes: "*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n" +[stage-16] master: Received RESP array: ["PSYNC", "?", "-1"] +[stage-16] master: Sent "FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0" +[stage-16] master: Sent bytes: "+FULLRESYNC 75cd7bc10c49047e0d163660f3b90625b1af31dc 0\r\n" +[stage-16] master: Sent bytes: "$88\r\nREDIS0011\xfa\tredis-ver\x057.2.0\xfa\nredis-bits\xc0@\xfa\x05ctime\xc2m\b\xbce\xfa\bused-mem°\xc4\x10\x00\xfa\baof-base\xc0\x00\xff\xf0n;\xfe\xc0\xffZ\xa2" +[stage-16] client: $ redis-cli INFO replication +[stage-16] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" +[stage-16] client: Received bytes: "$613\r\n# Replication\r\nrole:slave\r\nmaster_host:localhost\r\nmaster_port:6379\r\nmaster_link_status:down\r\nmaster_last_io_seconds_ago:-1\r\nmaster_sync_in_progress:0\r\nslave_read_repl_offset:0\r\nslave_repl_offset:0\r\nmaster_link_down_since_seconds:0\r\nslave_priority:100\r\nslave_read_only:1\r\nreplica_announced:1\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:75cd7bc10c49047e0d163660f3b90625b1af31dc\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:1\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:1\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-16] client: Received RESP bulk string: "# Replication\r\nrole:slave\r\nmaster_host:localhost\r\nmaster_port:6379\r\nmaster_link_status:down\r\nmaster_last_io_seconds_ago:-1\r\nmaster_sync_in_progress:0\r\nslave_read_repl_offset:0\r\nslave_repl_offset:0\r\nmaster_link_down_since_seconds:0\r\nslave_priority:100\r\nslave_read_only:1\r\nreplica_announced:1\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:75cd7bc10c49047e0d163660f3b90625b1af31dc\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:1\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:1\r\nrepl_backlog_histlen:0\r\n" +[stage-16] Received "# Replication\r\nrole:slave\r\nmaster_host:localhost\r\nmaster_port:6379\r\nmaster_link_status:down\r\nmaster_last_io_seconds_ago:-1\r\nmaster_sync_in_progress:0\r\nslave_read_repl_offset:0\r\nslave_repl_offset:0\r\nmaster_link_down_since_seconds:0\r\nslave_priority:100\r\nslave_read_only:1\r\nreplica_announced:1\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:75cd7bc10c49047e0d163660f3b90625b1af31dc\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:1\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:1\r\nrepl_backlog_histlen:0\r\n" +[stage-16] Found role:slave in response. +[stage-16] Test passed. +[stage-16] Terminating program +[stage-16] Program terminated successfully + +[stage-15] Running tests for Stage #15: ye5 +[stage-15] $ ./spawn_redis_server.sh +[stage-15] client: $ redis-cli INFO replication +[stage-15] client: Sent bytes: "*2\r\n$4\r\nINFO\r\n$11\r\nreplication\r\n" +[stage-15] client: Received bytes: "$349\r\n# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e6651c8a5c2e8dd0a7ad1b4ac62ffcc84fb639fb\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n\r\n" +[stage-15] client: Received RESP bulk string: "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e6651c8a5c2e8dd0a7ad1b4ac62ffcc84fb639fb\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] Received "# Replication\r\nrole:master\r\nconnected_slaves:0\r\nmaster_failover_state:no-failover\r\nmaster_replid:e6651c8a5c2e8dd0a7ad1b4ac62ffcc84fb639fb\r\nmaster_replid2:0000000000000000000000000000000000000000\r\nmaster_repl_offset:0\r\nsecond_repl_offset:-1\r\nrepl_backlog_active:0\r\nrepl_backlog_size:1048576\r\nrepl_backlog_first_byte_offset:0\r\nrepl_backlog_histlen:0\r\n" +[stage-15] Found role:master in response. +[stage-15] Test passed. +[stage-15] Terminating program +[stage-15] Program terminated successfully + +[stage-14] Running tests for Stage #14: bw1 +[stage-14] $ ./spawn_redis_server.sh --port 6380 +[stage-14] Connecting to port 6380... +[stage-14] Connection successful +[stage-14] Test passed. +[stage-14] Terminating program +[stage-14] Program terminated successfully + +[stage-13] Running tests for Stage #13: sm4 +[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles202461335 --dbfilename apple.rdb +[stage-13] client: $ redis-cli GET strawberry +[stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" +[stage-13] client: Received bytes: "$-1\r\n" +[stage-13] client: Received RESP null bulk string: "$-1\r\n" +[stage-13] Received "$-1\r\n" +[stage-13] client: > GET orange +[stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\norange\r\n" +[stage-13] client: Received bytes: "$9\r\nblueberry\r\n" +[stage-13] client: Received RESP bulk string: "blueberry" +[stage-13] Received "blueberry" +[stage-13] client: > GET apple +[stage-13] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" +[stage-13] client: Received bytes: "$6\r\norange\r\n" +[stage-13] client: Received RESP bulk string: "orange" +[stage-13] Received "orange" +[stage-13] Test passed. +[stage-13] Terminating program +[stage-13] Program terminated successfully + +[stage-12] Running tests for Stage #12: dq3 +[stage-12] Created RDB file with key-value pairs: "apple"="pineapple", "raspberry"="strawberry", "mango"="apple", "strawberry"="grape" +[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2321023724 --dbfilename grape.rdb +[stage-12] client: $ redis-cli GET apple +[stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" +[stage-12] client: Received bytes: "$9\r\npineapple\r\n" +[stage-12] client: Received RESP bulk string: "pineapple" +[stage-12] Received "pineapple" +[stage-12] client: > GET raspberry +[stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\nraspberry\r\n" +[stage-12] client: Received bytes: "$10\r\nstrawberry\r\n" +[stage-12] client: Received RESP bulk string: "strawberry" +[stage-12] Received "strawberry" +[stage-12] client: > GET mango +[stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\nmango\r\n" +[stage-12] client: Received bytes: "$5\r\napple\r\n" +[stage-12] client: Received RESP bulk string: "apple" +[stage-12] Received "apple" +[stage-12] client: > GET strawberry +[stage-12] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$10\r\nstrawberry\r\n" +[stage-12] client: Received bytes: "$5\r\ngrape\r\n" +[stage-12] client: Received RESP bulk string: "grape" +[stage-12] Received "grape" +[stage-12] Test passed. +[stage-12] Terminating program +[stage-12] Program terminated successfully + +[stage-11] Running tests for Stage #11: jw4 +[stage-11] Created RDB file with 3 keys: ["orange" "banana" "pear"] +[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2091869705 --dbfilename grape.rdb +[stage-11] client: $ redis-cli KEYS * +[stage-11] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" +[stage-11] client: Received bytes: "*3\r\n$4\r\npear\r\n$6\r\nbanana\r\n$6\r\norange\r\n" +[stage-11] client: Received RESP array: ["pear", "banana", "orange"] +[stage-11] Received ["pear", "banana", "orange"] +[stage-11] Test passed. +[stage-11] Terminating program +[stage-11] Program terminated successfully + +[stage-10] Running tests for Stage #10: gc6 +[stage-10] Created RDB file with single key-value pair: pineapple="blueberry" +[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1208672642 --dbfilename mango.rdb +[stage-10] client: $ redis-cli GET pineapple +[stage-10] client: Sent bytes: "*2\r\n$3\r\nGET\r\n$9\r\npineapple\r\n" +[stage-10] client: Received bytes: "$9\r\nblueberry\r\n" +[stage-10] client: Received RESP bulk string: "blueberry" +[stage-10] Received "blueberry" +[stage-10] Test passed. +[stage-10] Terminating program +[stage-10] Program terminated successfully + +[stage-9] Running tests for Stage #9: jz6 +[stage-9] Created RDB file with single key: "apple" +[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles73015925 --dbfilename mango.rdb +[stage-9] client: $ redis-cli KEYS * +[stage-9] client: Sent bytes: "*2\r\n$4\r\nKEYS\r\n$1\r\n*\r\n" +[stage-9] client: Received bytes: "*1\r\n$5\r\napple\r\n" +[stage-9] client: Received RESP array: ["apple"] +[stage-9] Received ["apple"] +[stage-9] Test passed. +[stage-9] Terminating program +[stage-9] Program terminated successfully + +[stage-8] Running tests for Stage #8: zg5 +[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3503538548 --dbfilename blueberry.rdb +[stage-8] client: $ redis-cli CONFIG GET dir +[stage-8] client: Sent bytes: "*3\r\n$6\r\nCONFIG\r\n$3\r\nGET\r\n$3\r\ndir\r\n" +[stage-8] client: Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3503538548\r\n" +[stage-8] client: Received RESP array: ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3503538548"] +[stage-8] Received ["dir", "/private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3503538548"] +[stage-8] Test passed. +[stage-8] Terminating program +[stage-8] Program terminated successfully + +[stage-7] Running tests for Stage #7: yz1 +[stage-7] $ ./spawn_redis_server.sh +[stage-7] $ redis-cli SET apple banana px 100 +[stage-7] Sent bytes: "*5\r\n$3\r\nSET\r\n$5\r\napple\r\n$6\r\nbanana\r\n$2\r\npx\r\n$3\r\n100\r\n" +[stage-7] Received bytes: "+OK\r\n" +[stage-7] Received RESP simple string: "OK" +[stage-7] Received "OK" +[stage-7] Received OK at 22:20:21.189 +[stage-7] Fetching key "apple" at 22:20:21.189 (should not be expired) +[stage-7] > GET apple +[stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" +[stage-7] Received bytes: "$6\r\nbanana\r\n" +[stage-7] Received RESP bulk string: "banana" +[stage-7] Received "banana" +[stage-7] Sleeping for 101ms +[stage-7] Fetching key "apple" at 22:20:21.295 (should be expired) +[stage-7] > GET apple +[stage-7] Sent bytes: "*2\r\n$3\r\nGET\r\n$5\r\napple\r\n" +[stage-7] Received bytes: "$-1\r\n" +[stage-7] Received RESP null bulk string: "$-1\r\n" +[stage-7] Received "$-1\r\n" +[stage-7] Test passed. +[stage-7] Terminating program +[stage-7] Program terminated successfully + +[stage-6] Running tests for Stage #6: la7 +[stage-6] $ ./spawn_redis_server.sh +[stage-6] Setting key banana to pear +[stage-6] $ redis-cli SET banana pear +[stage-6] Sent bytes: "*3\r\n$3\r\nSET\r\n$6\r\nbanana\r\n$4\r\npear\r\n" +[stage-6] Received bytes: "+OK\r\n" +[stage-6] Received RESP simple string: "OK" +[stage-6] Received "OK" +[stage-6] Getting key banana +[stage-6] > GET banana +[stage-6] Sent bytes: "*2\r\n$3\r\nGET\r\n$6\r\nbanana\r\n" +[stage-6] Received bytes: "$4\r\npear\r\n" +[stage-6] Received RESP bulk string: "pear" +[stage-6] Received "pear" +[stage-6] Test passed. +[stage-6] Terminating program +[stage-6] Program terminated successfully + +[stage-5] Running tests for Stage #5: qq0 +[stage-5] $ ./spawn_redis_server.sh +[stage-5] $ redis-cli ECHO pear +[stage-5] Sent bytes: "*2\r\n$4\r\nECHO\r\n$4\r\npear\r\n" +[stage-5] Received bytes: "$4\r\npear\r\n" +[stage-5] Received RESP bulk string: "pear" +[stage-5] Received "pear" +[stage-5] Test passed. +[stage-5] Terminating program +[stage-5] Program terminated successfully + +[stage-4] Running tests for Stage #4: zu2 +[stage-4] $ ./spawn_redis_server.sh +[stage-4] client-1: $ redis-cli PING +[stage-4] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-1: Received bytes: "+PONG\r\n" +[stage-4] client-1: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-2: $ redis-cli PING +[stage-4] client-2: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-2: Received bytes: "+PONG\r\n" +[stage-4] client-2: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-1: > PING +[stage-4] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-1: Received bytes: "+PONG\r\n" +[stage-4] client-1: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-1: > PING +[stage-4] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-1: Received bytes: "+PONG\r\n" +[stage-4] client-1: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-2: > PING +[stage-4] client-2: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-2: Received bytes: "+PONG\r\n" +[stage-4] client-2: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-1: Success, closing connection... +[stage-4] client-3: $ redis-cli PING +[stage-4] client-3: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-4] client-3: Received bytes: "+PONG\r\n" +[stage-4] client-3: Received RESP simple string: "PONG" +[stage-4] Received "PONG" +[stage-4] client-2: Success, closing connection... +[stage-4] client-3: Success, closing connection... +[stage-4] Test passed. +[stage-4] Terminating program +[stage-4] Program terminated successfully + +[stage-3] Running tests for Stage #3: wy1 +[stage-3] $ ./spawn_redis_server.sh +[stage-3] client-1: $ redis-cli PING +[stage-3] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-3] client-1: Received bytes: "+PONG\r\n" +[stage-3] client-1: Received RESP simple string: "PONG" +[stage-3] Received "PONG" +[stage-3] client-1: > PING +[stage-3] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-3] client-1: Received bytes: "+PONG\r\n" +[stage-3] client-1: Received RESP simple string: "PONG" +[stage-3] Received "PONG" +[stage-3] client-1: > PING +[stage-3] client-1: Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-3] client-1: Received bytes: "+PONG\r\n" +[stage-3] client-1: Received RESP simple string: "PONG" +[stage-3] Received "PONG" +[stage-3] Success, closing connection... +[stage-3] Test passed. +[stage-3] Terminating program +[stage-3] Program terminated successfully + +[stage-2] Running tests for Stage #2: rg2 +[stage-2] $ ./spawn_redis_server.sh +[stage-2] Connection established, sending ping command... +[stage-2] $ redis-cli PING +[stage-2] Sent bytes: "*1\r\n$4\r\nPING\r\n" +[stage-2] Received bytes: "+PONG\r\n" +[stage-2] Received RESP simple string: "PONG" +[stage-2] Received "PONG" +[stage-2] Test passed. +[stage-2] Terminating program +[stage-2] Program terminated successfully + +[stage-1] Running tests for Stage #1: jm1 +[stage-1] $ ./spawn_redis_server.sh +[stage-1] Connecting to port 6379... +[stage-1] Connection successful +[stage-1] Test passed. +[stage-1] Terminating program +[stage-1] Program terminated successfully diff --git a/internal/test_txn_discard.go b/internal/test_txn_discard.go new file mode 100644 index 00000000..eb8b6562 --- /dev/null +++ b/internal/test_txn_discard.go @@ -0,0 +1,75 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxDiscard(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + uniqueKeys := random.RandomWords(2) + key1, key2 := uniqueKeys[0], uniqueKeys[1] + randomInt1, randomInt2 := random.RandomInt(1, 100), random.RandomInt(1, 100) + + commandTestCase := test_cases.SendCommandTestCase{ + Command: "SET", + Args: []string{key2, fmt.Sprint(randomInt2)}, + Assertion: resp_assertions.NewStringAssertion("OK"), + } + + if err := commandTestCase.Run(client, logger); err != nil { + return err + } + + transactionTestCase := test_cases.TransactionTestCase{ + CommandQueue: [][]string{ + {"SET", key1, fmt.Sprint(randomInt1)}, + {"INCR", key1}, + }, + } + + if err := transactionTestCase.RunWithoutExec(client, logger); err != nil { + return err + } + + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"DISCARD"}, + {"GET", key1}, + {"GET", key2}, + {"DISCARD"}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion("OK"), + resp_assertions.NewNilAssertion(), + resp_assertions.NewStringAssertion(fmt.Sprint(randomInt2)), + resp_assertions.NewErrorAssertion("ERR DISCARD without MULTI"), + }, + } + + if err := multiCommandTestCase.RunAll(client, logger); err != nil { + return err + } + + return nil +} diff --git a/internal/test_txn_empty.go b/internal/test_txn_empty.go new file mode 100644 index 00000000..835d1b58 --- /dev/null +++ b/internal/test_txn_empty.go @@ -0,0 +1,40 @@ +package internal + +import ( + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxEmpty(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + emptyTransactionTestCase := test_cases.TransactionTestCase{} + + if err := emptyTransactionTestCase.RunAll(client, logger); err != nil { + return err + } + + bareExecCommandTestCase := test_cases.SendCommandTestCase{ + Command: "EXEC", + Args: []string{}, + Assertion: resp_assertions.NewErrorAssertion("ERR EXEC without MULTI"), + } + + return bareExecCommandTestCase.Run(client, logger) +} diff --git a/internal/test_txn_exec.go b/internal/test_txn_exec.go new file mode 100644 index 00000000..d7b0044e --- /dev/null +++ b/internal/test_txn_exec.go @@ -0,0 +1,34 @@ +package internal + +import ( + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxExec(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + bareExecCommandTestCase := test_cases.SendCommandTestCase{ + Command: "EXEC", + Args: []string{}, + Assertion: resp_assertions.NewErrorAssertion("ERR EXEC without MULTI"), + } + + return bareExecCommandTestCase.Run(client, logger) +} diff --git a/internal/test_txn_incr1.go b/internal/test_txn_incr1.go new file mode 100644 index 00000000..996a3723 --- /dev/null +++ b/internal/test_txn_incr1.go @@ -0,0 +1,45 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxIncr1(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + randomValue := random.RandomInt(1, 100) + randomKey := random.RandomWord() + + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"SET", randomKey, fmt.Sprint(randomValue)}, + {"INCR", randomKey}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion("OK"), + resp_assertions.NewIntegerAssertion(randomValue + 1), + }, + } + + return multiCommandTestCase.RunAll(client, logger) +} diff --git a/internal/test_txn_incr2.go b/internal/test_txn_incr2.go new file mode 100644 index 00000000..addaaef6 --- /dev/null +++ b/internal/test_txn_incr2.go @@ -0,0 +1,44 @@ +package internal + +import ( + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxIncr2(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + randomKey := random.RandomWord() + + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"INCR", randomKey}, + {"INCR", randomKey}, + {"GET", randomKey}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewIntegerAssertion(1), + resp_assertions.NewIntegerAssertion(2), + resp_assertions.NewStringAssertion("2"), + }, + } + + return multiCommandTestCase.RunAll(client, logger) +} diff --git a/internal/test_txn_incr3.go b/internal/test_txn_incr3.go new file mode 100644 index 00000000..475c38a5 --- /dev/null +++ b/internal/test_txn_incr3.go @@ -0,0 +1,43 @@ +package internal + +import ( + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxIncr3(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + uniqueKeys := random.RandomWords(2) + randomKey, randomValue := uniqueKeys[0], uniqueKeys[1] + + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"SET", randomKey, randomValue}, + {"INCR", randomKey}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion("OK"), + resp_assertions.NewErrorAssertion("ERR value is not an integer or out of range"), + }, + } + + return multiCommandTestCase.RunAll(client, logger) +} diff --git a/internal/test_txn_multi.go b/internal/test_txn_multi.go new file mode 100644 index 00000000..b38311b8 --- /dev/null +++ b/internal/test_txn_multi.go @@ -0,0 +1,29 @@ +package internal + +import ( + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + + "github.com/codecrafters-io/redis-tester/internal/instrumented_resp_connection" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxMulti(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, "localhost:6379", "client") + if err != nil { + logFriendlyError(logger, err) + return err + } + defer client.Close() + + transactionTestCase := test_cases.TransactionTestCase{} + + return transactionTestCase.RunMulti(client, logger) +} diff --git a/internal/test_txn_multi_tx.go b/internal/test_txn_multi_tx.go new file mode 100644 index 00000000..b05b28eb --- /dev/null +++ b/internal/test_txn_multi_tx.go @@ -0,0 +1,78 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxMultiTx(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + clients, err := SpawnClients(3, "localhost:6379", stageHarness, logger) + if err != nil { + return err + } + for _, client := range clients { + defer client.Close() + } + + uniqueKeys := random.RandomWords(2) + key1, key2 := uniqueKeys[0], uniqueKeys[1] + randomIntegerValue := random.RandomInt(1, 100) + + for i, client := range clients { + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"SET", key2, fmt.Sprint(randomIntegerValue)}, + {"INCR", key1}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion("OK"), + resp_assertions.NewIntegerAssertion(i + 1), + }, + } + + if err := multiCommandTestCase.RunAll(client, logger); err != nil { + return err + } + } + + for _, client := range clients { + transactionTestCase := test_cases.TransactionTestCase{ + CommandQueue: [][]string{ + {"INCR", key1}, + {"INCR", key2}, + }, + } + if err := transactionTestCase.RunWithoutExec(client, logger); err != nil { + return err + } + } + + for i, client := range clients { + transactionTestCase := test_cases.TransactionTestCase{ + // Before a single transaction is queued, + // We run 3x INCR key1, and set key2 to randomIntegerValue + // Inside each transaction, we run 1x INCR key1, key2 + // So it increases by 1 for each transaction + // `i` here is 0-indexed, so we add 1 to the expected value + ExpectedResponseArray: []resp_assertions.RESPAssertion{resp_assertions.NewIntegerAssertion(3 + (1 + i)), resp_assertions.NewIntegerAssertion(randomIntegerValue + (1 + i))}, + } + if err := transactionTestCase.RunExec(client, logger); err != nil { + return err + } + } + + return nil +} diff --git a/internal/test_txn_queue.go b/internal/test_txn_queue.go new file mode 100644 index 00000000..60f46b68 --- /dev/null +++ b/internal/test_txn_queue.go @@ -0,0 +1,51 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxQueue(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + clients, err := SpawnClients(2, "localhost:6379", stageHarness, logger) + if err != nil { + return err + } + for _, client := range clients { + defer client.Close() + } + + key := random.RandomWord() + randomIntegerValue := random.RandomInt(1, 100) + + transactionTestCase := test_cases.TransactionTestCase{ + CommandQueue: [][]string{ + {"SET", key, fmt.Sprint(randomIntegerValue)}, + {"INCR", key}, + }, + } + + if err := transactionTestCase.RunWithoutExec(clients[0], logger); err != nil { + return err + } + + commandTestCase := test_cases.SendCommandTestCase{ + Command: "GET", + Args: []string{key}, + Assertion: resp_assertions.NewNilAssertion(), + } + + return commandTestCase.Run(clients[1], logger) +} diff --git a/internal/test_txn_tx.go b/internal/test_txn_tx.go new file mode 100644 index 00000000..38995dbd --- /dev/null +++ b/internal/test_txn_tx.go @@ -0,0 +1,55 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxSuccess(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + clients, err := SpawnClients(2, "localhost:6379", stageHarness, logger) + if err != nil { + return err + } + for _, client := range clients { + defer client.Close() + } + + uniqueKeys := random.RandomWords(2) + key1, key2 := uniqueKeys[0], uniqueKeys[1] + randomIntegerValue := random.RandomInt(1, 100) + + transactionTestCase := test_cases.TransactionTestCase{ + CommandQueue: [][]string{ + {"SET", key1, fmt.Sprint(randomIntegerValue)}, + {"INCR", key1}, + {"INCR", key2}, + {"GET", key2}, + }, + ExpectedResponseArray: []resp_assertions.RESPAssertion{resp_assertions.NewStringAssertion("OK"), resp_assertions.NewIntegerAssertion(randomIntegerValue + 1), resp_assertions.NewIntegerAssertion(1), resp_assertions.NewStringAssertion("1")}, + } + + if err := transactionTestCase.RunAll(clients[0], logger); err != nil { + return err + } + + commandTestCase := test_cases.SendCommandTestCase{ + Command: "GET", + Args: []string{key1}, + Assertion: resp_assertions.NewStringAssertion(fmt.Sprint(randomIntegerValue + 1)), + } + + return commandTestCase.Run(clients[1], logger) +} diff --git a/internal/test_txn_tx_failure.go b/internal/test_txn_tx_failure.go new file mode 100644 index 00000000..27a8c3aa --- /dev/null +++ b/internal/test_txn_tx_failure.go @@ -0,0 +1,77 @@ +package internal + +import ( + "fmt" + + "github.com/codecrafters-io/redis-tester/internal/redis_executable" + + "github.com/codecrafters-io/redis-tester/internal/resp_assertions" + "github.com/codecrafters-io/redis-tester/internal/test_cases" + "github.com/codecrafters-io/tester-utils/random" + "github.com/codecrafters-io/tester-utils/test_case_harness" +) + +func testTxErr(stageHarness *test_case_harness.TestCaseHarness) error { + b := redis_executable.NewRedisExecutable(stageHarness) + if err := b.Run(); err != nil { + return err + } + + logger := stageHarness.Logger + + clients, err := SpawnClients(2, "localhost:6379", stageHarness, logger) + if err != nil { + return err + } + for _, client := range clients { + defer client.Close() + } + + uniqueKeys := random.RandomWords(3) + key1, key2 := uniqueKeys[0], uniqueKeys[1] + randomStringValue := uniqueKeys[2] + randomIntegerValue := random.RandomInt(1, 100) + + multiCommandTestCase := test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"SET", key1, randomStringValue}, + {"SET", key2, fmt.Sprint(randomIntegerValue)}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion("OK"), + resp_assertions.NewStringAssertion("OK"), + }, + } + + if err := multiCommandTestCase.RunAll(clients[0], logger); err != nil { + return err + } + + transactionTestCase := test_cases.TransactionTestCase{ + CommandQueue: [][]string{ + {"INCR", key1}, + {"INCR", key2}, + }, + ExpectedResponseArray: []resp_assertions.RESPAssertion{ + resp_assertions.NewErrorAssertion("ERR value is not an integer or out of range"), + resp_assertions.NewIntegerAssertion(randomIntegerValue + 1), + }, + } + + if err := transactionTestCase.RunAll(clients[0], logger); err != nil { + return err + } + + multiCommandTestCase = test_cases.MultiCommandTestCase{ + Commands: [][]string{ + {"GET", key2}, + {"GET", key1}, + }, + Assertions: []resp_assertions.RESPAssertion{ + resp_assertions.NewStringAssertion(fmt.Sprint(randomIntegerValue + 1)), + resp_assertions.NewStringAssertion(randomStringValue), + }, + } + + return multiCommandTestCase.RunAll(clients[1], logger) +} diff --git a/internal/tester_definition.go b/internal/tester_definition.go index f7a470b9..0d3de6c3 100644 --- a/internal/tester_definition.go +++ b/internal/tester_definition.go @@ -192,5 +192,49 @@ var testerDefinition = tester_definition.TesterDefinition{ Slug: "xu1", TestFunc: testStreamsXreadBlockMaxID, }, + { + Slug: "si4", + TestFunc: testTxIncr1, + }, + { + Slug: "lz8", + TestFunc: testTxIncr2, + }, + { + Slug: "mk1", + TestFunc: testTxIncr3, + }, + { + Slug: "pn0", + TestFunc: testTxMulti, + }, + { + Slug: "lo4", + TestFunc: testTxExec, + }, + { + Slug: "we1", + TestFunc: testTxEmpty, + }, + { + Slug: "rs9", + TestFunc: testTxQueue, + }, + { + Slug: "fy6", + TestFunc: testTxSuccess, + }, + { + Slug: "rl9", + TestFunc: testTxDiscard, + }, + { + Slug: "sg9", + TestFunc: testTxErr, + }, + { + Slug: "jf8", + TestFunc: testTxMultiTx, + }, }, } diff --git a/internal/util.go b/internal/util.go index edb28340..e12e55d0 100644 --- a/internal/util.go +++ b/internal/util.go @@ -55,3 +55,20 @@ func SpawnReplicas(replicaCount int, stageHarness *test_case_harness.TestCaseHar } return replicas, nil } + +// SpawnClients creates `clientCount` clients connected to the given address. +// The clients are created using the `instrumented_resp_connection.NewFromAddr` function. +// Clients are supposed to be closed after use. +func SpawnClients(clientCount int, addr string, stageHarness *test_case_harness.TestCaseHarness, logger *logger.Logger) ([]*resp_connection.RespConnection, error) { + var clients []*resp_connection.RespConnection + + for i := 0; i < clientCount; i++ { + client, err := instrumented_resp_connection.NewFromAddr(stageHarness, addr, fmt.Sprintf("client-%d", i+1)) + if err != nil { + logFriendlyError(logger, err) + return nil, err + } + clients = append(clients, client) + } + return clients, nil +}