//////////////////////////////////////////
 // TEST: testTSODeleteObjectBelowLBTS() //
 //////////////////////////////////////////
 @Test
 public void testTSODeleteObjectBelowLBTS() {
   try {
     LogicalTime time = TypeFactory.createTime(1.0);
     defaultFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
     expectedException(InvalidLogicalTime.class);
   } catch (InvalidLogicalTime ilt) {
     // success!
   } catch (Exception e) {
     wrongException(e, InvalidLogicalTime.class);
   }
 }
 //////////////////////////////////////////////////
 // TEST: testTSODeleteObjectWithInvalidHandle() //
 //////////////////////////////////////////////////
 @Test
 public void testTSODeleteObjectWithInvalidHandle() {
   // try and delete and object that doesn't exist
   try {
     LogicalTime time = TypeFactory.createTime(5.0);
     defaultFederate.rtiamb.deleteObjectInstance(getObjectHandle(111111), tag, time);
     expectedException(ObjectInstanceNotKnown.class);
   } catch (ObjectInstanceNotKnown oink) {
     // success!
   } catch (Exception e) {
     wrongException(e, ObjectInstanceNotKnown.class);
   }
 }
  ///////////////////////////////////////
  // TEST: testTSODeleteObjectInPast() //
  ///////////////////////////////////////
  @Test
  public void testTSODeleteObjectInPast() {
    // advance the federate a bit, so that we can delete them in the past
    defaultFederate.quickAdvanceAndWait(20.0);

    try {
      LogicalTime time = TypeFactory.createTime(10.0);
      defaultFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
      expectedException(InvalidLogicalTime.class);
    } catch (InvalidLogicalTime ilt) {
      // success!
    } catch (Exception e) {
      wrongException(e, InvalidLogicalTime.class);
    }
  }
  //////////////////////////////////////////////
  // TEST: testTSODeleteObjectThatIsUnowned() //
  //////////////////////////////////////////////
  @Test
  public void testTSODeleteObjectThatIsUnowned() {
    // delete it with the second federate, where the defaultFederate is the owner
    // enable regulating so that the time isn't just disregarded as a matter of course
    secondFederate.quickEnableRegulating(1.0);

    try {
      LogicalTime time = TypeFactory.createTime(5.0);
      secondFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
      expectedException(DeletePrivilegeNotHeld.class);
    } catch (DeletePrivilegeNotHeld dpnh) {
      // success!
    } catch (Exception e) {
      wrongException(e, DeletePrivilegeNotHeld.class);
    }
  }
  ///////////////////////////////////////////////
  // TEST: (valid) testRODeleteWithTimestamp() //
  ///////////////////////////////////////////////
  @Test
  public void testRODeleteWithTimestamp() {
    // disable regulating so that the method SHOULD be sent RO even through
    // we supply it with a timestamp
    defaultFederate.quickDisableRegulating();

    // try and delete an existing object
    try {
      LogicalTime time = TypeFactory.createTime(10.0);
      defaultFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
    } catch (Exception e) {
      Assert.fail("Exception while deleting object RO");
    }

    // wait for the object to be removed
    secondFederate.fedamb.waitForRORemoval(oHandle);
    thirdFederate.fedamb.waitForRORemoval(oHandle);
  }
  /////////////////////////////////////////////
  // TEST: testTSODeleteObjectUndiscovered() //
  /////////////////////////////////////////////
  @Test
  public void testTSODeleteObjectUndiscovered() {
    // try and delete and object that hasn't been discovered
    // this will require a new federate that doesn't subscribe to ObjectRoot.A or below
    // it also needs to be regulating so that the time isn't disregarded as a matter of course
    TestFederate fourthFederate = new TestFederate("fourthFederate", this);
    fourthFederate.quickJoin();
    fourthFederate.quickEnableRegulating(5.0);

    try {
      LogicalTime time = TypeFactory.createTime(5.0);
      fourthFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
      expectedException(ObjectInstanceNotKnown.class);
    } catch (ObjectInstanceNotKnown onk) {
      // success!
    } catch (Exception e) {
      wrongException(e, ObjectInstanceNotKnown.class);
    } finally {
      // clean up after ourselves
      fourthFederate.quickResign();
    }
  }
  /////////////////////////////////////////
  // TEST: (valid) testTSODeleteObject() //
  /////////////////////////////////////////
  @Test
  public void testTSODeleteObject() {
    // try and delete an existing object
    try {
      LogicalTime time = TypeFactory.createTime(10.0);
      defaultFederate.rtiamb.deleteObjectInstance(getObjectHandle(oHandle), tag, time);
    } catch (Exception e) {
      Assert.fail("Exception while deleting object RO");
    }

    // wait for the object to be removed in the non-constrained federate
    thirdFederate.fedamb.waitForRORemoval(oHandle);

    // wait for the removal in the constrained federate, we shouldn't get it yet
    secondFederate.fedamb.waitForTSORemovalTimeout(oHandle);

    // advance time in the relevant federates far enough to enable
    // delivery of the removal notification
    defaultFederate.quickAdvanceAndWait(20.0);
    secondFederate.quickAdvanceRequest(20.0);
    // make sure we receive the event
    secondFederate.fedamb.waitForTSORemoval(oHandle);
  }