moving ActorTest-style tests from common to pslogin (#300)

This commit is contained in:
Fate-JH 2019-12-13 03:00:55 -05:00 committed by GitHub
parent 1b26396bb3
commit e4d607533f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 343 additions and 331 deletions

View file

@ -1,19 +1,10 @@
// Copyright (c) 2017 PSForever
package objects
import akka.actor.{ActorRef, ActorSystem, Props}
import akka.testkit.TestProbe
import base.ActorTest
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
import net.psforever.objects.serverobject.structures.StructureType
import net.psforever.objects.{Avatar, GlobalDefinitions, Player, Vehicle}
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types._
import akka.actor.ActorRef
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.GlobalDefinitions
import org.specs2.mutable.Specification
import services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._
class VehicleSpawnPadTest extends Specification {
"VehicleSpawnPadDefinition" should {
@ -30,230 +21,3 @@ class VehicleSpawnPadTest extends Specification {
}
}
}
class VehicleSpawnControl1Test extends ActorTest {
"VehicleSpawnControl" should {
"construct" in {
val obj = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "mb_pad_creation")
assert(obj.Actor != ActorRef.noSender)
}
}
}
class VehicleSpawnControl2Test extends ActorTest {
"VehicleSpawnControl" should {
"complete a vehicle order" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
vehicle.Seats(0).Occupant = player
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.PlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideStart])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
//if we move the vehicle away from the pad, we should receive a ResetSpawnPad message
//that means that the first order has cleared and the spawn pad is now waiting for additional orders
vehicle.Position = Vector3(12,0,0)
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ResetSpawnPad])
}
}
}
class VehicleSpawnControl3Test extends ActorTest {
"VehicleSpawnControl" should {
"block the second vehicle order until the first is completed" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
//we can recycle the vehicle and the player for each order
val probe = new TestProbe(system, "zone-events")
val player2 = Player(Avatar("test2", player.Faction, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
player2.Continent = zone.Id
player2.Spawn
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //first order
pad.Actor ! VehicleSpawnPad.VehicleOrder(player2, vehicle) //second order (vehicle shared)
assert(probe.receiveOne(1 seconds) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Queue, _) => true
case _ => false
})
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
vehicle.Seats(0).Occupant = player
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.PlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideStart])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
//if we move the vehicle away from the pad, we should receive a second ConcealPlayer message
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
player.VehicleSeated = None //since shared between orders, as necessary
vehicle.Seats(0).Occupant = None
vehicle.Position = Vector3(12,0,0)
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ResetSpawnPad])
probe.expectMsgClass(3 seconds, classOf[VehicleSpawnPad.ConcealPlayer])
}
}
}
class VehicleSpawnControl4Test extends ActorTest {
"VehicleSpawnControl" should {
"clean up the vehicle if the driver-to-be is on the wrong continent" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
player.Continent = "problem" //problem
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DisposeVehicle])
probe.expectNoMsg(5 seconds)
}
}
}
class VehicleSpawnControl5Test extends ActorTest() {
"VehicleSpawnControl" should {
"abandon a destroyed vehicle on the spawn pad (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
vehicle.Health = 0 //problem
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
class VehicleSpawnControl6Test extends ActorTest() {
"VehicleSpawnControl" should {
"abandon a vehicle on the spawn pad if driver is unfit to drive (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
player.Die
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
class VehicleSpawnControl7Test extends ActorTest {
"VehicleSpawnControl" should {
"abandon a vehicle on the spawn pad if driver is unfit to drive (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
player.ExoSuit = ExoSuitType.MAX
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
object VehicleSpawnPadControlTest {
import net.psforever.objects.zones.ZoneMap
private val map = new ZoneMap("test-map")
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Vehicle, Player, VehicleSpawnPad, Zone) = {
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.LimitedNumberSource
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.zones.ZoneActor
import net.psforever.objects.Tool
import net.psforever.types.CharacterGender
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
val weapon = vehicle.WeaponControlledFromSeat(1).get.asInstanceOf[Tool]
val zone = new Zone("test-zone", map, 0) {
override def SetupNumberPools() = {
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(5))
guid.AddPool("test-pool", (0 to 2).toList)
//do not do this under normal conditions
guid.register(vehicle, "test-pool")
guid.register(weapon, "test-pool")
guid.register(weapon.AmmoSlot.Box, "test-pool")
GUID(guid)
}
}
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), s"test-zone-${System.nanoTime()}")
zone.Actor ! Zone.Init()
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), s"vehicle-control-${System.nanoTime()}")
val pad = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
pad.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], pad), s"test-pad-${System.nanoTime()}")
pad.Owner = new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
pad.Owner.Faction = faction
val player = Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
player.GUID = PlanetSideGUID(10)
player.Continent = zone.Id
player.Spawn
//note: pad and vehicle are both at Vector3(1,0,0) so they count as blocking
pad.Position = Vector3(1,0,0)
vehicle.Position = Vector3(1,0,0)
(vehicle, player, pad, zone)
}
}

