Testing
This commit is contained in:
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user