#/*
# * 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
#---------------------------------------------------------------------

#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
import sys              # arg
import re               # reg
import fileinput
import logging
import os
import time
import subprocess
from multiprocessing import Process, Lock, SimpleQueue

import constants as CONST

#-----------------------------------------------------------
# Class Declaration
#-----------------------------------------------------------
class HTMLManagement():

	def __init__(self):

		self.htmlFile = ''
		self.htmlHeaderCreated = False
		self.htmlFooterCreated = False

		self.ranRepository = ''
		self.ranBranch = ''
		self.ranCommitID = ''
		self.ranAllowMerge = False
		self.ranTargetBranch = ''

		self.nbTestXMLfiles = 0
		self.htmlTabRefs = []
		self.htmlTabNames = []
		self.htmlTabIcons = []
		self.testXMLfiles = []

		self.testUnstable = False
		self.testMinStableId = '999999'
		self.testStabilityPointReached = False

		self.htmleNBFailureMsg = ''
		self.htmlUEFailureMsg = ''

		self.startTime = int(round(time.time() * 1000))
		self.testCase_id = ''
		self.desc = ''

		self.OsVersion = ['', '']
		self.KernelVersion = ['', '']
		self.UhdVersion = ['', '']
		self.UsrpBoard = ['', '']
		self.CpuNb = ['', '']
		self.CpuModel = ['', '']
		self.CpuMHz = ['', '']



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


	def CreateHtmlHeader(self):
		if (not self.htmlHeaderCreated):
			logging.info('\u001B[1m----------------------------------------\u001B[0m')
			logging.info('\u001B[1m  Creating HTML header \u001B[0m')
			logging.info('\u001B[1m----------------------------------------\u001B[0m')
			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')
			self.htmlFile.write('<body><div class="container-fluid" style="margin-left:1em; margin-right:1em">\n')
			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):
				if count == 0:
					pillMsg = '    <li class="active"><a data-toggle="pill" href="#'
				else:
					pillMsg = '    <li><a data-toggle="pill" href="#'
				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')
			self.htmlFile.write('        <th style="width:5%">Relative Time (s)</th>\n')
			self.htmlFile.write('        <th style="width:5%">Test Id</th>\n')
			self.htmlFile.write('        <th>Test Desc</th>\n')
			self.htmlFile.write('        <th>Test Options</th>\n')
			self.htmlFile.write('        <th style="width:5%">Test Status</th>\n')

			self.htmlFile.write('        <th>Info</th>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()
		self.htmlHeaderCreated = True

	def CreateHtmlTabFooter(self, passStatus):
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
			testOkEvenIfUnstable = False
			if self.testUnstable and not passStatus:
				if self.testStabilityPointReached or self.testMinStableId == '999999':
					testOkEvenIfUnstable = True
			self.htmlFile = open('test_results.html', 'a')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <th bgcolor = "#33CCFF" colspan="3">Final Tab Status</th>\n')
			if passStatus:
				self.htmlFile.write('        <th bgcolor = "green" colspan="3"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span> </font></th>\n')
			else:
				if testOkEvenIfUnstable:
					self.htmlFile.write('        <th bgcolor = "orange" colspan="3"><font color="white">KNOWN UNSTABLE SCENARIO <span class="glyphicon glyphicon-exclamation-sign"></span> </font></th>\n')
				else:
					self.htmlFile.write('        <th bgcolor = "red" colspan="3"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
			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:
				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"
				subprocess.run(cmd, shell=True)
		self.htmlFooterCreated = False

	def CreateHtmlFooter(self, passStatus):
		if (os.path.isfile('test_results.html')):
			# 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 ='')

			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')
			self.htmlFile.write('        <th colspan="5" bgcolor = "#33CCFF">Final Status</th>\n')
			if passStatus:
				self.htmlFile.write('        <th colspan="3" bgcolor="green"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span></font></th>\n')
			else:
				self.htmlFile.write('        <th colspan="3" bgcolor="red"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
			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')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
			self.htmlFile.write('        <td colspan="6"><b> ---- Try Run #' + str(cntnumfails) + ' ---- </b></td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()

	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
		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')
			elif (processesStatus == CONST.ENB_PROCESS_FAILED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process not found</td>\n')
			elif (processesStatus == CONST.OAI_UE_PROCESS_FAILED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - OAI UE process not found</td>\n')
			elif (processesStatus == CONST.ENB_PROCESS_SEG_FAULT) or (processesStatus == CONST.OAI_UE_PROCESS_SEG_FAULT):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
			elif (processesStatus == CONST.ENB_PROCESS_ASSERTION) or (processesStatus == CONST.OAI_UE_PROCESS_ASSERTION):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
			elif (processesStatus == CONST.ENB_PROCESS_REALTIME_ISSUE):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process faced Real Time issue(s)</td>\n')
			elif (processesStatus == CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
				self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
			elif (processesStatus == CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' Slave RRU could not synch</td>\n')
			elif (processesStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
			elif (processesStatus == CONST.HSS_PROCESS_FAILED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
			elif (processesStatus == CONST.MME_PROCESS_FAILED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - MME process not found</td>\n')
			elif (processesStatus == CONST.SPGW_PROCESS_FAILED):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - SPGW process not found</td>\n')
			elif (processesStatus == CONST.UE_IP_ADDRESS_ISSUE):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not retrieve UE IP address</td>\n')
			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')
			else:
				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)
				if result is not None:
					cellBgColor = 'orange'
			self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan="1"><pre style="background-color:' + cellBgColor + '">' + self.htmleNBFailureMsg + '</pre></td>\n')
			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'
			else:
				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'
			self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan="1"><pre style="background-color:' + cellBgColor + '">' + self.htmlUEFailureMsg + '</pre></td>\n')
			self.htmlUEFailureMsg = ''
		else:
			self.htmlFile.write('        <td>-</td>\n')
		self.htmlFile.write('      </tr>\n')
		self.htmlFile.close()


	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')
			self.htmlFile.write('        <td colspan="6"><b> ----IMAGES BUILDING FAILED - Unable to recover the image logs ---- </b></td>\n')
			self.htmlFile.write('      </tr>\n')
		else:
			for image in collectInfo:
				files = collectInfo[image]
        		# TabHeader for image logs on built shared and target images
				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')
				self.htmlFile.write('        <td colspan="6"><b> ---- ' + image  + ' IMAGE STATUS ----> Size ' + allImagesSize[image] + ' </b></td>\n')
				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')
				self.htmlFile.write('        <th colspan="2">Status</th>\n')
				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')
					if (parameters['errors'] > 0):
						self.htmlFile.write('        <td bgcolor = "red" >' + str(parameters['warnings'])  + '</td>\n')
					elif (parameters['warnings'] == 0):
						self.htmlFile.write('        <td bgcolor = "green" >' + str(parameters['warnings'])  + '</td>\n')
					else:
						self.htmlFile.write('        <td bgcolor = "orange" >' + str(parameters['warnings'])  + '</td>\n')
					if (parameters['errors'] == 0) and (parameters['warnings'] == 0):
						self.htmlFile.write('        <th colspan="2" bgcolor = "green" ><font color="white">OK </font></th>\n')
					elif (parameters['errors'] == 0):
						self.htmlFile.write('        <th colspan="2" bgcolor = "orange" ><font color="white">OK </font></th>\n')
					else:
						self.htmlFile.write('        <th colspan="2" bgcolor = "red" > NOT OK  </th>\n')
					self.htmlFile.write('      </tr>\n')
		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="6"><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 colspan="2">' + DataLog['ColNames'][1] + '</th>\n')
		self.htmlFile.write('        <th colspan="2">'+ DataLog['ColNames'][2] +'</th>\n')
		self.htmlFile.write('      </tr>\n')

		for k in DataLog['Data']:
			# TestRow 
			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]
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td colspan="3" bgcolor = "lightcyan" >' + k  + ' </td>\n')				
			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')
			else:
				self.htmlFile.write(f'        <th bgcolor = "green" ><font color="white">{valnorm} (Avg over Ref = {avg} over {ref}; max allowed deviation = {dev})</font></th>\n')
			self.htmlFile.write('      </tr>\n')
		self.htmlFile.close()


	def CreateHtmlTestRowQueue(self, options, status, infoList):
		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'):
				self.htmlFile.write(f'        <td bgcolor = "lightgreen" >{status}</td>\n')
			elif (str(status) == 'KO'):
				self.htmlFile.write(f'        <td bgcolor = "lightcoral" >{status}</td>\n')
			else:
				addOrangeBK = True
				self.htmlFile.write(f'        <td bgcolor = "orange" >{status}</td>\n')
			if (addOrangeBK):
				self.htmlFile.write('        <td bgcolor = "orange" >')
			else:
				self.htmlFile.write('        <td>')
			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>')

			self.htmlFile.write('                </td>')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.close()

	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')
			self.htmlFile.write('        <td colspan="6"><b> Results for cppcheck v ' + version + ' </b></td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> NB ERRORS</b></td>\n')
			if CCR.nbErrors[vId] == 0:
				myColor = 'lightgreen'
			elif CCR.nbErrors[vId] < 20:
				myColor = 'orange'
			else:
				myColor = 'lightcoral'
			self.htmlFile.write('        <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbErrors[vId]) + '</b></td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			self.htmlFile.write('        <td colspan="2" bgcolor = "lightcyan" ><b> NB WARNINGS</b></td>\n')
			if CCR.nbWarnings[vId] == 0:
				myColor = 'lightgreen'
			elif CCR.nbWarnings[vId] < 20:
				myColor = 'orange'
			else:
				myColor = 'lightcoral'
			self.htmlFile.write('        <td colspan="3" bgcolor = "' + myColor + '"><b>' + str(CCR.nbWarnings[vId]) + '</b></td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
			self.htmlFile.write('        <td colspan="6"> ----------------- </td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
			self.htmlFile.write('        <td colspan="6"> </td>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td></td>\n')
			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')
			self.htmlFile.write('      </tr>\n')
			vId += 1

	def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
		if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
			return
		self.htmlFile = open('test_results.html', 'a')
		if bool(testResult) == False and bool(testSummary) == False:
			self.htmlFile.write('      <tr bgcolor = "red" >\n')
			self.htmlFile.write('        <td colspan="6"><b> ----PHYSIM TESTING FAILED - Unable to recover the test logs ---- </b></td>\n')
			self.htmlFile.write('      </tr>\n')
		else:
		# Tab header
			self.htmlFile.write('      <tr bgcolor = "#F0F0F0" >\n')
			self.htmlFile.write('        <td colspan="6"><b> ---- PHYSIM TEST SUMMARY---- </b></td>\n')
			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')
			self.htmlFile.write('      <tr>\n')
			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')
			else:
				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')
			self.htmlFile.write('        <td colspan="6"><b> ---- PHYSIM TEST DETAIL INFO---- </b></td>\n')
			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')
			self.htmlFile.write('        <th colspan="2">Result</th>\n')
			self.htmlFile.write('      </tr>\n')
			y = ''
			for key, value in testResult.items():
				x = key.split(".")
				if x[0] != y:
					self.htmlFile.write('      <tr bgcolor = "lightgreen" >\n')
					self.htmlFile.write('        <td style="text-align: center;" colspan="6"><b>"' + x[0] + '" series </b></td>\n')
					self.htmlFile.write('      </tr>\n')
					y = x[0]
				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:
					self.htmlFile.write('        <td colspan="2" bgcolor = "green" >' + value[1]  + '</td>\n')
				else:
					self.htmlFile.write('        <td colspan="2" bgcolor = "red" >' + value[1]  + '</td>\n')

		self.htmlFile.close()
