mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
171 lines
6.1 KiB
Scala
171 lines
6.1 KiB
Scala
// Copyright (c) 2016 PSForever.net to present
|
|
|
|
import org.specs2.mutable._
|
|
import org.specs2.specification
|
|
import net.psforever.packet._
|
|
import net.psforever.packet.control._
|
|
import org.specs2.specification.core.Fragment
|
|
import scodec.Attempt.Successful
|
|
import scodec.bits._
|
|
import scodec.codecs.uint16
|
|
|
|
class ControlPacketTest extends Specification {
|
|
|
|
"PlanetSide control packet" in {
|
|
"ControlSync" should {
|
|
val string = hex"0007 5268 0000004D 00000052 0000004D 0000007C 0000004D 0000000000000276 0000000000000275"
|
|
|
|
"decode" in {
|
|
PacketCoding.DecodePacket(string).require match {
|
|
case ControlSync(a, b, c, d, e, f, g, h) =>
|
|
a mustEqual 21096
|
|
|
|
b mustEqual 0x4d
|
|
c mustEqual 0x52
|
|
d mustEqual 0x4d
|
|
e mustEqual 0x7c
|
|
f mustEqual 0x4d
|
|
|
|
g mustEqual 0x276
|
|
h mustEqual 0x275
|
|
case default =>
|
|
ko
|
|
}
|
|
}
|
|
|
|
"encode" in {
|
|
val encoded = PacketCoding.EncodePacket(ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275)).require
|
|
|
|
encoded.toByteVector mustEqual string
|
|
}
|
|
}
|
|
|
|
"ControlSyncResp" should {
|
|
val string = hex"0008 5268 21392D92 0000000000000276 0000000000000275 0000000000000275 0000000000000276"
|
|
|
|
"decode" in {
|
|
PacketCoding.DecodePacket(string).require match {
|
|
case ControlSyncResp(a, b, c, d, e, f) =>
|
|
a mustEqual 21096
|
|
|
|
b mustEqual 0x21392D92
|
|
c mustEqual 0x276
|
|
d mustEqual 0x275
|
|
e mustEqual 0x275
|
|
f mustEqual 0x276
|
|
case default =>
|
|
ko
|
|
}
|
|
}
|
|
|
|
"encode" in {
|
|
val encoded = PacketCoding.EncodePacket(ControlSyncResp(21096, 0x21392D92, 0x276, 0x275, 0x275, 0x276)).require
|
|
|
|
encoded.toByteVector mustEqual string
|
|
}
|
|
}
|
|
|
|
"SlottedMetaPacket" should {
|
|
val string = hex"00 09 00 00 00194302484C36563130433F" ++
|
|
hex"4C6835316369774A0000000018FABE0C" ++
|
|
hex"00000000000000000000000001000000" ++
|
|
hex"020000006B7BD8288C6469666671756F" ++
|
|
hex"7469656E740000000000440597570065" ++
|
|
hex"006C0063006F006D006500200074006F" ++
|
|
hex"00200050006C0061006E006500740053" ++
|
|
hex"0069006400650021002000018667656D" ++
|
|
hex"696E690100040001459E2540377540"
|
|
|
|
def createMetaPacket(slot : Int, subslot : Int, rest : ByteVector) = hex"00" ++
|
|
ControlPacketOpcode.codec.encode(
|
|
ControlPacketOpcode(ControlPacketOpcode.SlottedMetaPacket0.id + slot)
|
|
).require.toByteVector ++ uint16.encode(subslot).require.toByteVector ++ rest
|
|
|
|
"decode as the base slot and subslot" in {
|
|
PacketCoding.DecodePacket(string).require match {
|
|
case SlottedMetaPacket(slot, subslot, rest) =>
|
|
slot mustEqual 0
|
|
subslot mustEqual 0
|
|
rest mustEqual string.drop(4)
|
|
case default =>
|
|
ko
|
|
}
|
|
}
|
|
|
|
"decode as an arbitrary slot and subslot" in {
|
|
val maxSlots = ControlPacketOpcode.SlottedMetaPacket7.id - ControlPacketOpcode.SlottedMetaPacket0.id
|
|
|
|
// create all possible SlottedMetaPackets
|
|
Fragment.foreach(0 to maxSlots) { i =>
|
|
"slot " + i ! {
|
|
val subslot = 12323
|
|
val pkt = createMetaPacket(i, subslot, ByteVector.empty)
|
|
|
|
PacketCoding.DecodePacket(pkt).require match {
|
|
case SlottedMetaPacket(slot, subslotDecoded, rest) =>
|
|
|
|
// XXX: there isn't a simple solution to Slot0 and Slot4 be aliases of each other structurally
|
|
// This is probably best left to higher layers
|
|
//slot mustEqual i % 4 // this is seen at 0x00A3FBFA
|
|
slot mustEqual i
|
|
subslotDecoded mustEqual subslot
|
|
rest mustEqual ByteVector.empty // empty in this case
|
|
case default =>
|
|
ko
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"encode" in {
|
|
val encoded = PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x1000, ByteVector.empty)).require
|
|
val encoded2 = PacketCoding.EncodePacket(SlottedMetaPacket(3, 0xffff, hex"414243")).require
|
|
val encoded3 = PacketCoding.EncodePacket(SlottedMetaPacket(7, 0, hex"00")).require
|
|
|
|
encoded.toByteVector mustEqual createMetaPacket(0, 0x1000, ByteVector.empty)
|
|
encoded2.toByteVector mustEqual createMetaPacket(3, 0xffff, hex"414243")
|
|
encoded3.toByteVector mustEqual createMetaPacket(7, 0, hex"00")
|
|
|
|
PacketCoding.EncodePacket(SlottedMetaPacket(8, 0, hex"00")).require must throwA[AssertionError]
|
|
PacketCoding.EncodePacket(SlottedMetaPacket(-1, 0, hex"00")).require must throwA[AssertionError]
|
|
PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x10000, hex"00")).require must throwA[IllegalArgumentException]
|
|
}
|
|
}
|
|
|
|
"MultiPacketEx" should {
|
|
val strings = Vector(
|
|
hex"00",
|
|
hex"01 41",
|
|
hex"01 41" ++ hex"02 4142",
|
|
hex"fe" ++ ByteVector.fill(0xfe)(0x41),
|
|
hex"ffff00" ++ ByteVector.fill(0xff)(0x41),
|
|
hex"ff0001" ++ ByteVector.fill(0x100)(0x41),
|
|
hex"ff ffff ffff 0000" ++ ByteVector.fill(0x0000ffff)(0x41),
|
|
hex"ff ffff 0000 0100" ++ ByteVector.fill(0x00010000)(0x41)
|
|
)
|
|
|
|
val packets = Vector(
|
|
MultiPacketEx(Vector(ByteVector.empty)),
|
|
MultiPacketEx(Vector(hex"41")),
|
|
MultiPacketEx(Vector(hex"41", hex"4142")),
|
|
MultiPacketEx(Vector(ByteVector.fill(0xfe)(0x41))),
|
|
MultiPacketEx(Vector(ByteVector.fill(0xff)(0x41))),
|
|
MultiPacketEx(Vector(ByteVector.fill(0x100)(0x41))),
|
|
MultiPacketEx(Vector(ByteVector.fill(0x0000ffff)(0x41))),
|
|
MultiPacketEx(Vector(ByteVector.fill(0x00010000)(0x41)))
|
|
)
|
|
|
|
"decode" in {
|
|
Fragment.foreach(strings.indices) { i =>
|
|
"test "+i ! { MultiPacketEx.decode(strings{i}.bits).require.value mustEqual packets{i} }
|
|
}
|
|
}
|
|
|
|
"encode" in {
|
|
Fragment.foreach(packets.indices) { i =>
|
|
"test "+i ! { MultiPacketEx.encode(packets{i}).require.toByteVector mustEqual strings{i} }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |