453 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			453 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package pdu
 | |
| 
 | |
| import (
 | |
| 	"encoding/binary"
 | |
| 	"math"
 | |
| 	"sync"
 | |
| 	"testing"
 | |
| )
 | |
| 
 | |
| // region encode
 | |
| func TestEncodeReturnsByteSliceOfLength16(t *testing.T) {
 | |
| 	p := &PDU_HEADER{
 | |
| 		command_length:  1,
 | |
| 		command_id:      1,
 | |
| 		command_status:  1,
 | |
| 		sequence_number: 1,
 | |
| 	}
 | |
| 	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))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestEncodeHandlesZeroValues(t *testing.T) {
 | |
| 	p := &PDU_HEADER{
 | |
| 		command_length:  0,
 | |
| 		command_id:      0,
 | |
| 		command_status:  0,
 | |
| 		sequence_number: 0,
 | |
| 	}
 | |
| 	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] {
 | |
| 			t.Errorf("Expected byte slice with zero values, got %v", *result)
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestEncodeEncodesProperly(t *testing.T) {
 | |
| 	p := &PDU_HEADER{
 | |
| 		command_length:  1,
 | |
| 		command_id:      2,
 | |
| 		command_status:  3,
 | |
| 		sequence_number: 4,
 | |
| 	}
 | |
| 	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] {
 | |
| 			t.Errorf("Expected byte slice with values %v, got %v", expected, *result)
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestEncodeEncodesProperlyComplex(t *testing.T) {
 | |
| 	p := &PDU_HEADER{
 | |
| 		command_length:  13426724,
 | |
| 		command_id:      254352,
 | |
| 		command_status:  35634264,
 | |
| 		sequence_number: 476543523,
 | |
| 	}
 | |
| 	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] {
 | |
| 			t.Errorf("Expected byte slice with values %v, got %v", expected, *result)
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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
 | |
| 	data := []uint8{0, 0, 0, 10}
 | |
| 	defer func() {
 | |
| 		if r := recover(); r != nil {
 | |
| 			t.Errorf("Decode panicked with short byte slice")
 | |
| 		}
 | |
| 	}()
 | |
| 	err := p.Decode(data)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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}
 | |
| 	err := p.Decode(data)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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")
 | |
| 		}
 | |
| 	}()
 | |
| 	err := p.Decode(data)
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDecodeHandlesNilDataInput(t *testing.T) {
 | |
| 	var p PDU_HEADER
 | |
| 	err := p.Decode(nil)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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{}
 | |
| 	err := p.Decode(data)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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)
 | |
| 
 | |
| 	err := p.Decode(data)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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}
 | |
| 	err := p.Decode(data)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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 != math.MaxUint32 {
 | |
| 		t.Errorf("Expected command_id to be %d, got %d", math.MaxUint32, p.command_id)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDecodeHandlesByteSlicesWithMinimumUint32Values(t *testing.T) {
 | |
| 	var p PDU_HEADER
 | |
| 	data := []uint8{0, 0, 0, 0, 0, 0, 0, 0}
 | |
| 	err := p.Decode(data)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		t.Errorf("Expected no error, got %v", err)
 | |
| 	}
 | |
| 
 | |
| 	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)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // region size
 | |
| func TestSizeReturns16(t *testing.T) {
 | |
| 	var p PDU_HEADER
 | |
| 	if p.Size() != 16 {
 | |
| 		t.Errorf("Expected size to be 16, got %d", p.Size())
 | |
| 	}
 | |
| }
 | 
