Commit b7c6e890c038aadcc7d147594a870a2a299e5692

Authored by Etienne Pallier
1 parent 0ab234ad
Exists in dev

Test de tous les cas d'erreur possibles dans AgentBasic

privatedev/plugin/agent/AgentBasic.py
1 1 #!/usr/bin/env python3
2 2  
3 3  
  4 +import time
4 5 import sys
5 6 ##import utils.Logger as L
6 7  
... ... @@ -24,7 +25,7 @@ class AgentBasic(Agent):
24 25 # Run the assertion tests at the end
25 26 TEST_WITH_FINAL_TEST = False
26 27 #TEST_MAX_DURATION_SEC = None
27   - TEST_MAX_DURATION_SEC = 100
  28 + TEST_MAX_DURATION_SEC = 180
28 29 # Who should I send commands to ?
29 30 TEST_COMMANDS_DEST = "myself"
30 31 #TEST_COMMANDS_DEST = "AgentB"
... ... @@ -36,7 +37,7 @@ class AgentBasic(Agent):
36 37 ("do_specific10", 10, 0),
37 38 #("set_specific2", 5, 0),
38 39 ("do_specific30", 3, 0),
39   - ####("existing_but_unimplemented_cmd", 3, 0),
  40 + ("existing_but_unimplemented_cmd", 3, 0),
40 41 ]
41 42  
42 43 # @override
... ... @@ -46,28 +47,66 @@ class AgentBasic(Agent):
46 47 #("self do_stop now", 200, '', Agent.CMD_STATUS.CMD_EXECUTED),
47 48  
48 49 # do_stop
  50 +
49 51 #("self do_stop now", 200, 'STOPPING now', Agent.CMD_STATUS.CMD_EXECUTED),
50 52 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
51 53 #("self do_stop asap", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
52 54  
  55 + # do_restart
  56 +
53 57 ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
54   - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
55   - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
56   - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  58 + #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
57 59  
  60 + # ------------------------------
  61 + # ------ A - ERROR CASES -------
  62 + # ------------------------------
58 63  
59   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', None),
60   -
61   - # bad parameters (missing or too many, or bad type)=> CMD_INVALID
62   - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
63   -
64   - # bad command => CMD_INVALID
  64 + # - Error case 1 - unimplemented command in agent specific commands list
  65 + # get_specific_cmds KO (with existing_but_unimplemented_cmd)
  66 + ("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
  67 + # get_specific_cmds OK (all commands implemented)
  68 + #("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
  69 +
  70 + # - Error case 2 - CMD_INVALID
  71 + # unknwon command
65 72 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
66 73 ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID),
67   -
68   - # Existing but unimplemented cmd => CMD_UNIMPLEMENTED
  74 + # bad parameters (missing or too many, or bad type)
  75 + # missing args
  76 + ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  77 + # missing args
  78 + ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  79 + # - too many args
  80 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  81 + # - bad type
  82 + ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  83 + # - OK
  84 + #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  85 +
  86 + # - Error case 3 - CMD_UNIMPLEMENTED
69 87 ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
70 88  
  89 + # - Error case 4 - CMD_EXPIRED
  90 + # This command has a validity of 0s and thus should be tagged as "expired"
  91 + ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
  92 +
  93 + # - Error case 5 - CMD_SKIPPED
  94 + # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
  95 + ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  96 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
  97 + # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
  98 + ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  99 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  100 +
  101 + # ------------------------------
  102 + # ------ B - NORMAL CASES -------
  103 + # ------------------------------
  104 +
  105 + # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
  106 + #("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
  107 + # FIXME: ajouter la possibilité d'utiliser des expressions pour tester le résultat :
  108 + #("self get_iteration_number", 200, 'EXPR:<=4', Agent.CMD_STATUS.CMD_EXECUTED),
  109 +
71 110 # 1) First, 3 EXCEPTION CASES (uncomment to activate exception)
72 111 # Each of these lines will stop execution with an exception
73 112 # ------------------------------------------------------------
... ... @@ -89,10 +128,6 @@ class AgentBasic(Agent):
89 128 # All these commands should be executed without error, from the 1st to the last one
90 129 # -------------------------------
91 130  
92   - # This command has a validity of 0s and thus should be tagged as "expired"
93   - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
94   - # ("self set_mode ATTENTIVE", 0, "MODE = ATTENTIVE", AgentCmd.CMD_STATUS_CODES),
95   -
96 131 # Agent general command
97 132 ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
98 133 ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
... ... @@ -100,7 +135,8 @@ class AgentBasic(Agent):
100 135 ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
101 136  
102 137 # End test
103   - ("self do_stop asap", 200, None, Agent.CMD_STATUS.CMD_EXECUTED),
  138 + ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  139 +
