fix(channelserver): post-RC1 stabilization sprint

Fix rasta_id=0 overwriting NULL in SaveMercenary, which prevented
game state saving for characters without a mercenary (#163).

Also includes:
- CHANGELOG updated with all 10 post-RC1 commits
- Setup wizard fmt.Printf replaced with zap structured logging
- technical-debt.md updated with 6 newly completed items
- Scenario binary format documented (docs/scenario-format.md)
- Tests: alliance nil-guard (#171), handler dispatch table,
  migrations (sorted/SQL/baseline), setup wizard (10 tests),
  protbot protocol sign/entrance/channel (23 tests)
This commit is contained in:
Houmgaor
2026-03-05 16:39:15 +01:00
parent 10ac803a45
commit 03adb21e99
13 changed files with 1314 additions and 6 deletions

View File

@@ -505,3 +505,49 @@ func TestOperateJoint_NilAlliance(t *testing.T) {
t.Error("No response packet queued — would softlock the client")
}
}
// --- scanAllianceWithGuilds nil guild tests (issue #171) ---
func TestInfoJoint_MissingSubGuild1(t *testing.T) {
// Verify that GetAllianceByID returns an error when sub guild 1 references
// a non-existent guild (nil return from GetByID). This is the scenario from
// issue #171 — a deleted guild causes a nil dereference in scanAllianceWithGuilds.
server := createMockServer()
guildMock := &mockGuildRepo{
// GetAllianceByID returns an error for missing guilds because
// scanAllianceWithGuilds calls GetByID for each sub guild.
// With guild=nil and SubGuild1ID > 0, GetByID returns nil,
// and scanAllianceWithGuilds should return an error rather than panic.
getAllianceErr: errNotFound,
}
server.guildRepo = guildMock
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfInfoJoint{AckHandle: 100, AllianceID: 5}
handleMsgMhfInfoJoint(session, pkt)
// Handler should send a response even on error (not softlock)
select {
case <-session.sendPackets:
default:
t.Error("No response packet queued — would softlock the client")
}
}
func TestInfoJoint_MissingSubGuild2(t *testing.T) {
server := createMockServer()
guildMock := &mockGuildRepo{
getAllianceErr: errNotFound,
}
server.guildRepo = guildMock
session := createMockSession(1, server)
pkt := &mhfpacket.MsgMhfInfoJoint{AckHandle: 100, AllianceID: 6}
handleMsgMhfInfoJoint(session, pkt)
select {
case <-session.sendPackets:
default:
t.Error("No response packet queued — would softlock the client")
}
}