mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
- Fix duplicate test declarations across coverage2, misc, mercenary, event files - Fix signserver TestHandlePacketDELETE timeout (multi-write pipe deadlock) - Fix entranceserver build error (invalid -1 for uint16 port) - Add handlers_reserve_test.go covering all 56 reserve handler stubs - Add handlers_coverage3_test.go with 115+ handler tests - Add handlers_register_test.go with 55 Raviente register/load tests - Add handlers_coverage_test.go, signserver, entranceserver, usercheck tests
1565 lines
43 KiB
Go
1565 lines
43 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"erupe-ce/common/byteframe"
|
|
"erupe-ce/network/mhfpacket"
|
|
)
|
|
|
|
// createMockServerWithRaviente creates a mock server with raviente and semaphore
|
|
// initialized, which the base createMockServer() does not do.
|
|
func createMockServerWithRaviente() *Server {
|
|
s := createMockServer()
|
|
s.raviente = NewRaviente()
|
|
s.semaphore = make(map[string]*Semaphore)
|
|
return s
|
|
}
|
|
|
|
// --- NewRaviente ---
|
|
|
|
func TestNewRaviente_FullValidation(t *testing.T) {
|
|
r := NewRaviente()
|
|
if r == nil {
|
|
t.Fatal("NewRaviente returned nil")
|
|
}
|
|
if r.register == nil {
|
|
t.Fatal("register is nil")
|
|
}
|
|
if r.state == nil {
|
|
t.Fatal("state is nil")
|
|
}
|
|
if r.support == nil {
|
|
t.Fatal("support is nil")
|
|
}
|
|
if len(r.register.register) != 5 {
|
|
t.Errorf("register length = %d, want 5", len(r.register.register))
|
|
}
|
|
if len(r.state.stateData) != 29 {
|
|
t.Errorf("stateData length = %d, want 29", len(r.state.stateData))
|
|
}
|
|
if len(r.support.supportData) != 25 {
|
|
t.Errorf("supportData length = %d, want 25", len(r.support.supportData))
|
|
}
|
|
// All values should be zero-initialized
|
|
for i, v := range r.register.register {
|
|
if v != 0 {
|
|
t.Errorf("register[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
for i, v := range r.state.stateData {
|
|
if v != 0 {
|
|
t.Errorf("stateData[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
for i, v := range r.support.supportData {
|
|
if v != 0 {
|
|
t.Errorf("supportData[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
if r.register.nextTime != 0 {
|
|
t.Errorf("nextTime = %d, want 0", r.register.nextTime)
|
|
}
|
|
if r.register.startTime != 0 {
|
|
t.Errorf("startTime = %d, want 0", r.register.startTime)
|
|
}
|
|
if r.register.killedTime != 0 {
|
|
t.Errorf("killedTime = %d, want 0", r.register.killedTime)
|
|
}
|
|
if r.register.postTime != 0 {
|
|
t.Errorf("postTime = %d, want 0", r.register.postTime)
|
|
}
|
|
if r.register.ravienteType != 0 {
|
|
t.Errorf("ravienteType = %d, want 0", r.register.ravienteType)
|
|
}
|
|
if r.register.maxPlayers != 0 {
|
|
t.Errorf("maxPlayers = %d, want 0", r.register.maxPlayers)
|
|
}
|
|
if r.register.carveQuest != 0 {
|
|
t.Errorf("carveQuest = %d, want 0", r.register.carveQuest)
|
|
}
|
|
}
|
|
|
|
// --- handleMsgSysLoadRegister ---
|
|
|
|
func TestHandleMsgSysLoadRegister_Case12(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.nextTime = 100
|
|
server.raviente.register.startTime = 200
|
|
server.raviente.register.killedTime = 300
|
|
server.raviente.register.postTime = 400
|
|
server.raviente.register.register[0] = 10
|
|
server.raviente.register.register[1] = 20
|
|
server.raviente.register.register[2] = 30
|
|
server.raviente.register.register[3] = 40
|
|
server.raviente.register.register[4] = 50
|
|
server.raviente.register.carveQuest = 500
|
|
server.raviente.register.maxPlayers = 32
|
|
server.raviente.register.ravienteType = 2
|
|
session := createMockSession(1, server)
|
|
|
|
handleMsgSysLoadRegister(session, &mhfpacket.MsgSysLoadRegister{
|
|
AckHandle: 1, RegisterID: 0, Unk1: 12,
|
|
})
|
|
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("response should have data")
|
|
}
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysLoadRegister_Case29(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[0] = 111
|
|
server.raviente.state.stateData[14] = 222
|
|
server.raviente.state.stateData[28] = 333
|
|
session := createMockSession(1, server)
|
|
|
|
handleMsgSysLoadRegister(session, &mhfpacket.MsgSysLoadRegister{
|
|
AckHandle: 2, RegisterID: 0, Unk1: 29,
|
|
})
|
|
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("response should have data")
|
|
}
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysLoadRegister_Case25(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.support.supportData[0] = 777
|
|
server.raviente.support.supportData[12] = 888
|
|
server.raviente.support.supportData[24] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
handleMsgSysLoadRegister(session, &mhfpacket.MsgSysLoadRegister{
|
|
AckHandle: 3, RegisterID: 0, Unk1: 25,
|
|
})
|
|
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("response should have data")
|
|
}
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysLoadRegister_UnknownCase(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
// Unk1=99 doesn't match any case, so no response should be sent
|
|
handleMsgSysLoadRegister(session, &mhfpacket.MsgSysLoadRegister{
|
|
AckHandle: 4, RegisterID: 0, Unk1: 99,
|
|
})
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
t.Error("no response expected for unknown Unk1 value")
|
|
default:
|
|
// Expected: no packet queued
|
|
}
|
|
}
|
|
|
|
// --- handleMsgSysOperateRegister ---
|
|
|
|
type opEntry struct {
|
|
op uint8
|
|
dest uint8
|
|
data uint32
|
|
}
|
|
|
|
func buildPayload(entries ...opEntry) []byte {
|
|
bf := byteframe.NewByteFrame()
|
|
for _, e := range entries {
|
|
bf.WriteUint8(e.op)
|
|
bf.WriteUint8(e.dest)
|
|
bf.WriteUint32(e.data)
|
|
}
|
|
bf.WriteUint8(0) // terminator
|
|
return bf.Data()
|
|
}
|
|
|
|
// --- SemaphoreID=4 (stateData) ---
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_Normal(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[0] = 100
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 0, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// With no ravi semaphore, GetRaviMultiplier returns 0, so data becomes 0
|
|
// *ref += 0 => stateData[0] stays 100
|
|
if server.raviente.state.stateData[0] != 100 {
|
|
t.Errorf("stateData[0] = %d, want 100 (multiplier=0 makes data=0)", server.raviente.state.stateData[0])
|
|
}
|
|
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("response should have data")
|
|
}
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_Dest28(t *testing.T) {
|
|
// dest=28 is the Berserk resurrection tracker, no multiplier applied
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[28] = 100
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 28, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// dest=28 adds data directly without multiplier
|
|
if server.raviente.state.stateData[28] != 150 {
|
|
t.Errorf("stateData[28] = %d, want 150", server.raviente.state.stateData[28])
|
|
}
|
|
|
|
select {
|
|
case p := <-session.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("response should have data")
|
|
}
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_Dest17_MultiplierIs1(t *testing.T) {
|
|
// dest=17 is Berserk poison tracker, only adds when damageMultiplier==1
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[17] = 100
|
|
server.raviente.register.maxPlayers = 4 // small ravi, minPlayers=4
|
|
|
|
// Create a ravi semaphore with enough clients for multiplier=1
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B51234_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// Need > 4 clients (minPlayers) for multiplier=1
|
|
for i := 0; i < 5; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session := createMockSession(1, server)
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 17, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// multiplier=1, so dest=17 adds data
|
|
if server.raviente.state.stateData[17] != 150 {
|
|
t.Errorf("stateData[17] = %d, want 150", server.raviente.state.stateData[17])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_Dest17_MultiplierNot1(t *testing.T) {
|
|
// dest=17 with multiplier != 1 should NOT add data
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[17] = 100
|
|
server.raviente.register.maxPlayers = 4 // small ravi, minPlayers=4
|
|
|
|
// Create a ravi semaphore with fewer clients than minPlayers for multiplier > 1
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B51234_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// Need <= 4 clients so multiplier = 4/len(clients) != 1
|
|
for i := 0; i < 2; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session := createMockSession(1, server)
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 17, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// multiplier=4/2=2 != 1, so dest=17 does NOT add data
|
|
if server.raviente.state.stateData[17] != 100 {
|
|
t.Errorf("stateData[17] = %d, want 100 (should not change)", server.raviente.state.stateData[17])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[5] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 5, data: 42}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.state.stateData[5] != 42 {
|
|
t.Errorf("stateData[5] = %d, want 42", server.raviente.state.stateData[5])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[3] = 888
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 3, data: 77}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// op=13 falls through to op=14 behavior: sets value
|
|
if server.raviente.state.stateData[3] != 77 {
|
|
t.Errorf("stateData[3] = %d, want 77", server.raviente.state.stateData[3])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_MultipleEntries(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(
|
|
opEntry{op: 14, dest: 0, data: 10},
|
|
opEntry{op: 14, dest: 1, data: 20},
|
|
opEntry{op: 14, dest: 2, data: 30},
|
|
),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.state.stateData[0] != 10 {
|
|
t.Errorf("stateData[0] = %d, want 10", server.raviente.state.stateData[0])
|
|
}
|
|
if server.raviente.state.stateData[1] != 20 {
|
|
t.Errorf("stateData[1] = %d, want 20", server.raviente.state.stateData[1])
|
|
}
|
|
if server.raviente.state.stateData[2] != 30 {
|
|
t.Errorf("stateData[2] = %d, want 30", server.raviente.state.stateData[2])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
// --- SemaphoreID=5 (supportData) ---
|
|
|
|
func TestHandleMsgSysOperateRegister_Support_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.support.supportData[0] = 100
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 5,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 0, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.support.supportData[0] != 150 {
|
|
t.Errorf("supportData[0] = %d, want 150", server.raviente.support.supportData[0])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Support_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.support.supportData[10] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 5,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 10, data: 42}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.support.supportData[10] != 42 {
|
|
t.Errorf("supportData[10] = %d, want 42", server.raviente.support.supportData[10])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Support_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.support.supportData[5] = 888
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 5,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 5, data: 77}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.support.supportData[5] != 77 {
|
|
t.Errorf("supportData[5] = %d, want 77", server.raviente.support.supportData[5])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Support_MultipleEntries(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 5,
|
|
RawDataPayload: buildPayload(
|
|
opEntry{op: 2, dest: 0, data: 10},
|
|
opEntry{op: 14, dest: 1, data: 20},
|
|
opEntry{op: 13, dest: 2, data: 30},
|
|
),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.support.supportData[0] != 10 {
|
|
t.Errorf("supportData[0] = %d, want 10", server.raviente.support.supportData[0])
|
|
}
|
|
if server.raviente.support.supportData[1] != 20 {
|
|
t.Errorf("supportData[1] = %d, want 20", server.raviente.support.supportData[1])
|
|
}
|
|
if server.raviente.support.supportData[2] != 30 {
|
|
t.Errorf("supportData[2] = %d, want 30", server.raviente.support.supportData[2])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
// --- SemaphoreID=6 (register fields) ---
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest0_NextTime(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 0, data: 12345}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.nextTime != 12345 {
|
|
t.Errorf("nextTime = %d, want 12345", server.raviente.register.nextTime)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest1_StartTime(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 1, data: 67890}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.startTime != 67890 {
|
|
t.Errorf("startTime = %d, want 67890", server.raviente.register.startTime)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest2_KilledTime(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 2, data: 11111}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.killedTime != 11111 {
|
|
t.Errorf("killedTime = %d, want 11111", server.raviente.register.killedTime)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest3_PostTime(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 3, data: 22222}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.postTime != 22222 {
|
|
t.Errorf("postTime = %d, want 22222", server.raviente.register.postTime)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest4_Register0_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[0] = 100
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 4, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[0] != 150 {
|
|
t.Errorf("register[0] = %d, want 150", server.raviente.register.register[0])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest4_Register0_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[0] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 4, data: 42}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[0] != 42 {
|
|
t.Errorf("register[0] = %d, want 42", server.raviente.register.register[0])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest4_Register0_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[0] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 4, data: 77}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// op=14 for dest=4 writes response data but does NOT set *ref (unlike op=13)
|
|
if server.raviente.register.register[0] != 999 {
|
|
t.Errorf("register[0] = %d, want 999 (op=14 doesn't set ref)", server.raviente.register.register[0])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest5_CarveQuest(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 5, data: 33333}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.carveQuest != 33333 {
|
|
t.Errorf("carveQuest = %d, want 33333", server.raviente.register.carveQuest)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest6_Register1_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[1] = 200
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 6, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[1] != 250 {
|
|
t.Errorf("register[1] = %d, want 250", server.raviente.register.register[1])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest6_Register1_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 6, data: 55}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[1] != 55 {
|
|
t.Errorf("register[1] = %d, want 55", server.raviente.register.register[1])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest6_Register1_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[1] = 999
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 6, data: 77}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// op=14 for register dests doesn't set *ref
|
|
if server.raviente.register.register[1] != 999 {
|
|
t.Errorf("register[1] = %d, want 999", server.raviente.register.register[1])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest7_Register2_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[2] = 300
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 7, data: 25}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[2] != 325 {
|
|
t.Errorf("register[2] = %d, want 325", server.raviente.register.register[2])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest7_Register2_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 7, data: 66}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[2] != 66 {
|
|
t.Errorf("register[2] = %d, want 66", server.raviente.register.register[2])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest7_Register2_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[2] = 500
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 7, data: 88}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[2] != 500 {
|
|
t.Errorf("register[2] = %d, want 500", server.raviente.register.register[2])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest8_Register3_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[3] = 400
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 8, data: 10}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[3] != 410 {
|
|
t.Errorf("register[3] = %d, want 410", server.raviente.register.register[3])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest8_Register3_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 8, data: 99}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[3] != 99 {
|
|
t.Errorf("register[3] = %d, want 99", server.raviente.register.register[3])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest8_Register3_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[3] = 777
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 8, data: 11}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[3] != 777 {
|
|
t.Errorf("register[3] = %d, want 777", server.raviente.register.register[3])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest9_MaxPlayers(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 9, data: 32}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.maxPlayers != 32 {
|
|
t.Errorf("maxPlayers = %d, want 32", server.raviente.register.maxPlayers)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest10_RavienteType(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 10, data: 3}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.ravienteType != 3 {
|
|
t.Errorf("ravienteType = %d, want 3", server.raviente.register.ravienteType)
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest11_Register4_Op2(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[4] = 500
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 11, data: 100}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[4] != 600 {
|
|
t.Errorf("register[4] = %d, want 600", server.raviente.register.register[4])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest11_Register4_Op13(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 13, dest: 11, data: 44}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[4] != 44 {
|
|
t.Errorf("register[4] = %d, want 44", server.raviente.register.register[4])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_Dest11_Register4_Op14(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.register[4] = 888
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 11, data: 55}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.register[4] != 888 {
|
|
t.Errorf("register[4] = %d, want 888", server.raviente.register.register[4])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_DefaultDest(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
// dest=99 doesn't match any case, hits default branch
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 99, data: 123}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
// Default case writes zeros and sends response
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_Register_AllDests(t *testing.T) {
|
|
// Exercise all dest cases in a single operation to test full branch coverage
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 6,
|
|
RawDataPayload: buildPayload(
|
|
opEntry{op: 14, dest: 0, data: 1}, // nextTime
|
|
opEntry{op: 14, dest: 1, data: 2}, // startTime
|
|
opEntry{op: 14, dest: 2, data: 3}, // killedTime
|
|
opEntry{op: 14, dest: 3, data: 4}, // postTime
|
|
opEntry{op: 2, dest: 4, data: 5}, // register[0] op2
|
|
opEntry{op: 14, dest: 5, data: 6}, // carveQuest
|
|
opEntry{op: 2, dest: 6, data: 7}, // register[1] op2
|
|
opEntry{op: 2, dest: 7, data: 8}, // register[2] op2
|
|
opEntry{op: 2, dest: 8, data: 9}, // register[3] op2
|
|
opEntry{op: 14, dest: 9, data: 10}, // maxPlayers
|
|
opEntry{op: 14, dest: 10, data: 11}, // ravienteType
|
|
opEntry{op: 2, dest: 11, data: 12}, // register[4] op2
|
|
opEntry{op: 14, dest: 99, data: 0}, // default
|
|
),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
if server.raviente.register.nextTime != 1 {
|
|
t.Errorf("nextTime = %d, want 1", server.raviente.register.nextTime)
|
|
}
|
|
if server.raviente.register.startTime != 2 {
|
|
t.Errorf("startTime = %d, want 2", server.raviente.register.startTime)
|
|
}
|
|
if server.raviente.register.killedTime != 3 {
|
|
t.Errorf("killedTime = %d, want 3", server.raviente.register.killedTime)
|
|
}
|
|
if server.raviente.register.postTime != 4 {
|
|
t.Errorf("postTime = %d, want 4", server.raviente.register.postTime)
|
|
}
|
|
if server.raviente.register.register[0] != 5 {
|
|
t.Errorf("register[0] = %d, want 5", server.raviente.register.register[0])
|
|
}
|
|
if server.raviente.register.carveQuest != 6 {
|
|
t.Errorf("carveQuest = %d, want 6", server.raviente.register.carveQuest)
|
|
}
|
|
if server.raviente.register.register[1] != 7 {
|
|
t.Errorf("register[1] = %d, want 7", server.raviente.register.register[1])
|
|
}
|
|
if server.raviente.register.register[2] != 8 {
|
|
t.Errorf("register[2] = %d, want 8", server.raviente.register.register[2])
|
|
}
|
|
if server.raviente.register.register[3] != 9 {
|
|
t.Errorf("register[3] = %d, want 9", server.raviente.register.register[3])
|
|
}
|
|
if server.raviente.register.maxPlayers != 10 {
|
|
t.Errorf("maxPlayers = %d, want 10", server.raviente.register.maxPlayers)
|
|
}
|
|
if server.raviente.register.ravienteType != 11 {
|
|
t.Errorf("ravienteType = %d, want 11", server.raviente.register.ravienteType)
|
|
}
|
|
if server.raviente.register.register[4] != 12 {
|
|
t.Errorf("register[4] = %d, want 12", server.raviente.register.register[4])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
// --- getRaviSemaphore ---
|
|
|
|
func TestGetRaviSemaphore_NoMatch(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
result := getRaviSemaphore(server)
|
|
if result != nil {
|
|
t.Error("should return nil when no semaphore matches")
|
|
}
|
|
}
|
|
|
|
func TestGetRaviSemaphore_WrongPrefix(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.semaphore["wrong"] = &Semaphore{
|
|
id_semaphore: "wrong_prefix_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
result := getRaviSemaphore(server)
|
|
if result != nil {
|
|
t.Error("should return nil when no semaphore has correct prefix")
|
|
}
|
|
}
|
|
|
|
func TestGetRaviSemaphore_WrongSuffix(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.semaphore["wrong"] = &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_4",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
result := getRaviSemaphore(server)
|
|
if result != nil {
|
|
t.Error("should return nil when semaphore has wrong suffix")
|
|
}
|
|
}
|
|
|
|
func TestGetRaviSemaphore_Match(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
expected := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5some_data_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
server.semaphore["ravi"] = expected
|
|
result := getRaviSemaphore(server)
|
|
if result != expected {
|
|
t.Error("should return matching semaphore")
|
|
}
|
|
}
|
|
|
|
func TestGetRaviSemaphore_ExactMinimal(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
expected := &Semaphore{
|
|
id_semaphore: "hs_l0u3B53",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
server.semaphore["ravi"] = expected
|
|
result := getRaviSemaphore(server)
|
|
if result != expected {
|
|
t.Error("should match when prefix immediately followed by suffix '3'")
|
|
}
|
|
}
|
|
|
|
func TestGetRaviSemaphore_MultipleOnlyOneMatches(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.semaphore["wrong1"] = &Semaphore{
|
|
id_semaphore: "something_else",
|
|
id: 8,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
expected := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5ravi_3",
|
|
id: 9,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
server.semaphore["ravi"] = expected
|
|
server.semaphore["wrong2"] = &Semaphore{
|
|
id_semaphore: "hs_l0u3B5_no_suffix",
|
|
id: 10,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
result := getRaviSemaphore(server)
|
|
if result != expected {
|
|
t.Error("should return the one matching semaphore")
|
|
}
|
|
}
|
|
|
|
// --- notifyRavi ---
|
|
|
|
func TestNotifyRavi_NoSemaphore(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
// Should not panic when no ravi semaphore exists
|
|
session.notifyRavi()
|
|
|
|
// No clients to receive notifications, so nothing should be queued
|
|
select {
|
|
case <-session.sendPackets:
|
|
t.Error("no packet should be queued on the calling session")
|
|
default:
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
func TestNotifyRavi_WithSemaphoreAndClients(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
client1 := createMockSession(10, server)
|
|
client2 := createMockSession(20, server)
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
sema.clients[client1] = client1.charID
|
|
sema.clients[client2] = client2.charID
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session.notifyRavi()
|
|
|
|
// Both clients on the semaphore should receive notification packets
|
|
receivedCount := 0
|
|
select {
|
|
case p := <-client1.sendPackets:
|
|
if len(p.data) > 0 {
|
|
receivedCount++
|
|
}
|
|
default:
|
|
t.Error("client1 should have received notification")
|
|
}
|
|
select {
|
|
case p := <-client2.sendPackets:
|
|
if len(p.data) > 0 {
|
|
receivedCount++
|
|
}
|
|
default:
|
|
t.Error("client2 should have received notification")
|
|
}
|
|
if receivedCount != 2 {
|
|
t.Errorf("received %d notifications, want 2", receivedCount)
|
|
}
|
|
}
|
|
|
|
// --- resetRavi ---
|
|
|
|
func TestResetRavi(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
// Set various values
|
|
server.raviente.register.nextTime = 12345
|
|
server.raviente.register.startTime = 67890
|
|
server.raviente.register.killedTime = 11111
|
|
server.raviente.register.postTime = 22222
|
|
server.raviente.register.ravienteType = 3
|
|
server.raviente.register.maxPlayers = 32
|
|
server.raviente.register.carveQuest = 44444
|
|
server.raviente.register.register[0] = 100
|
|
server.raviente.register.register[1] = 200
|
|
server.raviente.register.register[2] = 300
|
|
server.raviente.register.register[3] = 400
|
|
server.raviente.register.register[4] = 500
|
|
server.raviente.state.stateData[0] = 999
|
|
server.raviente.state.stateData[14] = 888
|
|
server.raviente.state.stateData[28] = 777
|
|
server.raviente.support.supportData[0] = 666
|
|
server.raviente.support.supportData[12] = 555
|
|
server.raviente.support.supportData[24] = 444
|
|
|
|
resetRavi(session)
|
|
|
|
// Verify all register fields reset
|
|
if server.raviente.register.nextTime != 0 {
|
|
t.Errorf("nextTime = %d, want 0", server.raviente.register.nextTime)
|
|
}
|
|
if server.raviente.register.startTime != 0 {
|
|
t.Errorf("startTime = %d, want 0", server.raviente.register.startTime)
|
|
}
|
|
if server.raviente.register.killedTime != 0 {
|
|
t.Errorf("killedTime = %d, want 0", server.raviente.register.killedTime)
|
|
}
|
|
if server.raviente.register.postTime != 0 {
|
|
t.Errorf("postTime = %d, want 0", server.raviente.register.postTime)
|
|
}
|
|
if server.raviente.register.ravienteType != 0 {
|
|
t.Errorf("ravienteType = %d, want 0", server.raviente.register.ravienteType)
|
|
}
|
|
if server.raviente.register.maxPlayers != 0 {
|
|
t.Errorf("maxPlayers = %d, want 0", server.raviente.register.maxPlayers)
|
|
}
|
|
if server.raviente.register.carveQuest != 0 {
|
|
t.Errorf("carveQuest = %d, want 0", server.raviente.register.carveQuest)
|
|
}
|
|
|
|
// Verify register array reset
|
|
for i, v := range server.raviente.register.register {
|
|
if v != 0 {
|
|
t.Errorf("register[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
if len(server.raviente.register.register) != 5 {
|
|
t.Errorf("register length = %d, want 5", len(server.raviente.register.register))
|
|
}
|
|
|
|
// Verify stateData reset
|
|
for i, v := range server.raviente.state.stateData {
|
|
if v != 0 {
|
|
t.Errorf("stateData[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
if len(server.raviente.state.stateData) != 29 {
|
|
t.Errorf("stateData length = %d, want 29", len(server.raviente.state.stateData))
|
|
}
|
|
|
|
// Verify supportData reset
|
|
for i, v := range server.raviente.support.supportData {
|
|
if v != 0 {
|
|
t.Errorf("supportData[%d] = %d, want 0", i, v)
|
|
}
|
|
}
|
|
if len(server.raviente.support.supportData) != 25 {
|
|
t.Errorf("supportData length = %d, want 25", len(server.raviente.support.supportData))
|
|
}
|
|
}
|
|
|
|
// --- GetRaviMultiplier ---
|
|
|
|
func TestGetRaviMultiplier_NoSemaphore(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
result := server.raviente.GetRaviMultiplier(server)
|
|
if result != 0 {
|
|
t.Errorf("expected 0, got %f", result)
|
|
}
|
|
}
|
|
|
|
func TestGetRaviMultiplier_LargeRavi_EnoughPlayers(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.maxPlayers = 32 // > 8, so minPlayers=24
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// Need > 24 clients
|
|
for i := 0; i < 25; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
result := server.raviente.GetRaviMultiplier(server)
|
|
if result != 1 {
|
|
t.Errorf("expected 1, got %f", result)
|
|
}
|
|
}
|
|
|
|
func TestGetRaviMultiplier_LargeRavi_NotEnoughPlayers(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.maxPlayers = 32 // > 8, so minPlayers=24
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// 12 clients < 24 minPlayers => multiplier = 24/12 = 2
|
|
for i := 0; i < 12; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
result := server.raviente.GetRaviMultiplier(server)
|
|
expected := float64(24 / 12) // integer division: 2
|
|
if result != expected {
|
|
t.Errorf("expected %f, got %f", expected, result)
|
|
}
|
|
}
|
|
|
|
func TestGetRaviMultiplier_SmallRavi_EnoughPlayers(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.maxPlayers = 4 // <= 8, so minPlayers=4
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// Need > 4 clients
|
|
for i := 0; i < 5; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
result := server.raviente.GetRaviMultiplier(server)
|
|
if result != 1 {
|
|
t.Errorf("expected 1, got %f", result)
|
|
}
|
|
}
|
|
|
|
func TestGetRaviMultiplier_SmallRavi_NotEnoughPlayers(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.register.maxPlayers = 4 // <= 8, so minPlayers=4
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// 2 clients < 4 minPlayers => multiplier = 4/2 = 2
|
|
for i := 0; i < 2; i++ {
|
|
s := createMockSession(uint32(100+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
result := server.raviente.GetRaviMultiplier(server)
|
|
expected := float64(4 / 2) // integer division: 2
|
|
if result != expected {
|
|
t.Errorf("expected %f, got %f", expected, result)
|
|
}
|
|
}
|
|
|
|
// --- handleMsgSysNotifyRegister (empty handler) ---
|
|
|
|
func TestHandleMsgSysNotifyRegister(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
session := createMockSession(1, server)
|
|
|
|
// Should not panic - handler is empty
|
|
handleMsgSysNotifyRegister(session, &mhfpacket.MsgSysNotifyRegister{
|
|
RegisterID: 4,
|
|
})
|
|
|
|
// No response expected from empty handler
|
|
select {
|
|
case <-session.sendPackets:
|
|
t.Error("empty handler should not queue packets")
|
|
default:
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
// --- State op2 with multiplier applied (normal dest, not 17 or 28) ---
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_WithMultiplier(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[5] = 100
|
|
server.raviente.register.maxPlayers = 32 // large ravi, minPlayers=24
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
// 12 clients < 24 minPlayers => multiplier = 24/12 = 2
|
|
for i := 0; i < 12; i++ {
|
|
s := createMockSession(uint32(200+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session := createMockSession(1, server)
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 5, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// data = uint32(float64(50) * 2.0) = 100
|
|
// stateData[5] = 100 + 100 = 200
|
|
if server.raviente.state.stateData[5] != 200 {
|
|
t.Errorf("stateData[5] = %d, want 200", server.raviente.state.stateData[5])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
func TestHandleMsgSysOperateRegister_State_Op2_Dest28_WithMultiplier(t *testing.T) {
|
|
// dest=28 should ignore multiplier regardless
|
|
server := createMockServerWithRaviente()
|
|
server.raviente.state.stateData[28] = 100
|
|
server.raviente.register.maxPlayers = 32
|
|
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
for i := 0; i < 12; i++ {
|
|
s := createMockSession(uint32(200+i), server)
|
|
sema.clients[s] = s.charID
|
|
}
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session := createMockSession(1, server)
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 4,
|
|
RawDataPayload: buildPayload(opEntry{op: 2, dest: 28, data: 50}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// dest=28 always adds raw data, ignoring multiplier
|
|
if server.raviente.state.stateData[28] != 150 {
|
|
t.Errorf("stateData[28] = %d, want 150", server.raviente.state.stateData[28])
|
|
}
|
|
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("no response queued")
|
|
}
|
|
}
|
|
|
|
// Test that notifyRavi is called as part of handleMsgSysOperateRegister
|
|
// by verifying that clients on the ravi semaphore get notifications.
|
|
func TestHandleMsgSysOperateRegister_NotifiesRaviClients(t *testing.T) {
|
|
server := createMockServerWithRaviente()
|
|
|
|
raviClient := createMockSession(50, server)
|
|
sema := &Semaphore{
|
|
id_semaphore: "hs_l0u3B5test_3",
|
|
id: 7,
|
|
clients: make(map[*Session]uint32),
|
|
}
|
|
sema.clients[raviClient] = raviClient.charID
|
|
server.semaphore["ravi"] = sema
|
|
|
|
session := createMockSession(1, server)
|
|
pkt := &mhfpacket.MsgSysOperateRegister{
|
|
AckHandle: 1,
|
|
SemaphoreID: 5,
|
|
RawDataPayload: buildPayload(opEntry{op: 14, dest: 0, data: 1}),
|
|
}
|
|
handleMsgSysOperateRegister(session, pkt)
|
|
|
|
// The calling session should receive the ack response
|
|
select {
|
|
case <-session.sendPackets:
|
|
default:
|
|
t.Error("calling session should receive ack response")
|
|
}
|
|
|
|
// The ravi client should receive a notification
|
|
select {
|
|
case p := <-raviClient.sendPackets:
|
|
if len(p.data) == 0 {
|
|
t.Error("ravi client should receive non-empty notification")
|
|
}
|
|
default:
|
|
t.Error("ravi client should receive notification")
|
|
}
|
|
}
|