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
+109
View File
@@ -0,0 +1,109 @@
package ca
import (
"context"
"net"
"testing"
"github.com/uopi/goca/proto"
)
// ---- encodePut: every DBF branch + error paths -----------------------
func TestEncodePut(t *testing.T) {
cases := []struct {
name string
dbf int
v any
wantDBR uint16
}{
{"double", proto.DBFDouble, 1.5, proto.DBRDouble},
{"float", proto.DBFFloat, float32(2.0), proto.DBRDouble},
{"long", proto.DBFLong, int(3), proto.DBRLong},
{"short", proto.DBFShort, int16(4), proto.DBRShort},
{"char", proto.DBFChar, int(5), proto.DBRShort},
{"enum", proto.DBFEnum, int(1), proto.DBRShort},
{"string", proto.DBFString, "hi", proto.DBRString},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
dbr, payload, err := encodePut(c.dbf, c.v)
if err != nil {
t.Fatalf("encodePut: %v", err)
}
if dbr != c.wantDBR {
t.Errorf("dbr = %d, want %d", dbr, c.wantDBR)
}
if len(payload) == 0 {
t.Error("empty payload")
}
})
}
// Coercion failures propagate.
if _, _, err := encodePut(proto.DBFDouble, "nope"); err == nil {
t.Error("double from string: want error")
}
if _, _, err := encodePut(proto.DBFLong, "nope"); err == nil {
t.Error("long from string: want error")
}
if _, _, err := encodePut(proto.DBFShort, "nope"); err == nil {
t.Error("short from string: want error")
}
// Unsupported field type.
if _, _, err := encodePut(9999, 1); err == nil {
t.Error("unsupported DBF: want error")
}
}
// ---- NewClient: error path + default name/host -----------------------
func TestNewClientNoAddrs(t *testing.T) {
if _, err := NewClient(context.Background(), Config{AutoAddrList: false}); err == nil {
t.Error("NewClient with no addresses: want error")
}
}
func TestNewClientDefaultsNameHost(t *testing.T) {
// AddrList present but ClientName/HostName empty → default branches run.
cli, err := NewClient(context.Background(), Config{
AddrList: []string{"127.0.0.1:5064"},
AutoAddrList: false,
})
if err != nil {
t.Fatalf("NewClient: %v", err)
}
defer cli.Close()
if cli.cfg.ClientName == "" {
t.Error("ClientName should be defaulted")
}
}
// ---- EncodeSearchReply with an explicit server IP --------------------
func TestEncodeSearchReplyExplicitIP(t *testing.T) {
pkt := EncodeSearchReply(7, net.ParseIP("10.1.2.3"), 5064)
h, _, err := proto.DecodeHeader(newBytesReader(pkt))
if err != nil {
t.Fatalf("DecodeHeader: %v", err)
}
if h.Command != proto.CmdSearch {
t.Errorf("command = %d, want CmdSearch", h.Command)
}
}
// ---- parseReply robustness -------------------------------------------
func TestParseReplyTruncated(t *testing.T) {
se := &searchEngine{waiters: make(map[uint32]*searchWaiter)}
src := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 5064}
// Must not panic on a too-short datagram.
se.parseReply([]byte{0x00, 0x01}, src)
}
func TestParseReplyUnknownSearchID(t *testing.T) {
se := &searchEngine{waiters: make(map[uint32]*searchWaiter)}
src := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 5064}
// Valid reply but no waiter is registered for this search ID → dropped.
se.parseReply(EncodeSearchReply(12345, nil, 5064), src)
}