View file

@ -1,67 +0,0 @@
// Copyright (c) 2017 PSForever
import akka.actor.{ActorRef, ActorSystem, MDCContextAware}
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
import com.typesafe.config.ConfigFactory
import net.psforever.packet.{ControlPacket, GamePacket}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
import org.specs2.specification.Scope
abstract class ActorTest(sys : ActorSystem = ActorSystem("system", ConfigFactory.parseMap(ActorTest.LoggingConfig)))
extends TestKit(sys) with Scope with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
override def afterAll {
TestKit.shutdownActorSystem(system)
}
}
object ActorTest {
import scala.collection.JavaConverters._
private val LoggingConfig = Map(
"akka.loggers" -> List("akka.testkit.TestEventListener").asJava,
"akka.loglevel" -> "OFF",
"akka.stdout-loglevel" -> "OFF",
"akka.log-dead-letters" -> "OFF"
).asJava
final case class MDCGamePacket(packet : GamePacket)
final case class MDCControlPacket(packet : ControlPacket)
class MDCTestProbe(probe : TestProbe) extends MDCContextAware {
/*
The way this test mediator works needs to be explained.
MDCContextAware objects initialize themselves in a chain of ActorRefs defined in the HelloFriend message.
As the iterator is consumed, it produces a right-neighbor (r-neighbor) that is much further along the chain.
The HelloFriend is passed to that r-neighbor and that is how subsequent neighbors are initialized and chained.
MDCContextAware objects consume and produce internal messages called MdcMsg that wrap around the payload.
Normally inaccessible from the outside, the payload is unwrapped within the standard receive PartialFunction.
By interacting with a TestProbe constructor param, information that would be concealed by MdcMsg can be polled.
The l-neighbor of the MDCContextAware is the system of the base.ActorTest TestKit.
The r-neighbor of the MDCContextAware is this MDCTestProbe and, indirectly, the TestProbe that was interjected.
Pass l-input into the MDCContextAware itself.
The r-output is a normal message that can be polled on that TestProbe.
Pass r-input into this MDCTestProbe directly.
The l-output is an MdcMsg that can be treated just as r-output, sending it to this Actor and polling the TestProbe.
*/
private var left : ActorRef = ActorRef.noSender
def receive : Receive = {
case msg @ HelloFriend(_, _) =>
left = sender()
probe.ref ! msg
case MDCGamePacket(msg) =>
left ! msg
case MDCControlPacket(msg) =>
left ! msg
case msg =>
left ! msg
probe.ref ! msg
}
}
}

View file

