def settings(self): return SimSettings.SimSettings(failIfNotInit=True)
def test_avg_hops(sim_engine, fragmentation, app_pkLength, pkt_loss_mode): sim_engine = sim_engine( diff_config = { 'exec_numSlotframesPerRun': 40, 'exec_numMotes' : 10, 'fragmentation' : fragmentation, 'app' : 'AppPeriodic', 'app_pkPeriod' : 0, 'app_pkLength' : app_pkLength, 'tsch_probBcast_ebProb' : 0, 'rpl_daoPeriod' : 0, 'conn_class' : 'Linear' }, force_initial_routing_and_scheduling_state = True, ) # in this test, the leaf sends two application packets. when pkt_loss_mode # is 'with_pkt_loss', the second application packet will be lost at the # root. # shorthands root = sim_engine.motes[0] leaf = sim_engine.motes[-1] sim_settings = SimSettings.SimSettings() # make the app send an application packet leaf.app._send_a_single_packet() # wait for some time u.run_until_asn(sim_engine, 2020) # make sure SimEngine datalock is disengaged with pytest.raises(RuntimeError): assert sim_engine.dataLock.release() # the root should receive the first application packet logs = u.read_log_file([SimLog.LOG_APP_RX['type']]) assert len(logs) == 1 assert logs[0]['_mote_id'] == root.id assert logs[0]['packet']['net']['srcIp'] == leaf.get_ipv6_global_addr() assert logs[0]['packet']['net']['dstIp'] == root.get_ipv6_global_addr() assert logs[0]['packet']['type'] == d.PKT_TYPE_DATA # make the root not receive at 6LoWPAN layer anything if pkt_loss_mode is # 'with_pkt_loss' if pkt_loss_mode == 'with_pkt_loss': assert root.dagRoot is True def recvPacket(self, packet): # do nothing; ignore the incoming packet pass root.sixlowpan.recvPacket = types.MethodType( recvPacket, root.sixlowpan ) elif pkt_loss_mode == 'without_pkt_loss': # do nothing pass else: raise NotImplemented() # make the app send another application packet leaf.app._send_a_single_packet() # run the simulator until it ends u.run_until_end(sim_engine) # confirm the leaf sent two application packets logs = u.read_log_file([SimLog.LOG_APP_TX['type']]) assert len(logs) == 2 for i in range(2): assert logs[i]['_mote_id'] == leaf.id assert logs[i]['packet']['net']['srcIp'] == leaf.get_ipv6_global_addr() assert logs[i]['packet']['net']['dstIp'] == root.get_ipv6_global_addr() assert logs[i]['packet']['type'] == d.PKT_TYPE_DATA # run compute_kpis.py against the log file output = run_compute_kpis_py() # remove blank lines output = [line for line in output if not re.match(r'^\s*$', line)] # confirm if compute_kpis.py referred the right log file # the first line of output has the log directory name assert ( re.search( os.path.basename(sim_settings.getOutputFile()), output[0] ) is not None ) # convert the body of the output, which is a JSON string, to an object json_string = '\n'.join(output[1:-1]) kpis = json.loads(json_string) # the avg_hops should be the same number as leaf.id since we use a linear # topology here. assert kpis['null'][str(leaf.id)]['avg_hops'] == leaf.id
def start(settings, log_notification_filter='all', stderr_redirect=True): global _sim_engine global _elapsed_minutes sim_settings = None sim_log = None ret_val = {} if _sim_engine is not None: return { 'status': RETURN_STATUS_FAILURE, 'message': 'SimEngine has been started already', 'trace': None } try: sim_settings = SimSettings.SimSettings( cpuID=0, run_id=0, log_root_dir=backend.SIM_DATA_PATH, **settings) start_time = time.time() sim_settings.setLogDirectory('{0}-{1:03d}'.format( time.strftime("%Y%m%d-%H%M%S", time.localtime(start_time)), int(round(start_time * 1000)) % 1000)) sim_settings.setCombinationKeys(DUMMY_COMBINATION_KEYS) sim_log = SimLog.SimLog() sim_log.set_log_filters(SIM_LOG_FILTERS) _overwrite_sim_log_log(log_notification_filter) _save_config_json(sim_settings, saving_settings={ 'combination': {}, 'regular': settings.copy() }) crash_report_path = os.path.join(sim_settings.logRootDirectoryPath, sim_settings.logDirectory, 'crash_report.log') if stderr_redirect is True: _redirect_stderr(redirect_to=open(crash_report_path, 'w')) _sim_engine = SimEngine.SimEngine() _elapsed_minutes = 0 _overwrite_sim_engine_actionEndSlotframe() # start and wait until the simulation ends _sim_engine.start() _sim_engine.join() except Exception as e: ret_val['status'] = RETURN_STATUS_FAILURE ret_val['message'] = str(e) ret_val['trace'] = traceback.format_exc() else: if _sim_engine.getAsn() == (sim_settings.exec_numSlotframesPerRun * sim_settings.tsch_slotframeLength): ret_val['status'] = RETURN_STATUS_SUCCESS # rename .dat file and remove the subdir dat_file_path = sim_settings.getOutputFile() subdir_path = os.path.dirname(dat_file_path) new_file_name = subdir_path + '.dat' os.rename(dat_file_path, new_file_name) os.rmdir(subdir_path) else: # simulation is aborted ret_val['status'] = RETURN_STATUS_ABORTED finally: # housekeeping for crash_report and stderr if stderr_redirect is True: crash_report = _restore_stderr() crash_report.close() if os.stat(crash_report.name).st_size == 0: os.remove(crash_report.name) else: ret_val['crash_report_path'] = crash_report.name # cleanup if _sim_engine is None: if sim_settings is not None: sim_settings.destroy() if sim_log is not None: sim_log.destroy() else: _destroy_sim() return ret_val