1
0
mirror of https://github.com/gsi-upm/soil synced 2024-11-22 03:02:28 +00:00

Add test cases for 'ASK'

This commit is contained in:
J. Fernando Sánchez 2022-10-20 14:10:34 +02:00
parent a1262edd2a
commit b2d48cb4df
4 changed files with 48 additions and 33 deletions

View File

@ -52,11 +52,11 @@ class EventedAgent(BaseAgent):
def tell(self, msg, sender=None): def tell(self, msg, sender=None):
self._inbox.append(Tell(timestamp=self.now, payload=msg, sender=sender)) self._inbox.append(Tell(timestamp=self.now, payload=msg, sender=sender))
def ask(self, msg, timeout=None): def ask(self, msg, timeout=None, **kwargs):
ask = Ask(timestamp=self.now, payload=msg) ask = Ask(timestamp=self.now, payload=msg, sender=self)
self._inbox.append(ask) self._inbox.append(ask)
expiration = float('inf') if timeout is None else self.now + timeout expiration = float('inf') if timeout is None else self.now + timeout
return ask.replied(expiration=expiration) return ask.replied(expiration=expiration, **kwargs)
def check_messages(self): def check_messages(self):
changed = False changed = False

View File

@ -38,7 +38,7 @@ class BaseEnvironment(Model):
self, self,
id="unnamed_env", id="unnamed_env",
seed="default", seed="default",
schedule=None, schedule_class=time.TimedActivation,
dir_path=None, dir_path=None,
interval=1, interval=1,
agent_class=None, agent_class=None,
@ -58,9 +58,11 @@ class BaseEnvironment(Model):
self.dir_path = dir_path or os.getcwd() self.dir_path = dir_path or os.getcwd()
if schedule is None: if schedule_class is None:
schedule = time.TimedActivation(self) schedule_class = time.TimedActivation
self.schedule = schedule else:
schedule_class = serialization.deserialize(schedule_class)
self.schedule = schedule_class(self)
self.agent_class = agent_class or agentmod.BaseAgent self.agent_class = agent_class or agentmod.BaseAgent

View File

@ -192,3 +192,13 @@ class TimedActivation(BaseScheduler):
self.logger.debug(f"Updating time step: {self.time} -> {next_time}") self.logger.debug(f"Updating time step: {self.time} -> {next_time}")
self.time = next_time self.time = next_time
class ShuffledTimedActivation(TimedActivation):
def __init__(self, *args, **kwargs):
super().__init__(*args, shuffle=True, **kwargs)
class OrderedTimedActivation(TimedActivation):
def __init__(self, *args, **kwargs):
super().__init__(*args, shuffle=False, **kwargs)

View File

@ -103,7 +103,19 @@ class TestAgents(TestCase):
An agent should be able to ask another agent, and wait for a response. An agent should be able to ask another agent, and wait for a response.
''' '''
# #Results depend on ordering (agents are shuffled), so force the first agent # There are two agents, they try to send pings
# This is arguably a very contrived example. In practice, the or
# There should be a delay of one step between agent 0 and 1
# On the first step:
# Agent 0 sends a PING, but blocks before a PONG
# Agent 1 detects the PING, responds with a PONG, and blocks after its own PING
# After that step, every agent can both receive (there are pending messages) and send.
# In each step, for each agent, one message is sent, and another one is received
# (although not necessarily in that order).
# Results depend on ordering (agents are normally shuffled)
# so we force the timedactivation not to be shuffled
pings = [] pings = []
pongs = [] pongs = []
responses = [] responses = []
@ -114,46 +126,37 @@ class TestAgents(TestCase):
target = self.model.agents[target_id] target = self.model.agents[target_id]
print('starting') print('starting')
while True: while True:
print('Pings: ', pings, responses or not pings, self.model.schedule._queue) if pongs or not pings: #First agent, or anyone after that
if pongs or not pings:
pings.append(self.now) pings.append(self.now)
response = yield target.ask('PING') response = yield target.ask('PING')
responses.append(response) responses.append(response)
else: else:
print('NOT sending ping') print('NOT sending ping')
print('Checking msgs') print('Checking msgs')
# Do not advance until we have received a message. # Do not block if we have already received a PING
# warning: it will wait at least until the next time in the simulation if not self.check_messages():
yield self.received(check=True) yield self.received()
print('done') print('done')
def on_receive(self, msg, sender=None): def on_receive(self, msg, sender=None):
if msg == 'PING': if msg == 'PING':
pongs.append(self.now) pongs.append(self.now)
return 'PONG' return 'PONG'
raise Exception("This should never happen")
e = environment.EventedEnvironment() e = environment.EventedEnvironment(schedule_class=stime.OrderedTimedActivation)
for i in range(2): for i in range(2):
e.add_agent(agent_class=Ping) e.add_agent(agent_class=Ping)
assert e.now == 0 assert e.now == 0
# There should be a delay of one step between agent 0 and 1
# On the first step:
# Agent 0 sends a PING, but blocks before a PONG
# Agent 1 sends a PONG, and blocks after its PING
# After that step, every agent can both receive (there are pending messages) and then send.
for i in range(5):
e.step() e.step()
assert e.now == 1 time = i + 1
assert pings == [0] assert e.now == time
assert pongs == [] assert len(pings) == 2 * time
assert len(pongs) == (2 * time) - 1
e.step() # Every step between 0 and t appears twice
assert e.now == 2 assert sum(pings) == sum(range(time)) * 2
assert pings == [0, 1] # It is the same as pings, without the leading 0
assert pongs == [1] assert sum(pongs) == sum(range(time)) * 2
e.step()
assert e.now == 3
assert pings == [0, 1, 2]
assert pongs == [1, 2]