Skip to content

Commit 9b8419a

Browse files
committed
refactor: enhance XReadResponseAssertion with ToSerializable method for improved serialization of response values
1 parent ff642ea commit 9b8419a

File tree

2 files changed

+51
-55
lines changed

2 files changed

+51
-55
lines changed

internal/resp/value/value.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,19 @@ func (v *Value) FormattedString() string {
125125

126126
return ""
127127
}
128+
129+
func (v Value) ToSerializable() interface{} {
130+
switch v.Type {
131+
case BULK_STRING:
132+
return v.String()
133+
case ARRAY:
134+
arr := v.Array()
135+
result := make([]interface{}, len(arr))
136+
for i, elem := range arr {
137+
result[i] = elem.ToSerializable()
138+
}
139+
return result
140+
default:
141+
return v.String()
142+
}
143+
}

internal/resp_assertions/xread_response_assertion.go

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package resp_assertions
33
import (
44
"encoding/json"
55
"fmt"
6-
"reflect"
76

87
resp_value "github.com/codecrafters-io/redis-tester/internal/resp/value"
98
)
@@ -31,72 +30,53 @@ func (a XReadResponseAssertion) Run(value resp_value.Value) error {
3130
return fmt.Errorf("Expected array, got %s", value.Type)
3231
}
3332

34-
expected := a.normalizeExpected()
35-
actual := normalizeActual(value)
33+
expected := a.buildExpected().ToSerializable()
34+
actual := value.ToSerializable()
3635

37-
if !reflect.DeepEqual(expected, actual) {
38-
expectedJSON, err := json.MarshalIndent(expected, "", " ")
39-
if err != nil {
40-
return fmt.Errorf("failed to marshal expected value: %w", err)
41-
}
42-
actualJSON, err := json.MarshalIndent(actual, "", " ")
43-
if err != nil {
44-
return fmt.Errorf("failed to marshal actual value: %w", err)
45-
}
36+
expectedJSON, err := json.MarshalIndent(expected, "", " ")
37+
if err != nil {
38+
return fmt.Errorf("failed to marshal expected value: %w", err)
39+
}
40+
actualJSON, err := json.MarshalIndent(actual, "", " ")
41+
if err != nil {
42+
return fmt.Errorf("failed to marshal actual value: %w", err)
43+
}
44+
45+
if string(expectedJSON) != string(actualJSON) {
4646
return fmt.Errorf("XREAD response mismatch:\nExpected:\n%s\nGot:\n%s", expectedJSON, actualJSON)
4747
}
4848

4949
return nil
5050
}
5151

52-
func (a XReadResponseAssertion) normalizeExpected() []interface{} {
53-
result := make([]interface{}, len(a.ExpectedStreamResponses))
54-
52+
func (a XReadResponseAssertion) buildExpected() resp_value.Value {
53+
streams := make([]resp_value.Value, len(a.ExpectedStreamResponses))
5554
for i, stream := range a.ExpectedStreamResponses {
56-
entries := make([][]interface{}, 0, len(stream.Entries))
57-
for _, entry := range stream.Entries {
58-
flatPairs := make([]string, 0, len(entry.FieldValuePairs)*2)
59-
for _, pair := range entry.FieldValuePairs {
60-
flatPairs = append(flatPairs, pair[0], pair[1])
61-
}
62-
entries = append(entries, []interface{}{entry.Id, flatPairs})
63-
}
64-
result[i] = []interface{}{stream.Key, entries}
55+
streams[i] = stream.toRESPValue()
6556
}
57+
return resp_value.NewArrayValue(streams)
58+
}
6659

67-
return result
60+
func (s StreamResponse) toRESPValue() resp_value.Value {
61+
entries := make([]resp_value.Value, len(s.Entries))
62+
for i, entry := range s.Entries {
63+
entries[i] = entry.toRESPValue()
64+
}
65+
return resp_value.NewArrayValue([]resp_value.Value{
66+
resp_value.NewBulkStringValue(s.Key),
67+
resp_value.NewArrayValue(entries),
68+
})
6869
}
6970

70-
func normalizeActual(v resp_value.Value) interface{} {
71-
switch v.Type {
72-
case resp_value.BULK_STRING:
73-
return v.String()
74-
case resp_value.ARRAY:
75-
arr := v.Array()
76-
result := make([]interface{}, len(arr))
77-
for i, elem := range arr {
78-
// Special handling for stream entries (second element of the outer array)
79-
if i == 1 && len(arr) == 2 {
80-
entries := elem.Array()
81-
typedEntries := make([][]interface{}, len(entries))
82-
for j, entry := range entries {
83-
entryArr := entry.Array()
84-
if len(entryArr) == 2 {
85-
fvPairs := entryArr[1].Array()
86-
strPairs := make([]string, len(fvPairs))
87-
for k, pair := range fvPairs {
88-
strPairs[k] = pair.String()
89-
}
90-
typedEntries[j] = []interface{}{normalizeActual(entryArr[0]), strPairs}
91-
}
92-
}
93-
result[i] = typedEntries
94-
continue
95-
}
96-
result[i] = normalizeActual(elem)
71+
func (e StreamEntry) toRESPValue() resp_value.Value {
72+
var fieldValues []resp_value.Value
73+
for _, pair := range e.FieldValuePairs {
74+
for _, v := range pair {
75+
fieldValues = append(fieldValues, resp_value.NewBulkStringValue(v))
9776
}
98-
return result
99-
default:
100-
return v.String()
10177
}
78+
return resp_value.NewArrayValue([]resp_value.Value{
79+
resp_value.NewBulkStringValue(e.Id),
80+
resp_value.NewArrayValue(fieldValues),
81+
})
10282
}

0 commit comments

Comments
 (0)