Files
Erupe/server/channelserver/handlers_register_test.go
Houmgaor e5133e5dcf 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.
2026-02-20 18:58:32 +01:00

223 lines
5.1 KiB
Go

package channelserver
import (
"testing"
"erupe-ce/common/byteframe"
)
// createMockServerWithRaviente creates a mock server with raviente and semaphore
// initialized, which the base createMockServer() does not do.
func createMockServerWithRaviente() *Server {
s := createMockServer()
s.raviente = &Raviente{
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
}
s.semaphore = make(map[string]*Semaphore)
return s
}
func TestRavienteInitialization(t *testing.T) {
r := &Raviente{
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
}
if len(r.register) != 30 {
t.Errorf("register length = %d, want 30", len(r.register))
}
if len(r.state) != 30 {
t.Errorf("state length = %d, want 30", len(r.state))
}
if len(r.support) != 30 {
t.Errorf("support length = %d, want 30", len(r.support))
}
// All values should be zero-initialized
for i, v := range r.register {
if v != 0 {
t.Errorf("register[%d] = %d, want 0", i, v)
}
}
for i, v := range r.state {
if v != 0 {
t.Errorf("state[%d] = %d, want 0", i, v)
}
}
for i, v := range r.support {
if v != 0 {
t.Errorf("support[%d] = %d, want 0", i, v)
}
}
if r.id != 0 {
t.Errorf("id = %d, want 0", r.id)
}
}
func TestRavienteMutex(t *testing.T) {
r := &Raviente{
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
}
// Test that we can lock and unlock without deadlock
r.Lock()
r.register[0] = 42
r.Unlock()
r.Lock()
val := r.register[0]
r.Unlock()
if val != 42 {
t.Errorf("register[0] = %d, want 42", val)
}
}
func TestRavienteDataAccess(t *testing.T) {
r := &Raviente{
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
}
// Write and verify register data
r.register[0] = 100
r.register[4] = 200
r.register[29] = 300
if r.register[0] != 100 {
t.Errorf("register[0] = %d, want 100", r.register[0])
}
if r.register[4] != 200 {
t.Errorf("register[4] = %d, want 200", r.register[4])
}
if r.register[29] != 300 {
t.Errorf("register[29] = %d, want 300", r.register[29])
}
// Write and verify state data
r.state[0] = 500
r.state[28] = 600
if r.state[0] != 500 {
t.Errorf("state[0] = %d, want 500", r.state[0])
}
if r.state[28] != 600 {
t.Errorf("state[28] = %d, want 600", r.state[28])
}
// Write and verify support data
r.support[0] = 700
r.support[24] = 800
if r.support[0] != 700 {
t.Errorf("support[0] = %d, want 700", r.support[0])
}
if r.support[24] != 800 {
t.Errorf("support[24] = %d, want 800", r.support[24])
}
}
func TestRavienteID(t *testing.T) {
r := &Raviente{
register: make([]uint32, 30),
state: make([]uint32, 30),
support: make([]uint32, 30),
}
r.id = 12345
if r.id != 12345 {
t.Errorf("id = %d, want 12345", r.id)
}
r.id = 0xFFFF
if r.id != 0xFFFF {
t.Errorf("id = %d, want %d", r.id, uint16(0xFFFF))
}
}
func TestCreateMockServerWithRaviente(t *testing.T) {
s := createMockServerWithRaviente()
if s == nil {
t.Fatal("createMockServerWithRaviente() returned nil")
}
if s.raviente == nil {
t.Fatal("raviente should not be nil")
}
if s.semaphore == nil {
t.Fatal("semaphore should not be nil")
}
if len(s.raviente.register) != 30 {
t.Errorf("raviente register length = %d, want 30", len(s.raviente.register))
}
if len(s.raviente.state) != 30 {
t.Errorf("raviente state length = %d, want 30", len(s.raviente.state))
}
if len(s.raviente.support) != 30 {
t.Errorf("raviente support length = %d, want 30", len(s.raviente.support))
}
}
func TestHandlerTableRegistered(t *testing.T) {
s := createMockServer()
if s == nil {
t.Fatal("createMockServer() returned nil")
}
// Verify handler table is populated
table := buildHandlerTable()
if len(table) == 0 {
t.Error("handlers table should not be empty")
}
// Check that key handler types are registered
// (these are critical handlers that must always be present)
criticalHandlers := []string{
"handleMsgSysCreateStage",
"handleMsgSysStageDestruct",
}
_ = criticalHandlers // We just verify the table is non-empty since handler function names aren't directly accessible
// Verify minimum handler count
if len(table) < 50 {
t.Errorf("handlers count = %d, expected at least 50", len(table))
}
}
func TestHandlerTableNilSession(t *testing.T) {
// This test verifies that the handler table exists and has entries
// but doesn't call handlers (which would require a real session)
_ = createMockServer()
table := buildHandlerTable()
count := 0
for range table {
count++
}
if count == 0 {
t.Error("No handlers registered")
}
}
func TestMockServerPacketHandling(t *testing.T) {
s := createMockServerWithRaviente()
session := createMockSession(1, s)
// Verify the session and server are properly linked
if session.server != s {
t.Error("Session server reference mismatch")
}
// Verify byteframe can be created for packet construction
bf := byteframe.NewByteFrame()
bf.WriteUint32(0) // AckHandle
if len(bf.Data()) != 4 {
t.Errorf("ByteFrame length = %d, want 4", len(bf.Data()))
}
}