@ -0,0 +1,46 @@
// Copyright (c) 2019 PSForever
import akka.actor.{ActorRef, MDCContextAware}
import akka.testkit.TestProbe
import net.psforever.packet.{ControlPacket, GamePacket}
final case class MDCGamePacket(packet : GamePacket)
final case class MDCControlPacket(packet : ControlPacket)
class MDCTestProbe(probe : TestProbe) extends MDCContextAware {
/*
The way this test mediator works needs to be explained.
MDCContextAware objects initialize themselves in a chain of ActorRefs defined in the HelloFriend message.
As the iterator is consumed, it produces a right-neighbor (r-neighbor) that is much further along the chain.
The HelloFriend is passed to that r-neighbor and that is how subsequent neighbors are initialized and chained.
MDCContextAware objects consume and produce internal messages called MdcMsg that wrap around the payload.
Normally inaccessible from the outside, the payload is unwrapped within the standard receive PartialFunction.
By interacting with a TestProbe constructor param, information that would be concealed by MdcMsg can be polled.
The l-neighbor of the MDCContextAware is the system of the base.actor.base.ActorTest TestKit.
The r-neighbor of the MDCContextAware is this MDCTestProbe and, indirectly, the TestProbe that was interjected.
Pass l-input into the MDCContextAware itself.
The r-output is a normal message that can be polled on that TestProbe.
Pass r-input into this MDCTestProbe directly.
The l-output is an MdcMsg that can be treated just as r-output, sending it to this Actor and polling the TestProbe.
*/
private var left : ActorRef = ActorRef.noSender
def receive : Receive = {
case msg @ HelloFriend(_, _) =>
left = sender()
probe.ref ! msg
case MDCGamePacket(msg) =>
left ! msg
case MDCControlPacket(msg) =>
left ! msg
case msg =>
left ! msg
probe.ref ! msg
}
}

View file

