diff --git a/pdu/pdu.go b/pdu/pdu.go index f40ec0c..9a4602d 100644 --- a/pdu/pdu.go +++ b/pdu/pdu.go @@ -38,8 +38,17 @@ func (p *PDU_HEADER) EncodeInto(buf *[]uint8) { binary.BigEndian.PutUint32(bufVal[12:16], p.sequence_number) } func (p *PDU_HEADER) Decode(data []uint8) { - p.command_length = binary.BigEndian.Uint32(data[0:4]) - p.command_id = binary.BigEndian.Uint32(data[4:8]) - p.command_status = binary.BigEndian.Uint32(data[8:12]) - p.sequence_number = binary.BigEndian.Uint32(data[12:16]) + if len(data) >= 4 { + p.command_length = binary.BigEndian.Uint32(data[0:4]) + } + if len(data) >= 8 { + p.command_id = binary.BigEndian.Uint32(data[4:8]) + } + if len(data) >= 12 { + p.command_status = binary.BigEndian.Uint32(data[8:12]) + + } + if len(data) >= 16 { + p.sequence_number = binary.BigEndian.Uint32(data[12:16]) + } } diff --git a/pdu/pdu_test.go b/pdu/pdu_test.go index fd6d33e..6f83a75 100644 --- a/pdu/pdu_test.go +++ b/pdu/pdu_test.go @@ -1,7 +1,10 @@ package pdu -import "testing" +import ( + "testing" +) +// region encode func TestEncodeReturnsByteSliceOfLength16(t *testing.T) { p := &PDU_HEADER{ command_length: 1, @@ -23,7 +26,7 @@ func TestEncodeHandlesZeroValues(t *testing.T) { sequence_number: 0, } result := p.Encode() - expected := make([]byte, 16) + expected := make([]uint8, 16) for i, v := range result { if v != expected[i] { t.Errorf("Expected byte slice with zero values, got %v", result) @@ -40,7 +43,7 @@ func TestEncodeEncodesProperly(t *testing.T) { sequence_number: 4, } result := p.Encode() - expected := []byte{0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4} + expected := []uint8{0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4} for i, v := range result { if v != expected[i] { t.Errorf("Expected byte slice with values %v, got %v", expected, result) @@ -57,11 +60,126 @@ func TestEncodeEncodesProperlyComplex(t *testing.T) { sequence_number: 476543523, } result := p.Encode() - expected := []byte{0, 204, 224, 36, 0, 3, 225, 144, 2, 31, 188, 88, 28, 103, 122, 35} + expected := []uint8{0, 204, 224, 36, 0, 3, 225, 144, 2, 31, 188, 88, 28, 103, 122, 35} for i, v := range result { if v != expected[i] { t.Errorf("Expected byte slice with values %v, got %v", expected, result) break } } -} \ No newline at end of file +} + +// region decode +func TestDecodeHandlesShortByteSlice(t *testing.T) { + var p PDU_HEADER + data := []uint8{0, 0, 0, 10} + defer func() { + if r := recover(); r != nil { + t.Errorf("Decode panicked with short byte slice") + } + }() + p.Decode(data) +} + +func TestDecodeParsesValidByteSlice(t *testing.T) { + var p PDU_HEADER + data := []uint8{0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3} + p.Decode(data) + if p.command_length != 16 { + t.Errorf("Expected command_length to be 16, got %d", p.command_length) + } + if p.command_id != 1 { + t.Errorf("Expected command_id to be 1, got %d", p.command_id) + } + if p.command_status != 2 { + t.Errorf("Expected command_status to be 2, got %d", p.command_status) + } + if p.sequence_number != 3 { + t.Errorf("Expected sequence_number to be 3, got %d", p.sequence_number) + } +} + +func TestDecodeHandlesLongerByteSliceWithoutCrashing(t *testing.T) { + var p PDU_HEADER + data := make([]uint8, 20) + defer func() { + if r := recover(); r != nil { + t.Errorf("Decode panicked with long byte slice") + } + }() + p.Decode(data) +} + +func TestDecodeHandlesNilDataInput(t *testing.T) { + var p PDU_HEADER + p.Decode(nil) + if p.command_length != 0 { + t.Errorf("Expected command_length to be 0, got %d", p.command_length) + } + if p.command_id != 0 { + t.Errorf("Expected command_id to be 0, got %d", p.command_id) + } + if p.command_status != 0 { + t.Errorf("Expected command_status to be 0, got %d", p.command_status) + } + if p.sequence_number != 0 { + t.Errorf("Expected sequence_number to be 0, got %d", p.sequence_number) + } +} + +func TestDecodeHandlesEmptyByteSliceGracefully(t *testing.T) { + var p PDU_HEADER + data := []uint8{} + p.Decode(data) + if p.command_length != 0 { + t.Errorf("Expected command_length to be 0, got %d", p.command_length) + } + if p.command_id != 0 { + t.Errorf("Expected command_id to be 0, got %d", p.command_id) + } + if p.command_status != 0 { + t.Errorf("Expected command_status to be 0, got %d", p.command_status) + } + if p.sequence_number != 0 { + t.Errorf("Expected sequence_number to be 0, got %d", p.sequence_number) + } +} + +func TestDecodeDoesNotModifyInputByteSlice(t *testing.T) { + var p PDU_HEADER + data := []uint8{0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3} + originalData := make([]uint8, len(data)) + copy(originalData, data) + + p.Decode(data) + + for i := range data { + if data[i] != originalData[i] { + t.Errorf("Expected data at index %d to be %d, got %d", i, originalData[i], data[i]) + } + } +} + +func TestDecodeHandlesByteSlicesWithMaxUint32Values(t *testing.T) { + var p PDU_HEADER + data := []uint8{255, 255, 255, 255, 255, 255, 255, 255} + p.Decode(data) + if p.command_length != 4294967295 { + t.Errorf("Expected command_length to be 4294967295, got %d", p.command_length) + } + if p.command_id != 4294967295 { + t.Errorf("Expected command_id to be 4294967295, got %d", p.command_id) + } +} + +func TestDecodeHandlesByteSlicesWithMinimumUint32Values(t *testing.T) { + var p PDU_HEADER + data := []uint8{0, 0, 0, 0, 0, 0, 0, 0} + p.Decode(data) + if p.command_length != 0 { + t.Errorf("Expected command_length to be 0, got %d", p.command_length) + } + if p.command_id != 0 { + t.Errorf("Expected command_id to be 0, got %d", p.command_id) + } +}