462 lines
13 KiB
Go
462 lines
13 KiB
Go
package eq2net
|
|
|
|
import (
|
|
"bytes"
|
|
"net"
|
|
"testing"
|
|
)
|
|
|
|
func TestEQPacket(t *testing.T) {
|
|
t.Run("NewEQPacket", func(t *testing.T) {
|
|
data := []byte{0x01, 0x02, 0x03, 0x04}
|
|
packet := NewEQPacket(0x1234, data)
|
|
|
|
if packet.Opcode != 0x1234 {
|
|
t.Errorf("Expected opcode 0x1234, got 0x%04x", packet.Opcode)
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, data) {
|
|
t.Errorf("Expected buffer %v, got %v", data, packet.Buffer)
|
|
}
|
|
|
|
if packet.Version != PROTOCOL_VERSION {
|
|
t.Errorf("Expected version %d, got %d", PROTOCOL_VERSION, packet.Version)
|
|
}
|
|
})
|
|
|
|
t.Run("ParsePacket", func(t *testing.T) {
|
|
// Test single-byte opcode
|
|
data1 := []byte{0x55, 0x01, 0x02, 0x03}
|
|
packet1, err := ParsePacket(data1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse single-byte opcode: %v", err)
|
|
}
|
|
if packet1.Opcode != 0x55 {
|
|
t.Errorf("Expected opcode 0x55, got 0x%04x", packet1.Opcode)
|
|
}
|
|
if len(packet1.Buffer) != 3 {
|
|
t.Errorf("Expected buffer length 3, got %d", len(packet1.Buffer))
|
|
}
|
|
|
|
// Test two-byte opcode
|
|
data2 := []byte{0x12, 0x34, 0x01, 0x02, 0x03}
|
|
packet2, err := ParsePacket(data2)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse two-byte opcode: %v", err)
|
|
}
|
|
if packet2.Opcode != 0x1234 {
|
|
t.Errorf("Expected opcode 0x1234, got 0x%04x", packet2.Opcode)
|
|
}
|
|
if len(packet2.Buffer) != 3 {
|
|
t.Errorf("Expected buffer length 3, got %d", len(packet2.Buffer))
|
|
}
|
|
})
|
|
|
|
t.Run("Serialize", func(t *testing.T) {
|
|
// Test single-byte opcode serialization
|
|
packet1 := NewEQPacket(0x55, []byte{0x01, 0x02, 0x03})
|
|
serialized1 := packet1.Serialize()
|
|
expected1 := []byte{0x55, 0x01, 0x02, 0x03}
|
|
if !bytes.Equal(serialized1, expected1) {
|
|
t.Errorf("Expected serialized %v, got %v", expected1, serialized1)
|
|
}
|
|
|
|
// Test two-byte opcode serialization
|
|
packet2 := NewEQPacket(0x1234, []byte{0x01, 0x02, 0x03})
|
|
serialized2 := packet2.Serialize()
|
|
expected2 := []byte{0x12, 0x34, 0x01, 0x02, 0x03}
|
|
if !bytes.Equal(serialized2, expected2) {
|
|
t.Errorf("Expected serialized %v, got %v", expected2, serialized2)
|
|
}
|
|
})
|
|
|
|
t.Run("PreparePacket", func(t *testing.T) {
|
|
packet := NewEQPacket(0x1234, []byte{0x01, 0x02, 0x03})
|
|
packet.EmuOpcode = 0x5678
|
|
packet.OpcodeSize = 2
|
|
|
|
// Prepare packet for wire transmission
|
|
packet.PreparePacket(100)
|
|
|
|
if !packet.PacketPrepared {
|
|
t.Error("Expected packet to be marked as prepared")
|
|
}
|
|
|
|
// Should have headers and emulator opcode
|
|
// Format: 2 bytes sequence, 1 byte compression, then opcode
|
|
if len(packet.Buffer) < 5 {
|
|
t.Fatal("Buffer too small after preparation")
|
|
}
|
|
|
|
// Check that emulator opcode was added at correct position
|
|
// After 2-byte sequence and 1-byte compression flag
|
|
emuOpcode := uint16(packet.Buffer[4])<<8 | uint16(packet.Buffer[5])
|
|
if emuOpcode != 0x5678 {
|
|
t.Errorf("Expected emulator opcode 0x5678, got 0x%04x", emuOpcode)
|
|
}
|
|
})
|
|
|
|
t.Run("Clone", func(t *testing.T) {
|
|
original := NewEQPacket(0x1234, []byte{0x01, 0x02, 0x03})
|
|
original.SrcIP = net.ParseIP("192.168.1.1")
|
|
original.SrcPort = 9000
|
|
original.DstIP = net.ParseIP("192.168.1.2")
|
|
original.DstPort = 9001
|
|
original.EmuOpcode = 0x5678
|
|
original.OpcodeSize = 2
|
|
|
|
cloned := original.Clone()
|
|
|
|
// Verify clone has same values
|
|
if cloned.Opcode != original.Opcode {
|
|
t.Errorf("Cloned opcode mismatch: %v != %v", cloned.Opcode, original.Opcode)
|
|
}
|
|
if !bytes.Equal(cloned.Buffer, original.Buffer) {
|
|
t.Errorf("Cloned buffer mismatch: %v != %v", cloned.Buffer, original.Buffer)
|
|
}
|
|
if !cloned.SrcIP.Equal(original.SrcIP) {
|
|
t.Errorf("Cloned SrcIP mismatch: %v != %v", cloned.SrcIP, original.SrcIP)
|
|
}
|
|
if cloned.EmuOpcode != original.EmuOpcode {
|
|
t.Errorf("Cloned EmuOpcode mismatch: %v != %v", cloned.EmuOpcode, original.EmuOpcode)
|
|
}
|
|
|
|
// Verify it's a deep copy
|
|
original.Buffer[0] = 0xFF
|
|
if cloned.Buffer[0] == 0xFF {
|
|
t.Error("Clone shares buffer with original")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestProtocolPacket(t *testing.T) {
|
|
t.Run("NewProtocolPacket", func(t *testing.T) {
|
|
data := []byte{0x01, 0x02, 0x03}
|
|
packet := NewProtocolPacket(OP_Packet, data)
|
|
|
|
if packet.Opcode != OP_Packet {
|
|
t.Errorf("Expected opcode OP_Packet, got 0x%04x", packet.Opcode)
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, data) {
|
|
t.Errorf("Expected buffer %v, got %v", data, packet.Buffer)
|
|
}
|
|
})
|
|
|
|
t.Run("Compression", func(t *testing.T) {
|
|
// Test large packet compression (zlib)
|
|
largeData := make([]byte, 100)
|
|
for i := range largeData {
|
|
largeData[i] = byte(i % 256)
|
|
}
|
|
|
|
packet := NewProtocolPacket(OP_Packet, largeData)
|
|
originalLen := len(packet.Buffer)
|
|
|
|
// Compress
|
|
err := packet.Compress()
|
|
if err != nil {
|
|
t.Fatalf("Failed to compress: %v", err)
|
|
}
|
|
|
|
if !packet.Compressed {
|
|
t.Error("Packet should be marked as compressed")
|
|
}
|
|
|
|
if packet.Buffer[0] != 0x5a {
|
|
t.Errorf("Expected zlib compression flag 0x5a, got 0x%02x", packet.Buffer[0])
|
|
}
|
|
|
|
// Decompress
|
|
err = packet.Decompress()
|
|
if err != nil {
|
|
t.Fatalf("Failed to decompress: %v", err)
|
|
}
|
|
|
|
if packet.Compressed {
|
|
t.Error("Packet should not be marked as compressed after decompression")
|
|
}
|
|
|
|
if len(packet.Buffer) != originalLen {
|
|
t.Errorf("Decompressed size mismatch: expected %d, got %d", originalLen, len(packet.Buffer))
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, largeData) {
|
|
t.Error("Decompressed data does not match original")
|
|
}
|
|
})
|
|
|
|
t.Run("SimpleEncoding", func(t *testing.T) {
|
|
// Test small packet encoding
|
|
smallData := []byte{0x01, 0x02, 0x03}
|
|
packet := NewProtocolPacket(OP_Packet, smallData)
|
|
|
|
// Compress (should use simple encoding)
|
|
err := packet.Compress()
|
|
if err != nil {
|
|
t.Fatalf("Failed to compress: %v", err)
|
|
}
|
|
|
|
if !packet.Compressed {
|
|
t.Error("Packet should be marked as compressed")
|
|
}
|
|
|
|
if packet.Buffer[0] != 0xa5 {
|
|
t.Errorf("Expected simple encoding flag 0xa5, got 0x%02x", packet.Buffer[0])
|
|
}
|
|
|
|
// Decompress
|
|
err = packet.Decompress()
|
|
if err != nil {
|
|
t.Fatalf("Failed to decompress: %v", err)
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, smallData) {
|
|
t.Error("Decompressed data does not match original")
|
|
}
|
|
})
|
|
|
|
t.Run("Combine", func(t *testing.T) {
|
|
packet1 := NewProtocolPacket(OP_Packet, []byte{0x01, 0x02})
|
|
packet2 := NewProtocolPacket(OP_Ack, []byte{0x03, 0x04})
|
|
|
|
// Combine packets
|
|
success := packet1.Combine(packet2)
|
|
if !success {
|
|
t.Fatal("Failed to combine packets")
|
|
}
|
|
|
|
if packet1.Opcode != OP_Combined {
|
|
t.Errorf("Expected combined opcode, got 0x%04x", packet1.Opcode)
|
|
}
|
|
|
|
if len(packet1.SubPackets) != 2 {
|
|
t.Errorf("Expected 2 sub-packets, got %d", len(packet1.SubPackets))
|
|
}
|
|
})
|
|
|
|
t.Run("ExtractSubPackets", func(t *testing.T) {
|
|
// Create combined packet manually
|
|
packet1Data := []byte{0x00, 0x09, 0x01, 0x02} // OP_Packet with data
|
|
packet2Data := []byte{0x00, 0x15, 0x03, 0x04} // OP_Ack with data
|
|
|
|
combinedBuffer := []byte{
|
|
byte(len(packet1Data)), // Size of first packet
|
|
}
|
|
combinedBuffer = append(combinedBuffer, packet1Data...)
|
|
combinedBuffer = append(combinedBuffer, byte(len(packet2Data))) // Size of second packet
|
|
combinedBuffer = append(combinedBuffer, packet2Data...)
|
|
|
|
combined := NewProtocolPacket(OP_Combined, combinedBuffer)
|
|
|
|
// Extract sub-packets
|
|
subPackets, err := combined.ExtractSubPackets()
|
|
if err != nil {
|
|
t.Fatalf("Failed to extract sub-packets: %v", err)
|
|
}
|
|
|
|
if len(subPackets) != 2 {
|
|
t.Fatalf("Expected 2 sub-packets, got %d", len(subPackets))
|
|
}
|
|
|
|
if subPackets[0].Opcode != OP_Packet {
|
|
t.Errorf("Expected first packet opcode OP_Packet, got 0x%04x", subPackets[0].Opcode)
|
|
}
|
|
|
|
if subPackets[1].Opcode != OP_Ack {
|
|
t.Errorf("Expected second packet opcode OP_Ack, got 0x%04x", subPackets[1].Opcode)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestLoginPacket(t *testing.T) {
|
|
t.Run("NewLoginPacket", func(t *testing.T) {
|
|
data := []byte{0x01, 0x02, 0x03}
|
|
packet := NewLoginPacket(LOP_LoginRequestMsg, data)
|
|
|
|
if packet.LoginEmuOpcode != LOP_LoginRequestMsg {
|
|
t.Errorf("Expected opcode LOP_LoginRequestMsg, got %v", packet.LoginEmuOpcode)
|
|
}
|
|
|
|
if packet.OpcodeSize != 1 {
|
|
t.Errorf("Expected opcode size 1, got %d", packet.OpcodeSize)
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, data) {
|
|
t.Errorf("Expected buffer %v, got %v", data, packet.Buffer)
|
|
}
|
|
})
|
|
|
|
t.Run("ParseLoginPacket", func(t *testing.T) {
|
|
data := []byte{byte(LOP_LoginRequestMsg), 0x01, 0x02, 0x03}
|
|
packet, err := ParseLoginPacket(data)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse login packet: %v", err)
|
|
}
|
|
|
|
if packet.LoginEmuOpcode != LOP_LoginRequestMsg {
|
|
t.Errorf("Expected opcode LOP_LoginRequestMsg, got %v", packet.LoginEmuOpcode)
|
|
}
|
|
|
|
if len(packet.Buffer) != 3 {
|
|
t.Errorf("Expected buffer length 3, got %d", len(packet.Buffer))
|
|
}
|
|
})
|
|
|
|
t.Run("SerializeLogin", func(t *testing.T) {
|
|
packet := NewLoginPacket(LOP_WorldListMsg, []byte{0x01, 0x02})
|
|
serialized := packet.SerializeLogin()
|
|
|
|
expected := []byte{byte(LOP_WorldListMsg), 0x01, 0x02}
|
|
if !bytes.Equal(serialized, expected) {
|
|
t.Errorf("Expected serialized %v, got %v", expected, serialized)
|
|
}
|
|
})
|
|
|
|
t.Run("ConvertToProtocolPacket", func(t *testing.T) {
|
|
loginPacket := NewLoginPacket(LOP_LoginReplyMsg, []byte{0x01, 0x02})
|
|
loginPacket.SrcIP = net.ParseIP("192.168.1.1")
|
|
loginPacket.DstIP = net.ParseIP("192.168.1.2")
|
|
|
|
protoPacket := loginPacket.ConvertToProtocolPacket()
|
|
|
|
if protoPacket.Opcode != OP_Packet {
|
|
t.Errorf("Expected protocol opcode OP_Packet, got 0x%04x", protoPacket.Opcode)
|
|
}
|
|
|
|
// Should contain serialized login packet
|
|
expectedData := loginPacket.SerializeLogin()
|
|
if !bytes.Equal(protoPacket.Buffer, expectedData) {
|
|
t.Errorf("Protocol packet buffer mismatch")
|
|
}
|
|
|
|
// Should preserve network info
|
|
if !protoPacket.SrcIP.Equal(loginPacket.SrcIP) {
|
|
t.Errorf("Source IP not preserved")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGamePacket(t *testing.T) {
|
|
t.Run("NewGamePacket", func(t *testing.T) {
|
|
data := []byte{0x01, 0x02, 0x03}
|
|
packet := NewGamePacket(GOP_LoginReplyMsg, data)
|
|
|
|
if packet.GameEmuOpcode != GOP_LoginReplyMsg {
|
|
t.Errorf("Expected opcode GOP_LoginReplyMsg, got %v", packet.GameEmuOpcode)
|
|
}
|
|
|
|
if packet.OpcodeSize != 2 {
|
|
t.Errorf("Expected opcode size 2, got %d", packet.OpcodeSize)
|
|
}
|
|
|
|
if !bytes.Equal(packet.Buffer, data) {
|
|
t.Errorf("Expected buffer %v, got %v", data, packet.Buffer)
|
|
}
|
|
})
|
|
|
|
t.Run("ParseGamePacket", func(t *testing.T) {
|
|
// Test normal 2-byte opcode
|
|
opcode := uint16(GOP_ZoneInfoMsg)
|
|
data1 := []byte{byte(opcode >> 8), byte(opcode), 0x01, 0x02}
|
|
packet1, err := ParseGamePacket(data1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse game packet: %v", err)
|
|
}
|
|
|
|
if packet1.GameEmuOpcode != GOP_ZoneInfoMsg {
|
|
t.Errorf("Expected opcode GOP_ZoneInfoMsg, got %v", packet1.GameEmuOpcode)
|
|
}
|
|
|
|
// Test special encoding (low byte = 0x00)
|
|
data2 := []byte{0x00, 0x12, 0x00, 0x01, 0x02} // Extra 0x00 prefix
|
|
packet2, err := ParseGamePacket(data2)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse special encoded packet: %v", err)
|
|
}
|
|
|
|
if packet2.GameEmuOpcode != 0x1200 {
|
|
t.Errorf("Expected opcode 0x1200, got 0x%04x", packet2.GameEmuOpcode)
|
|
}
|
|
})
|
|
|
|
t.Run("SerializeGame", func(t *testing.T) {
|
|
// Test normal opcode
|
|
packet1 := NewGamePacket(GOP_MOTDMsg, []byte{0x01, 0x02})
|
|
serialized1 := packet1.SerializeGame()
|
|
|
|
opcode1 := uint16(GOP_MOTDMsg)
|
|
expected1 := []byte{byte(opcode1 >> 8), byte(opcode1), 0x01, 0x02}
|
|
if !bytes.Equal(serialized1, expected1) {
|
|
t.Errorf("Expected serialized %v, got %v", expected1, serialized1)
|
|
}
|
|
|
|
// Test special encoding (low byte = 0x00)
|
|
packet2 := NewGamePacket(0x1200, []byte{0x01, 0x02})
|
|
serialized2 := packet2.SerializeGame()
|
|
|
|
expected2 := []byte{0x00, 0x12, 0x00, 0x01, 0x02} // Extra 0x00 prefix
|
|
if !bytes.Equal(serialized2, expected2) {
|
|
t.Errorf("Expected special encoded %v, got %v", expected2, serialized2)
|
|
}
|
|
})
|
|
|
|
t.Run("CombineGamePackets", func(t *testing.T) {
|
|
packet1 := NewGamePacket(GOP_UpdateDataMsg, []byte{0x01})
|
|
packet2 := NewGamePacket(GOP_UpdateSpawnMsg, []byte{0x02})
|
|
packet3 := NewGamePacket(GOP_UpdateTimeMsg, []byte{0x03})
|
|
|
|
combined := CombineGamePackets([]*GamePacket{packet1, packet2, packet3})
|
|
|
|
if combined == nil {
|
|
t.Fatal("Failed to combine game packets")
|
|
}
|
|
|
|
if combined.Opcode != OP_AppCombined {
|
|
t.Errorf("Expected opcode OP_AppCombined, got 0x%04x", combined.Opcode)
|
|
}
|
|
|
|
// Verify buffer contains size-prefixed packets
|
|
if len(combined.Buffer) < 3 {
|
|
t.Error("Combined buffer too small")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOpcodeNames(t *testing.T) {
|
|
t.Run("GetOpcodeName", func(t *testing.T) {
|
|
name := GetOpcodeName(OP_SessionRequest)
|
|
if name != "OP_SessionRequest" {
|
|
t.Errorf("Expected 'OP_SessionRequest', got '%s'", name)
|
|
}
|
|
|
|
unknownName := GetOpcodeName(0xFFFF)
|
|
if unknownName != "Unknown(65535)" {
|
|
t.Errorf("Expected 'Unknown(65535)', got '%s'", unknownName)
|
|
}
|
|
})
|
|
|
|
t.Run("GetLoginOpcodeName", func(t *testing.T) {
|
|
name := GetLoginOpcodeName(LOP_LoginRequestMsg)
|
|
if name != "LOP_LoginRequestMsg" {
|
|
t.Errorf("Expected 'LOP_LoginRequestMsg', got '%s'", name)
|
|
}
|
|
|
|
unknownName := GetLoginOpcodeName(0xFFFF)
|
|
if !bytes.Contains([]byte(unknownName), []byte("Unknown")) {
|
|
t.Errorf("Expected Unknown opcode name, got '%s'", unknownName)
|
|
}
|
|
})
|
|
|
|
t.Run("GetGameOpcodeName", func(t *testing.T) {
|
|
name := GetGameOpcodeName(GOP_ZoneInfoMsg)
|
|
if name != "GOP_ZoneInfoMsg" {
|
|
t.Errorf("Expected 'GOP_ZoneInfoMsg', got '%s'", name)
|
|
}
|
|
|
|
unknownName := GetGameOpcodeName(0xFFFF)
|
|
if !bytes.Contains([]byte(unknownName), []byte("Unknown")) {
|
|
t.Errorf("Expected Unknown opcode name, got '%s'", unknownName)
|
|
}
|
|
})
|
|
} |