11# SPDX-License-Identifier: Apache-2.0
22from __future__ import annotations
33
4+ import glob
45import json
56import logging
67import os
1314import threading
1415import time
1516import xml .etree .ElementTree as ET
17+ import random
1618from collections import OrderedDict
1719from enum import Enum
1820
@@ -969,13 +971,15 @@ class Bsim(Harness):
969971 DEFAULT_VERBOSITY = 2
970972 DEFAULT_SIM_LENGTH = 60e6
971973
972- BSIM_READY_TIMEOUT_S = 20
974+ BSIM_READY_TIMEOUT_S = 60
973975
974976 cacheable = True
975977
976978 def __init__ (self ):
977979 super ().__init__ ()
978980 self ._bsim_out_path = os .getenv ('BSIM_OUT_PATH' , '' )
981+ if self ._bsim_out_path :
982+ self ._bsim_out_path = os .path .join (self ._bsim_out_path , 'bin' )
979983 self ._exe_paths = []
980984 self ._tc_output = []
981985 self ._start_time = 0
@@ -1002,7 +1006,7 @@ def configure(self, instance):
10021006 exe_names = [f'bs_{ self .instance .name } ' ]
10031007
10041008 self ._exe_paths = \
1005- [os .path .join (self ._bsim_out_path , 'bin' , exe_name ) for exe_name in exe_names ]
1009+ [os .path .join (self ._bsim_out_path , exe_name ) for exe_name in exe_names ]
10061010
10071011 def clean_exes (self ):
10081012 for exe_path in [self ._get_exe_path (i ) for i in range (len (self ._exe_paths ))]:
@@ -1045,8 +1049,9 @@ def build(self):
10451049 self .instance .execution_time = time .time () - self ._start_time
10461050
10471051 def _run_cmd (self , cmd , timeout ):
1052+ logger .debug (' ' .join (cmd ))
10481053 with subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .PIPE ,
1049- cwd = os . path . join ( self ._bsim_out_path , 'bin' ) ) as proc :
1054+ cwd = self ._bsim_out_path ) as proc :
10501055 try :
10511056 reader_t = threading .Thread (target = self ._output_reader , args = (proc ,), daemon = True )
10521057 reader_t .start ()
@@ -1061,8 +1066,11 @@ def _run_cmd(self, cmd, timeout):
10611066 self .status = TwisterStatus .ERROR
10621067 proc .kill ()
10631068
1064- if self .status == TwisterStatus .NONE :
1065- self .status = TwisterStatus .FAIL if proc .returncode != 0 else TwisterStatus .PASS
1069+ if proc .returncode != 0 :
1070+ self .status = TwisterStatus .ERROR
1071+ self .instance .reason = f'Bsim error - return code { proc .returncode } '
1072+ else :
1073+ self .status = TwisterStatus .PASS if self .status == TwisterStatus .NONE else self .status
10661074
10671075 def _output_reader (self , proc ):
10681076 while proc .stdout .readable () and proc .poll () is None :
@@ -1074,25 +1082,48 @@ def _output_reader(self, proc):
10741082 proc .communicate ()
10751083
10761084 def _generate_commands (self ):
1077- bsim_phy_path = os .path .join (self ._bsim_out_path , 'bin' , 'bs_2G4_phy_v1' )
1085+ def rs ():
1086+ return f'-rs={ random .randint (0 , 2 ** 10 - 1 )} '
1087+
1088+ def expand_args (dev_id ):
1089+ try :
1090+ args = [str (eval (v )[dev_id ]) if v .startswith ('[' ) else v for v in extra_args ]
1091+ return [arg for arg in args if args if arg ]
1092+ except Exception as e :
1093+ logger .warning (f'Unable to expand extra arguments set { extra_args } : { e } ' )
1094+ return extra_args
1095+
1096+ bsim_phy_path = os .path .join (self ._bsim_out_path , 'bs_2G4_phy_v1' )
10781097 suite_id = f'-s={ self .instance .name .split (os .path .sep )[- 1 ].replace ("." , "_" )} '
10791098
10801099 cfg = self .instance .testsuite .harness_config
10811100 verbosity = f'-v={ cfg .get ("bsim_verbosity" , self .DEFAULT_VERBOSITY )} '
10821101 sim_length = f'-sim_length={ cfg .get ("bsim_sim_length" , self .DEFAULT_SIM_LENGTH )} '
10831102 extra_args = cfg .get ('bsim_options' , [])
1103+ phy_extra_args = cfg .get ('bsim_phy_options' , [])
10841104 test_ids = cfg .get ('bsim_test_ids' , [])
10851105 if not test_ids :
10861106 logger .error ('No test ids specified for bsim test' )
10871107 self .status = TwisterStatus .ERROR
10881108 return []
10891109
1090- cmds = [[self ._get_exe_path (i ), verbosity , suite_id , f'-d={ i } ' , f'-testid={ t_id } ' ] + extra_args
1091- for i , t_id in enumerate (test_ids )]
1092- cmds .append ([bsim_phy_path , verbosity , suite_id , f'-D={ len (test_ids )} ' , sim_length ])
1110+ cmds = [[self ._get_exe_path (i ), verbosity , suite_id , f'-d={ i } ' , f'-testid={ t_id } ' , rs ()]
1111+ + expand_args (i ) for i , t_id in enumerate (test_ids )]
1112+ cmds .append ([bsim_phy_path , verbosity , suite_id , f'-D={ len (test_ids )} ' , sim_length ]
1113+ + phy_extra_args )
10931114
10941115 return cmds
10951116
1117+ def _clean_up_files (self ):
1118+ # Clean-up any log files that the test may have generated
1119+ files = glob .glob (os .path .join (self ._bsim_out_path , '*.log' ))
1120+ # files += glob.glob(os.path.join(self._bsim_out_path, '*.bin'))
1121+ try :
1122+ for file in [f for f in files if os .path .getctime (f ) > self ._start_time ]:
1123+ os .remove (file )
1124+ except Exception as e :
1125+ logger .warning (f'Failed to clean up bsim log files: { e } ' )
1126+
10961127 def bsim_run (self , timeout ):
10971128 try :
10981129 self ._set_start_time ()
@@ -1110,6 +1141,7 @@ def bsim_run(self, timeout):
11101141 self .status = TwisterStatus .ERROR
11111142 finally :
11121143 self ._update_test_status ()
1144+ self ._clean_up_files ()
11131145
11141146 def _update_test_status (self ):
11151147 self .instance .execution_time += time .time () - self ._start_time
0 commit comments