Skip to content

Commit

Permalink
Merge pull request #127 from codecrafters-io/fix-rdb-persistence-stage-1
Browse files Browse the repository at this point in the history
Add StringArrayAssertion and update test cases
  • Loading branch information
rohitpaulk authored Apr 3, 2024
2 parents e9b632f + c89a666 commit bcfbce1
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 181 deletions.
39 changes: 39 additions & 0 deletions internal/resp_assertions/string_array_assertion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package resp_assertions

import (
"fmt"

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

type StringArrayAssertion struct {
ExpectedValue []string
}

func NewStringArrayAssertion(expectedValue []string) RESPAssertion {
return StringArrayAssertion{ExpectedValue: expectedValue}
}

func (a StringArrayAssertion) 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, expectedValue := range a.ExpectedValue {
actualElement := value.Array()[i]

if actualElement.Type != resp_value.BULK_STRING && actualElement.Type != resp_value.SIMPLE_STRING {
return fmt.Errorf("Expected element #%d to be a string, got %s", i+1, actualElement.Type)
}

if actualElement.String() != expectedValue {
return fmt.Errorf("Expected element #%d to be %q, got %q", i+1, expectedValue, actualElement.String())
}
}

return nil
}
20 changes: 11 additions & 9 deletions internal/stages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,17 @@ func TestStages(t *testing.T) {

func normalizeTesterOutput(testerOutput []byte) []byte {
replacements := map[string][]*regexp.Regexp{
"tcp_port": {regexp.MustCompile(`read tcp 127.0.0.1:\d+->127.0.0.1:6379: read: connection reset by peer`)},
" tmp_dir ": {regexp.MustCompile(` /private/var/folders/[^ ]+ `), regexp.MustCompile(` /tmp/[^ ]+ `)},
"timestamp": {regexp.MustCompile(`\d{2}:\d{2}:\d{2}\.\d{3}`)},
"info_replication": {regexp.MustCompile(`"# Replication\\r\\n[^"]+"`)},
"replication_id": {regexp.MustCompile(`FULLRESYNC [A-Za-z0-9]+ 0`)},
"wait_timeout": {regexp.MustCompile(`WAIT command returned after [0-9]+ ms`)},
"xadd_id": {regexp.MustCompile(`\d{13}-\d+`)},
"rdb_bytes": {regexp.MustCompile(`"\$[0-9]+\\r\\nREDIS.*"`)},
"info_replication_bytes": {regexp.MustCompile(`"\$[0-9]+\\r\\n# Replication\\r\\n[^"]+"`)},
"tcp_port": {regexp.MustCompile(`read tcp 127.0.0.1:\d+->127.0.0.1:6379: read: connection reset by peer`)},
" tmp_dir ": {regexp.MustCompile(` /private/var/folders/[^ ]+ `), regexp.MustCompile(` /tmp/[^ ]+ `)},
"$length\\r\\ntmp_dir\\r": {regexp.MustCompile(`\$\d+\\r\\n/private/var/folders/[^ ]+\\r\\n`), regexp.MustCompile(`\$\d+\\r\\n/tmp/[^ ]+\\r\\n`)},
"\"tmp_dir\"": {regexp.MustCompile(`"/private/var/folders/[^"]+"`), regexp.MustCompile(`"/tmp/[^"]+"`)},
"timestamp": {regexp.MustCompile(`\d{2}:\d{2}:\d{2}\.\d{3}`)},
"info_replication": {regexp.MustCompile(`"# Replication\\r\\n[^"]+"`)},
"replication_id": {regexp.MustCompile(`FULLRESYNC [A-Za-z0-9]+ 0`)},
"wait_timeout": {regexp.MustCompile(`WAIT command returned after [0-9]+ ms`)},
"xadd_id": {regexp.MustCompile(`\d{13}-\d+`)},
"rdb_bytes": {regexp.MustCompile(`"\$[0-9]+\\r\\nREDIS.*"`)},
"info_replication_bytes": {regexp.MustCompile(`"\$[0-9]+\\r\\n# Replication\\r\\n[^"]+"`)},
}

for replacement, regexes := range replacements {
Expand Down
24 changes: 14 additions & 10 deletions internal/test_helpers/fixtures/rdb-read-value-with-expiry/pass
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ Debug = true
[stage-7] Received bytes: "+OK\r\n"
[stage-7] Received RESP value: "OK"
[stage-7] Received "OK"
[stage-7] Received OK at 23:38:34.936
[stage-7] Fetching key "pineapple" at 23:38:34.936 (should not be expired)
[stage-7] Received OK at 17:35:38.574
[stage-7] Fetching key "pineapple" at 17:35:38.574 (should not be expired)
[stage-7] $ redis-cli get pineapple
[stage-7] Sent bytes: "*2\r\n$3\r\nget\r\n$9\r\npineapple\r\n"
[stage-7] Received bytes: "$5\r\ngrape\r\n"
[stage-7] Received RESP value: "grape"
[stage-7] Received "grape"
[stage-7] Sleeping for 101ms
[stage-7] Fetching key "pineapple" at 23:38:35.040 (should be expired)
[stage-7] Fetching key "pineapple" at 17:35:38.678 (should be expired)
[stage-7] $ redis-cli get pineapple
[stage-7] Sent bytes: "*2\r\n$3\r\nget\r\n$9\r\npineapple\r\n"
[stage-7] Received bytes: "$-1\r\n"
Expand All @@ -136,39 +136,43 @@ Debug = true
[stage-7] Program terminated successfully

[stage-8] Running tests for Stage #8: rdb-config
[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4183027736 --dbfilename banana.rdb
[stage-8] $ redis-cli CONFIG GET dir
[stage-8] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles3201160377 --dbfilename banana.rdb
[stage-8] $ redis-cli config get dir
[stage-8] Sent bytes: "*3\r\n$6\r\nconfig\r\n$3\r\nget\r\n$3\r\ndir\r\n"
[stage-8] Received bytes: "*2\r\n$3\r\ndir\r\n$75\r\n/private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles3201160377\r\n"
[stage-8] Received RESP value: ["dir", "/private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles3201160377"]
[stage-8] Received ["dir", "/private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles3201160377"]
[stage-8] Test passed.
[stage-8] Terminating program
[stage-8] Error terminating program: 'program failed to exit in 2 seconds after receiving sigterm'

[stage-9] Running tests for Stage #9: rdb-read-key
[stage-9] Created RDB file with single key: "orange"
[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2711962083 --dbfilename pineapple.rdb
[stage-9] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles612685144 --dbfilename pineapple.rdb
[stage-9] $ redis-cli KEYS *
[stage-9] Test passed.
[stage-9] Terminating program
[stage-9] Error terminating program: 'program failed to exit in 2 seconds after receiving sigterm'

[stage-10] Running tests for Stage #10: rdb-read-string-value
[stage-10] Created RDB file with single key-value pair: blueberry="orange"
[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles4240521256 --dbfilename pear.rdb
[stage-10] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles1355706126 --dbfilename pear.rdb
[stage-10] $ redis-cli GET blueberry
[stage-10] Test passed.
[stage-10] Terminating program
[stage-10] Error terminating program: 'program failed to exit in 2 seconds after receiving sigterm'

[stage-11] Running tests for Stage #11: rdb-read-multiple-keys
[stage-11] Created RDB file with 4 keys: ["grape" "pear" "strawberry" "banana"]
[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles1371607472 --dbfilename pineapple.rdb
[stage-11] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles2695265970 --dbfilename pineapple.rdb
[stage-11] $ redis-cli KEYS *
[stage-11] Test passed.
[stage-11] Terminating program
[stage-11] Error terminating program: 'program failed to exit in 2 seconds after receiving sigterm'

[stage-12] Running tests for Stage #12: rdb-read-multiple-string-values
[stage-12] Created RDB file with key-value pairs: "grape"="raspberry", "pineapple"="mango", "mango"="blueberry"
[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles3568218811 --dbfilename pineapple.rdb
[stage-12] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles1310138984 --dbfilename pineapple.rdb
[stage-12] $ redis-cli GET grape
[stage-12] $ redis-cli GET pineapple
[stage-12] $ redis-cli GET mango
Expand All @@ -177,7 +181,7 @@ Debug = true
[stage-12] Error terminating program: 'program failed to exit in 2 seconds after receiving sigterm'

[stage-13] Running tests for Stage #13: rdb-read-value-with-expiry
[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/5l/z5y3dkwn68sgb6htzc5w7vnm0000gn/T/rdbfiles2503190132 --dbfilename banana.rdb
[stage-13] $ ./spawn_redis_server.sh --dir /private/var/folders/f1/bs24_53x44j26flrfvyg416m0000gn/T/rdbfiles3173545518 --dbfilename banana.rdb
[stage-13] $ redis-cli GET strawberry
[stage-13] $ redis-cli GET pear
[stage-13] $ redis-cli GET raspberry
Expand Down
Loading

0 comments on commit bcfbce1

Please sign in to comment.