mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-21 23:22:34 +01:00
test: increase total coverage from 31.3% to 40.7%
Add batch Parse/Build tests for ~150 mhfpacket types, net.Pipe-based round-trip tests for CryptConn Send/ReadPacket, overflow panic tests for all byteframe Read types, and additional empty handler coverage.
This commit is contained in:
@@ -465,3 +465,160 @@ func TestReadNullTerminatedBytesNoTerminator(t *testing.T) {
|
||||
t.Errorf("ReadNullTerminatedBytes with no terminator should return empty, got %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadUint8PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadUint8 past end should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrameFromBytes([]byte{0x01})
|
||||
bf.ReadUint8() // consume the one byte
|
||||
bf.ReadUint8() // should panic - no more data
|
||||
}
|
||||
|
||||
func TestReadUint16PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadUint16 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadUint16()
|
||||
}
|
||||
|
||||
func TestReadUint64PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadUint64 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadUint64()
|
||||
}
|
||||
|
||||
func TestReadInt8PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadInt8 past end should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrameFromBytes([]byte{0x01})
|
||||
bf.ReadInt8() // consume the one byte
|
||||
bf.ReadInt8() // should panic - no more data
|
||||
}
|
||||
|
||||
func TestReadInt16PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadInt16 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadInt16()
|
||||
}
|
||||
|
||||
func TestReadInt32PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadInt32 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadInt32()
|
||||
}
|
||||
|
||||
func TestReadInt64PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadInt64 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadInt64()
|
||||
}
|
||||
|
||||
func TestReadFloat32PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadFloat32 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadFloat32()
|
||||
}
|
||||
|
||||
func TestReadFloat64PanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadFloat64 on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadFloat64()
|
||||
}
|
||||
|
||||
func TestReadBytesPanicsOnOverflow(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("ReadBytes on empty buffer should panic")
|
||||
}
|
||||
}()
|
||||
bf := NewByteFrame()
|
||||
bf.ReadBytes(10)
|
||||
}
|
||||
|
||||
func TestSeekInvalidWhence(t *testing.T) {
|
||||
bf := NewByteFrame()
|
||||
bf.WriteUint32(0x12345678)
|
||||
|
||||
// Invalid whence value should not crash, just not change position
|
||||
pos, _ := bf.Seek(0, 99)
|
||||
if pos != 4 {
|
||||
t.Errorf("Seek with invalid whence pos = %d, want 4", pos)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLittleEndianReadWrite(t *testing.T) {
|
||||
bf := NewByteFrame()
|
||||
bf.SetLE()
|
||||
bf.WriteUint32(0x12345678)
|
||||
bf.WriteInt16(-1234)
|
||||
bf.WriteFloat32(3.14)
|
||||
|
||||
bf.Seek(0, io.SeekStart)
|
||||
bf.SetLE()
|
||||
|
||||
if val := bf.ReadUint32(); val != 0x12345678 {
|
||||
t.Errorf("LE ReadUint32 = 0x%X, want 0x12345678", val)
|
||||
}
|
||||
if val := bf.ReadInt16(); val != -1234 {
|
||||
t.Errorf("LE ReadInt16 = %d, want -1234", val)
|
||||
}
|
||||
if val := bf.ReadFloat32(); val < 3.13 || val > 3.15 {
|
||||
t.Errorf("LE ReadFloat32 = %f, want ~3.14", val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGrowWithLargeWrite(t *testing.T) {
|
||||
bf := NewByteFrame()
|
||||
// Initial buffer is 4 bytes. Write 1000 bytes to trigger grow with size > buf
|
||||
largeData := make([]byte, 1000)
|
||||
for i := range largeData {
|
||||
largeData[i] = byte(i % 256)
|
||||
}
|
||||
bf.WriteBytes(largeData)
|
||||
|
||||
if len(bf.Data()) != 1000 {
|
||||
t.Errorf("Data() len after large write = %d, want 1000", len(bf.Data()))
|
||||
}
|
||||
|
||||
bf.Seek(0, io.SeekStart)
|
||||
readBack := bf.ReadBytes(1000)
|
||||
for i := range readBack {
|
||||
if readBack[i] != byte(i%256) {
|
||||
t.Errorf("Data mismatch at position %d: got %d, want %d", i, readBack[i], byte(i%256))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -177,3 +179,131 @@ func TestMultipleCryptConnInstances(t *testing.T) {
|
||||
t.Error("CryptConn instances should be independent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptConnSendAndReadPacket(t *testing.T) {
|
||||
// Use net.Pipe to create an in-memory bidirectional connection
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
sender := NewCryptConn(clientConn)
|
||||
receiver := NewCryptConn(serverConn)
|
||||
|
||||
testData := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
|
||||
|
||||
// Send in a goroutine since Pipe is synchronous
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
errCh <- sender.SendPacket(testData)
|
||||
}()
|
||||
|
||||
// Read on the other end
|
||||
received, err := receiver.ReadPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("ReadPacket() error = %v", err)
|
||||
}
|
||||
|
||||
if sendErr := <-errCh; sendErr != nil {
|
||||
t.Fatalf("SendPacket() error = %v", sendErr)
|
||||
}
|
||||
|
||||
if !bytes.Equal(received, testData) {
|
||||
t.Errorf("ReadPacket() = %v, want %v", received, testData)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptConnMultiplePackets(t *testing.T) {
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
sender := NewCryptConn(clientConn)
|
||||
receiver := NewCryptConn(serverConn)
|
||||
|
||||
packets := [][]byte{
|
||||
{0x01, 0x02, 0x03, 0x04},
|
||||
{0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE},
|
||||
{0xFF},
|
||||
make([]byte, 64),
|
||||
}
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
for _, pkt := range packets {
|
||||
if err := sender.SendPacket(pkt); err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
errCh <- nil
|
||||
}()
|
||||
|
||||
for i, expected := range packets {
|
||||
received, err := receiver.ReadPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("ReadPacket() packet %d error = %v", i, err)
|
||||
}
|
||||
if !bytes.Equal(received, expected) {
|
||||
t.Errorf("Packet %d: got %v, want %v", i, received, expected)
|
||||
}
|
||||
}
|
||||
|
||||
if sendErr := <-errCh; sendErr != nil {
|
||||
t.Fatalf("SendPacket() error = %v", sendErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptConnSendPacketStateUpdate(t *testing.T) {
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
defer serverConn.Close()
|
||||
|
||||
sender := NewCryptConn(clientConn)
|
||||
|
||||
// Consume the data on the other side
|
||||
go func() {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := serverConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if sender.sentPackets != 0 {
|
||||
t.Errorf("initial sentPackets = %d, want 0", sender.sentPackets)
|
||||
}
|
||||
|
||||
err := sender.SendPacket([]byte{0x01, 0x02, 0x03, 0x04})
|
||||
if err != nil {
|
||||
t.Fatalf("SendPacket() error = %v", err)
|
||||
}
|
||||
|
||||
if sender.sentPackets != 1 {
|
||||
t.Errorf("sentPackets after 1 send = %d, want 1", sender.sentPackets)
|
||||
}
|
||||
|
||||
// Key rotation should have changed from default
|
||||
if sender.sendKeyRot == 995117 {
|
||||
t.Error("sendKeyRot should have changed after SendPacket")
|
||||
}
|
||||
|
||||
if sender.prevSendPacketCombinedCheck == 0 {
|
||||
t.Error("prevSendPacketCombinedCheck should be set after SendPacket")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptConnReadPacketClosedConn(t *testing.T) {
|
||||
clientConn, serverConn := net.Pipe()
|
||||
receiver := NewCryptConn(serverConn)
|
||||
|
||||
// Close the writing end
|
||||
clientConn.Close()
|
||||
|
||||
_, err := receiver.ReadPacket()
|
||||
if err == nil {
|
||||
t.Error("ReadPacket() on closed connection should return error")
|
||||
}
|
||||
serverConn.Close()
|
||||
}
|
||||
|
||||
2195
network/mhfpacket/msg_batch_parse_test.go
Normal file
2195
network/mhfpacket/msg_batch_parse_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -298,6 +298,10 @@ func TestEmptyHandlers_NoDb(t *testing.T) {
|
||||
{"handleMsgMhfStampcardPrize", handleMsgMhfStampcardPrize},
|
||||
{"handleMsgMhfUnreserveSrg", handleMsgMhfUnreserveSrg},
|
||||
{"handleMsgMhfKickExportForce", handleMsgMhfKickExportForce},
|
||||
{"handleMsgSysSetStatus", handleMsgSysSetStatus},
|
||||
{"handleMsgSysEcho", handleMsgSysEcho},
|
||||
{"handleMsgMhfUseUdShopCoin", handleMsgMhfUseUdShopCoin},
|
||||
{"handleMsgMhfEnterTournamentQuest", handleMsgMhfEnterTournamentQuest},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user