From 2e569fab5f52d83f413287d9910c12af717ae0d5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 20 Dec 2025 01:50:21 +0000
Subject: [PATCH 1/3] Initial plan
From bcaa1464fceba815960579c5675c0961b4fb7251 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 20 Dec 2025 01:59:24 +0000
Subject: [PATCH 2/3] Add inline frame format helper classes to C# tests
Co-authored-by: rijesha <7819200+rijesha@users.noreply.github.com>
---
tests/csharp/TestCodec.cs | 361 ++++++++++++++++++++++++++++++++++++-
tests/csharp/TestRunner.cs | 4 +-
2 files changed, 362 insertions(+), 3 deletions(-)
diff --git a/tests/csharp/TestCodec.cs b/tests/csharp/TestCodec.cs
index f4ee0133..e428ada8 100644
--- a/tests/csharp/TestCodec.cs
+++ b/tests/csharp/TestCodec.cs
@@ -5,6 +5,7 @@
using System.Runtime.InteropServices;
using StructFrame;
using StructFrame.SerializationTest;
+using StructFrame.FrameHeaders;
namespace StructFrameTests
{
@@ -186,6 +187,356 @@ public static bool ValidateMessageBytes(byte[] msgData)
return valid;
}
+ ///
+ /// Calculate Fletcher-16 checksum
+ ///
+ internal static (byte, byte) FletcherChecksum(byte[] buffer, int start, int length)
+ {
+ byte byte1 = 0;
+ byte byte2 = 0;
+
+ for (int i = start; i < start + length; i++)
+ {
+ byte1 = (byte)((byte1 + buffer[i]) % 256);
+ byte2 = (byte)((byte2 + byte1) % 256);
+ }
+
+ return (byte1, byte2);
+ }
+ }
+
+ /* Minimal frame format helper classes (replacing frame_compat) */
+
+ ///
+ /// Basic + Default frame format helper
+ ///
+ class BasicDefault : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 4;
+ const int footerSize = 2;
+ int totalSize = headerSize + msgData.Length + footerSize;
+
+ if (msgData.Length > 255)
+ return new byte[0];
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderConstants.BASIC_START_BYTE;
+ buffer[1] = HeaderBasic.GetSecondStartByte(1); // DEFAULT = 1
+ buffer[2] = (byte)msgData.Length;
+ buffer[3] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(buffer, 2, headerSize + msgData.Length - 2);
+ buffer[totalSize - 2] = ck1;
+ buffer[totalSize - 1] = ck2;
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 6 || data[0] != HeaderConstants.BASIC_START_BYTE || !HeaderBasic.IsSecondStartByte(data[1]))
+ return result;
+
+ int msgLen = data[2];
+ int msgId = data[3];
+ int totalSize = 4 + msgLen + 2;
+
+ if (length < totalSize)
+ return result;
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(data, 2, 4 + msgLen - 2);
+ if (ck1 == data[totalSize - 2] && ck2 == data[totalSize - 1])
+ {
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 4, result.MsgData, 0, msgLen);
+ }
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Tiny + Minimal frame format helper
+ ///
+ class TinyMinimal : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 2;
+ int totalSize = headerSize + msgData.Length;
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderTiny.GetStartByte(0); // MINIMAL = 0
+ buffer[1] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 2 || !HeaderTiny.IsStartByte(data[0]))
+ return result;
+
+ int msgId = data[1];
+ int msgLen = length - 2;
+
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 2, result.MsgData, 0, msgLen);
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Basic + Extended frame format helper
+ ///
+ class BasicExtended : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 6;
+ const int footerSize = 2;
+ int totalSize = headerSize + msgData.Length + footerSize;
+
+ if (msgData.Length > 65535)
+ return new byte[0];
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderConstants.BASIC_START_BYTE;
+ buffer[1] = HeaderBasic.GetSecondStartByte(4); // EXTENDED = 4
+ buffer[2] = (byte)(msgData.Length & 0xFF);
+ buffer[3] = (byte)((msgData.Length >> 8) & 0xFF);
+ buffer[4] = 0; // PKG_ID
+ buffer[5] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(buffer, 2, headerSize + msgData.Length - 2);
+ buffer[totalSize - 2] = ck1;
+ buffer[totalSize - 1] = ck2;
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 8 || data[0] != HeaderConstants.BASIC_START_BYTE || !HeaderBasic.IsSecondStartByte(data[1]))
+ return result;
+
+ int msgLen = data[2] | (data[3] << 8);
+ int msgId = data[5];
+ int totalSize = 6 + msgLen + 2;
+
+ if (length < totalSize)
+ return result;
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(data, 2, 6 + msgLen - 2);
+ if (ck1 == data[totalSize - 2] && ck2 == data[totalSize - 1])
+ {
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 6, result.MsgData, 0, msgLen);
+ }
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Basic + Extended + Multi System Stream frame format helper
+ ///
+ class BasicExtendedMultiSystemStream : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 9;
+ const int footerSize = 2;
+ int totalSize = headerSize + msgData.Length + footerSize;
+
+ if (msgData.Length > 65535)
+ return new byte[0];
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderConstants.BASIC_START_BYTE;
+ buffer[1] = HeaderBasic.GetSecondStartByte(8); // EXTENDED_MULTI_SYSTEM_STREAM = 8
+ buffer[2] = 0; // SEQ
+ buffer[3] = 0; // SYS_ID
+ buffer[4] = 0; // COMP_ID
+ buffer[5] = (byte)(msgData.Length & 0xFF);
+ buffer[6] = (byte)((msgData.Length >> 8) & 0xFF);
+ buffer[7] = 0; // PKG_ID
+ buffer[8] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(buffer, 2, headerSize + msgData.Length - 2);
+ buffer[totalSize - 2] = ck1;
+ buffer[totalSize - 1] = ck2;
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 11 || data[0] != HeaderConstants.BASIC_START_BYTE || !HeaderBasic.IsSecondStartByte(data[1]))
+ return result;
+
+ int msgLen = data[5] | (data[6] << 8);
+ int msgId = data[8];
+ int totalSize = 9 + msgLen + 2;
+
+ if (length < totalSize)
+ return result;
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(data, 2, 9 + msgLen - 2);
+ if (ck1 == data[totalSize - 2] && ck2 == data[totalSize - 1])
+ {
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 9, result.MsgData, 0, msgLen);
+ }
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Basic + Minimal frame format helper
+ ///
+ class BasicMinimal : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 3;
+ int totalSize = headerSize + msgData.Length;
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderConstants.BASIC_START_BYTE;
+ buffer[1] = HeaderBasic.GetSecondStartByte(0); // MINIMAL = 0
+ buffer[2] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 3 || data[0] != HeaderConstants.BASIC_START_BYTE || !HeaderBasic.IsSecondStartByte(data[1]))
+ return result;
+
+ int msgId = data[2];
+ int msgLen = length - 3;
+
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 3, result.MsgData, 0, msgLen);
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Tiny + Default frame format helper
+ ///
+ class TinyDefault : FrameFormatBase
+ {
+ public override byte[] Encode(int msgId, byte[] msgData)
+ {
+ const int headerSize = 3;
+ const int footerSize = 2;
+ int totalSize = headerSize + msgData.Length + footerSize;
+
+ if (msgData.Length > 255)
+ return new byte[0];
+
+ byte[] buffer = new byte[totalSize];
+ buffer[0] = HeaderTiny.GetStartByte(1); // DEFAULT = 1
+ buffer[1] = (byte)msgData.Length;
+ buffer[2] = (byte)msgId;
+ Array.Copy(msgData, 0, buffer, headerSize, msgData.Length);
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(buffer, 1, headerSize + msgData.Length - 1);
+ buffer[totalSize - 2] = ck1;
+ buffer[totalSize - 1] = ck2;
+
+ return buffer;
+ }
+
+ public override FrameParseResult ValidatePacket(byte[] data, int length)
+ {
+ var result = new FrameParseResult { Valid = false, MsgId = 0, MsgData = new byte[0], MsgSize = 0 };
+
+ if (length < 5 || !HeaderTiny.IsStartByte(data[0]))
+ return result;
+
+ int msgLen = data[1];
+ int msgId = data[2];
+ int totalSize = 3 + msgLen + 2;
+
+ if (length < totalSize)
+ return result;
+
+ var (ck1, ck2) = TestCodec.FletcherChecksum(data, 1, 3 + msgLen - 1);
+ if (ck1 == data[totalSize - 2] && ck2 == data[totalSize - 1])
+ {
+ result.Valid = true;
+ result.MsgId = msgId;
+ result.MsgSize = msgLen;
+ result.MsgData = new byte[msgLen];
+ Array.Copy(data, 3, result.MsgData, 0, msgLen);
+ }
+
+ return result;
+ }
+
+ public override FrameParseResult ParseByte(byte b) => throw new NotImplementedException();
+ public override void Reset() => throw new NotImplementedException();
+ }
+
+ ///
+ /// Test codec for encoding/decoding test messages with various frame formats
+ ///
+ public static class TestCodecHelpers
+ {
///
/// Get the frame parser for a given format name or profile
///
@@ -222,7 +573,7 @@ public static FrameFormatBase GetParser(string formatName)
public static byte[] EncodeTestMessage(string formatName)
{
var parser = GetParser(formatName);
- byte[] msgData = CreateTestMessageBytes();
+ byte[] msgData = TestCodec.CreateTestMessageBytes();
// Use MsgId from the generated struct definition
return parser.Encode(SerializationTestSerializationTestMessage.MsgId, msgData);
@@ -244,5 +595,13 @@ public static byte[] DecodeTestMessage(string formatName, byte[] data)
return result.MsgData;
}
+
+ ///
+ /// Create serialized test message bytes with expected values
+ ///
+ private static byte[] CreateTestMessageBytes()
+ {
+ return TestCodec.CreateTestMessageBytes();
+ }
}
}
diff --git a/tests/csharp/TestRunner.cs b/tests/csharp/TestRunner.cs
index df9aeb4b..f21dd69f 100644
--- a/tests/csharp/TestRunner.cs
+++ b/tests/csharp/TestRunner.cs
@@ -37,7 +37,7 @@ static int RunEncode(string formatName, string outputFile)
byte[] encodedData;
try
{
- encodedData = TestCodec.EncodeTestMessage(formatName);
+ encodedData = TestCodecHelpers.EncodeTestMessage(formatName);
}
catch (Exception e)
{
@@ -80,7 +80,7 @@ static int RunDecode(string formatName, string inputFile)
return 1;
}
- var msgData = TestCodec.DecodeTestMessage(formatName, data);
+ var msgData = TestCodecHelpers.DecodeTestMessage(formatName, data);
if (msgData == null)
{
Console.WriteLine("[DECODE] FAILED: Frame validation failed");
From 999cf2be1bded07b339f293ece385dfadcfff813 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 20 Dec 2025 02:00:58 +0000
Subject: [PATCH 3/3] Remove unnecessary wrapper method in TestCodecHelpers
Co-authored-by: rijesha <7819200+rijesha@users.noreply.github.com>
---
tests/csharp/TestCodec.cs | 8 --------
1 file changed, 8 deletions(-)
diff --git a/tests/csharp/TestCodec.cs b/tests/csharp/TestCodec.cs
index e428ada8..191e31f1 100644
--- a/tests/csharp/TestCodec.cs
+++ b/tests/csharp/TestCodec.cs
@@ -595,13 +595,5 @@ public static byte[] DecodeTestMessage(string formatName, byte[] data)
return result.MsgData;
}
-
- ///
- /// Create serialized test message bytes with expected values
- ///
- private static byte[] CreateTestMessageBytes()
- {
- return TestCodec.CreateTestMessageBytes();
- }
}
}