refactor(channelserver): replace init() handler registration with explicit construction

The handler table was a package-level global populated by init(), making
registration implicit and untestable. Move it to buildHandlerTable()
which returns the map, store it as a Server struct field initialized in
NewServer(), and add a missing-handler guard in handlePacketGroup to log
a warning instead of panicking on unknown opcodes.
This commit is contained in:
Houmgaor
2026-02-20 18:58:32 +01:00
parent 45c29837a5
commit e5133e5dcf
6 changed files with 66 additions and 35 deletions

View File

@@ -7,23 +7,26 @@ import (
)
func TestHandlerTableInitialized(t *testing.T) {
if handlerTable == nil {
t.Fatal("handlerTable should be initialized by init()")
table := buildHandlerTable()
if table == nil {
t.Fatal("buildHandlerTable() should return a non-nil map")
}
}
func TestHandlerTableHasEntries(t *testing.T) {
if len(handlerTable) == 0 {
table := buildHandlerTable()
if len(table) == 0 {
t.Error("handlerTable should have entries")
}
// Should have many handlers
if len(handlerTable) < 100 {
t.Errorf("handlerTable has %d entries, expected 100+", len(handlerTable))
if len(table) < 100 {
t.Errorf("handlerTable has %d entries, expected 100+", len(table))
}
}
func TestHandlerTableSystemPackets(t *testing.T) {
table := buildHandlerTable()
// Test that key system packets have handlers
systemPackets := []network.PacketID{
network.MSG_HEAD,
@@ -38,7 +41,7 @@ func TestHandlerTableSystemPackets(t *testing.T) {
for _, opcode := range systemPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for %s", opcode)
}
})
@@ -46,6 +49,7 @@ func TestHandlerTableSystemPackets(t *testing.T) {
}
func TestHandlerTableStagePackets(t *testing.T) {
table := buildHandlerTable()
// Test stage-related packet handlers
stagePackets := []network.PacketID{
network.MSG_SYS_CREATE_STAGE,
@@ -60,7 +64,7 @@ func TestHandlerTableStagePackets(t *testing.T) {
for _, opcode := range stagePackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for stage packet %s", opcode)
}
})
@@ -68,6 +72,7 @@ func TestHandlerTableStagePackets(t *testing.T) {
}
func TestHandlerTableBinaryPackets(t *testing.T) {
table := buildHandlerTable()
// Test binary message handlers
binaryPackets := []network.PacketID{
network.MSG_SYS_CAST_BINARY,
@@ -78,7 +83,7 @@ func TestHandlerTableBinaryPackets(t *testing.T) {
for _, opcode := range binaryPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for binary packet %s", opcode)
}
})
@@ -86,6 +91,7 @@ func TestHandlerTableBinaryPackets(t *testing.T) {
}
func TestHandlerTableReservedPackets(t *testing.T) {
table := buildHandlerTable()
// Reserved packets should still have handlers (usually no-ops)
reservedPackets := []network.PacketID{
network.MSG_SYS_reserve01,
@@ -99,7 +105,7 @@ func TestHandlerTableReservedPackets(t *testing.T) {
for _, opcode := range reservedPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for reserved packet %s", opcode)
}
})
@@ -107,8 +113,9 @@ func TestHandlerTableReservedPackets(t *testing.T) {
}
func TestHandlerFuncType(t *testing.T) {
table := buildHandlerTable()
// Verify all handlers are valid functions
for opcode, handler := range handlerTable {
for opcode, handler := range table {
if handler == nil {
t.Errorf("handler for %s is nil", opcode)
}
@@ -116,6 +123,7 @@ func TestHandlerFuncType(t *testing.T) {
}
func TestHandlerTableObjectPackets(t *testing.T) {
table := buildHandlerTable()
objectPackets := []network.PacketID{
network.MSG_SYS_ADD_OBJECT,
network.MSG_SYS_DEL_OBJECT,
@@ -125,7 +133,7 @@ func TestHandlerTableObjectPackets(t *testing.T) {
for _, opcode := range objectPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for object packet %s", opcode)
}
})
@@ -133,6 +141,7 @@ func TestHandlerTableObjectPackets(t *testing.T) {
}
func TestHandlerTableClientPackets(t *testing.T) {
table := buildHandlerTable()
clientPackets := []network.PacketID{
network.MSG_SYS_SET_STATUS,
network.MSG_SYS_HIDE_CLIENT,
@@ -141,7 +150,7 @@ func TestHandlerTableClientPackets(t *testing.T) {
for _, opcode := range clientPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for client packet %s", opcode)
}
})
@@ -149,6 +158,7 @@ func TestHandlerTableClientPackets(t *testing.T) {
}
func TestHandlerTableSemaphorePackets(t *testing.T) {
table := buildHandlerTable()
semaphorePackets := []network.PacketID{
network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE,
network.MSG_SYS_ACQUIRE_SEMAPHORE,
@@ -157,7 +167,7 @@ func TestHandlerTableSemaphorePackets(t *testing.T) {
for _, opcode := range semaphorePackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for semaphore packet %s", opcode)
}
})
@@ -165,6 +175,7 @@ func TestHandlerTableSemaphorePackets(t *testing.T) {
}
func TestHandlerTableMHFPackets(t *testing.T) {
table := buildHandlerTable()
// Test some core MHF packets have handlers
mhfPackets := []network.PacketID{
network.MSG_MHF_SAVEDATA,
@@ -173,7 +184,7 @@ func TestHandlerTableMHFPackets(t *testing.T) {
for _, opcode := range mhfPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for MHF packet %s", opcode)
}
})
@@ -181,6 +192,7 @@ func TestHandlerTableMHFPackets(t *testing.T) {
}
func TestHandlerTableEnumeratePackets(t *testing.T) {
table := buildHandlerTable()
enumPackets := []network.PacketID{
network.MSG_SYS_ENUMERATE_CLIENT,
network.MSG_SYS_ENUMERATE_STAGE,
@@ -188,7 +200,7 @@ func TestHandlerTableEnumeratePackets(t *testing.T) {
for _, opcode := range enumPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for enumerate packet %s", opcode)
}
})
@@ -196,6 +208,7 @@ func TestHandlerTableEnumeratePackets(t *testing.T) {
}
func TestHandlerTableLogPackets(t *testing.T) {
table := buildHandlerTable()
logPackets := []network.PacketID{
network.MSG_SYS_TERMINAL_LOG,
network.MSG_SYS_ISSUE_LOGKEY,
@@ -204,7 +217,7 @@ func TestHandlerTableLogPackets(t *testing.T) {
for _, opcode := range logPackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for log packet %s", opcode)
}
})
@@ -212,13 +225,14 @@ func TestHandlerTableLogPackets(t *testing.T) {
}
func TestHandlerTableFilePackets(t *testing.T) {
table := buildHandlerTable()
filePackets := []network.PacketID{
network.MSG_SYS_GET_FILE,
}
for _, opcode := range filePackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for file packet %s", opcode)
}
})
@@ -226,12 +240,14 @@ func TestHandlerTableFilePackets(t *testing.T) {
}
func TestHandlerTableEchoPacket(t *testing.T) {
if _, ok := handlerTable[network.MSG_SYS_ECHO]; !ok {
table := buildHandlerTable()
if _, ok := table[network.MSG_SYS_ECHO]; !ok {
t.Error("handler missing for MSG_SYS_ECHO")
}
}
func TestHandlerTableReserveStagePackets(t *testing.T) {
table := buildHandlerTable()
reservePackets := []network.PacketID{
network.MSG_SYS_RESERVE_STAGE,
network.MSG_SYS_UNRESERVE_STAGE,
@@ -241,7 +257,7 @@ func TestHandlerTableReserveStagePackets(t *testing.T) {
for _, opcode := range reservePackets {
t.Run(opcode.String(), func(t *testing.T) {
if _, ok := handlerTable[opcode]; !ok {
if _, ok := table[opcode]; !ok {
t.Errorf("handler missing for reserve stage packet %s", opcode)
}
})
@@ -249,14 +265,16 @@ func TestHandlerTableReserveStagePackets(t *testing.T) {
}
func TestHandlerTableThresholdPacket(t *testing.T) {
if _, ok := handlerTable[network.MSG_SYS_EXTEND_THRESHOLD]; !ok {
table := buildHandlerTable()
if _, ok := table[network.MSG_SYS_EXTEND_THRESHOLD]; !ok {
t.Error("handler missing for MSG_SYS_EXTEND_THRESHOLD")
}
}
func TestHandlerTableNoNilValues(t *testing.T) {
table := buildHandlerTable()
nilCount := 0
for opcode, handler := range handlerTable {
for opcode, handler := range table {
if handler == nil {
nilCount++
t.Errorf("nil handler for opcode %s", opcode)