Add more tests for encoding
This commit is contained in:
18
pdu/pdu.go
18
pdu/pdu.go
@@ -1,6 +1,9 @@
|
||||
package pdu
|
||||
|
||||
import "encoding/binary"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
PDU interface {
|
||||
@@ -22,20 +25,27 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PDU_HEADER) Encode() []uint8 {
|
||||
func (p *PDU_HEADER) Encode() ([]uint8, error) {
|
||||
buf := make([]uint8, 16)
|
||||
binary.BigEndian.PutUint32(buf[0:4], p.command_length)
|
||||
binary.BigEndian.PutUint32(buf[4:8], p.command_id)
|
||||
binary.BigEndian.PutUint32(buf[8:12], p.command_status)
|
||||
binary.BigEndian.PutUint32(buf[12:16], p.sequence_number)
|
||||
return buf
|
||||
return buf, nil
|
||||
}
|
||||
func (p *PDU_HEADER) EncodeInto(buf *[]uint8) {
|
||||
func (p *PDU_HEADER) EncodeInto(buf *[]uint8) error {
|
||||
if buf == nil {
|
||||
return fmt.Errorf("cannot encode PDU_HEADER, buffer is nil")
|
||||
}
|
||||
if len(*buf) < 16 {
|
||||
return fmt.Errorf("cannot encode PDU_HEADER, buffer too small (%d, required 16)", len(*buf))
|
||||
}
|
||||
bufVal := *buf
|
||||
binary.BigEndian.PutUint32(bufVal[0:4], p.command_length)
|
||||
binary.BigEndian.PutUint32(bufVal[4:8], p.command_id)
|
||||
binary.BigEndian.PutUint32(bufVal[8:12], p.command_status)
|
||||
binary.BigEndian.PutUint32(bufVal[12:16], p.sequence_number)
|
||||
return nil
|
||||
}
|
||||
func (p *PDU_HEADER) Decode(data []uint8) {
|
||||
if len(data) >= 4 {
|
||||
|
239
pdu/pdu_test.go
239
pdu/pdu_test.go
@@ -1,6 +1,9 @@
|
||||
package pdu
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -12,7 +15,11 @@ func TestEncodeReturnsByteSliceOfLength16(t *testing.T) {
|
||||
command_status: 1,
|
||||
sequence_number: 1,
|
||||
}
|
||||
result := p.Encode()
|
||||
result, err := p.Encode()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
if len(result) != 16 {
|
||||
t.Errorf("Expected byte slice of length 16, got %d", len(result))
|
||||
}
|
||||
@@ -25,7 +32,11 @@ func TestEncodeHandlesZeroValues(t *testing.T) {
|
||||
command_status: 0,
|
||||
sequence_number: 0,
|
||||
}
|
||||
result := p.Encode()
|
||||
result, err := p.Encode()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
expected := make([]uint8, 16)
|
||||
for i, v := range result {
|
||||
if v != expected[i] {
|
||||
@@ -42,7 +53,12 @@ func TestEncodeEncodesProperly(t *testing.T) {
|
||||
command_status: 3,
|
||||
sequence_number: 4,
|
||||
}
|
||||
result := p.Encode()
|
||||
result, err := p.Encode()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
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] {
|
||||
@@ -59,7 +75,12 @@ func TestEncodeEncodesProperlyComplex(t *testing.T) {
|
||||
command_status: 35634264,
|
||||
sequence_number: 476543523,
|
||||
}
|
||||
result := p.Encode()
|
||||
result, err := p.Encode()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
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] {
|
||||
@@ -69,6 +90,208 @@ func TestEncodeEncodesProperlyComplex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoCorrectlyEncodesFields(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
buf := make([]uint8, 16)
|
||||
err := p.EncodeInto(&buf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoHandlesNilBuffer(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
var buf *[]uint8 = nil
|
||||
|
||||
err := p.EncodeInto(buf)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error when buffer is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoHandlesSmallerBuffer(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
buf := make([]uint8, 12) // smaller buffer size
|
||||
|
||||
err := p.EncodeInto(&buf)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error when buffer is too small")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoHandlesLargerBuffer(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
buf := make([]uint8, 20)
|
||||
err := p.EncodeInto(&buf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoUsesBigEndianEncoding(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
buf := make([]uint8, 16)
|
||||
err := p.EncodeInto(&buf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoConcurrencySafety(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 16,
|
||||
command_id: 1,
|
||||
command_status: 0,
|
||||
sequence_number: 12345,
|
||||
}
|
||||
buf := make([]uint8, 16)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 1000; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
p.EncodeInto(&buf)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoWithMaximumValues(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: math.MaxUint32,
|
||||
command_id: math.MaxUint32,
|
||||
command_status: math.MaxUint32,
|
||||
sequence_number: math.MaxUint32,
|
||||
}
|
||||
buf := make([]uint8, 16)
|
||||
err := p.EncodeInto(&buf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeIntoWithBoundaryValues(t *testing.T) {
|
||||
p := &PDU_HEADER{
|
||||
command_length: 0,
|
||||
command_id: 0,
|
||||
command_status: 0,
|
||||
sequence_number: 0,
|
||||
}
|
||||
buf := make([]uint8, 16)
|
||||
err := p.EncodeInto(&buf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if binary.BigEndian.Uint32(buf[0:4]) != p.command_length {
|
||||
t.Errorf("Expected command_length %d, got %d", p.command_length, binary.BigEndian.Uint32(buf[0:4]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[4:8]) != p.command_id {
|
||||
t.Errorf("Expected command_id %d, got %d", p.command_id, binary.BigEndian.Uint32(buf[4:8]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[8:12]) != p.command_status {
|
||||
t.Errorf("Expected command_status %d, got %d", p.command_status, binary.BigEndian.Uint32(buf[8:12]))
|
||||
}
|
||||
if binary.BigEndian.Uint32(buf[12:16]) != p.sequence_number {
|
||||
t.Errorf("Expected sequence_number %d, got %d", p.sequence_number, binary.BigEndian.Uint32(buf[12:16]))
|
||||
}
|
||||
}
|
||||
|
||||
// region decode
|
||||
func TestDecodeHandlesShortByteSlice(t *testing.T) {
|
||||
var p PDU_HEADER
|
||||
@@ -164,11 +387,11 @@ 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_length != math.MaxUint32 {
|
||||
t.Errorf("Expected command_length to be %d, got %d", math.MaxUint32, p.command_length)
|
||||
}
|
||||
if p.command_id != 4294967295 {
|
||||
t.Errorf("Expected command_id to be 4294967295, got %d", p.command_id)
|
||||
if p.command_id != math.MaxUint32 {
|
||||
t.Errorf("Expected command_id to be %d, got %d", math.MaxUint32, p.command_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user