modified zone ground actor operation to include no-callback item removal message; adjusted tests for Zone and wrote tests for RemoverActor

This commit is contained in:
FateJH 2018-05-27 02:24:20 -04:00
parent ee5d0c666c
commit c7641fc117
8 changed files with 754 additions and 68 deletions

View file

@ -89,7 +89,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
if(accessor == ActorRef.noSender) {
implicit val guid : NumberPoolHub = this.guid //passed into builderObject.Build implicitly
accessor = context.actorOf(RandomPool(25).props(Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystem.AllocateNumberPoolActors(guid))), s"$Id-uns")
ground = context.actorOf(Props(classOf[ZoneGroundActor], equipmentOnGround), s"$Id-ground")
ground = context.actorOf(Props(classOf[ZoneGroundActor], this, equipmentOnGround), s"$Id-ground")
transport = context.actorOf(Props(classOf[ZoneVehicleActor], this, vehicles), s"$Id-vehicles")
population = context.actorOf(Props(classOf[ZonePopulationActor], this, players, corpses), s"$Id-players")
@ -389,11 +389,13 @@ object Zone {
object Ground {
final case class DropItem(item : Equipment, pos : Vector3, orient : Vector3)
final case class ItemOnGround(item : Equipment, pos : Vector3, orient : Vector3)
final case class CanNotDropItem(item : Equipment)
final case class CanNotDropItem(zone : Zone, item : Equipment, reason : String)
final case class PickupItem(item_guid : PlanetSideGUID)
final case class ItemInHand(item : Equipment)
final case class CanNotPickupItem(item_guid : PlanetSideGUID)
final case class CanNotPickupItem(zone : Zone, item_guid : PlanetSideGUID, reason : String)
final case class RemoveItem(item_guid : PlanetSideGUID)
}
object Vehicle {

View file

@ -12,17 +12,23 @@ import scala.collection.mutable.ListBuffer
* na
* @param equipmentOnGround a `List` of items (`Equipment`) dropped by players on the ground and can be collected again
*/
class ZoneGroundActor(equipmentOnGround : ListBuffer[Equipment]) extends Actor {
class ZoneGroundActor(zone : Zone, equipmentOnGround : ListBuffer[Equipment]) extends Actor {
//private[this] val log = org.log4s.getLogger
def receive : Receive = {
case Zone.Ground.DropItem(item, pos, orient) =>
sender ! (FindItemOnGround(item.GUID) match {
case None =>
equipmentOnGround += item
Zone.Ground.ItemOnGround(item, pos, orient)
case Some(_) =>
Zone.Ground.CanNotDropItem(item)
sender ! (if(!item.HasGUID) {
Zone.Ground.CanNotDropItem(zone, item, "not registered yet")
}
else if(zone.GUID(item.GUID).isEmpty) {
Zone.Ground.CanNotDropItem(zone, item, "registered to some other zone")
}
else if(equipmentOnGround.contains(item)) {
Zone.Ground.CanNotDropItem(zone, item, "already dropped")
}
else {
equipmentOnGround += item
Zone.Ground.ItemOnGround(item, pos, orient)
})
case Zone.Ground.PickupItem(item_guid) =>
@ -30,9 +36,12 @@ class ZoneGroundActor(equipmentOnGround : ListBuffer[Equipment]) extends Actor {
case Some(item) =>
Zone.Ground.ItemInHand(item)
case None =>
Zone.Ground.CanNotPickupItem(item_guid)
Zone.Ground.CanNotPickupItem(zone, item_guid, "can not find")
})
case Zone.Ground.RemoveItem(item_guid) =>
FindItemOnGround(item_guid) //intentionally no callback
case _ => ;
}

View file

@ -155,7 +155,13 @@ class PlayerTest extends Specification {
"has visible slots" in {
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
obj.VisibleSlots mustEqual Set(0,2,4) //Standard
obj.ExoSuit = ExoSuitType.Agile
obj.VisibleSlots mustEqual Set(0,1,2,4)
obj.ExoSuit = ExoSuitType.Reinforced
obj.VisibleSlots mustEqual Set(0,1,2,3,4)
obj.ExoSuit = ExoSuitType.Infiltration
obj.VisibleSlots mustEqual Set(0,4)
obj.ExoSuit = ExoSuitType.MAX
obj.VisibleSlots mustEqual Set(0)
}

View file

@ -18,7 +18,7 @@ import net.psforever.objects.zones.{Zone, ZoneActor, ZoneMap}
import net.psforever.objects.Vehicle
import org.specs2.mutable.Specification
import scala.concurrent.duration.Duration
import scala.concurrent.duration._
class ZoneTest extends Specification {
def test(a: Int, b : Zone, c : ActorContext) : Building = { Building.NoBuilding }
@ -464,55 +464,184 @@ class ZonePopulationTest extends ActorTest {
}
}
class ZoneGroundTest extends ActorTest {
class ZoneGroundDropItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
item.GUID = PlanetSideGUID(10)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub)
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
receiveOne(200 milliseconds) //consume
"ZoneGroundActor" should {
"DropItem" should {
"drop item on ground" in {
val zone = new Zone("test", new ZoneMap(""), 0)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-item-test") ! "!"
receiveOne(Duration.create(200, "ms")) //consume
assert(zone.EquipmentOnGround.isEmpty)
assert(item.Position == Vector3.Zero)
assert(item.Orientation == Vector3.Zero)
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.DropItem(item, Vector3(1.1f, 2.2f, 3.3f), Vector3(4.4f, 5.5f, 6.6f))
expectNoMsg(Duration.create(100, "ms"))
assert(zone.EquipmentOnGround == List(item))
assert(item.Position == Vector3(1.1f, 2.2f, 3.3f))
assert(item.Orientation == Vector3(4.4f, 5.5f, 6.6f))
val reply = receiveOne(200 milliseconds)
assert(reply.isInstanceOf[Zone.Ground.ItemOnGround])
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].item == item)
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].pos == Vector3(1.1f, 2.2f, 3.3f))
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].orient == Vector3(4.4f, 5.5f, 6.6f))
assert(zone.EquipmentOnGround.contains(item))
}
}
}
"get item from ground (success)" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5))
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "get-item-test-good") ! "!"
receiveOne(Duration.create(200, "ms")) //consume
class ZoneGroundCanNotDropItem1Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
//hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub)
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"DropItem" should {
"not drop an item that is not registered" in {
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
expectNoMsg(Duration.create(100, "ms"))
assert(zone.EquipmentOnGround == List(item))
zone.Ground ! Zone.Ground.PickupItem(PlanetSideGUID(10))
val reply = receiveOne(Duration.create(100, "ms"))
val reply = receiveOne(300 milliseconds)
assert(reply.isInstanceOf[Zone.Ground.CanNotDropItem])
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "not registered yet")
assert(!zone.EquipmentOnGround.contains(item))
}
}
}
class ZoneGroundCanNotDropItem2Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
//zone.GUID(hub) //!important
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"DropItem" should {
"not drop an item that is not registered to the zone" in {
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
val reply = receiveOne(300 milliseconds)
assert(reply.isInstanceOf[Zone.Ground.CanNotDropItem])
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "registered to some other zone")
assert(!zone.EquipmentOnGround.contains(item))
}
}
}
class ZoneGroundCanNotDropItem3Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub) //!important
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"DropItem" should {
"not drop an item that has already been dropped" in {
assert(!zone.EquipmentOnGround.contains(item))
assert(zone.EquipmentOnGround.isEmpty)
assert(reply.isInstanceOf[Zone.Ground.ItemInHand])
assert(reply.asInstanceOf[Zone.Ground.ItemInHand].item == item)
}
"get item from ground (failure)" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5))
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "get-item-test-fail") ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
expectNoMsg(Duration.create(100, "ms"))
assert(zone.EquipmentOnGround == List(item))
zone.Ground ! Zone.Ground.PickupItem(PlanetSideGUID(11)) //wrong guid
expectNoMsg(Duration.create(500, "ms"))
val reply1 = receiveOne(300 milliseconds)
assert(reply1.isInstanceOf[Zone.Ground.ItemOnGround])
assert(reply1.asInstanceOf[Zone.Ground.ItemOnGround].item == item)
assert(zone.EquipmentOnGround.contains(item))
assert(zone.EquipmentOnGround.size == 1)
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
val reply2 = receiveOne(300 milliseconds)
assert(reply2.isInstanceOf[Zone.Ground.CanNotDropItem])
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "already dropped")
assert(zone.EquipmentOnGround.size == 1)
}
}
}
class ZoneGroundPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub)
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"PickupItem" should {
"pickup an item from ground" in {
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
val reply1 = receiveOne(200 milliseconds)
assert(reply1.isInstanceOf[Zone.Ground.ItemOnGround])
assert(zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.PickupItem(item.GUID)
val reply2 = receiveOne(200 milliseconds)
assert(reply2.isInstanceOf[Zone.Ground.ItemInHand])
assert(reply2.asInstanceOf[Zone.Ground.ItemInHand].item == item)
assert(!zone.EquipmentOnGround.contains(item))
}
}
}
class ZoneGroundCanNotPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub) //still registered to this zone
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"PickupItem" should {
"not pickup an item if it can not be found" in {
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.PickupItem(item.GUID)
val reply2 = receiveOne(200 milliseconds)
assert(reply2.isInstanceOf[Zone.Ground.CanNotPickupItem])
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].item_guid == item.GUID)
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].zone == zone)
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].reason == "can not find")
}
}
}
class ZoneGroundRemoveItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
zone.GUID(hub) //still registered to this zone
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "drop-test-zone")
zone.Actor ! Zone.Init()
"RemoveItem" should {
"remove an item from the ground without callback (even if the item is not found)" in {
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
receiveOne(200 milliseconds)
assert(zone.EquipmentOnGround.contains(item)) //dropped
zone.Ground ! Zone.Ground.RemoveItem(item.GUID)
expectNoMsg(500 milliseconds)
assert(!zone.EquipmentOnGround.contains(item))
zone.Ground ! Zone.Ground.RemoveItem(item.GUID) //repeat
expectNoMsg(500 milliseconds)
assert(!zone.EquipmentOnGround.contains(item))
}
}
}

View file

@ -217,7 +217,7 @@ object PsLogin {
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Success}
implicit val timeout = Timeout(200 milliseconds)
implicit val timeout = Timeout(500 milliseconds)
val requestVehicleEventBus : Future[ServiceManager.LookupResult] =
(ServiceManager.serviceManager ask ServiceManager.Lookup("vehicle")).mapTo[ServiceManager.LookupResult]
requestVehicleEventBus.onComplete {

View file

@ -1364,13 +1364,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.DropItem(exclusionId, item, continent))
case Zone.Ground.CanNotDropItem(item) =>
log.warn(s"DropItem: $player tried to drop a $item on the ground, but he missed")
player.Find(item) match {
case None => //item in limbo
taskResolver ! GUIDTask.UnregisterEquipment(item)(continent.GUID)
case Some(_) => ;
}
case Zone.Ground.CanNotDropItem(zone, item, reason) =>
log.warn(s"DropItem: $player tried to drop a $item on the ground, but $reason")
case Zone.Ground.ItemInHand(item) =>
player.Fit(item) match {
@ -1392,8 +1387,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
continent.Ground ! Zone.Ground.DropItem(item, item.Position, item.Orientation) //restore previous state
}
case Zone.Ground.CanNotPickupItem(item_guid) =>
continent.GUID(item_guid) match {
case Zone.Ground.CanNotPickupItem(zone, item_guid, _) =>
zone.GUID(item_guid) match {
case Some(item) =>
log.warn(s"DropItem: finding a $item on the ground was suggested, but $player can not reach it")
case None =>
@ -2283,10 +2278,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
&& ((vehicle.Owner.isEmpty || continent.GUID(vehicle.Owner.get).isEmpty) || vehicle.Health == 0))) {
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, Some(0 seconds)))
log.info(s"RequestDestroy: vehicle $object_guid")
log.info(s"RequestDestroy: vehicle $vehicle")
}
else {
log.info(s"RequestDestroy: must own vehicle $object_guid in order to deconstruct it")
log.info(s"RequestDestroy: must own vehicle in order to deconstruct it")
}
case Some(obj : Equipment) =>
@ -2308,20 +2303,28 @@ class WorldSessionActor extends Actor with MDCContextAware {
})
match {
case Some((parent, Some(slot))) =>
obj.Position = Vector3.Zero
taskResolver ! RemoveEquipmentFromSlot(parent, obj, slot)
log.info(s"RequestDestroy: equipment $object_guid")
log.info(s"RequestDestroy: equipment $obj")
case _ =>
//TODO search for item on ground
sendResponse(ObjectDeleteMessage(object_guid, 0))
log.warn(s"RequestDestroy: object $object_guid not found")
if(continent.EquipmentOnGround.contains(obj)) {
obj.Position = Vector3.Zero
continent.Ground ! Zone.Ground.RemoveItem(object_guid)
avatarService ! AvatarServiceMessage.Ground(RemoverActor.ClearSpecific(List(obj), continent))
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(PlanetSideGUID(0), object_guid))
log.info(s"RequestDestroy: equipment $obj on ground")
}
else {
log.warn(s"RequestDestroy: equipment $obj exists, but can not be reached")
}
}
case Some(thing) =>
log.warn(s"RequestDestroy: not allowed to delete object $thing")
case None =>
log.warn(s"RequestDestroy: object $object_guid not found")
case _ =>
log.warn(s"RequestDestroy: not allowed to delete object $object_guid")
}
case msg @ ObjectDeleteMessage(object_guid, unk1) =>

