From 6bb502dbf2df98d3a7c421ee8cb0f3ac300b98c8 Mon Sep 17 00:00:00 2001 From: Jan Barfuss Date: Sun, 12 Jan 2025 01:01:08 +0100 Subject: [PATCH] Basic structurre without crc and 1 test fails, v0.0.1 --- go.mod | 3 ++ spf.go | 64 +++++++++++++++++++++++++++++++++++ spf_test.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 go.mod create mode 100644 spf.go create mode 100644 spf_test.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..42c9046 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.barfuss.email/jan/SimpleFinancePackage + +go 1.22.1 diff --git a/spf.go b/spf.go new file mode 100644 index 0000000..107c02b --- /dev/null +++ b/spf.go @@ -0,0 +1,64 @@ +package sfp + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" +) + +type SimpleFinancePackage struct { + Key [8]byte // 8 bytes for the key + Operation byte // 1 byte for operation + Asset byte // 1 byte for asset + Price float64 // 8 bytes for price (float64 for precision) + Volume float64 // 8 bytes for volume +} + +func ParseSimpleFinanacePackage(data []byte) (*SimpleFinancePackage, error) { + if len(data) != 26 { + return nil, errors.New("invalid packet size, expected 26 bytes") + } + + reader := bytes.NewReader(data) + var packet SimpleFinancePackage + + // Read binary data into the struct + if err := binary.Read(reader, binary.BigEndian, &packet); err != nil { + return nil, fmt.Errorf("failed to parse packet: %w", err) + } + + // Validate fields (example rules, customize as needed) + if packet.Price < 0 || packet.Volume < 0 { + return nil, errors.New("price and volume must be non-negative") + } + if packet.Operation > 127 { // Example: Valid operation values are 0-127 + return nil, errors.New("invalid operation value") + } + + return &packet, nil +} + +func EncodeSimpleFinanacePackage(packet SimpleFinancePackage) ([]byte, error) { + buf := new(bytes.Buffer) + + // Write binary data to the buffer in Big-Endian order + if err := binary.Write(buf, binary.BigEndian, packet.Key); err != nil { + return nil, fmt.Errorf("failed to encode key: %w", err) + } + if err := binary.Write(buf, binary.BigEndian, packet.Operation); err != nil { + return nil, fmt.Errorf("failed to encode operation: %w", err) + } + if err := binary.Write(buf, binary.BigEndian, packet.Asset); err != nil { + return nil, fmt.Errorf("failed to encode asset: %w", err) + } + if err := binary.Write(buf, binary.BigEndian, packet.Price); err != nil { + return nil, fmt.Errorf("failed to encode price: %w", err) + } + if err := binary.Write(buf, binary.BigEndian, packet.Volume); err != nil { + return nil, fmt.Errorf("failed to encode volume: %w", err) + } + + // Return the resulting byte slice + return buf.Bytes(), nil +} diff --git a/spf_test.go b/spf_test.go new file mode 100644 index 0000000..c09b9c8 --- /dev/null +++ b/spf_test.go @@ -0,0 +1,96 @@ +package sfp + +import ( + "bytes" + "testing" +) + +//ChatGPT Generated Code to test the Encode and Decode functions + +func TestEncodeDecodeCustomPacket(t *testing.T) { + // Define a sample packet + originalPacket := SimpleFinancePackage{ + Key: [8]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'}, + Operation: 1, + Asset: 2, + Price: 1234.56, + Volume: 7890.12, + } + + // Encode the packet + encoded, err := EncodeSimpleFinanacePackage(originalPacket) + if err != nil { + t.Fatalf("Encoding failed: %v", err) + } + + // Check the encoded length + if len(encoded) != 26 { + t.Fatalf("Encoded data has incorrect length: got %d, want 26", len(encoded)) + } + + // Decode the packet + decodedPacket, err := ParseSimpleFinanacePackage(encoded) + if err != nil { + t.Fatalf("Decoding failed: %v", err) + } + + // Compare the original and decoded packets + if !bytes.Equal(originalPacket.Key[:], decodedPacket.Key[:]) { + t.Errorf("Key mismatch: got %v, want %v", decodedPacket.Key, originalPacket.Key) + } + if originalPacket.Operation != decodedPacket.Operation { + t.Errorf("Operation mismatch: got %d, want %d", decodedPacket.Operation, originalPacket.Operation) + } + if originalPacket.Asset != decodedPacket.Asset { + t.Errorf("Asset mismatch: got %d, want %d", decodedPacket.Asset, originalPacket.Asset) + } + if originalPacket.Price != decodedPacket.Price { + t.Errorf("Price mismatch: got %f, want %f", decodedPacket.Price, originalPacket.Price) + } + if originalPacket.Volume != decodedPacket.Volume { + t.Errorf("Volume mismatch: got %f, want %f", decodedPacket.Volume, originalPacket.Volume) + } +} + +func TestInvalidPacketSizes(t *testing.T) { + // Test with too small a packet + smallPacket := make([]byte, 10) + _, err := ParseSimpleFinanacePackage(smallPacket) + if err == nil { + t.Fatal("Expected error for small packet, got nil") + } + + // Test with too large a packet + largePacket := make([]byte, 30) + _, err = ParseSimpleFinanacePackage(largePacket) + if err == nil { + t.Fatal("Expected error for large packet, got nil") + } +} + +func TestInvalidPacketValues(t *testing.T) { + // Create a valid packet and modify its fields + validPacket := SimpleFinancePackage{ + Key: [8]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'}, + Operation: 1, + Asset: 2, + Price: 1234.56, + Volume: 7890.12, + } + encoded, _ := EncodeSimpleFinanacePackage(validPacket) + + // Modify encoded data to introduce errors + encoded[9] = 255 // Invalid operation value + + _, err := ParseSimpleFinanacePackage(encoded) + if err == nil { + t.Fatal("Expected error for invalid operation value, got nil") + } + + // Modify price to a negative value + copy(encoded[10:], []byte{255, 255, 255, 255, 255, 255, 255, 255}) // Represents -1 in float64 (Big-Endian) + _, err = ParseSimpleFinanacePackage(encoded) + if err == nil { + t.Fatal("Expected error for negative price, got nil") + } +}