Skip to content

Commit def065d

Browse files
atharvaladeStanding-Man
authored andcommitted
fix(go): return error instead of panic on S2 decode failure (#3166)
1 parent 0958a09 commit def065d

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

foreign/go/binary_serialization/binary_response_deserializer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func DeserializeFetchMessagesResponse(payload []byte, compression iggcon.IggyMes
157157
}
158158
payloadSlice, err = s2.Decode(nil, payloadSlice)
159159
if err != nil {
160-
panic("iggy: failed to decode s2 payload: " + err.Error())
160+
return nil, fmt.Errorf("failed to decode s2 payload: %w", err)
161161
}
162162
}
163163

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package binaryserialization
19+
20+
import (
21+
"encoding/binary"
22+
"strings"
23+
"testing"
24+
25+
iggcon "github.com/apache/iggy/foreign/go/contracts"
26+
)
27+
28+
func buildFetchPayload(payloadBody []byte) []byte {
29+
header := iggcon.NewMessageHeader(iggcon.MessageID{}, uint32(len(payloadBody)), 0)
30+
headerBytes := header.ToBytes()
31+
32+
// 4 (partitionId) + 8 (currentOffset) + 4 (messagesCount) + header + body
33+
buf := make([]byte, 16+len(headerBytes)+len(payloadBody))
34+
binary.LittleEndian.PutUint32(buf[0:4], 1)
35+
binary.LittleEndian.PutUint64(buf[4:12], 0)
36+
binary.LittleEndian.PutUint32(buf[12:16], 1)
37+
copy(buf[16:], headerBytes)
38+
copy(buf[16+len(headerBytes):], payloadBody)
39+
return buf
40+
}
41+
42+
func TestDeserializeFetchMessages_MalformedS2ReturnsError(t *testing.T) {
43+
garbage := []byte{0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03,
44+
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
45+
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
46+
0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x00}
47+
payload := buildFetchPayload(garbage)
48+
49+
result, err := DeserializeFetchMessagesResponse(payload, iggcon.MESSAGE_COMPRESSION_S2)
50+
51+
if result != nil {
52+
t.Errorf("expected nil result, got %+v", result)
53+
}
54+
if err == nil {
55+
t.Fatal("expected error for malformed S2 payload, got nil")
56+
}
57+
if !strings.Contains(err.Error(), "failed to decode s2 payload") {
58+
t.Errorf("error message %q does not mention S2 decode failure", err.Error())
59+
}
60+
}
61+
62+
func TestDeserializeFetchMessages_NoCompressionSkipsS2(t *testing.T) {
63+
body := []byte("hello world")
64+
payload := buildFetchPayload(body)
65+
66+
result, err := DeserializeFetchMessagesResponse(payload, iggcon.MESSAGE_COMPRESSION_NONE)
67+
68+
if err != nil {
69+
t.Fatalf("unexpected error: %v", err)
70+
}
71+
if len(result.Messages) != 1 {
72+
t.Fatalf("expected 1 message, got %d", len(result.Messages))
73+
}
74+
if string(result.Messages[0].Payload) != "hello world" {
75+
t.Errorf("payload = %q, want %q", result.Messages[0].Payload, "hello world")
76+
}
77+
}
78+
79+
func TestDeserializeFetchMessages_EmptyPayload(t *testing.T) {
80+
result, err := DeserializeFetchMessagesResponse([]byte{}, iggcon.MESSAGE_COMPRESSION_S2)
81+
82+
if err != nil {
83+
t.Fatalf("unexpected error: %v", err)
84+
}
85+
if len(result.Messages) != 0 {
86+
t.Fatalf("expected 0 messages, got %d", len(result.Messages))
87+
}
88+
}

0 commit comments

Comments
 (0)