View file

@ -163,7 +163,7 @@ abstract class RemoverActor extends Actor {
trace(s"item removal task has removed ${in.size} items")
case RemoverActor.FailureToWork(entry, ex) =>
log.error(s"${entry.obj} from ${entry.zone} not properly unregistered - $ex")
log.error(s"${entry.obj} from ${entry.zone} not properly deleted - $ex")
case _ => ;
}

View file

@ -0,0 +1,537 @@
// Copyright (c) 2017 PSForever
import akka.actor.{ActorRef, Props}
import akka.routing.RandomPool
import akka.testkit.TestProbe
import net.psforever.objects.PlanetSideGameObject
import net.psforever.objects.definition.{EquipmentDefinition, ObjectDefinition}
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.PlanetSideGUID
import services.{RemoverActor, ServiceManager}
import scala.concurrent.duration._
class StandardRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
"RemoverActor" should {
"handle a simple task" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere)
val reply1 = probe.receiveOne(100 milliseconds)
assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
val reply2 = probe.receiveOne(100 milliseconds)
assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
probe.expectNoMsg(1 seconds) //delay
val reply3 = probe.receiveOne(300 milliseconds)
assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4 = probe.receiveOne(300 milliseconds)
assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5 = probe.receiveOne(300 milliseconds)
assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6 = probe.receiveOne(300 milliseconds)
assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7 = probe.receiveOne(300 milliseconds)
assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class DelayedRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
"RemoverActor" should {
"handle a simple task (timed)" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(100 milliseconds))
val reply1 = probe.receiveOne(100 milliseconds)
assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
val reply2 = probe.receiveOne(100 milliseconds)
assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
//no delay
val reply3 = probe.receiveOne(300 milliseconds)
assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4 = probe.receiveOne(300 milliseconds)
assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5 = probe.receiveOne(300 milliseconds)
assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6 = probe.receiveOne(300 milliseconds)
assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7 = probe.receiveOne(300 milliseconds)
assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class ExcludedRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
val AlternateTestObject = new PlanetSideGameObject() { def Definition = new ObjectDefinition(0) { } }
"RemoverActor" should {
"allow only specific objects" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(AlternateTestObject, Zone.Nowhere)
val reply1 = probe.receiveOne(100 milliseconds)
assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
expectNoMsg(2 seconds)
//RemoverActor is stalled because it received an object that it was not allowed to act upon
}
}
}
class MultipleRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
"RemoverActor" should {
"work on parallel tasks" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere)
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere)
val replies = probe.receiveN(14, 3 seconds)
var ita : Int = 0
var ija : Int = 0
var fja : Int = 0
var cta : Int = 0
var sja : Int = 0
var dta : Int = 0
var dtr : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case RemoverActorTest.FirstJobAlert() => fja += 1
case RemoverActorTest.ClearanceTestAlert() => cta += 1
case RemoverActorTest.SecondJobAlert() => sja += 1
case RemoverActorTest.DeletionTaskAlert() => dta += 1
case RemoverActorTest.DeletionTaskRunAlert() => dtr += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2 && fja == 2 && cta == 2 && sja == 2 && dta == 2 && dtr == 2)
}
}
}
class HurrySpecificRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
"RemoverActor" should {
"be able to hurry certain tasks" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(10 minutes)) //TEN MINUTE WAIT
val reply1 = probe.receiveOne(100 milliseconds)
assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
val reply2 = probe.receiveOne(100 milliseconds)
assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
probe.expectNoMsg(3 seconds) //long delay, longer than standard but not yet 10 minutes
remover ! RemoverActor.HurrySpecific(List(RemoverActorTest.TestObject), Zone.Nowhere) //hurried
val reply3 = probe.receiveOne(300 milliseconds)
assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4 = probe.receiveOne(300 milliseconds)
assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5 = probe.receiveOne(300 milliseconds)
assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6 = probe.receiveOne(300 milliseconds)
assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7 = probe.receiveOne(300 milliseconds)
assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class HurrySelectionRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
"RemoverActor" should {
"be able to hurry certain tasks" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(10 seconds))
val replies = probe.receiveN(4, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2)
probe.expectNoMsg(3 seconds) //long delay, longer than standard but not yet 5 seconds
remover ! RemoverActor.HurrySpecific(List(RemoverActorTest.TestObject), Zone.Nowhere) //hurried
//first
val reply3a = probe.receiveOne(300 milliseconds)
assert(reply3a.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4a = probe.receiveOne(300 milliseconds)
assert(reply4a.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5a = probe.receiveOne(300 milliseconds)
assert(reply5a.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6a = probe.receiveOne(300 milliseconds)
assert(reply6a.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7a = probe.receiveOne(300 milliseconds)
assert(reply7a.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
//second
remover ! RemoverActor.HurrySpecific(List(TestObject2), Zone.Nowhere) //hurried
val reply3b = probe.receiveOne(300 milliseconds)
assert(reply3b.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4b = probe.receiveOne(300 milliseconds)
assert(reply4b.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5b = probe.receiveOne(300 milliseconds)
assert(reply5b.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6b = probe.receiveOne(300 milliseconds)
assert(reply6b.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7b = probe.receiveOne(300 milliseconds)
assert(reply7b.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class HurryMultipleRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
final val TestObject3 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(3) } }
"RemoverActor" should {
"be able to hurry certain tasks, but only valid ones" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(5 seconds))
val replies = probe.receiveN(4, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2)
probe.expectNoMsg(3 seconds) //long delay, longer than standard but not yet 5 seconds
remover ! RemoverActor.HurrySpecific(List(RemoverActorTest.TestObject, TestObject3), Zone.Nowhere) //multiple hurried, only one valid
//first
val reply3a = probe.receiveOne(300 milliseconds)
assert(reply3a.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4a = probe.receiveOne(300 milliseconds)
assert(reply4a.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5a = probe.receiveOne(300 milliseconds)
assert(reply5a.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6a = probe.receiveOne(300 milliseconds)
assert(reply6a.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7a = probe.receiveOne(300 milliseconds)
assert(reply7a.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
//second
remover ! RemoverActor.HurrySpecific(List(TestObject2), Zone.Nowhere) //hurried
val reply3b = probe.receiveOne(300 milliseconds)
assert(reply3b.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4b = probe.receiveOne(300 milliseconds)
assert(reply4b.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5b = probe.receiveOne(300 milliseconds)
assert(reply5b.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6b = probe.receiveOne(300 milliseconds)
assert(reply6b.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7b = probe.receiveOne(300 milliseconds)
assert(reply7b.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class HurryByZoneRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
final val TestObject3 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(3) } }
final val zone = new Zone("test", new ZoneMap("test-map"), 11)
"RemoverActor" should {
"be able to hurry certain tasks by their zone" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, zone, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject3, Zone.Nowhere, Some(5 seconds))
val replies1 = probe.receiveN(6, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies1.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 3 && ija == 3)
probe.expectNoMsg(3 seconds) //long delay, longer than standard but not yet 5 seconds
remover ! RemoverActor.HurrySpecific(List(), Zone.Nowhere) //multiple hurried, only the two entries with Zone.Nowhere
//
val replies2 = probe.receiveN(10, 3 seconds)
var fja : Int = 0
var cta : Int = 0
var sja : Int = 0
var dta : Int = 0
var dtr : Int = 0
replies2.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case RemoverActorTest.FirstJobAlert() => fja += 1
case RemoverActorTest.ClearanceTestAlert() => cta += 1
case RemoverActorTest.SecondJobAlert() => sja += 1
case RemoverActorTest.DeletionTaskAlert() => dta += 1
case RemoverActorTest.DeletionTaskRunAlert() => dtr += 1
case msg => assert(false, s"$msg")
}
assert(fja == 2 && cta == 2 && sja == 2 && dta == 2 && dtr == 2)
//final
remover ! RemoverActor.HurrySpecific(List(), zone) //hurried
val reply3b = probe.receiveOne(300 milliseconds)
assert(reply3b.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4b = probe.receiveOne(300 milliseconds)
assert(reply4b.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5b = probe.receiveOne(300 milliseconds)
assert(reply5b.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6b = probe.receiveOne(300 milliseconds)
assert(reply6b.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7b = probe.receiveOne(300 milliseconds)
assert(reply7b.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
}
}
}
class HurryAllRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
final val TestObject3 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(3) } }
"RemoverActor" should {
"be able to hurry all tasks to completion" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(20 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(15 seconds))
remover ! RemoverActor.AddTask(TestObject3, Zone.Nowhere, Some(10 seconds))
val replies1 = probe.receiveN(6, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies1.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 3 && ija == 3)
probe.expectNoMsg(3 seconds) //long delay, longer than standard but not yet longer than any of the tasks
remover ! RemoverActor.HurryAll() //all hurried
//
val replies2 = probe.receiveN(15, 3 seconds)
var fja : Int = 0
var cta : Int = 0
var sja : Int = 0
var dta : Int = 0
var dtr : Int = 0
replies2.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case RemoverActorTest.FirstJobAlert() => fja += 1
case RemoverActorTest.ClearanceTestAlert() => cta += 1
case RemoverActorTest.SecondJobAlert() => sja += 1
case RemoverActorTest.DeletionTaskAlert() => dta += 1
case RemoverActorTest.DeletionTaskRunAlert() => dtr += 1
case msg => assert(false, s"$msg")
}
assert(fja == 3 && cta == 3 && sja == 3 && dta == 3 && dtr == 3)
}
}
}
class ClearSelectionRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
"RemoverActor" should {
"be able to clear certain tasks" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(5 seconds))
val replies = probe.receiveN(4, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2)
probe.expectNoMsg(4 seconds) //long delay, longer than standard but not yet 5 seconds
remover ! RemoverActor.ClearSpecific(List(RemoverActorTest.TestObject), Zone.Nowhere) //cleared
//
val reply3 = probe.receiveOne(2 seconds)
assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
val reply4 = probe.receiveOne(300 milliseconds)
assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
val reply5 = probe.receiveOne(300 milliseconds)
assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
val reply6 = probe.receiveOne(300 milliseconds)
assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
val reply7 = probe.receiveOne(300 milliseconds)
assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
//wait
probe.expectNoMsg(2 seconds) //nothing more to do
}
}
}
class ClearAllRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
"RemoverActor" should {
"be able to clear all tasks, with no more work on them" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(5 seconds))
val replies = probe.receiveN(4, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2)
probe.expectNoMsg(4 seconds) //long delay, longer than standard but not yet 5 seconds
remover ! RemoverActor.ClearAll() //cleared
//wait
probe.expectNoMsg(3 seconds) //nothing more to do
}
}
}
class EarlyDeathRemoverActorTest extends ActorTest {
ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
"RemoverActor" should {
"be able to hurry certain tasks" in {
expectNoMsg(200 milliseconds)
val probe = TestProbe()
val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(5 seconds))
remover ! RemoverActor.AddTask(TestObject2, Zone.Nowhere, Some(5 seconds))
val replies = probe.receiveN(4, 3 seconds)
var ita : Int = 0
var ija : Int = 0
replies.collect {
case RemoverActorTest.InclusionTestAlert() => ita += 1
case RemoverActorTest.InitialJobAlert() => ija += 1
case msg => assert(false, s"$msg")
}
assert(ita == 2 && ija == 2)
probe.expectNoMsg(2 seconds)
remover ! akka.actor.PoisonPill
//
val replies2 = probe.receiveN(8, 2 seconds)
var fja : Int = 0
var cta : Int = 0
var sja : Int = 0
var dta : Int = 0
var dtr : Int = 0
replies2.collect {
case RemoverActorTest.FirstJobAlert() => fja += 1
case RemoverActorTest.ClearanceTestAlert() => cta += 1
case RemoverActorTest.SecondJobAlert() => sja += 1
case RemoverActorTest.DeletionTaskAlert() => dta += 1
case RemoverActorTest.DeletionTaskRunAlert() => dtr += 1
case msg => assert(false, s"$msg")
}
assert(fja == 2 && cta == 0 && sja == 2 && dta == 2 && dtr == 2) //no clearance tests
}
}
}
object RemoverActorTest {
final val TestObject = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(1) } }
final case class InclusionTestAlert()
final case class InitialJobAlert()
final case class FirstJobAlert()
final case class SecondJobAlert()
final case class ClearanceTestAlert()
final case class DeletionTaskAlert()
final case class DeletionTaskRunAlert()
class TestRemover(probe : TestProbe) extends RemoverActor {
import net.psforever.objects.guid.{Task, TaskResolver}
val FirstStandardDuration = 1 seconds
val SecondStandardDuration = 100 milliseconds
def InclusionTest(entry : RemoverActor.Entry) : Boolean = {
probe.ref ! InclusionTestAlert()
entry.obj.isInstanceOf[Equipment]
}
def InitialJob(entry : RemoverActor.Entry) : Unit = {
probe.ref ! InitialJobAlert()
}
def FirstJob(entry : RemoverActor.Entry) : Unit = {
probe.ref ! FirstJobAlert()
}
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
probe.ref ! SecondJobAlert()
super.SecondJob(entry)
}
def ClearanceTest(entry : RemoverActor.Entry) : Boolean = {
probe.ref ! ClearanceTestAlert()
true
}
def DeletionTask(entry : RemoverActor.Entry) : TaskResolver.GiveTask = {
probe.ref ! DeletionTaskAlert()
TaskResolver.GiveTask(new Task() {
private val localProbe = probe
override def isComplete = Task.Resolution.Success
def Execute(resolver : ActorRef) : Unit = {
localProbe.ref ! DeletionTaskRunAlert()
resolver ! scala.util.Success(this)
}
})
}
}
}