mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
test(signserver): push coverage from 62.9% to 70.3%
Add handlePacket dispatch tests for all switch cases (DSGN, SIGN, DLTSKEYSIGN, PS4SGN, PS3SGN, VITASGN, WIIUSGN, COGLNK, VITACOGLNK, DELETE). Add makeSignResponse branch tests covering PSN client PSNID field, CapLink key/host paths, MezFes minigame switch, non-localhost remote addr, and PSN token registration. Add startSignCapture enabled-path tests with temp dir and default output dir.
This commit is contained in:
@@ -2,6 +2,7 @@ package signserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -263,3 +264,310 @@ func TestMakeSignResponse_FullFlow(t *testing.T) {
|
||||
t.Errorf("makeSignResponse() first byte = %d, want %d (SIGN_SUCCESS)", result[0], SIGN_SUCCESS)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_PSNClientWritesPSNID verifies PSN client appends PSNID field.
|
||||
func TestMakeSignResponse_PSNClientWritesPSNID(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
server.charRepo = &mockSignCharacterRepo{
|
||||
characters: []character{{ID: 1, Name: "PSNHunter", HR: 50}},
|
||||
}
|
||||
server.userRepo = &mockSignUserRepo{
|
||||
returnExpiry: time.Now().Add(time.Hour * 24 * 30),
|
||||
lastLogin: time.Now(),
|
||||
psnIDForUser: "MyPSNID",
|
||||
}
|
||||
|
||||
// PC response
|
||||
pcConn := newMockConn()
|
||||
pcSession := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: pcConn,
|
||||
client: PC100,
|
||||
}
|
||||
pcResult := pcSession.makeSignResponse(1)
|
||||
|
||||
// PS4 response
|
||||
ps4Conn := newMockConn()
|
||||
ps4Session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: ps4Conn,
|
||||
client: PS4,
|
||||
}
|
||||
ps4Result := ps4Session.makeSignResponse(1)
|
||||
|
||||
// PSN response should be longer due to 20-byte PSNID field
|
||||
if len(ps4Result) <= len(pcResult) {
|
||||
t.Errorf("PS4 response len (%d) should be > PC response len (%d)", len(ps4Result), len(pcResult))
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_CapLink51728_20000 verifies CapLink key is written.
|
||||
func TestMakeSignResponse_CapLink51728_20000(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{51728, 20000, 0, 0, 0},
|
||||
Key: "caplink-key-test",
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
conn := newMockConn()
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: conn,
|
||||
client: PC100,
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(1)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
|
||||
// The response with CapLink key should be longer than without
|
||||
configNoKey := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
serverNoKey := newMakeSignResponseServer(configNoKey)
|
||||
sessionNoKey := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: serverNoKey,
|
||||
rawConn: newMockConn(),
|
||||
client: PC100,
|
||||
}
|
||||
resultNoKey := sessionNoKey.makeSignResponse(1)
|
||||
|
||||
if len(result) <= len(resultNoKey) {
|
||||
t.Errorf("CapLink 51728/20000 response len (%d) should be > base response len (%d)", len(result), len(resultNoKey))
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_CapLink51728_20002 verifies the 20002 variant also writes key.
|
||||
func TestMakeSignResponse_CapLink51728_20002(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{51728, 20002, 0, 0, 0},
|
||||
Key: "caplink-key-20002",
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: newMockConn(),
|
||||
client: PC100,
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(1)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Error("makeSignResponse() returned empty result")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_CapLink51729Combo verifies the 51729 host:port write.
|
||||
func TestMakeSignResponse_CapLink51729Combo(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 51729, 1, 20000},
|
||||
Host: "caplink.example.com",
|
||||
Port: 9999,
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: newMockConn(),
|
||||
client: PC100,
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(1)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
|
||||
// Response with 51729 combo should include host:port string, making it longer
|
||||
configNoCap := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
serverNoCap := newMakeSignResponseServer(configNoCap)
|
||||
sessionNoCap := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: serverNoCap,
|
||||
rawConn: newMockConn(),
|
||||
client: PC100,
|
||||
}
|
||||
resultNoCap := sessionNoCap.makeSignResponse(1)
|
||||
|
||||
if len(result) <= len(resultNoCap) {
|
||||
t.Errorf("CapLink 51729 combo response len (%d) should be > base len (%d)", len(result), len(resultNoCap))
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_MezFesSwitchMinigame verifies stalls[4] is set to 2.
|
||||
func TestMakeSignResponse_MezFesSwitchMinigame(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
MezFesSwitchMinigame: true,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: newMockConn(),
|
||||
client: PC100,
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(1)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Error("makeSignResponse() returned empty result")
|
||||
}
|
||||
}
|
||||
|
||||
// mockConnRemote is a mockConn variant with a configurable RemoteAddr.
|
||||
type mockConnRemote struct {
|
||||
mockConn
|
||||
remoteAddr net.Addr
|
||||
}
|
||||
|
||||
func (m *mockConnRemote) RemoteAddr() net.Addr {
|
||||
return m.remoteAddr
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_NonLocalhostRemote verifies the non-localhost entrance addr path.
|
||||
func TestMakeSignResponse_NonLocalhostRemote(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
Host: "192.168.1.100",
|
||||
Entrance: cfg.Entrance{
|
||||
Port: 53310,
|
||||
},
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
conn := &mockConnRemote{
|
||||
mockConn: *newMockConn(),
|
||||
remoteAddr: &net.TCPAddr{IP: net.ParseIP("10.0.0.5"), Port: 12345},
|
||||
}
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: conn,
|
||||
client: PC100,
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(1)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
// Response should contain the Host address (192.168.1.100) rather than 127.0.0.1
|
||||
resultStr := string(result)
|
||||
if !strings.Contains(resultStr, "192.168.1.100") {
|
||||
t.Error("non-localhost response should contain Host address")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMakeSignResponse_PSNTokenPath verifies the PSN token registration when uid=0 with psn set.
|
||||
func TestMakeSignResponse_PSNTokenPath(t *testing.T) {
|
||||
config := &cfg.Config{
|
||||
DebugOptions: cfg.DebugOptions{
|
||||
CapLink: cfg.CapLinkOptions{
|
||||
Values: []uint16{0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
GameplayOptions: cfg.GameplayOptions{
|
||||
MezFesSoloTickets: 100,
|
||||
MezFesGroupTickets: 100,
|
||||
},
|
||||
}
|
||||
|
||||
server := newMakeSignResponseServer(config)
|
||||
server.sessionRepo = &mockSignSessionRepo{
|
||||
registerPSNTokenID: 500,
|
||||
}
|
||||
session := &Session{
|
||||
logger: zap.NewNop(),
|
||||
server: server,
|
||||
rawConn: newMockConn(),
|
||||
client: PS4,
|
||||
psn: "my_psn_id",
|
||||
}
|
||||
|
||||
result := session.makeSignResponse(0)
|
||||
if result[0] != uint8(SIGN_SUCCESS) {
|
||||
t.Errorf("first byte = %d, want SIGN_SUCCESS", result[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,4 +252,3 @@ func (m *mockSignSessionRepo) Validate(token string, tokenID uint32) (bool, erro
|
||||
func (m *mockSignSessionRepo) GetPSNIDByToken(token string) (string, error) {
|
||||
return m.psnIDByToken, m.psnIDByTokenErr
|
||||
}
|
||||
|
||||
|
||||
@@ -846,3 +846,245 @@ func TestAuthenticate_RegisterTokenError(t *testing.T) {
|
||||
t.Errorf("authenticate() token error first byte = %d, want SIGN_EABORT(%d)", pkt[0], SIGN_EABORT)
|
||||
}
|
||||
}
|
||||
|
||||
// --- handlePacket dispatch ---
|
||||
|
||||
func TestHandlePacket_DSGN(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{credErr: sql.ErrNoRows}
|
||||
session, spy := newHandlerSession(userRepo, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DSGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("user"))
|
||||
bf.WriteNullTerminatedBytes([]byte("pass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(DSGN) error: %v", err)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(DSGN) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_SIGN(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{credErr: sql.ErrNoRows}
|
||||
session, spy := newHandlerSession(userRepo, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("SIGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("user"))
|
||||
bf.WriteNullTerminatedBytes([]byte("pass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(SIGN) error: %v", err)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(SIGN) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_DLTSKEYSIGN(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{credErr: sql.ErrNoRows}
|
||||
session, spy := newHandlerSession(userRepo, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DLTSKEYSIGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("user"))
|
||||
bf.WriteNullTerminatedBytes([]byte("pass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("unk"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(DLTSKEYSIGN) error: %v", err)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(DLTSKEYSIGN) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_PS4SGN(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{psnUID: 10}
|
||||
charRepo := &mockSignCharacterRepo{characters: []character{{ID: 1, Name: "PS4Char"}}}
|
||||
sessionRepo := &mockSignSessionRepo{registerUIDTokenID: 100}
|
||||
session, spy := newHandlerSession(userRepo, charRepo, sessionRepo, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("PS4SGN:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("ps4_psn_id"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(PS4SGN) error: %v", err)
|
||||
}
|
||||
if session.client != PS4 {
|
||||
t.Errorf("handlePacket(PS4SGN) client = %d, want PS4(%d)", session.client, PS4)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(PS4SGN) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_PS3SGN(t *testing.T) {
|
||||
// PS3 with short buffer should abort
|
||||
session, spy := newHandlerSession(nil, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("PS3SGN:100"))
|
||||
bf.WriteBytes(make([]byte, 10)) // too short for PS3
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(PS3SGN) error: %v", err)
|
||||
}
|
||||
if session.client != PS3 {
|
||||
t.Errorf("handlePacket(PS3SGN) client = %d, want PS3(%d)", session.client, PS3)
|
||||
}
|
||||
pkt := spy.lastSent()
|
||||
if pkt == nil {
|
||||
t.Fatal("handlePacket(PS3SGN) sent no packet")
|
||||
}
|
||||
if len(pkt) != 1 || RespID(pkt[0]) != SIGN_EABORT {
|
||||
t.Errorf("handlePacket(PS3SGN) short buffer = %v, want SIGN_EABORT", pkt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_VITASGN(t *testing.T) {
|
||||
// VITA with short buffer should abort
|
||||
session, spy := newHandlerSession(nil, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("VITASGN:100"))
|
||||
bf.WriteBytes(make([]byte, 10)) // too short
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(VITASGN) error: %v", err)
|
||||
}
|
||||
if session.client != VITA {
|
||||
t.Errorf("handlePacket(VITASGN) client = %d, want VITA(%d)", session.client, VITA)
|
||||
}
|
||||
pkt := spy.lastSent()
|
||||
if pkt == nil {
|
||||
t.Fatal("handlePacket(VITASGN) sent no packet")
|
||||
}
|
||||
if len(pkt) != 1 || RespID(pkt[0]) != SIGN_EABORT {
|
||||
t.Errorf("handlePacket(VITASGN) short buffer = %v, want SIGN_EABORT", pkt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_WIIUSGN(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{wiiuUID: 10}
|
||||
charRepo := &mockSignCharacterRepo{characters: []character{{ID: 1, Name: "WiiUChar"}}}
|
||||
sessionRepo := &mockSignSessionRepo{registerUIDTokenID: 200}
|
||||
session, spy := newHandlerSession(userRepo, charRepo, sessionRepo, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("WIIUSGN:100"))
|
||||
bf.WriteBytes(make([]byte, 1)) // skip byte
|
||||
bf.WriteBytes(make([]byte, 64)) // wiiuKey
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(WIIUSGN) error: %v", err)
|
||||
}
|
||||
if session.client != WIIU {
|
||||
t.Errorf("handlePacket(WIIUSGN) client = %d, want WIIU(%d)", session.client, WIIU)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(WIIUSGN) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_COGLNK(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{credErr: sql.ErrNoRows}
|
||||
session, spy := newHandlerSession(userRepo, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("COGLNK:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("client_id"))
|
||||
bf.WriteNullTerminatedBytes([]byte("baduser\nbadpass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("token"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(COGLNK) error: %v", err)
|
||||
}
|
||||
pkt := spy.lastSent()
|
||||
if pkt == nil {
|
||||
t.Fatal("handlePacket(COGLNK) sent no packet")
|
||||
}
|
||||
// Invalid creds → SIGN_ECOGLINK
|
||||
if len(pkt) != 1 || RespID(pkt[0]) != SIGN_ECOGLINK {
|
||||
t.Errorf("handlePacket(COGLNK) = %v, want SIGN_ECOGLINK", pkt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_VITACOGLNK(t *testing.T) {
|
||||
userRepo := &mockSignUserRepo{credErr: sql.ErrNoRows}
|
||||
session, spy := newHandlerSession(userRepo, nil, nil, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("VITACOGLNK:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("client_id"))
|
||||
bf.WriteNullTerminatedBytes([]byte("user\npass"))
|
||||
bf.WriteNullTerminatedBytes([]byte("token"))
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(VITACOGLNK) error: %v", err)
|
||||
}
|
||||
if spy.lastSent() == nil {
|
||||
t.Fatal("handlePacket(VITACOGLNK) sent no packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_DELETE(t *testing.T) {
|
||||
charRepo := &mockSignCharacterRepo{isNew: true}
|
||||
sessionRepo := &mockSignSessionRepo{validateResult: true}
|
||||
session, spy := newHandlerSession(nil, charRepo, sessionRepo, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DELETE:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("sesstoken"))
|
||||
bf.WriteUint32(42) // characterID
|
||||
bf.WriteUint32(1) // tokenID
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(DELETE) error: %v", err)
|
||||
}
|
||||
pkt := spy.lastSent()
|
||||
if pkt == nil {
|
||||
t.Fatal("handlePacket(DELETE) sent no packet")
|
||||
}
|
||||
if pkt[0] != 0x01 {
|
||||
t.Errorf("handlePacket(DELETE) = %x, want 0x01 (DEL_SUCCESS)", pkt[0])
|
||||
}
|
||||
if !charRepo.hardDeleteCalled {
|
||||
t.Error("handlePacket(DELETE) should call HardDelete for new character")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePacket_DELETE_InvalidToken(t *testing.T) {
|
||||
sessionRepo := &mockSignSessionRepo{validateResult: false}
|
||||
session, spy := newHandlerSession(nil, nil, sessionRepo, defaultConfig())
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteNullTerminatedBytes([]byte("DELETE:100"))
|
||||
bf.WriteNullTerminatedBytes([]byte("badtoken"))
|
||||
bf.WriteUint32(42) // characterID
|
||||
bf.WriteUint32(1) // tokenID
|
||||
|
||||
err := session.handlePacket(bf.Data())
|
||||
if err != nil {
|
||||
t.Fatalf("handlePacket(DELETE) error: %v", err)
|
||||
}
|
||||
// Invalid token → deleteCharacter returns error → no packet sent
|
||||
if spy.lastSent() != nil {
|
||||
t.Error("handlePacket(DELETE) with invalid token should not send DEL_SUCCESS")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package signserver
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
cfg "erupe-ce/config"
|
||||
@@ -80,3 +81,76 @@ func TestStartSignCapture_EnabledButSignDisabled(t *testing.T) {
|
||||
}
|
||||
cleanup()
|
||||
}
|
||||
|
||||
func TestStartSignCapture_EnabledSuccess(t *testing.T) {
|
||||
outputDir := t.TempDir()
|
||||
server := &Server{
|
||||
logger: zap.NewNop(),
|
||||
erupeConfig: &cfg.Config{
|
||||
Host: "127.0.0.1",
|
||||
Sign: cfg.Sign{Port: 53312},
|
||||
Capture: cfg.CaptureOptions{
|
||||
Enabled: true,
|
||||
CaptureSign: true,
|
||||
OutputDir: outputDir,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
mc := newMockConn()
|
||||
origConn := network.NewCryptConn(mc, cfg.ZZ, nil)
|
||||
remoteAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345}
|
||||
|
||||
resultConn, cleanup := startSignCapture(server, origConn, remoteAddr)
|
||||
defer cleanup()
|
||||
|
||||
if resultConn == origConn {
|
||||
t.Error("startSignCapture() enabled should return a different (recording) conn")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartSignCapture_DefaultOutputDir(t *testing.T) {
|
||||
// Use a temp dir as working directory to avoid polluting the project
|
||||
origDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpDir := t.TempDir()
|
||||
if err := os.Chdir(tmpDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() { _ = os.Chdir(origDir) }()
|
||||
|
||||
server := &Server{
|
||||
logger: zap.NewNop(),
|
||||
erupeConfig: &cfg.Config{
|
||||
Host: "127.0.0.1",
|
||||
Sign: cfg.Sign{Port: 53312},
|
||||
Capture: cfg.CaptureOptions{
|
||||
Enabled: true,
|
||||
CaptureSign: true,
|
||||
OutputDir: "", // empty → should default to "captures"
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
mc := newMockConn()
|
||||
origConn := network.NewCryptConn(mc, cfg.ZZ, nil)
|
||||
remoteAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345}
|
||||
|
||||
resultConn, cleanup := startSignCapture(server, origConn, remoteAddr)
|
||||
defer cleanup()
|
||||
|
||||
if resultConn == origConn {
|
||||
t.Error("startSignCapture() with default dir should return recording conn")
|
||||
}
|
||||
|
||||
// Verify the "captures" directory was created
|
||||
info, err := os.Stat("captures")
|
||||
if err != nil {
|
||||
t.Fatalf("default 'captures' directory not created: %v", err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
t.Error("'captures' should be a directory")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user