@ -1,5 +1,5 @@
// Copyright (c) 2017 PSForever
import actor.base.ActorTest
import akka.actor.{ActorRef, Props}
import akka.testkit.TestProbe
import net.psforever.packet.control.{ControlSync, MultiPacketBundle, SlottedMetaPacket}
@ -36,7 +36,7 @@ class PacketCodingActor3Test extends ActorTest {
"PacketCodingActor" should {
"initialize (an r-neighbor)" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
val iter = List(probe2).iterator
val msg = HelloFriend(135, iter)
@ -56,12 +56,12 @@ class PacketCodingActor4Test extends ActorTest {
"PacketCodingActor" should {
"translate r-originating game packet into l-facing hexadecimal data" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
val msg = ActorTest.MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj))
val msg = MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj))
probe2 ! msg
val reply1 = receiveOne(300 milli) //we get a MdcMsg message back
probe2 ! reply1 //by feeding the MdcMsg into the actor, we get normal output on the probe
@ -77,7 +77,7 @@ class PacketCodingActor5Test extends ActorTest {
"PacketCodingActor" should {
"translate l-originating hexadecimal data into r-facing game packet" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -100,7 +100,7 @@ class PacketCodingActor6Test extends ActorTest {
"PacketCodingActor" should {
"permit l-originating game packet to pass through as an r-facing game packet" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -119,12 +119,12 @@ class PacketCodingActor7Test extends ActorTest {
"PacketCodingActor" should {
"translate r-originating control packet into l-facing hexadecimal data" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
val msg = ActorTest.MDCControlPacket(PacketCoding.CreateControlPacket(string_obj))
val msg = MDCControlPacket(PacketCoding.CreateControlPacket(string_obj))
probe2 ! msg
val reply1 = receiveOne(300 milli) //we get a MdcMsg message back
probe2 ! reply1 //by feeding the MdcMsg into the actor, we get normal output on the probe
@ -140,7 +140,7 @@ class PacketCodingActor8Test extends ActorTest {
"PacketCodingActor" should {
"translate l-originating hexadecimal data into r-facing control packet" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -163,7 +163,7 @@ class PacketCodingActor9Test extends ActorTest {
"PacketCodingActor" should {
"permit l-originating control packet to pass through as an r-facing control packet" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -179,7 +179,7 @@ class PacketCodingActorATest extends ActorTest {
"PacketCodingActor" should {
"permit l-originating unhandled message to pass through as an r-facing unhandled message" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -194,7 +194,7 @@ class PacketCodingActorBTest extends ActorTest {
"PacketCodingActor" should {
"permit r-originating unhandled message to pass through as an l-facing unhandled message" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -213,7 +213,7 @@ class PacketCodingActorCTest extends ActorTest {
"PacketCodingActor" should {
"should split r-originating hexadecimal data if it is larger than the MTU limit" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -353,12 +353,12 @@ class PacketCodingActorDTest extends ActorTest {
"PacketCodingActor" should {
"should split r-originating game packet if it is larger than the MTU limit" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
val msg = ActorTest.MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj))
val msg = MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj))
probe2 ! msg
receiveN(4)
}
@ -373,7 +373,7 @@ class PacketCodingActorETest extends ActorTest {
val string_obj2 = GamePacket(GamePacketOpcode.PlayerStateMessageUpstream, 0, PlayerStateMessageUpstream(PlanetSideGUID(1256),Vector3(3077.0469f,4734.258f,56.390625f),Some(Vector3(5.5f,1.1875f,0.0f)),36.5625f,-2.8125f,0.0f,867,0,false,false,false,false,168,0))
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -394,7 +394,7 @@ class PacketCodingActorFTest extends ActorTest {
val string_obj = GamePacket(GamePacketOpcode.GenericObjectStateMsg, 0, GenericObjectStateMsg(PlanetSideGUID(242), 16))
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -415,7 +415,7 @@ class PacketCodingActorGTest extends ActorTest {
val string_obj = GamePacket(GamePacketOpcode.GenericObjectStateMsg, 0, GenericObjectStateMsg(PlanetSideGUID(242), 16))
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -437,7 +437,7 @@ class PacketCodingActorHTest extends ActorTest {
val string_obj2 = GamePacket(GamePacketOpcode.ObjectDeleteMessage, 0, ObjectDeleteMessage(PlanetSideGUID(1105), 2))
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -491,7 +491,7 @@ class PacketCodingActorITest extends ActorTest {
"PacketCodingActor" should {
"bundle an r-originating packet into an l-facing SlottedMetaPacket byte stream data (SlottedMetaPacket)" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -525,7 +525,7 @@ class PacketCodingActorJTest extends ActorTest {
val string_hex = hex"00090000001904194f044004195104400419530440"
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -653,7 +653,7 @@ class PacketCodingActorKTest extends ActorTest {
val pkt = MultiPacketBundle(list)
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume
@ -804,7 +804,7 @@ class PacketCodingActorLTest extends ActorTest {
"PacketCodingActor" should {
"split, rather than bundle, r-originating packets into a number of MTU-acceptable l-facing byte streams" in {
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
val probe2 = system.actorOf(Props(classOf[MDCTestProbe], probe1), "mdc-probe")
val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca")
pca ! HelloFriend(135, List(probe2).iterator)
probe1.receiveOne(100 milli) //consume

View file

@ -0,0 +1,27 @@
package actor.base
// Copyright (c) 2017 PSForever
import akka.actor.{ActorRef, ActorSystem, MDCContextAware}
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
import com.typesafe.config.ConfigFactory
import net.psforever.packet.{ControlPacket, GamePacket}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
import org.specs2.specification.Scope
abstract class ActorTest(sys : ActorSystem = ActorSystem("system", ConfigFactory.parseMap(ActorTest.LoggingConfig)))
extends TestKit(sys) with Scope with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
override def afterAll {
TestKit.shutdownActorSystem(system)
}
}
object ActorTest {
import scala.collection.JavaConverters._
private val LoggingConfig = Map(
"akka.loggers" -> List("akka.testkit.TestEventListener").asJava,
"akka.loglevel" -> "OFF",
"akka.stdout-loglevel" -> "OFF",
"akka.log-dead-letters" -> "OFF"
).asJava
}

View file

@ -0,0 +1,242 @@
// Copyright (c) 2017 PSForever
package actor.objects
import akka.actor.{ActorRef, ActorSystem, Props}
import akka.testkit.TestProbe
import actor.base.ActorTest
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
import net.psforever.objects.serverobject.structures.StructureType
import net.psforever.objects.{Avatar, GlobalDefinitions, Player, Vehicle}
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types._
import services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._
class VehicleSpawnControl1Test extends ActorTest {
"VehicleSpawnControl" should {
"construct" in {
val obj = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "mb_pad_creation")
assert(obj.Actor != ActorRef.noSender)
}
}
}
class VehicleSpawnControl2Test extends ActorTest {
"VehicleSpawnControl" should {
"complete a vehicle order" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
vehicle.Seats(0).Occupant = player
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.PlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideStart])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
//if we move the vehicle away from the pad, we should receive a ResetSpawnPad message
//that means that the first order has cleared and the spawn pad is now waiting for additional orders
vehicle.Position = Vector3(12,0,0)
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ResetSpawnPad])
}
}
}
class VehicleSpawnControl3Test extends ActorTest {
"VehicleSpawnControl" should {
"block the second vehicle order until the first is completed" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
//we can recycle the vehicle and the player for each order
val probe = new TestProbe(system, "zone-events")
val player2 = Player(Avatar("test2", player.Faction, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
player2.Continent = zone.Id
player2.Spawn
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //first order
pad.Actor ! VehicleSpawnPad.VehicleOrder(player2, vehicle) //second order (vehicle shared)
assert(probe.receiveOne(1 seconds) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Queue, _) => true
case _ => false
})
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
vehicle.Seats(0).Occupant = player
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.PlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideStart])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
//if we move the vehicle away from the pad, we should receive a second ConcealPlayer message
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
player.VehicleSeated = None //since shared between orders, as necessary
vehicle.Seats(0).Occupant = None
vehicle.Position = Vector3(12,0,0)
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ResetSpawnPad])
probe.expectMsgClass(3 seconds, classOf[VehicleSpawnPad.ConcealPlayer])
}
}
}
class VehicleSpawnControl4Test extends ActorTest {
"VehicleSpawnControl" should {
"clean up the vehicle if the driver-to-be is on the wrong continent" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
player.Continent = "problem" //problem
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DisposeVehicle])
probe.expectNoMsg(5 seconds)
}
}
}
class VehicleSpawnControl5Test extends ActorTest() {
"VehicleSpawnControl" should {
"abandon a destroyed vehicle on the spawn pad (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
vehicle.Health = 0 //problem
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
class VehicleSpawnControl6Test extends ActorTest() {
"VehicleSpawnControl" should {
"abandon a vehicle on the spawn pad if driver is unfit to drive (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
zone.VehicleEvents = probe.ref
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
player.Die
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
class VehicleSpawnControl7Test extends ActorTest {
"VehicleSpawnControl" should {
"abandon a vehicle on the spawn pad if driver is unfit to drive (blocking)" in {
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system, "zone-events")
player.ExoSuit = ExoSuitType.MAX
zone.VehicleEvents = probe.ref //zone events
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails])
probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.RevealPlayer])
assert(probe.receiveOne(1 minute) match {
case VehicleServiceMessage(_, VehicleAction.LoadVehicle(_,_,_,_,_)) => true
case _ => false
})
assert(probe.receiveOne(1 minute) match {
case VehicleSpawnPad.PeriodicReminder(_, VehicleSpawnPad.Reminders.Blocked, _) => true
case _ => false
})
}
}
}
object VehicleSpawnPadControlTest {
import net.psforever.objects.zones.ZoneMap
private val map = new ZoneMap("test-map")
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Vehicle, Player, VehicleSpawnPad, Zone) = {
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.LimitedNumberSource
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.zones.ZoneActor
import net.psforever.objects.Tool
import net.psforever.types.CharacterGender
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
val weapon = vehicle.WeaponControlledFromSeat(1).get.asInstanceOf[Tool]
val zone = new Zone("test-zone", map, 0) {
override def SetupNumberPools() = {
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(5))
guid.AddPool("test-pool", (0 to 2).toList)
//do not do this under normal conditions
guid.register(vehicle, "test-pool")
guid.register(weapon, "test-pool")
guid.register(weapon.AmmoSlot.Box, "test-pool")
GUID(guid)
}
}
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), s"test-zone-${System.nanoTime()}")
zone.Actor ! Zone.Init()
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), s"vehicle-control-${System.nanoTime()}")
val pad = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
pad.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], pad), s"test-pad-${System.nanoTime()}")
pad.Owner = new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
pad.Owner.Faction = faction
val player = Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
player.GUID = PlanetSideGUID(10)
player.Continent = zone.Id
player.Spawn
//note: pad and vehicle are both at Vector3(1,0,0) so they count as blocking
pad.Position = Vector3(1,0,0)
vehicle.Position = Vector3(1,0,0)
(vehicle, player, pad, zone)
}
}

View file

@ -1,9 +1,9 @@
// Copyright (c) 2017 PSForever
package service
package actor.service
import akka.actor.Props
import akka.routing.RandomPool
import base.ActorTest
import actor.base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.objects.zones.{Zone, ZoneActor, ZoneMap}