@@ -0,0 +1,1806 @@
+from thespian.actors import *%0Afrom thespian.test import *%0Aimport time%0Afrom datetime import timedelta%0Aimport sys%0A%0A%0Amax_response_delay = timedelta(seconds=1.0)%0A%0A%0Aclass BadMessage(object):%0A    def __init__(self, val):%0A        self.val = val%0A    def __str__(self):%0A        return 'Using an invalid member: ' + str(self.this_does_not_exist)%0A%0Aclass BadMessage2(object):     # ok to str() this one%0A    def __init__(self, val):%0A        self.val = val%0A    def __str__(self):%0A        return 'BadMsg2=' + str(self.val)%0A%0A%0Aclass MyActor(Actor):%0A    def __init__(self):%0A        self.count = 0%0A    def receiveMessage(self, msg, sender):%0A        self.count += 1%0A        if isinstance(msg, (BadMessage, BadMessage2)) and (self.count & 1):%0A            raise Exception('Got a BadMessage: ' + str(msg))%0A        if not isinstance(msg, ActorSystemMessage):%0A            self.send(sender, str(msg))%0A%0A%0Adef test01_actorWorks(asys):%0A    mya = asys.createActor(MyActor)%0A    r = asys.ask(mya, 123, max_response_delay)%0A    assert r == '123'%0A%0Adef test02_alwaysBad(asys):%0A    mya = asys.createActor(MyActor)%0A    r = asys.ask(mya, BadMessage(135), max_response_delay)%0A    assert isinstance(r, PoisonMessage)%0A    assert isinstance(r.poisonMessage, BadMessage)%0A    assert r.poisonMessage.val == 135%0A%0A%0Adef test03_intermittentlyBad(asys):%0A    mya = asys.createActor(MyActor)%0A%0A    # First one should be OK%0A    r = asys.ask(mya, BadMessage2(987), max_response_delay)%0A    assert r is not None%0A    assert '987' in r%0A%0A    # Second one gets the exception the first time around, but the%0A    # Actor should be re-instated and the message retried, and it%0A    # should work the second time, so the failure is undetectable at%0A    # this level.%0A    r2 = asys.ask(mya, BadMessage2(654), max_response_delay)%0A    assert r2 is not None%0A    assert '654' in r2%0A

Add tests for bad messages, and actor message retries.