cls_oai_html.py 32.3 KB
Newer Older
Raphael Defosseux's avatar
Raphael Defosseux committed
1
#/*
Gabriele Perrone's avatar
Gabriele Perrone committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements.  See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1  (the "License"); you may not use this file
# * except in compliance with the License.
# * You may obtain a copy of the License at
# *
# *      http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# *      contact@openairinterface.org
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
#   Required Python Version
#     Python 3.x
#
#   Required Python Package
#     pexpect
#---------------------------------------------------------------------

Gabriele Perrone's avatar
Gabriele Perrone committed
31 32 33 34 35
#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
import sys              # arg
import re               # reg
36
import fileinput
Gabriele Perrone's avatar
Gabriele Perrone committed
37 38 39 40 41 42
import logging
import os
import time
import subprocess
from multiprocessing import Process, Lock, SimpleQueue

Raphael Defosseux's avatar
Raphael Defosseux committed
43 44
import constants as CONST

Gabriele Perrone's avatar
Gabriele Perrone committed
45 46 47 48
#-----------------------------------------------------------
# Class Declaration
#-----------------------------------------------------------
class HTMLManagement():
Gabriele Perrone's avatar
Gabriele Perrone committed
49

Gabriele Perrone's avatar
Gabriele Perrone committed
50
	def __init__(self):
51

52
		self.htmlFile = ''
Gabriele Perrone's avatar
Gabriele Perrone committed
53 54
		self.htmlHeaderCreated = False
		self.htmlFooterCreated = False
55 56 57 58

		self.ranRepository = ''
		self.ranBranch = ''
		self.ranCommitID = ''
59
		self.ranAllowMerge = False
60 61
		self.ranTargetBranch = ''

62
		self.nbTestXMLfiles = 0
Gabriele Perrone's avatar
Gabriele Perrone committed
63 64 65
		self.htmlTabRefs = []
		self.htmlTabNames = []
		self.htmlTabIcons = []
Gabriele Perrone's avatar
Gabriele Perrone committed
66
		self.testXMLfiles = []
67

68 69 70 71
		self.testUnstable = False
		self.testMinStableId = '999999'
		self.testStabilityPointReached = False

72 73
		self.htmleNBFailureMsg = ''
		self.htmlUEFailureMsg = ''
74

75 76 77 78
		self.startTime = int(round(time.time() * 1000))
		self.testCase_id = ''
		self.desc = ''

79 80 81 82 83 84 85 86
		self.OsVersion = ['', '']
		self.KernelVersion = ['', '']
		self.UhdVersion = ['', '']
		self.UsrpBoard = ['', '']
		self.CpuNb = ['', '']
		self.CpuModel = ['', '']
		self.CpuMHz = ['', '']

87

Gabriele Perrone's avatar
Gabriele Perrone committed
88 89 90 91 92 93

#-----------------------------------------------------------
# HTML structure creation functions
#-----------------------------------------------------------


Robert Schmidt's avatar
Robert Schmidt committed
94
	def CreateHtmlHeader(self):
Gabriele Perrone's avatar
Gabriele Perrone committed
95
		if (not self.htmlHeaderCreated):
96 97 98
			logging.info('\u001B[1m----------------------------------------\u001B[0m')
			logging.info('\u001B[1m  Creating HTML header \u001B[0m')
			logging.info('\u001B[1m----------------------------------------\u001B[0m')
Gabriele Perrone's avatar
Gabriele Perrone committed
99 100 101 102 103 104 105 106 107 108
			self.htmlFile = open('test_results.html', 'w')
			self.htmlFile.write('<!DOCTYPE html>\n')
			self.htmlFile.write('<html class="no-js" lang="en-US">\n')
			self.htmlFile.write('<head>\n')
			self.htmlFile.write('  <meta name="viewport" content="width=device-width, initial-scale=1">\n')
			self.htmlFile.write('  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">\n')
			self.htmlFile.write('  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>\n')
			self.htmlFile.write('  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>\n')
			self.htmlFile.write('  <title>Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID</title>\n')
			self.htmlFile.write('</head>\n')
109
			self.htmlFile.write('<body><div class="container-fluid" style="margin-left:1em; margin-right:1em">\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
			self.htmlFile.write('  <br>\n')
			self.htmlFile.write('  <table style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('    <tr style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('      <td style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('        <a href="http://www.openairinterface.org/">\n')
			self.htmlFile.write('           <img src="http://www.openairinterface.org/wp-content/uploads/2016/03/cropped-oai_final_logo2.png" alt="" border="none" height=50 width=150>\n')
			self.htmlFile.write('           </img>\n')
			self.htmlFile.write('        </a>\n')
			self.htmlFile.write('      </td>\n')
			self.htmlFile.write('      <td style="border-collapse: collapse; border: none; vertical-align: center;">\n')
			self.htmlFile.write('        <b><font size = "6">Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID</font></b>\n')
			self.htmlFile.write('      </td>\n')
			self.htmlFile.write('    </tr>\n')
			self.htmlFile.write('  </table>\n')
			self.htmlFile.write('  <br>\n')
			self.htmlFile.write('  <div class="alert alert-info"><strong> <span class="glyphicon glyphicon-dashboard"></span> TEMPLATE_STAGE_NAME</strong></div>\n')
			self.htmlFile.write('  <table border = "1">\n')
			self.htmlFile.write('     <tr>\n')
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-time"></span> Build Start Time (UTC) </td>\n')
			self.htmlFile.write('       <td>TEMPLATE_BUILD_TIME</td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
			self.htmlFile.write('       <td><a href="' + self.ranRepository + '">' + self.ranRepository + '</a></td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
			if (self.ranAllowMerge):
				self.htmlFile.write('       <td>Merge-Request</td>\n')
			else:
				self.htmlFile.write('       <td>Push to Branch</td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
			if (self.ranAllowMerge):
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
			else:
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
			self.htmlFile.write('       <td>' + self.ranBranch + '</td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
			if (self.ranAllowMerge):
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
			else:
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
			self.htmlFile.write('       <td>' + self.ranCommitID + '</td>\n')
			self.htmlFile.write('     </tr>\n')
			if self.ranAllowMerge != '':
				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True)
				commit_message = commit_message.strip()
				self.htmlFile.write('     <tr>\n')
				if (self.ranAllowMerge):
					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Source Commit Message </td>\n')
				else:
					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
				self.htmlFile.write('       <td>' + commit_message + '</td>\n')
				self.htmlFile.write('     </tr>\n')
			if (self.ranAllowMerge):
				self.htmlFile.write('     <tr>\n')
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
				if (self.ranTargetBranch == ''):
					self.htmlFile.write('       <td>develop</td>\n')
				else:
					self.htmlFile.write('       <td>' + self.ranTargetBranch + '</td>\n')
				self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('  </table>\n')

			self.htmlFile.write('  <br>\n')
			self.htmlFile.write('  <ul class="nav nav-pills">\n')
			count = 0
			while (count < self.nbTestXMLfiles):
180 181 182 183
				if count == 0:
					pillMsg = '    <li class="active"><a data-toggle="pill" href="#'
				else:
					pillMsg = '    <li><a data-toggle="pill" href="#'
Gabriele Perrone's avatar
Gabriele Perrone committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
				pillMsg += self.htmlTabRefs[count]
				pillMsg += '">'
				pillMsg += '__STATE_' + self.htmlTabNames[count] + '__'
				pillMsg += self.htmlTabNames[count]
				pillMsg += ' <span class="glyphicon glyphicon-'
				pillMsg += self.htmlTabIcons[count]
				pillMsg += '"></span></a></li>\n'
				self.htmlFile.write(pillMsg)
				count += 1
			self.htmlFile.write('  </ul>\n')
			self.htmlFile.write('  <div class="tab-content">\n')
			self.htmlFile.close()

	def CreateHtmlTabHeader(self):
		if (not self.htmlHeaderCreated):
			if (not os.path.isfile('test_results.html')):
				self.CreateHtmlHeader('none')
			self.htmlFile = open('test_results.html', 'a')
			if (self.nbTestXMLfiles == 1):
				self.htmlFile.write('  <div id="' + self.htmlTabRefs[0] + '" class="tab-pane fade">\n')
				self.htmlFile.write('  <h3>Test Summary for <span class="glyphicon glyphicon-file"></span> ' + self.testXMLfiles[0] + '</h3>\n')
			else:
				self.htmlFile.write('  <div id="build-tab" class="tab-pane fade">\n')
			self.htmlFile.write('  <table class="table" border = "1">\n')
			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
209 210
			self.htmlFile.write('        <th style="width:5%">Relative Time (s)</th>\n')
			self.htmlFile.write('        <th style="width:5%">Test Id</th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
211 212
			self.htmlFile.write('        <th>Test Desc</th>\n')
			self.htmlFile.write('        <th>Test Options</th>\n')
213
			self.htmlFile.write('        <th style="width:5%">Test Status</th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
214

215
			self.htmlFile.write('        <th>Info</th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
216 217 218 219 220 221
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()
		self.htmlHeaderCreated = True

	def CreateHtmlTabFooter(self, passStatus):
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
222 223 224 225
			testOkEvenIfUnstable = False
			if self.testUnstable and not passStatus:
				if self.testStabilityPointReached or self.testMinStableId == '999999':
					testOkEvenIfUnstable = True
Gabriele Perrone's avatar
Gabriele Perrone committed
226 227
			self.htmlFile = open('test_results.html', 'a')
			self.htmlFile.write('      <tr>\n')
228
			self.htmlFile.write('        <th bgcolor = "#33CCFF" colspan="3">Final Tab Status</th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
229
			if passStatus:
230
				self.htmlFile.write('        <th bgcolor = "green" colspan="3"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span> </font></th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
231
			else:
232
				if testOkEvenIfUnstable:
233
					self.htmlFile.write('        <th bgcolor = "orange" colspan="3"><font color="white">KNOWN UNSTABLE SCENARIO <span class="glyphicon glyphicon-exclamation-sign"></span> </font></th>\n')
234
				else:
235
					self.htmlFile.write('        <th bgcolor = "red" colspan="3"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
236 237 238 239 240 241 242 243 244
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('  </table>\n')
			self.htmlFile.write('  </div>\n')
			self.htmlFile.close()
			time.sleep(1)
			if passStatus:
				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
				subprocess.run(cmd, shell=True)
			else:
245 246 247 248
				if testOkEvenIfUnstable:
					cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-exclamation-sign\"><\/span>/' test_results.html"
				else:
					cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
Gabriele Perrone's avatar
Gabriele Perrone committed
249 250 251 252 253
				subprocess.run(cmd, shell=True)
		self.htmlFooterCreated = False

	def CreateHtmlFooter(self, passStatus):
		if (os.path.isfile('test_results.html')):
254 255 256 257 258 259 260 261 262
			# Tagging the 1st tab as active so it is automatically opened.
			firstTabFound = False
			for line in fileinput.FileInput("test_results.html", inplace=1):
				if re.search('tab-pane fade', line) and not firstTabFound:
					firstTabFound = True
					print(line.replace('tab-pane fade', 'tab-pane fade in active'), end ='')
				else:
					print(line, end ='')

Gabriele Perrone's avatar
Gabriele Perrone committed
263 264 265 266 267 268
			self.htmlFile = open('test_results.html', 'a')
			self.htmlFile.write('</div>\n')
			self.htmlFile.write('  <p></p>\n')
			self.htmlFile.write('  <table class="table table-condensed">\n')

			self.htmlFile.write('      <tr>\n')
269
			self.htmlFile.write('        <th colspan="5" bgcolor = "#33CCFF">Final Status</th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
270
			if passStatus:
271
				self.htmlFile.write('        <th colspan="3" bgcolor="green"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span></font></th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
272
			else:
273
				self.htmlFile.write('        <th colspan="3" bgcolor="red"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
274 275 276 277 278 279 280 281 282 283 284
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('  </table>\n')
			self.htmlFile.write('  <p></p>\n')
			self.htmlFile.write('  <div class="well well-lg">End of Test Report -- Copyright <span class="glyphicon glyphicon-copyright-mark"></span> 2018 <a href="http://www.openairinterface.org/">OpenAirInterface</a>. All Rights Reserved.</div>\n')
			self.htmlFile.write('</div></body>\n')
			self.htmlFile.write('</html>\n')
			self.htmlFile.close()

	def CreateHtmlRetrySeparator(self, cntnumfails):
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
			self.htmlFile = open('test_results.html', 'a')
285
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
286
			self.htmlFile.write('        <td colspan="6"><b> ---- Try Run #' + str(cntnumfails) + ' ---- </b></td>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
287 288 289 290
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()

	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
291 292
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
293 294 295 296 297 298 299 300 301 302 303 304
		self.htmlFile = open('test_results.html', 'a')
		currentTime = int(round(time.time() * 1000)) - self.startTime
		self.htmlFile.write('      <tr>\n')
		self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
		self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
		self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
		self.htmlFile.write('        <td>' + str(options)  + '</td>\n')
		if (str(status) == 'OK'):
			self.htmlFile.write('        <td bgcolor = "lightgreen" >' + str(status)  + '</td>\n')
		elif (str(status) == 'KO'):
			if (processesStatus == 0):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
305
			elif (processesStatus == CONST.ENB_PROCESS_FAILED):
306
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process not found</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
307
			elif (processesStatus == CONST.OAI_UE_PROCESS_FAILED):
308
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - OAI UE process not found</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
309
			elif (processesStatus == CONST.ENB_PROCESS_SEG_FAULT) or (processesStatus == CONST.OAI_UE_PROCESS_SEG_FAULT):
310
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
311
			elif (processesStatus == CONST.ENB_PROCESS_ASSERTION) or (processesStatus == CONST.OAI_UE_PROCESS_ASSERTION):
312
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
313
			elif (processesStatus == CONST.ENB_PROCESS_REALTIME_ISSUE):
314
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process faced Real Time issue(s)</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
315
			elif (processesStatus == CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
316
				self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
317
			elif (processesStatus == CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED):
318
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' Slave RRU could not synch</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
319
			elif (processesStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC):
320
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
321
			elif (processesStatus == CONST.HSS_PROCESS_FAILED):
322
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
323
			elif (processesStatus == CONST.MME_PROCESS_FAILED):
324
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - MME process not found</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
325
			elif (processesStatus == CONST.SPGW_PROCESS_FAILED):
326
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - SPGW process not found</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
327
			elif (processesStatus == CONST.UE_IP_ADDRESS_ISSUE):
328
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not retrieve UE IP address</td>\n')
329 330 331 332 333 334 335 336 337 338
			elif (processesStatus == CONST.PHYSIM_IMAGE_ABSENT):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - No such image oai-physim</td>\n')
			elif (processesStatus == CONST.OC_LOGIN_FAIL):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not log onto cluster</td>\n')
			elif (processesStatus == CONST.OC_PROJECT_FAIL):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not register into cluster project</td>\n')
			elif (processesStatus == CONST.OC_IS_FAIL):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not create Image Stream</td>\n')
			elif (processesStatus == CONST.OC_PHYSIM_DEPLOY_FAIL):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not properly deploy physim on cluster</td>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
339
			else:
340 341 342 343 344 345 346 347 348 349
				self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
		else:
			self.htmlFile.write('        <td bgcolor = "orange" >' + str(status)  + '</td>\n')
		if (len(str(self.htmleNBFailureMsg)) > 2):
			cellBgColor = 'white'
			result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg)
			if result is not None:
				cellBgColor = 'red'
			else:
				result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg)
Gabriele Perrone's avatar
Gabriele Perrone committed
350
				if result is not None:
351
					cellBgColor = 'orange'
352
			self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan="1"><pre style="background-color:' + cellBgColor + '">' + self.htmleNBFailureMsg + '</pre></td>\n')
353 354 355 356 357 358
			self.htmleNBFailureMsg = ''
		elif (len(str(self.htmlUEFailureMsg)) > 2):
			cellBgColor = 'white'
			result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg)
			if result is not None:
				cellBgColor = 'red'
Gabriele Perrone's avatar
Gabriele Perrone committed
359
			else:
360 361 362
				result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg)
				if result is not None:
					cellBgColor = 'orange'
363
			self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan="1"><pre style="background-color:' + cellBgColor + '">' + self.htmlUEFailureMsg + '</pre></td>\n')
364 365
			self.htmlUEFailureMsg = ''
		else:
366
			self.htmlFile.write('        <td>-</td>\n')
367 368
		self.htmlFile.write('      </tr>\n')
		self.htmlFile.close()
Gabriele Perrone's avatar
Gabriele Perrone committed
369

370 371 372 373 374 375 376

	def CreateHtmlNextTabHeaderTestRow(self, collectInfo, allImagesSize, machine='eNB'):
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
		self.htmlFile = open('test_results.html', 'a')
		if bool(collectInfo) == False:
			self.htmlFile.write('      <tr bgcolor = "red" >\n')
377
			self.htmlFile.write('        <td colspan="6"><b> ----IMAGES BUILDING FAILED - Unable to recover the image logs ---- </b></td>\n')
378 379 380 381 382
			self.htmlFile.write('      </tr>\n')
		else:
			for image in collectInfo:
				files = collectInfo[image]
        		# TabHeader for image logs on built shared and target images
383 384 385 386 387 388
				if allImagesSize[image].count('unknown') > 0:
					self.htmlFile.write('      <tr bgcolor = "orange" >\n')
				elif allImagesSize[image].count('Build Failed') > 0:
					self.htmlFile.write('      <tr bgcolor = "red" >\n')
				else:
					self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
389
				self.htmlFile.write('        <td colspan="6"><b> ---- ' + image  + ' IMAGE STATUS ----> Size ' + allImagesSize[image] + ' </b></td>\n')
390 391 392 393 394
				self.htmlFile.write('      </tr>\n')
				self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
				self.htmlFile.write('        <th colspan="2">Element</th>\n')
				self.htmlFile.write('        <th>Nb Errors</th>\n')
				self.htmlFile.write('        <th>Nb Warnings</th>\n')
395
				self.htmlFile.write('        <th colspan="2">Status</th>\n')
396 397 398 399 400 401 402 403 404 405 406
				self.htmlFile.write('      </tr>\n')

				for fil in files:
					parameters = files[fil]
					# TestRow for image logs on built shared and target images
					self.htmlFile.write('      <tr>\n')
					self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" >' + fil  + ' </td>\n')
					if (parameters['errors'] == 0):
						self.htmlFile.write('        <td bgcolor = "green" >' + str(parameters['errors'])  + '</td>\n')
					else:
						self.htmlFile.write('        <td bgcolor = "red" >' + str(parameters['errors'])  + '</td>\n')
407 408 409
					if (parameters['errors'] > 0):
						self.htmlFile.write('        <td bgcolor = "red" >' + str(parameters['warnings'])  + '</td>\n')
					elif (parameters['warnings'] == 0):
410 411
						self.htmlFile.write('        <td bgcolor = "green" >' + str(parameters['warnings'])  + '</td>\n')
					else:
412
						self.htmlFile.write('        <td bgcolor = "orange" >' + str(parameters['warnings'])  + '</td>\n')
413
					if (parameters['errors'] == 0) and (parameters['warnings'] == 0):
414
						self.htmlFile.write('        <th colspan="2" bgcolor = "green" ><font color="white">OK </font></th>\n')
415
					elif (parameters['errors'] == 0):
416
						self.htmlFile.write('        <th colspan="2" bgcolor = "orange" ><font color="white">OK </font></th>\n')
417
					else:
418
						self.htmlFile.write('        <th colspan="2" bgcolor = "red" > NOT OK  </th>\n')
419 420 421
					self.htmlFile.write('      </tr>\n')
		self.htmlFile.close()

hardy's avatar
hardy committed
422 423 424 425 426 427 428 429
	#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')
430
		self.htmlFile.write('        <td colspan="6"><b> ---- ' + DataLog['Title'] + ' ---- </b></td>\n')
hardy's avatar
hardy committed
431 432
		self.htmlFile.write('      </tr>\n')
		self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
hardy's avatar
hardy committed
433
		self.htmlFile.write('        <th colspan="3">'+ DataLog['ColNames'][0] +'</th>\n')
434
		self.htmlFile.write('        <th colspan="2">' + DataLog['ColNames'][1] + '</th>\n')
435
		self.htmlFile.write('        <th colspan="2">'+ DataLog['ColNames'][2] +'</th>\n')
hardy's avatar
hardy committed
436 437 438 439
		self.htmlFile.write('      </tr>\n')

		for k in DataLog['Data']:
			# TestRow 
440 441 442 443 444 445
			avg = DataLog['Data'][k][0]
			maxval = DataLog['Data'][k][1]
			count = DataLog['Data'][k][2]
			valnorm = float(DataLog['Data'][k][3])
			dev = DataLog['DeviationThreshold'][k]
			ref = DataLog['Ref'][k]
hardy's avatar
hardy committed
446
			self.htmlFile.write('      <tr>\n')
hardy's avatar
hardy committed
447
			self.htmlFile.write('        <td colspan="3" bgcolor = "lightcyan" >' + k  + ' </td>\n')				
448 449 450
			self.htmlFile.write(f'        <td colspan="2" bgcolor = "lightcyan" >{avg}; {maxval}; {count}</td>\n')
			if valnorm > 1.0 + dev or valnorm < 1.0 - dev:
				self.htmlFile.write(f'        <th bgcolor = "red" >{valnorm} (Avg over Ref = {avg} over {ref}; max allowed deviation = {dev})</th>\n')
hardy's avatar
hardy committed
451
			else:
452
				self.htmlFile.write(f'        <th bgcolor = "green" ><font color="white">{valnorm} (Avg over Ref = {avg} over {ref}; max allowed deviation = {dev})</font></th>\n')
hardy's avatar
hardy committed
453 454 455 456
			self.htmlFile.write('      </tr>\n')
		self.htmlFile.close()


457
	def CreateHtmlTestRowQueue(self, options, status, infoList):
Gabriele Perrone's avatar
Gabriele Perrone committed
458 459 460 461 462 463 464 465 466 467
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
			self.htmlFile = open('test_results.html', 'a')
			currentTime = int(round(time.time() * 1000)) - self.startTime
			addOrangeBK = False
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
			self.htmlFile.write('        <td>' + str(options)  + '</td>\n')
			if (str(status) == 'OK'):
468
				self.htmlFile.write(f'        <td bgcolor = "lightgreen" >{status}</td>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
469
			elif (str(status) == 'KO'):
470
				self.htmlFile.write(f'        <td bgcolor = "lightcoral" >{status}</td>\n')
Gabriele Perrone's avatar
Gabriele Perrone committed
471 472
			else:
				addOrangeBK = True
473 474 475 476 477
				self.htmlFile.write(f'        <td bgcolor = "orange" >{status}</td>\n')
			if (addOrangeBK):
				self.htmlFile.write('        <td bgcolor = "orange" >')
			else:
				self.htmlFile.write('        <td>')
478 479
			for i in infoList: # add custom style to have elements side-by-side to reduce need for vertical space
				self.htmlFile.write(f'         <pre style="display: inline flow-root list-item; margin: 0 3px 0 3px; min-width: 24em;">{i}</pre>')
480 481

			self.htmlFile.write('                </td>')
Gabriele Perrone's avatar
Gabriele Perrone committed
482 483 484
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()

485 486 487 488 489 490 491
	def CreateHtmlTestRowCppCheckResults(self, CCR):
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
		self.htmlFile = open('test_results.html', 'a')
		vId = 0
		for version in CCR.versions:
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
492
			self.htmlFile.write('        <td colspan="6"><b> Results for cppcheck v ' + version + ' </b></td>\n')
493 494 495
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
496
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> NB ERRORS</b></td>\n')
497 498 499 500 501 502
			if CCR.nbErrors[vId] == 0:
				myColor = 'lightgreen'
			elif CCR.nbErrors[vId] < 20:
				myColor = 'orange'
			else:
				myColor = 'lightcoral'
503
			self.htmlFile.write('        <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbErrors[vId]) + '</b></td>\n')
504 505 506
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
507
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> NB WARNINGS</b></td>\n')
508 509 510 511 512 513
			if CCR.nbWarnings[vId] == 0:
				myColor = 'lightgreen'
			elif CCR.nbWarnings[vId] < 20:
				myColor = 'orange'
			else:
				myColor = 'lightcoral'
514
			self.htmlFile.write('        <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbWarnings[vId]) + '</b></td>\n')
515 516
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
517
			self.htmlFile.write('        <td colspan="6"> ----------------- </td>\n')
518 519 520
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
521 522
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Memory leak</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbMemLeaks[vId]) + '</td>\n')
523 524 525
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
526 527
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Possible null pointer deference</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbNullPtrs[vId]) + '</td>\n')
528 529 530
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
531 532
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Uninitialized variable</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbUninitVars[vId]) + '</td>\n')
533 534 535
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
536 537
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Undefined behaviour shifting</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbTooManyBitsShift[vId]) + '</td>\n')
538 539 540
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
541 542
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Signed integer overflow</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbIntegerOverflow[vId]) + '</td>\n')
543 544
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
545
			self.htmlFile.write('        <td colspan="6"> </td>\n')
546 547 548
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
549 550
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Printf formatting issues</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbInvalidPrintf[vId]) + '</td>\n')
551 552 553
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
554 555
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Modulo result is predetermined</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbModuloAlways[vId]) + '</td>\n')
556 557 558
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
559 560
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Opposite Condition -> dead code</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbOppoInnerCondition[vId]) + '</td>\n')
561 562 563
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
564 565
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> Wrong Scanf Nb Args</b></td>\n')
			self.htmlFile.write('        <td colspan="3">' + str(CCR.nbWrongScanfArg[vId]) + '</td>\n')
566 567
			self.htmlFile.write('      </tr>\n')
			vId += 1
568

Mohammed Ismail's avatar
Mohammed Ismail committed
569
	def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
570 571 572
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
		self.htmlFile = open('test_results.html', 'a')
Mohammed Ismail's avatar
Mohammed Ismail committed
573 574
		if bool(testResult) == False and bool(testSummary) == False:
			self.htmlFile.write('      <tr bgcolor = "red" >\n')
575
			self.htmlFile.write('        <td colspan="6"><b> ----PHYSIM TESTING FAILED - Unable to recover the test logs ---- </b></td>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
576 577
			self.htmlFile.write('      </tr>\n')
		else:
578
		# Tab header
Mohammed Ismail's avatar
Mohammed Ismail committed
579
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
580
			self.htmlFile.write('        <td colspan="6"><b> ---- PHYSIM TEST SUMMARY---- </b></td>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
581 582 583 584 585 586 587
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
			self.htmlFile.write('        <th colspan="2">LogFile Name</th>\n')
			self.htmlFile.write('        <th colspan="2">Nb Tests</th>\n')
			self.htmlFile.write('        <th>Nb Failure</th>\n')
			self.htmlFile.write('        <th>Nb Pass</th>\n')
			self.htmlFile.write('      </tr>\n')
588
			self.htmlFile.write('      <tr>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
589 590 591 592
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" > physim_test.txt  </td>\n')
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" >' + str(testSummary['Nbtests']) + ' </td>\n')
			if testSummary['Nbfail'] == 0:
				self.htmlFile.write('        <td bgcolor = "lightcyan" >' + str(testSummary['Nbfail']) + ' </td>\n')
593
			else:
Mohammed Ismail's avatar
Mohammed Ismail committed
594 595 596 597
				self.htmlFile.write('        <td bgcolor = "red" >' + str(testSummary['Nbfail']) + ' </td>\n')
			self.htmlFile.write('        <td gcolor = "lightcyan" >' + str(testSummary['Nbpass']) + ' </td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
598
			self.htmlFile.write('        <td colspan="6"><b> ---- PHYSIM TEST DETAIL INFO---- </b></td>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
599 600 601 602
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
			self.htmlFile.write('        <th colspan="2">Test Name</th>\n')
			self.htmlFile.write('        <th colspan="2">Test Description</th>\n')
603
			self.htmlFile.write('        <th colspan="2">Result</th>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
604
			self.htmlFile.write('      </tr>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
605
			y = ''
Mohammed Ismail's avatar
Mohammed Ismail committed
606
			for key, value in testResult.items():
Mohammed Ismail's avatar
Mohammed Ismail committed
607 608 609
				x = key.split(".")
				if x[0] != y:
					self.htmlFile.write('      <tr bgcolor = "lightgreen" >\n')
610
					self.htmlFile.write('        <td style="text-align: center;" colspan="6"><b>"' + x[0] + '" series </b></td>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
611 612
					self.htmlFile.write('      </tr>\n')
					y = x[0]
Mohammed Ismail's avatar
Mohammed Ismail committed
613 614 615 616
				self.htmlFile.write('      <tr>\n')
				self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" >' + key  + ' </td>\n')
				self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" >' + value[0]  + '</td>\n')
				if 'PASS' in value:
617
					self.htmlFile.write('        <td colspan="2" bgcolor = "green" >' + value[1]  + '</td>\n')
Mohammed Ismail's avatar
Mohammed Ismail committed
618
				else:
619
					self.htmlFile.write('        <td colspan="2" bgcolor = "red" >' + value[1]  + '</td>\n')
620 621

		self.htmlFile.close()