// Copyright (c) 2017 PSForever package objects import net.psforever.objects.PlanetSideGameObject import net.psforever.objects.definition.ObjectDefinition import net.psforever.objects.entity.{AssigningGUIDException, NoGUIDException} import net.psforever.types.{PlanetSideGUID, StalePlanetSideGUID, ValidPlanetSideGUID, Vector3} import org.specs2.mutable._ class EntityTest extends Specification { //both WorldEntity and IdentifiableEntity are components of PlanetSideGameObject private class EntityTestClass extends PlanetSideGameObject { def Definition: ObjectDefinition = new ObjectDefinition(0) {} } "PlanetSideGUID" should { "construct as valid" in { ValidPlanetSideGUID(1).isInstanceOf[PlanetSideGUID] mustEqual true } "construct as stale" in { StalePlanetSideGUID(1).isInstanceOf[PlanetSideGUID] mustEqual true } "apply construct (as valid)" in { val guid = PlanetSideGUID(1) guid.isInstanceOf[PlanetSideGUID] mustEqual true guid.isInstanceOf[ValidPlanetSideGUID] mustEqual true guid.isInstanceOf[StalePlanetSideGUID] mustEqual false } "valid and stale are equal by guid" in { //your linter will complain; let it ValidPlanetSideGUID(1) == StalePlanetSideGUID(1) mustEqual true ValidPlanetSideGUID(1) == StalePlanetSideGUID(2) mustEqual false } "valid and stale are pattern-matchable" in { val guid1: PlanetSideGUID = ValidPlanetSideGUID(1) val guid2: PlanetSideGUID = StalePlanetSideGUID(1) def getGuid(o: PlanetSideGUID): PlanetSideGUID = o //distancing the proper type getGuid(guid1) match { case ValidPlanetSideGUID(1) => ok case _ => ko } getGuid(guid2) match { case StalePlanetSideGUID(1) => ok case _ => ko } } } "SimpleWorldEntity" should { "construct" in { new EntityTestClass() ok } "initialize" in { val obj: EntityTestClass = new EntityTestClass() obj.Position mustEqual Vector3(0f, 0f, 0f) obj.Orientation mustEqual Vector3(0f, 0f, 0f) obj.Velocity.isEmpty mustEqual true } "mutate and access" in { val obj: EntityTestClass = new EntityTestClass obj.Position = Vector3(1f, 1f, 1f) obj.Orientation = Vector3(2f, 2f, 2f) obj.Velocity = Vector3(3f, 3f, 3f) obj.Position mustEqual Vector3(1f, 1f, 1f) obj.Orientation mustEqual Vector3(2f, 2f, 2f) obj.Velocity.contains(Vector3(3f, 3f, 3f)) mustEqual true } "clamp Orientation" in { val obj: EntityTestClass = new EntityTestClass obj.Orientation = Vector3(-1f, 361f, -0f) obj.Orientation mustEqual Vector3(359f, 1f, 0f) } "is moving (at all)" in { val obj: EntityTestClass = new EntityTestClass obj.Velocity.isEmpty mustEqual true obj.isMoving mustEqual false obj.Velocity = Vector3.Zero obj.isMoving mustEqual false obj.Velocity = Vector3(1, 0, 0) obj.isMoving mustEqual true obj.Velocity = None obj.isMoving mustEqual false } "is moving (Vector3 comparison)" in { val obj: EntityTestClass = new EntityTestClass val test1 = Vector3(1, 0, 0) val test2 = Vector3(2, 0, 0) obj.Velocity.isEmpty mustEqual true obj.isMoving mustEqual false obj.isMoving(test1) mustEqual false obj.isMoving(test2) mustEqual false obj.Velocity = Vector3(1, 0, 0) obj.isMoving(test1) mustEqual true obj.isMoving(test2) mustEqual false obj.Velocity = Vector3(3, 0, 0) obj.isMoving(test1) mustEqual true obj.isMoving(test2) mustEqual true obj.Velocity = Vector3(1, 1, 0) obj.isMoving(test1) mustEqual true obj.isMoving(test2) mustEqual false } "is moving (Float comparison)" in { val obj: EntityTestClass = new EntityTestClass obj.Velocity.isEmpty mustEqual true obj.isMoving mustEqual false obj.isMoving(1) mustEqual false obj.isMoving(2) mustEqual false obj.isMoving(4) mustEqual false obj.Velocity = Vector3(1, 0, 0) obj.isMoving(1) mustEqual true obj.isMoving(2) mustEqual false obj.isMoving(4) mustEqual false obj.Velocity = Vector3(3, 0, 0) obj.isMoving(1) mustEqual true obj.isMoving(2) mustEqual true obj.isMoving(4) mustEqual true obj.Velocity = Vector3(1, 1, 1) obj.isMoving(1) mustEqual true obj.isMoving(2) mustEqual true obj.isMoving(4) mustEqual false } } "IdentifiableEntity" should { "construct" in { new EntityTestClass() ok } "error while not set" in { val obj: EntityTestClass = new EntityTestClass obj.GUID must throwA[NoGUIDException] } "error if set to an invalid GUID before being set to a valid GUID" in { val obj: EntityTestClass = new EntityTestClass obj.GUID must throwA[NoGUIDException] try { obj.GUID = StalePlanetSideGUID(1) ko } catch { case AssigningGUIDException(_, _, _, _: StalePlanetSideGUID) => ok case _: Throwable => ko } } "work after valid mutation" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) } "raise complaint about subsequent mutations using a valid GUID" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) try { obj.GUID = ValidPlanetSideGUID(1) ko } catch { case AssigningGUIDException(_, _, _, ValidPlanetSideGUID(1)) => ok case _: Throwable => ko } } "ignore subsequent mutations using an invalid GUID" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) try { obj.GUID = StalePlanetSideGUID(1) ko } catch { case AssigningGUIDException(_, _, _, _: StalePlanetSideGUID) => ok case _: Throwable => ko } } "invalidate does nothing by default" in { val obj: EntityTestClass = new EntityTestClass obj.Invalidate() obj.GUID must throwA[NoGUIDException] } "invalidate changes the nature of the previous valid mutation" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true obj.Invalidate() obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true } "setting an invalid GUID after invalidating the previous valid mutation still raises complaint" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true obj.Invalidate() obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true (obj.GUID = StalePlanetSideGUID(2)) must throwA[AssigningGUIDException] obj.GUID mustEqual PlanetSideGUID(1051) } "setting a valid GUID after invalidating correctly sets the new valid GUID" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true obj.Invalidate() obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true obj.GUID = PlanetSideGUID(2) obj.GUID mustEqual PlanetSideGUID(2) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true } "setting the same valid GUID after invalidating correctly resets the valid GUID" in { val obj: EntityTestClass = new EntityTestClass obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true obj.Invalidate() obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true obj.GUID = PlanetSideGUID(1051) obj.GUID mustEqual PlanetSideGUID(1051) obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true } "report not having a GUID when not set" in { val obj: EntityTestClass = new EntityTestClass obj.HasGUID mustEqual false } "report having a GUID when a valid GUID is set" in { val obj: EntityTestClass = new EntityTestClass obj.HasGUID mustEqual false obj.GUID = PlanetSideGUID(1051) obj.HasGUID mustEqual true } "report not having a GUID after invalidating (staleness)" in { val obj: EntityTestClass = new EntityTestClass obj.HasGUID mustEqual false obj.GUID = PlanetSideGUID(1051) obj.HasGUID mustEqual true obj.Invalidate() obj.HasGUID mustEqual false //remember that we will still return a GUID in this case obj.GUID mustEqual PlanetSideGUID(1051) } "report having a GUID after setting a valid GUID, after invalidating" in { val obj: EntityTestClass = new EntityTestClass obj.HasGUID mustEqual false obj.GUID = PlanetSideGUID(1051) obj.HasGUID mustEqual true obj.Invalidate() obj.HasGUID mustEqual false obj.GUID = PlanetSideGUID(2) obj.HasGUID mustEqual true } } "hachCode test" in { ValidPlanetSideGUID(1051).hashCode mustEqual ValidPlanetSideGUID(1051).hashCode ValidPlanetSideGUID(1051).hashCode mustEqual StalePlanetSideGUID(1051).hashCode } }