This commit is contained in:
Martino Ferrari
2026-06-24 01:39:15 +02:00
parent 11120bedca
commit c0f7e662be
76 changed files with 4368 additions and 210 deletions
+163
View File
@@ -0,0 +1,163 @@
package proto_test
import (
"bytes"
"encoding/binary"
"math"
"testing"
"github.com/uopi/goca/proto"
)
// -------------------------------------------------------------------------- //
// DBR_TIME_* variants not covered by proto_test.go //
// -------------------------------------------------------------------------- //
func TestDecodeTimeFloat(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := make([]byte, 4)
binary.BigEndian.PutUint32(val, math.Float32bits(2.5))
tv, ok := proto.DecodeTimeValue(proto.DBRTimeFloat, 1, append(hdr, val...))
if !ok || math.Abs(float64(tv.Float)-2.5) > 1e-6 {
t.Errorf("float: ok=%v Float=%g", ok, tv.Float)
}
}
func TestDecodeTimeShort(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := []byte{0x00, 0x00, 0xFF, 0xD6} // 2-byte pad + int16(-42)
tv, ok := proto.DecodeTimeValue(proto.DBRTimeShort, 1, append(hdr, val...))
if !ok || tv.Short != -42 {
t.Errorf("short: ok=%v Short=%d", ok, tv.Short)
}
}
func TestDecodeTimeChar(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
val := []byte{0x00, 0x00, 0x00, 0x41} // pad0 + pad1 + value 'A'
tv, ok := proto.DecodeTimeValue(proto.DBRTimeChar, 1, append(hdr, val...))
if !ok || tv.Char != 0x41 {
t.Errorf("char: ok=%v Char=%d", ok, tv.Char)
}
}
func TestDecodeTimeUnknownType(t *testing.T) {
hdr := buildTimeHeader(0, 0, 0, 0)
if _, ok := proto.DecodeTimeValue(9999, 1, append(hdr, make([]byte, 16)...)); ok {
t.Error("unknown DBR type should return false")
}
}
// -------------------------------------------------------------------------- //
// DBR_CTRL_LONG / DBR_CTRL_STRING //
// -------------------------------------------------------------------------- //
func TestDecodeCtrlLong(t *testing.T) {
p := make([]byte, 48)
binary.BigEndian.PutUint16(p[2:], 2) // severity = Major
copy(p[4:], "counts")
i32 := func(off int, v int32) { binary.BigEndian.PutUint32(p[off:], uint32(v)) }
i32(12, 1000) // upper_disp
i32(16, -10) // lower_disp
i32(44, 777) // value
cl, ok := proto.DecodeCtrlLong(p)
if !ok {
t.Fatal("DecodeCtrlLong returned false")
}
if cl.Units != "counts" || cl.Value != 777 || cl.UpperDispLimit != 1000 || cl.LowerDispLimit != -10 {
t.Errorf("got %+v", cl)
}
if cl.Severity != proto.SeverityMajor {
t.Errorf("severity = %v, want Major", cl.Severity)
}
if _, ok := proto.DecodeCtrlLong(make([]byte, 10)); ok {
t.Error("short CtrlLong payload should return false")
}
}
func TestDecodeCtrlString(t *testing.T) {
p := make([]byte, 44)
binary.BigEndian.PutUint16(p[2:], 1) // severity = Minor
copy(p[4:], "READY")
cs, ok := proto.DecodeCtrlString(p)
if !ok {
t.Fatal("DecodeCtrlString returned false")
}
if cs.Value != "READY" || cs.Severity != proto.SeverityMinor {
t.Errorf("got %+v", cs)
}
if _, ok := proto.DecodeCtrlString(make([]byte, 10)); ok {
t.Error("short CtrlString payload should return false")
}
}
// -------------------------------------------------------------------------- //
// EncodeShort //
// -------------------------------------------------------------------------- //
func TestEncodeShort(t *testing.T) {
b := proto.EncodeShort(-7)
if len(b) != 8 {
t.Fatalf("len = %d, want 8", len(b))
}
if got := int16(binary.BigEndian.Uint16(b)); got != -7 {
t.Errorf("decoded = %d, want -7", got)
}
}
// -------------------------------------------------------------------------- //
// NativeCtrlType //
// -------------------------------------------------------------------------- //
func TestNativeCtrlType(t *testing.T) {
cases := []struct {
dbf int
want uint16
}{
{proto.DBFDouble, proto.DBRCtrlDouble},
{proto.DBFFloat, proto.DBRCtrlDouble},
{proto.DBFLong, proto.DBRCtrlLong},
{proto.DBFShort, proto.DBRCtrlLong},
{proto.DBFChar, proto.DBRCtrlLong},
{proto.DBFEnum, proto.DBRCtrlEnum},
{proto.DBFString, proto.DBRCtrlString},
{9999, proto.DBRCtrlDouble}, // default
}
for _, c := range cases {
if got := proto.NativeCtrlType(c.dbf); got != c.want {
t.Errorf("NativeCtrlType(%d) = %d, want %d", c.dbf, got, c.want)
}
}
}
// -------------------------------------------------------------------------- //
// DecodeHeader: extended encoding + error path //
// -------------------------------------------------------------------------- //
func TestDecodeHeaderExtended(t *testing.T) {
raw := make([]byte, 24)
binary.BigEndian.PutUint16(raw[0:], proto.CmdReadNotify)
binary.BigEndian.PutUint16(raw[2:], 0xFFFF) // extended marker
binary.BigEndian.PutUint16(raw[6:], 0x0000)
binary.BigEndian.PutUint32(raw[16:], 70000) // real payload size
binary.BigEndian.PutUint32(raw[20:], 5) // real count
h, n, err := proto.DecodeHeader(bytes.NewReader(raw))
if err != nil {
t.Fatal(err)
}
if n != 24 {
t.Errorf("bytes read = %d, want 24", n)
}
if h.PayloadSize != 70000 || h.DataCount != 5 {
t.Errorf("extended header = %+v", h)
}
}
func TestDecodeHeaderTruncated(t *testing.T) {
if _, _, err := proto.DecodeHeader(bytes.NewReader([]byte{0x00, 0x01})); err == nil {
t.Error("truncated header: want error")
}
}