104 140 ]
105 141  
106 142  
... ... @@ -141,6 +177,7 @@ class AgentBasic(Agent):
141 177  
142 178 # @override
143 179 def main_loop_end(self):
  180 + self.sleep(3)
144 181 print("AgentBasic LOOP END");
145 182  
146 183 # @override
... ...
src/core/pyros_django/agent/Agent.py
... ... @@ -397,9 +397,9 @@ class Agent:
397 397 #
398 398 # - validity : the command is valid for this duration, afterwards you can forget it
399 399 #
400   - # - expected_res : the expected result
  400 + # - expected_res : the expected result (set to None if not to be tested)
401 401 #
402   - # - expected_status : the status of the command expected after execution (expired, killed, skipped, executed...)
  402 + # - expected_status : the status of the command expected after execution (expired, killed, skipped, executed...) (set to None if not to be tested)
403 403 #
404 404 # Ex :
405 405 # - "AgentScheduler set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to the agent AgentScheduler
... ... @@ -407,7 +407,7 @@ class Agent:
407 407 # - "self set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to MYSELF
408 408 # - "self do_restart_loop" => means to send the command "do_restart_loop" to MYSELF (no args)
409 409 #
410   - TEST_COMMANDS_LIST: List[ Tuple[ str, int, str, Union[int,None] ] ] = [
  410 + TEST_COMMANDS_LIST: List[ Tuple[ str, int, Union[str,None], Union[int,None] ] ] = [
411 411  
412 412 # Format : ("self cmd_name cmd_args", timeout, "expected_result", expected_status),
413 413 #("self do_stop now", 200, '15.5', None),
... ... @@ -1092,6 +1092,8 @@ class Agent:
1092 1092 if cmd.name != "get_specific_cmds":
1093 1093 cmd.set_as_unimplemented("EXCEPTION: command known but unimplemented")
1094 1094 elif type(e) in (CmdBadArgsException, CmdUnknownException):
  1095 + # set back to "pending" if ever was wrongly marked "running"
  1096 + #cmd.set_as_pending()
1095 1097 cmd.set_as_invalid("EXCEPTION: command unknown or bad args")
1096 1098 # Execution Exception
1097 1099 elif type(e) != CmdExecErrorException:
... ... @@ -1184,7 +1186,7 @@ class Agent:
1184 1186  
1185 1187  
1186 1188 # To be overriden by subclass (AgentDevice)
1187   - def process_device_level_cmd(self):
  1189 + def process_device_level_cmd(self, cmd):
1188 1190 pass
1189 1191 '''
1190 1192 log.info("(DEVICE LEVEL CMD)")
... ... @@ -1247,51 +1249,11 @@ class Agent:
1247 1249 if self._is_agent_general_cmd(cmd):
1248 1250 try:
1249 1251 self._process_agent_general_cmd(cmd)
1250   - except CmdUnimplementedException as e:
1251   - #print(e)
1252   - #cmd.set_as_skipped("ERROR: Unimplemented Agent General command")
1253   - #self._cleanup_before_exist()
1254   - # This exception is managed at higher level :
1255   - raise
1256   - #except ValueError as e:
1257   - except CmdBadArgsException as e:
1258   - #print(e)
1259   - #cmd.set_as_skipped("ERROR: Bad Argument(s)")
1260   - #self._cleanup_before_exit()
1261   - # This exception is managed at higher level :
  1252 + except (CmdUnimplementedException, CmdBadArgsException) :
  1253 + # cmd should not be set as "running"
  1254 + cmd.set_as_pending()
  1255 + # These exceptions are managed at higher level :
1262 1256 raise
1263   - #raise AgentCmdBadArgsException(cmd.name)
1264   - # Must I stop or restart ?
1265   - # cmd.args => ['arg1','arg2',...]
1266   - #print("nom", cmd.name)
1267   - '''
1268   - if cmd.name=="do_stop":
1269   - # by default = "asap"
1270   - if cmd.args is None: cmd.full_name = "do_exit"
1271   - else:
1272   - arg = cmd.args[0]
1273   - if arg =='asap': cmd.full_name = "do_exit"
1274   - elif arg =='now': cmd.full_name = "do_abort"
1275   - else: raise CmdBadArgsException(cmd)
1276   - '''
1277   - #print("nom", cmd.name)
1278   - #print(self.get_specific_cmds())
1279   - #exit(0)
1280   - #if cmd.name in ('do_restart','do_exit','do_abort') :
1281   - '''
1282   - if cmd.name in ('do_restart','do_stop'):
1283   - #print(cmd)
1284   - self.DO_MAIN_LOOP = False
1285   - if cmd.name == 'do_abort':
1286   - self._abort_current_running_cmd_if_exists()
1287   - self._cleanup_before_exit()
1288   - if cmd.name != 'do_restart':
1289   - self.DO_RESTART_LOOP = False
1290   - self._set_status(self.AGT_STATUS.EXITING)
1291   - # log last agent mode & status
1292   - self._log_agent_state()
1293   - #cmd.set_result('EXITING')
1294   - '''
1295 1257 return cmd
1296 1258  
1297 1259 # CASE 2 - AGENT SPECIFIC command
... ... @@ -1306,16 +1268,8 @@ class Agent:
1306 1268 #self._exec_agent_cmd(cmd)
1307 1269 #except AttributeError as e:
1308 1270 except (CmdUnimplementedException, CmdBadArgsException) as e:
1309   - ##print(e)
1310   - #self.log_e(f"EXCEPTION: Agent level specific command '{cmd.name}' unknown (not implemented as a function) :", e)
1311   - #self.log_e("Thus => I ignore this command...")
1312   - ##log.error(f"EXCEPTION: Agent specific command '{cmd.name}' unknown (not implemented as a function) :", e)
1313   - #log.e("Thus => I ignore this command...")
1314   - #cmd.set_result("ERROR: UNIMPLEMENTED AGENT SPECIFIC COMMAND", False)
  1271 + # cmd should not be set as "running"
1315 1272 #cmd.set_as_pending()
1316   - ##cmd.set_as_skipped("ERROR: UNIMPLEMENTED AGENT SPECIFIC COMMAND")
1317   - ##self._cleanup_before_exit()
1318   - ##raise AgentCmdUnimplementedException(cmd.name)
1319 1273 # These exceptions are managed at higher level :
1320 1274 raise
1321 1275 return cmd
... ... @@ -2496,7 +2450,7 @@ class Agent:
2496 2450 log.debug(cmd.result)
2497 2451 log.debug(self._cmdts.expected_res)
2498 2452 ##if cmd.is_executed() and self._cmdts.expected_res:
2499   - if cmd.is_finished() and self._cmdts.expected_res:
  2453 + if cmd.is_finished() and self._cmdts.expected_res is not None:
2500 2454 actual=str(cmd.result)
2501 2455 expected=self._cmdts.expected_res
2502 2456 #print(actual, ' <= vs =>', expected)
... ... @@ -2505,7 +2459,7 @@ class Agent:
2505 2459 log.debug(cmd.state)
2506 2460 log.debug(self._cmdts.expected_status)
2507 2461 #if hasattr(self._cmdts,'expected_status'):
2508   - if self._cmdts.expected_status:
  2462 + if self._cmdts.expected_status is not None:
2509 2463 #assert(cmd.state == self._cmdts.expected_status)
2510 2464 actual=cmd.state
2511 2465 expected=self._cmdts.expected_status
... ...
src/core/pyros_django/agent/AgentBasic.py
1 1 #!/usr/bin/env python3
2 2  
3 3  
  4 +import time
4 5 import sys
5 6 ##import utils.Logger as L
6 7  
... ... @@ -24,7 +25,7 @@ class AgentBasic(Agent):
24 25 # Run the assertion tests at the end
25 26 TEST_WITH_FINAL_TEST = False
26 27 #TEST_MAX_DURATION_SEC = None
27   - TEST_MAX_DURATION_SEC = 100
  28 + TEST_MAX_DURATION_SEC = 180
28 29 # Who should I send commands to ?
29 30 TEST_COMMANDS_DEST = "myself"
30 31 #TEST_COMMANDS_DEST = "AgentB"
... ... @@ -36,7 +37,7 @@ class AgentBasic(Agent):
36 37 ("do_specific10", 10, 0),
37 38 #("set_specific2", 5, 0),
38 39 ("do_specific30", 3, 0),
39   - ####("existing_but_unimplemented_cmd", 3, 0),
  40 + ("existing_but_unimplemented_cmd", 3, 0),
40 41 ]
41 42  
42 43 # @override
... ... @@ -46,28 +47,66 @@ class AgentBasic(Agent):
46 47 #("self do_stop now", 200, '', Agent.CMD_STATUS.CMD_EXECUTED),
47 48  
48 49 # do_stop
  50 +
49 51 #("self do_stop now", 200, 'STOPPING now', Agent.CMD_STATUS.CMD_EXECUTED),
50 52 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
51 53 #("self do_stop asap", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
52 54  
  55 + # do_restart
  56 +
53 57 ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
54   - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
55   - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
56   - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  58 + #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
57 59  
  60 + # ------------------------------
  61 + # ------ A - ERROR CASES -------
  62 + # ------------------------------
58 63  
59   - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', None),
60   -
61   - # bad parameters (missing or too many, or bad type)=> CMD_INVALID
62   - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
63   -
64   - # bad command => CMD_INVALID
  64 + # - Error case 1 - unimplemented command in agent specific commands list
  65 + # get_specific_cmds KO (with existing_but_unimplemented_cmd)
  66 + ("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR),
  67 + # get_specific_cmds OK (all commands implemented)
  68 + #("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED),
  69 +
  70 + # - Error case 2 - CMD_INVALID
  71 + # unknwon command
65 72 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
66 73 ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID),
67   -
68   - # Existing but unimplemented cmd => CMD_UNIMPLEMENTED
  74 + # bad parameters (missing or too many, or bad type)
  75 + # missing args
  76 + ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  77 + # missing args
  78 + ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  79 + # - too many args
  80 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  81 + # - bad type
  82 + ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID),
  83 + # - OK
  84 + #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  85 +
  86 + # - Error case 3 - CMD_UNIMPLEMENTED
69 87 ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
70 88  
  89 + # - Error case 4 - CMD_EXPIRED
  90 + # This command has a validity of 0s and thus should be tagged as "expired"
  91 + ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
  92 +
  93 + # - Error case 5 - CMD_SKIPPED
  94 + # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
  95 + ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  96 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
  97 + # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
  98 + ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  99 + ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  100 +
  101 + # ------------------------------
  102 + # ------ B - NORMAL CASES -------
  103 + # ------------------------------
  104 +
  105 + # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
  106 + #("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
  107 + # FIXME: ajouter la possibilité d'utiliser des expressions pour tester le résultat :
  108 + #("self get_iteration_number", 200, 'EXPR:<=4', Agent.CMD_STATUS.CMD_EXECUTED),
  109 +
71 110 # 1) First, 3 EXCEPTION CASES (uncomment to activate exception)
72 111 # Each of these lines will stop execution with an exception
73 112 # ------------------------------------------------------------
... ... @@ -89,10 +128,6 @@ class AgentBasic(Agent):
89 128 # All these commands should be executed without error, from the 1st to the last one
90 129 # -------------------------------
91 130  
92   - # This command has a validity of 0s and thus should be tagged as "expired"
93   - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
94   - # ("self set_mode ATTENTIVE", 0, "MODE = ATTENTIVE", AgentCmd.CMD_STATUS_CODES),
95   -
96 131 # Agent general command
97 132 ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
98 133 ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
... ... @@ -100,7 +135,8 @@ class AgentBasic(Agent):
100 135 ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
101 136  
102 137 # End test
103   - ("self do_stop asap", 200, None, Agent.CMD_STATUS.CMD_EXECUTED),
  138 + ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
  139 +
104 140 ]
105 141  
106 142  
... ... @@ -141,6 +177,7 @@ class AgentBasic(Agent):
141 177  
142 178 # @override
143 179 def main_loop_end(self):
  180 + self.sleep(3)
144 181 print("AgentBasic LOOP END");
145 182  
146 183 # @override
... ...