mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-14 07:55:07 +00:00
revamped IdentifiableEntity to work with a revamped PlanetSideGUID; GUID's now have a characteristic that they can be valid or stale (this is a container-level distinction, now a value-level distinction); all appropriate behaviors should be roughly the same as before the changes
This commit is contained in:
parent
03bc52f52d
commit
0c1486dbcc
4 changed files with 255 additions and 115 deletions
|
|
@ -1,104 +1,110 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017-2019 PSForever
|
||||||
package net.psforever.objects.entity
|
package net.psforever.objects.entity
|
||||||
|
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.{PlanetSideGUID, StalePlanetSideGUID}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent any entity that must have its own globally unique identifier (GUID) to be functional.<br>
|
* Represent any entity that must have its own valid global unique identifier (GUID) to be functional.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* "Testing" the object refers to the act of acquiring a reference to the GUID the object is using.
|
* The basic design philosophy of the workflow of a GUID at this stage is a deterministic state machine.
|
||||||
* This object starts with a container class that represents a unprepared GUID state and raises an `Exception` when tested.
|
* At the start, an `Exception` will be thrown while the default conditions of the accessor and mutator are maintained.
|
||||||
* Setting a proper `PlanetSideGUID` replaces that container class with a container class that returns the GUID when tested.
|
* ("The ability to set a new valid GUID".)
|
||||||
* The object can be invalidated, retaining the previous identifier number, but marking that object as being "stale."
|
* Only a valid GUID may be set and, once it does, that changes the conditions of the accessor and mutator
|
||||||
* "Staleness" is a property indicating whether or not the number can be used as a valid representation of the object.
|
* to one where it will return the valid GUID and one where it will no longer accept a new GUID (valid or invalid).
|
||||||
|
* That GUID will continue being the GUID reported by the object, even if another valid GUID tries to be set.
|
||||||
|
* (No error or exception will be thrown.)
|
||||||
|
* To set a new GUID, the current one must be invalidated with the appropriate function,
|
||||||
|
* and this turns both the object and any object reference that can be acquired from the object "stale."
|
||||||
|
* Doing this prior to setting the initial valid GUID is fruitless
|
||||||
|
* as it restores the object to its default mutation option ("the ability to set a new valid GUID").
|
||||||
|
* Access to the GUID is retained.
|
||||||
|
* This can be done as many times as is necessary by following the same order of actions.<br>
|
||||||
|
* <br>
|
||||||
|
* The "staleness" of the object and the "staleness" of the GUID are related.
|
||||||
|
* The condition in general indicates that the object has somehow become externally disconnected from its GUID reference
|
||||||
|
* though the two still share something similar to their prior relationship internally.
|
||||||
|
* Do not expect a "stale" GUID to refer to the same object through some mapping mechanism.
|
||||||
|
* Do not expect a "stale" object to give you a GUID that will map back to itself.
|
||||||
* @throws `NoGUIDException` if a GUID has not yet been assigned
|
* @throws `NoGUIDException` if a GUID has not yet been assigned
|
||||||
*/
|
*/
|
||||||
abstract class IdentifiableEntity extends Identifiable {
|
abstract class IdentifiableEntity extends Identifiable {
|
||||||
|
/** storage for the GUID information; starts as a `StalePlanetSideGUID` */
|
||||||
|
private var current : PlanetSideGUID = StalePlanetSideGUID(0)
|
||||||
/** indicate the validity of the current GUID */
|
/** indicate the validity of the current GUID */
|
||||||
private var stale : Boolean = true
|
private var guidValid : Boolean = false
|
||||||
/** storage for the active GUID */
|
/** the current accessor; can be re-assigned */
|
||||||
private val container : GUIDContainable = GUIDContainer()
|
private var guidAccessor : IdentifiableEntity=>PlanetSideGUID = IdentifiableEntity.noGuidGet
|
||||||
/** the handle for the active GUID; starts as exception-throwing */
|
/** the current mutator; can be re-assigned */
|
||||||
private var current : GUIDContainable = IdentifiableEntity.noGUIDContainer
|
private var guidMutator : (IdentifiableEntity, PlanetSideGUID)=>PlanetSideGUID = IdentifiableEntity.noGuidSet
|
||||||
|
|
||||||
|
def GUID : PlanetSideGUID = guidAccessor(this)
|
||||||
|
|
||||||
|
/** Always intercept `StalePlanetSideGUID` references when attempting to mutate the GUID value. */
|
||||||
|
def GUID_=(guid : StalePlanetSideGUID) : PlanetSideGUID = guidAccessor(this)
|
||||||
|
|
||||||
|
def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = guidMutator(this, guid)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object will not originally having a valid GUID,
|
* Flag when the object has no GUID (initial condition) or is considered stale.
|
||||||
* so "stale" will be used to expressed "not initialized."
|
|
||||||
* After being set and then properly invalidated, then it will indicate proper staleness.
|
|
||||||
* @return whether the value of the GUID is a valid representation for this object
|
* @return whether the value of the GUID is a valid representation for this object
|
||||||
*/
|
*/
|
||||||
def HasGUID : Boolean = !stale
|
def HasGUID : Boolean = guidValid
|
||||||
|
|
||||||
def GUID : PlanetSideGUID = current.GUID
|
|
||||||
|
|
||||||
def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = {
|
|
||||||
stale = false
|
|
||||||
current = container
|
|
||||||
current.GUID = guid
|
|
||||||
GUID
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the staleness to indicate whether the GUID has ever been set
|
* Indicate that the current GUID is no longer a valid representation of the object.
|
||||||
* or that the set GUID is not a proper representation of the object.
|
* Transforms whatever the current GUID is into a `StalePlanetSideGUID` entity with the same value.
|
||||||
* It is always set to `true`.
|
* Doing this restores the object to its default mutation option ("the ability to set a new valid GUID").
|
||||||
|
* The current GUID will still be accessed as if it were valid, but it will be wrapped in the new stale object.
|
||||||
*/
|
*/
|
||||||
def Invalidate() : Unit = {
|
def Invalidate() : Unit = {
|
||||||
stale = true
|
guidValid = false
|
||||||
|
current = StalePlanetSideGUID(current.guid)
|
||||||
|
guidMutator = IdentifiableEntity.noGuidSet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object IdentifiableEntity {
|
object IdentifiableEntity {
|
||||||
private val noGUIDContainer : GUIDContainable = new NoGUIDContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mask the `Identifiable` `trait`.
|
|
||||||
*/
|
|
||||||
sealed trait GUIDContainable extends Identifiable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hidden container that represents an object that is not ready to be used by the game.
|
|
||||||
*/
|
|
||||||
private case class NoGUIDContainer() extends GUIDContainable {
|
|
||||||
/**
|
/**
|
||||||
* Raise an `Exception` because we have no GUID to give.
|
* Raise an `Exception` because the entity is never considered having a GUID to give.
|
||||||
|
* @param o the any entity with a GUID
|
||||||
* @throws `NoGUIDException` always
|
* @throws `NoGUIDException` always
|
||||||
* @return never returns
|
* @return never returns
|
||||||
*/
|
*/
|
||||||
def GUID : PlanetSideGUID = {
|
def noGuidGet(o : IdentifiableEntity) : PlanetSideGUID = {
|
||||||
throw NoGUIDException(s"object $this has not initialized a global identifier")
|
throw NoGUIDException(s"did not initialize this object $o with a valid global identifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normally, this should never be called.
|
* Provide the entity with a valid GUID replacing an invalid GUID.
|
||||||
* @param toGuid the globally unique identifier
|
* Modify the accessor and mutator function literals to ensure the entity will remain stable.
|
||||||
* @return never returns
|
* It will not be mutated by a new valid value without the existing valid value having to first be invalidated.
|
||||||
*/
|
* Its access is made standard.
|
||||||
def GUID_=(toGuid : PlanetSideGUID) : PlanetSideGUID = {
|
* @param o the any entity with a GUID
|
||||||
throw NoGUIDException("can not initialize a global identifier with this object")
|
* @param guid the valid GUID to assign
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hidden container that represents an object that has a working GUID and is ready to be used by the game.
|
|
||||||
* @param guid the object's globally unique identifier;
|
|
||||||
* defaults to a GUID equal to 0
|
|
||||||
*/
|
|
||||||
private case class GUIDContainer(private var guid : PlanetSideGUID = PlanetSideGUID(0)) extends GUIDContainable {
|
|
||||||
/**
|
|
||||||
* Provide the GUID used to initialize this object.
|
|
||||||
* @return the GUID
|
* @return the GUID
|
||||||
*/
|
*/
|
||||||
def GUID : PlanetSideGUID = guid
|
def noGuidSet(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = {
|
||||||
|
o.current = guid
|
||||||
|
o.guidValid = true
|
||||||
|
o.guidAccessor = guidGet
|
||||||
|
o.guidMutator = guidSet
|
||||||
|
guid
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchange the previous GUID for a new one, re-using this container.
|
* The entity should have a valid GUID that can be provided.
|
||||||
* @param toGuid the globally unique identifier
|
* @param o the entity
|
||||||
* @return the GUID
|
* @return the entity's GUID
|
||||||
*/
|
*/
|
||||||
def GUID_=(toGuid : PlanetSideGUID) : PlanetSideGUID = {
|
def guidGet(o : IdentifiableEntity) : PlanetSideGUID = o.current
|
||||||
guid = toGuid
|
|
||||||
GUID
|
/**
|
||||||
}
|
* The entity is in a condition where it can not be assigned the new valid GUID.
|
||||||
|
* This state establishes itself after setting the very first valid GUID and
|
||||||
|
* will persist to the end of the entity's life.
|
||||||
|
* @param o the any entity with a GUID
|
||||||
|
* @param guid the valid GUID to assign
|
||||||
|
* @return the entity's GUID
|
||||||
|
*/
|
||||||
|
def guidSet(o : IdentifiableEntity, guid : PlanetSideGUID) : PlanetSideGUID = o.current
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,40 @@
|
||||||
|
// Copyright (c) 2017-2019 PSForever
|
||||||
package net.psforever.types
|
package net.psforever.types
|
||||||
|
|
||||||
import scodec.codecs.uint16L
|
import scodec.codecs.uint16L
|
||||||
|
|
||||||
case class PlanetSideGUID(guid : Int)
|
abstract class PlanetSideGUID {
|
||||||
|
def guid : Int
|
||||||
|
|
||||||
|
/* overriding equals and hashCode to benefit the case class subclasses through inheritance;
|
||||||
|
* essentially, if not for these overrides, each case class would implement its own equivalence methods
|
||||||
|
* */
|
||||||
|
/**
|
||||||
|
* All subclasses of `PlanetSideGUID` are equivalent through being subclasses of `PlanetSideGUID`.
|
||||||
|
* @param o an entity
|
||||||
|
* @return whether that entity is a `PlanetSideGUID` object
|
||||||
|
*/
|
||||||
|
def canEqual(o : Any) : Boolean = o.isInstanceOf[PlanetSideGUID]
|
||||||
|
|
||||||
|
override def equals(o : Any) : Boolean = o match {
|
||||||
|
case that : PlanetSideGUID => that.canEqual(this) && that.guid == this.guid
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
override def hashCode: Int = java.util.Objects.hashCode(guid)
|
||||||
|
}
|
||||||
|
|
||||||
|
final case class ValidPlanetSideGUID(guid : Int) extends PlanetSideGUID
|
||||||
|
|
||||||
|
final case class StalePlanetSideGUID(guid : Int) extends PlanetSideGUID
|
||||||
|
|
||||||
object PlanetSideGUID {
|
object PlanetSideGUID {
|
||||||
implicit val codec = uint16L.as[PlanetSideGUID]
|
def apply(guid : Int) : PlanetSideGUID = ValidPlanetSideGUID(guid)
|
||||||
|
|
||||||
|
def unapply(n : PlanetSideGUID) : Option[Int] = Some(n.guid)
|
||||||
|
|
||||||
|
implicit val codec = uint16L.xmap[PlanetSideGUID] (
|
||||||
|
n => PlanetSideGUID(n),
|
||||||
|
n => n.guid
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,16 @@ class DeployableTest extends Specification {
|
||||||
"Deployable" should {
|
"Deployable" should {
|
||||||
"know its owner by GUID" in {
|
"know its owner by GUID" in {
|
||||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||||
obj.Owner mustEqual None
|
obj.Owner.isEmpty mustEqual true
|
||||||
obj.Owner = PlanetSideGUID(10)
|
obj.Owner = PlanetSideGUID(10)
|
||||||
obj.Owner mustEqual Some(PlanetSideGUID(10))
|
obj.Owner.contains(PlanetSideGUID(10)) mustEqual true
|
||||||
}
|
}
|
||||||
|
|
||||||
"know its owner by GUID" in {
|
"know its owner by GUID" in {
|
||||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||||
obj.OwnerName mustEqual None
|
obj.OwnerName.isEmpty mustEqual true
|
||||||
obj.OwnerName = "TestCharacter"
|
obj.OwnerName = "TestCharacter"
|
||||||
obj.OwnerName mustEqual Some("TestCharacter")
|
obj.OwnerName.contains("TestCharacter") mustEqual true
|
||||||
}
|
}
|
||||||
|
|
||||||
"know its faction allegiance" in {
|
"know its faction allegiance" in {
|
||||||
|
|
@ -66,7 +66,7 @@ class BoomerDeployableTest extends Specification {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
||||||
obj.Exploded mustEqual false
|
obj.Exploded mustEqual false
|
||||||
obj.Trigger mustEqual None
|
obj.Trigger.isEmpty mustEqual true
|
||||||
}
|
}
|
||||||
|
|
||||||
"explode" in {
|
"explode" in {
|
||||||
|
|
@ -78,14 +78,14 @@ class BoomerDeployableTest extends Specification {
|
||||||
|
|
||||||
"manage its trigger" in {
|
"manage its trigger" in {
|
||||||
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
||||||
obj.Trigger mustEqual None
|
obj.Trigger.isEmpty mustEqual true
|
||||||
|
|
||||||
val trigger = new BoomerTrigger
|
val trigger = new BoomerTrigger
|
||||||
obj.Trigger = trigger
|
obj.Trigger = trigger
|
||||||
obj.Trigger mustEqual Some(trigger)
|
obj.Trigger.contains(trigger) mustEqual true
|
||||||
|
|
||||||
obj.Trigger = None
|
obj.Trigger = None
|
||||||
obj.Trigger mustEqual None
|
obj.Trigger.isEmpty mustEqual true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +322,7 @@ class TelepadDeployableTest extends Specification {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
obj.Active mustEqual false
|
obj.Active mustEqual false
|
||||||
obj.Router mustEqual None
|
obj.Router.isEmpty mustEqual true
|
||||||
}
|
}
|
||||||
|
|
||||||
"activate and deactivate" in {
|
"activate and deactivate" in {
|
||||||
|
|
@ -336,15 +336,15 @@ class TelepadDeployableTest extends Specification {
|
||||||
|
|
||||||
"keep track of a Router" in {
|
"keep track of a Router" in {
|
||||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
obj.Router mustEqual None
|
obj.Router.isEmpty mustEqual true
|
||||||
obj.Router = PlanetSideGUID(1)
|
obj.Router = PlanetSideGUID(1)
|
||||||
obj.Router mustEqual Some(PlanetSideGUID(1))
|
obj.Router.contains(PlanetSideGUID(1)) mustEqual true
|
||||||
obj.Router = None
|
obj.Router = None
|
||||||
obj.Router mustEqual None
|
obj.Router.isEmpty mustEqual true
|
||||||
obj.Router = PlanetSideGUID(1)
|
obj.Router = PlanetSideGUID(1)
|
||||||
obj.Router mustEqual Some(PlanetSideGUID(1))
|
obj.Router.contains(PlanetSideGUID(1)) mustEqual true
|
||||||
obj.Router = PlanetSideGUID(0)
|
obj.Router = PlanetSideGUID(0)
|
||||||
obj.Router mustEqual None
|
obj.Router.isEmpty mustEqual true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package objects
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
import net.psforever.objects.definition.ObjectDefinition
|
import net.psforever.objects.definition.ObjectDefinition
|
||||||
import net.psforever.objects.entity.NoGUIDException
|
import net.psforever.objects.entity.NoGUIDException
|
||||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
import net.psforever.types.{PlanetSideGUID, StalePlanetSideGUID, ValidPlanetSideGUID, Vector3}
|
||||||
import org.specs2.mutable._
|
import org.specs2.mutable._
|
||||||
|
|
||||||
class EntityTest extends Specification {
|
class EntityTest extends Specification {
|
||||||
|
|
@ -13,6 +13,44 @@ class EntityTest extends Specification {
|
||||||
def Definition : ObjectDefinition = new ObjectDefinition(0) { }
|
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 {
|
"SimpleWorldEntity" should {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
new EntityTestClass()
|
new EntityTestClass()
|
||||||
|
|
@ -107,64 +145,129 @@ class EntityTest extends Specification {
|
||||||
|
|
||||||
"error while not set" in {
|
"error while not set" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.HasGUID mustEqual false
|
|
||||||
obj.GUID must throwA[NoGUIDException]
|
obj.GUID must throwA[NoGUIDException]
|
||||||
}
|
}
|
||||||
|
|
||||||
"work after mutation" in {
|
"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]
|
||||||
|
(obj.GUID = StalePlanetSideGUID(1)) must throwA[NoGUIDException]
|
||||||
|
}
|
||||||
|
|
||||||
|
"work after valid mutation" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.GUID = PlanetSideGUID(1051)
|
obj.GUID = PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual true
|
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
}
|
}
|
||||||
|
|
||||||
"work after multiple mutations" in {
|
"ignore subsequent mutations using a valid GUID" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.GUID = PlanetSideGUID(1051)
|
obj.GUID = PlanetSideGUID(1051)
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
obj.GUID = PlanetSideGUID(30052)
|
obj.GUID = ValidPlanetSideGUID(1)
|
||||||
obj.GUID mustEqual PlanetSideGUID(30052)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
obj.GUID = PlanetSideGUID(62)
|
|
||||||
obj.GUID mustEqual PlanetSideGUID(62)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"invalidate and report as not having a GUID, but continue to work" in {
|
"ignore subsequent mutations using an invalid GUID" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.GUID = PlanetSideGUID(1051)
|
obj.GUID = PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual true
|
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
|
obj.GUID = StalePlanetSideGUID(1)
|
||||||
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
|
}
|
||||||
|
|
||||||
|
"invalidate does nothing by default" in {
|
||||||
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.Invalidate()
|
obj.Invalidate()
|
||||||
obj.HasGUID mustEqual false
|
obj.GUID must throwA[NoGUIDException]
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"assign a new GUID after invalidation and continue to work" in {
|
"invalidate changes the nature of the previous valid mutation" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
obj.GUID = PlanetSideGUID(1051)
|
obj.GUID = PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual true
|
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
|
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||||
obj.Invalidate()
|
obj.Invalidate()
|
||||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual false
|
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||||
|
|
||||||
obj.GUID = PlanetSideGUID(1052)
|
|
||||||
obj.HasGUID mustEqual true
|
|
||||||
obj.GUID mustEqual PlanetSideGUID(1052)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"assignthe same GUID after invalidation and continue to work" in {
|
"setting an invalid GUID after invalidating the previous valid mutation returns the same" in {
|
||||||
val obj : EntityTestClass = new EntityTestClass
|
val obj : EntityTestClass = new EntityTestClass
|
||||||
val guid = new PlanetSideGUID(1051)
|
obj.GUID = PlanetSideGUID(1051)
|
||||||
obj.GUID = guid
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual true
|
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||||
obj.GUID mustEqual guid
|
|
||||||
obj.Invalidate()
|
obj.Invalidate()
|
||||||
obj.GUID mustEqual guid
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
obj.HasGUID mustEqual false
|
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||||
|
obj.GUID = StalePlanetSideGUID(2)
|
||||||
|
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||||
|
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||||
|
}
|
||||||
|
|
||||||
obj.GUID = guid
|
"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
|
obj.HasGUID mustEqual true
|
||||||
obj.GUID mustEqual guid
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"hachCode test" in {
|
||||||
|
ValidPlanetSideGUID(1051).hashCode mustEqual ValidPlanetSideGUID(1051).hashCode
|
||||||
|
ValidPlanetSideGUID(1051).hashCode mustEqual StalePlanetSideGUID(1051).hashCode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue