Merge remote-tracking branch 'origin/rh_ci_phy_test_improve' into integration_2021_wk18_a
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
#this is a configuration file
|
||||||
|
#used to build real time processing statistics
|
||||||
|
#for 5G NR phy test (gNB terminate)
|
||||||
|
Title : Processing Time (us)
|
||||||
|
ColNames :
|
||||||
|
- Metric
|
||||||
|
- Average
|
||||||
|
- Max
|
||||||
|
- Average vs Reference Deviation (Reference Value ; Acceptability Threshold)
|
||||||
|
Ref :
|
||||||
|
feprx : 60.0
|
||||||
|
feptx_prec : 8.0
|
||||||
|
feptx_ofdm : 85.0
|
||||||
|
feptx_total : 75.0
|
||||||
|
L1 Tx processing : 300.0
|
||||||
|
DLSCH encoding : 230.0
|
||||||
|
L1 Rx processing : 175.0
|
||||||
|
PUSCH inner-receiver : 100.0
|
||||||
|
PUSCH decoding : 140.0
|
||||||
|
DL & UL scheduling timing stats : 15.0
|
||||||
|
UL Indication : 20.0
|
||||||
|
Threshold :
|
||||||
|
feprx : 1.25
|
||||||
|
feptx_prec : 1.25
|
||||||
|
feptx_ofdm : 1.25
|
||||||
|
feptx_total : 1.25
|
||||||
|
L1 Tx processing : 1.25
|
||||||
|
DLSCH encoding : 1.25
|
||||||
|
L1 Rx processing : 1.25
|
||||||
|
PUSCH inner-receiver : 1.25
|
||||||
|
PUSCH decoding : 1.25
|
||||||
|
DL & UL scheduling timing stats : 1.25
|
||||||
|
UL Indication : 1.25
|
||||||
@@ -453,6 +453,37 @@ class HTMLManagement():
|
|||||||
self.htmlFile.write(' </tr>\n')
|
self.htmlFile.write(' </tr>\n')
|
||||||
self.htmlFile.close()
|
self.htmlFile.close()
|
||||||
|
|
||||||
|
#for the moment it is limited to 4 columns, to be made generic later
|
||||||
|
def CreateHtmlDataLogTable(self, DataLog):
|
||||||
|
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
||||||
|
return
|
||||||
|
self.htmlFile = open('test_results.html', 'a')
|
||||||
|
|
||||||
|
# TabHeader
|
||||||
|
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
||||||
|
self.htmlFile.write(' <td colspan=' + str(5+self.htmlUEConnected) + '><b> ---- ' + DataLog['Title'] + ' ---- </b></td>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
self.htmlFile.write(' <tr bgcolor = "#33CCFF" >\n')
|
||||||
|
self.htmlFile.write(' <th colspan="3">'+ DataLog['ColNames'][0] +'</th>\n')
|
||||||
|
self.htmlFile.write(' <th>' + DataLog['ColNames'][1] + '</th>\n')
|
||||||
|
self.htmlFile.write(' <th>' + DataLog['ColNames'][2] + '</th>\n')
|
||||||
|
self.htmlFile.write(' <th colspan=' + str(1+self.htmlUEConnected) + '>'+ DataLog['ColNames'][3] +'</th>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
|
||||||
|
for k in DataLog['Data']:
|
||||||
|
# TestRow
|
||||||
|
self.htmlFile.write(' <tr>\n')
|
||||||
|
self.htmlFile.write(' <td colspan="3" bgcolor = "lightcyan" >' + k + ' </td>\n')
|
||||||
|
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][0] + ' </td>\n')
|
||||||
|
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][1] + ' </td>\n')
|
||||||
|
if float(DataLog['Data'][k][2])> DataLog['Threshold'][k]:
|
||||||
|
self.htmlFile.write(' <th bgcolor = "red" >' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||||
|
else:
|
||||||
|
self.htmlFile.write(' <th bgcolor = "green" ><font color="white">' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
self.htmlFile.close()
|
||||||
|
|
||||||
|
|
||||||
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
|
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
|
||||||
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
||||||
self.htmlFile = open('test_results.html', 'a')
|
self.htmlFile = open('test_results.html', 'a')
|
||||||
|
|||||||
+41
-11
@@ -37,6 +37,8 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from multiprocessing import Process, Lock, SimpleQueue
|
from multiprocessing import Process, Lock, SimpleQueue
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
# OAI Testing modules
|
# OAI Testing modules
|
||||||
@@ -90,6 +92,7 @@ class RANManagement():
|
|||||||
self.testCase_id = ''
|
self.testCase_id = ''
|
||||||
self.epcPcapFile = ''
|
self.epcPcapFile = ''
|
||||||
self.runtime_stats= ''
|
self.runtime_stats= ''
|
||||||
|
self.datalog_rt_stats={}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -633,6 +636,8 @@ class RANManagement():
|
|||||||
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||||
else:
|
else:
|
||||||
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||||
|
if len(self.datalog_rt_stats)!=0:
|
||||||
|
HTML.CreateHtmlDataLogTable(self.datalog_rt_stats)
|
||||||
self.eNBmbmsEnables[int(self.eNB_instance)] = False
|
self.eNBmbmsEnables[int(self.eNB_instance)] = False
|
||||||
self.eNBstatuses[int(self.eNB_instance)] = -1
|
self.eNBstatuses[int(self.eNB_instance)] = -1
|
||||||
|
|
||||||
@@ -699,6 +704,21 @@ class RANManagement():
|
|||||||
#count "problem receiving samples" msg
|
#count "problem receiving samples" msg
|
||||||
pb_receiving_samples_cnt = 0
|
pb_receiving_samples_cnt = 0
|
||||||
|
|
||||||
|
#the datalog config file has to be loaded
|
||||||
|
datalog_rt_stats_file='datalog_rt_stats.yaml'
|
||||||
|
if (os.path.isfile(datalog_rt_stats_file)):
|
||||||
|
yaml_file=datalog_rt_stats_file
|
||||||
|
elif (os.path.isfile('ci-scripts/'+datalog_rt_stats_file)):
|
||||||
|
yaml_file='ci-scripts/'+datalog_rt_stats_file
|
||||||
|
else:
|
||||||
|
logging.error("Datalog RT stats yaml file cannot be found")
|
||||||
|
sys.exit("Datalog RT stats yaml file cannot be found")
|
||||||
|
|
||||||
|
with open(yaml_file,'r') as f:
|
||||||
|
datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader)
|
||||||
|
rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field
|
||||||
|
|
||||||
|
|
||||||
for line in enb_log_file.readlines():
|
for line in enb_log_file.readlines():
|
||||||
# Runtime statistics
|
# Runtime statistics
|
||||||
result = re.search('Run time:' ,str(line))
|
result = re.search('Run time:' ,str(line))
|
||||||
@@ -857,21 +877,21 @@ class RANManagement():
|
|||||||
#keys below are the markers we are loooking for, loop over this keys list
|
#keys below are the markers we are loooking for, loop over this keys list
|
||||||
#everytime these markers are found in the log file, the previous ones are overwritten in the dict
|
#everytime these markers are found in the log file, the previous ones are overwritten in the dict
|
||||||
#eventually we record and print only the last occurence
|
#eventually we record and print only the last occurence
|
||||||
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled', 'scheduling timing stats'}
|
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled'}
|
||||||
for k in keys:
|
for k in keys:
|
||||||
result = re.search(k, line)
|
result = re.search(k, line)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
|
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
|
||||||
dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
|
dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
|
||||||
#real time statistics
|
#real time statistics for gNB
|
||||||
#same method as above
|
for k in rt_keys:
|
||||||
keys = {'feprx','feptx_prec','feptx_ofdm','feptx_total','L1 Tx processing','DLSCH encoding','L1 Rx processing','PUSCH inner-receiver','PUSCH decoding'}
|
|
||||||
for k in keys:
|
|
||||||
result = re.search(k, line)
|
result = re.search(k, line)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
#remove 1- all useless char before relevant info 2- trailing char
|
#remove 1- all useless char before relevant info 2- trailing char
|
||||||
|
line=line.replace('[0m','')
|
||||||
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
|
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
|
||||||
real_time_stats[k]=tmp.group(1)
|
real_time_stats[k]=tmp.group(1)
|
||||||
|
|
||||||
#count "problem receiving samples" msg
|
#count "problem receiving samples" msg
|
||||||
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
|
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
|
||||||
if result is not None:
|
if result is not None:
|
||||||
@@ -920,13 +940,23 @@ class RANManagement():
|
|||||||
logging.debug(dlsch_ulsch_stats[key])
|
logging.debug(dlsch_ulsch_stats[key])
|
||||||
htmleNBFailureMsg += statMsg
|
htmleNBFailureMsg += statMsg
|
||||||
|
|
||||||
#real time statistics statistics
|
#real time statistics
|
||||||
|
datalog_rt_stats['Data']={}
|
||||||
if len(real_time_stats)!=0: #check if dictionary is not empty
|
if len(real_time_stats)!=0: #check if dictionary is not empty
|
||||||
statMsg=''
|
for k in real_time_stats:
|
||||||
for key in real_time_stats: #for each dictionary key
|
tmp=re.match(r'^(?P<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+\d+;\s+(?P<max>\d+\.\d+) us;',real_time_stats[k])
|
||||||
statMsg += real_time_stats[key] + '\n'
|
if tmp is not None:
|
||||||
logging.debug(real_time_stats[key])
|
metric=tmp.group('metric')
|
||||||
htmleNBFailureMsg += statMsg
|
avg=float(tmp.group('avg'))
|
||||||
|
max=float(tmp.group('max'))
|
||||||
|
datalog_rt_stats['Data'][metric]=["{:.0f}".format(avg),"{:.0f}".format(max),"{:.2f}".format(avg/datalog_rt_stats['Ref'][metric])]
|
||||||
|
#once all metrics are collected, store the data as a class attribute to build a dedicated HTML table afterward
|
||||||
|
self.datalog_rt_stats=datalog_rt_stats
|
||||||
|
#check if there is a fail => will render the test as failed
|
||||||
|
for k in datalog_rt_stats['Data']:
|
||||||
|
if float(datalog_rt_stats['Data'][k][2])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold
|
||||||
|
#setting prematureExit is ok although not the best option
|
||||||
|
self.prematureExit=True
|
||||||
else:
|
else:
|
||||||
statMsg = 'No real time stats found in the log file\n'
|
statMsg = 'No real time stats found in the log file\n'
|
||||||
logging.debug('No real time stats found in the log file')
|
logging.debug('No real time stats found in the log file')
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
|
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
|
||||||
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
|
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
|
||||||
<htmlTabIcon>tasks</htmlTabIcon>
|
<htmlTabIcon>tasks</htmlTabIcon>
|
||||||
<repeatCount>2</repeatCount>
|
<repeatCount>3</repeatCount>
|
||||||
<TestCaseRequestedList>
|
<TestCaseRequestedList>
|
||||||
090101 000001 090109
|
090101 000001 090109
|
||||||
</TestCaseRequestedList>
|
</TestCaseRequestedList>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<testCase id="000001">
|
<testCase id="000001">
|
||||||
<class>IdleSleep</class>
|
<class>IdleSleep</class>
|
||||||
<desc>Sleep</desc>
|
<desc>Sleep</desc>
|
||||||
<idle_sleep_time_in_sec>180</idle_sleep_time_in_sec>
|
<idle_sleep_time_in_sec>300</idle_sleep_time_in_sec>
|
||||||
</testCase>
|
</testCase>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user