164 lines
5.2 KiB
Go
164 lines
5.2 KiB
Go
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")
|
|
}
|
|
}
|