205 lines
8.5 KiB
Python
205 lines
8.5 KiB
Python
#
|
|
# Copyright(c) 2019-2021 Intel Corporation
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
|
|
import os
|
|
from os import path, environ, makedirs
|
|
from datetime import datetime
|
|
from shutil import copyfile
|
|
from lxml.etree import Element
|
|
from log.base_log import BaseLogResult
|
|
from log.presentation_policy import null_policy
|
|
|
|
|
|
def convert_seconds_to_str(time_in_sec):
|
|
h = str(int(time_in_sec / 3600) % 24).zfill(2)
|
|
m = str(int(time_in_sec / 60) % 60).zfill(2)
|
|
s = str(int(time_in_sec % 60)).zfill(2)
|
|
time_msg = f"{h}:{m}:{s} [s]"
|
|
if time_in_sec > 86400:
|
|
time_msg = f"{int(time_in_sec // (3600 * 24))}d {time_msg}"
|
|
return time_msg
|
|
|
|
|
|
class HtmlLogConfig:
|
|
STYLE = {
|
|
BaseLogResult.DEBUG: 'debug',
|
|
BaseLogResult.PASSED: '',
|
|
BaseLogResult.WORKAROUND: 'workaround',
|
|
BaseLogResult.WARNING: 'warning',
|
|
BaseLogResult.SKIPPED: 'skip',
|
|
BaseLogResult.FAILED: 'fail',
|
|
BaseLogResult.BLOCKED: 'blocked',
|
|
BaseLogResult.CRITICAL: 'critical',
|
|
BaseLogResult.EXCEPTION: 'exception'}
|
|
|
|
__MAIN = 'main'
|
|
__SETUP = 'setup'
|
|
__T_ITERATION = 'iteration'
|
|
__FRAMEWORK_T_FOLDER = 'template'
|
|
|
|
MAIN = __MAIN + '.html'
|
|
CSS = __MAIN + '.css'
|
|
JS = __MAIN + '.js'
|
|
|
|
ITERATION_FOLDER = 'iterations'
|
|
SETUP = __SETUP + ".html"
|
|
|
|
def iteration(self):
|
|
return f'{HtmlLogConfig.__T_ITERATION}_{str(self._iteration_id).zfill(3)}.html'
|
|
|
|
def __init__(self, base_dir=None, presentation_policy=null_policy):
|
|
self._log_base_dir = base_dir
|
|
if base_dir is None:
|
|
if os.name == 'nt':
|
|
self._log_base_dir = 'c:\\History'
|
|
else:
|
|
if environ["USER"] == 'root':
|
|
self._log_base_dir = '/root/history'
|
|
else:
|
|
self._log_base_dir = f'/home/{environ["USER"]}'
|
|
self._log_dir = None
|
|
self._presentation_policy = {}
|
|
self.register_presentation_policy(str, presentation_policy)
|
|
self._iteration_id = 0
|
|
|
|
def get_iteration_id(self):
|
|
return self._iteration_id
|
|
|
|
def get_policy(self, type):
|
|
return self._presentation_policy[type]
|
|
|
|
def get_policy_collection(self):
|
|
for type, policy in self._presentation_policy.items():
|
|
yield policy
|
|
|
|
def register_presentation_policy(self, type, presentation_policy):
|
|
self._presentation_policy[type] = presentation_policy
|
|
|
|
def __find_template_file(self, name, relative_path=None):
|
|
base_dir = path.dirname(path.abspath(__file__))
|
|
file_path = path.join(base_dir, HtmlLogConfig.__FRAMEWORK_T_FOLDER)
|
|
if relative_path is not None:
|
|
file_path = path.join(file_path, relative_path)
|
|
file_path = path.join(file_path, name)
|
|
if path.isfile(file_path):
|
|
return file_path
|
|
else:
|
|
raise Exception(
|
|
f"Unable to find file: {name} in location: {os.path.dirname(file_path)}")
|
|
|
|
def __get_main_template_file_path(self):
|
|
return self.__find_template_file(HtmlLogConfig.MAIN)
|
|
|
|
def _get_setup_template_file_path(self):
|
|
return self.__find_template_file(HtmlLogConfig.SETUP, HtmlLogConfig.ITERATION_FOLDER)
|
|
|
|
def __get_iteration_template_path(self):
|
|
return self.__find_template_file(HtmlLogConfig.__T_ITERATION + '.html',
|
|
HtmlLogConfig.ITERATION_FOLDER)
|
|
|
|
def create_html_test_log(self, test_title):
|
|
now = datetime.now()
|
|
time_stamp = f"{now.year}_{str(now.month).zfill(2)}_{str(now.day).zfill(2)}_" \
|
|
f"{str(now.hour).zfill(2)}_{str(now.minute).zfill(2)}_{str(now.second).zfill(2)}"
|
|
self._log_dir = path.join(self._log_base_dir, test_title, time_stamp)
|
|
makedirs(self._log_dir)
|
|
additional_location = path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER)
|
|
makedirs(additional_location)
|
|
dut_info_folder = path.join(self._log_dir, 'dut_info')
|
|
makedirs(dut_info_folder)
|
|
main_html = self.__get_main_template_file_path()
|
|
main_css = main_html.replace('html', 'css')
|
|
main_js = main_html.replace('html', 'js')
|
|
copyfile(main_html, path.join(self._log_dir, HtmlLogConfig.MAIN))
|
|
copyfile(main_css, path.join(self._log_dir, HtmlLogConfig.CSS))
|
|
copyfile(main_js, path.join(self._log_dir, HtmlLogConfig.JS))
|
|
copyfile(self._get_setup_template_file_path(), path.join(additional_location,
|
|
HtmlLogConfig.SETUP))
|
|
return self._log_dir
|
|
|
|
def get_main_file_path(self):
|
|
return path.join(self._log_dir, HtmlLogConfig.MAIN)
|
|
|
|
def get_setup_file_path(self):
|
|
return path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER, HtmlLogConfig.SETUP)
|
|
|
|
def create_iteration_file(self):
|
|
self._iteration_id += 1
|
|
template_file = self.__get_iteration_template_path()
|
|
new_file_name = self.iteration()
|
|
result = path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER, new_file_name)
|
|
copyfile(template_file, result)
|
|
return result
|
|
|
|
def end_iteration(self,
|
|
iteration_selector_div,
|
|
iteration_selector_select,
|
|
iteration_id,
|
|
iteration_result):
|
|
style = "iteration-selector"
|
|
if iteration_result != BaseLogResult.PASSED:
|
|
style = f'{style} {HtmlLogConfig.STYLE[iteration_result]}'
|
|
if iteration_id and iteration_id % 8 == 0:
|
|
new_element = Element("br")
|
|
iteration_selector_div[0].append(new_element)
|
|
new_element = Element("a")
|
|
new_element.set('class', style)
|
|
new_element.set('onclick', f"selectIteration('{iteration_id}')")
|
|
new_element.text = str(iteration_id)
|
|
iteration_selector_div[0].append(new_element)
|
|
new_element = Element('option', value=f"{iteration_id}")
|
|
new_element.text = 'iteration_' + str(iteration_id).zfill(3)
|
|
if iteration_result != BaseLogResult.PASSED:
|
|
new_element.set('class', HtmlLogConfig.STYLE[iteration_result])
|
|
iteration_selector_select.append(new_element)
|
|
|
|
def end_setup_iteration(self, iteration_selector_div, iteration_selector_select, log_result):
|
|
if log_result != BaseLogResult.PASSED:
|
|
a_element = iteration_selector_div[0]
|
|
select_element = iteration_selector_select[0]
|
|
a_element.set('class', f'iteration-selector {HtmlLogConfig.STYLE[log_result]}')
|
|
select_element.set('class', HtmlLogConfig.STYLE[log_result])
|
|
|
|
def end_iteration_func(self, time_node, status_node, time_in_sec, log_result):
|
|
time_node.text = f"Execution time: {convert_seconds_to_str(time_in_sec)}"
|
|
status_node.text = f"Iteration status: {log_result.name}"
|
|
if log_result != BaseLogResult.PASSED:
|
|
status_node.set('class', f'iteration-status {HtmlLogConfig.STYLE[log_result]}')
|
|
|
|
def end_main_log(self, test_status_div, log_result):
|
|
if log_result != BaseLogResult.PASSED:
|
|
test_status_div[0].set('class',
|
|
f"sidebar-test-status {HtmlLogConfig.STYLE[log_result]}")
|
|
test_status_div[0].text = f"Test status: {log_result.name}"
|
|
|
|
def group_end(self, msg_id, html_header, html_container, log_result):
|
|
html_header.set('onclick', f"showHide('ul_{msg_id}')")
|
|
sub_element = Element('a', href="#top")
|
|
sub_element.text = "[TOP]"
|
|
sub_element.set('class', "top-time-marker")
|
|
html_header.append(sub_element)
|
|
div_style = 'test-group-step'
|
|
ul_style = 'iteration-content'
|
|
if log_result == BaseLogResult.PASSED:
|
|
html_container.set('style', "display: none;")
|
|
else:
|
|
div_style = f"{div_style} {HtmlLogConfig.STYLE[log_result]}"
|
|
ul_style = f"{ul_style} {HtmlLogConfig.STYLE[log_result]}"
|
|
html_header.set('class', div_style)
|
|
html_container.set('class', ul_style)
|
|
|
|
def group_chapter_end(self, time_in_sec, html_header, html_container, log_result):
|
|
sub_element = Element('a')
|
|
sub_element.text = convert_seconds_to_str(time_in_sec)
|
|
sub_element.set('class', 'top-marker')
|
|
html_header.append(sub_element)
|
|
div_style = 'test-group-step'
|
|
ul_style = 'iteration-content'
|
|
if log_result != BaseLogResult.PASSED:
|
|
div_style = f"{div_style} {HtmlLogConfig.STYLE[log_result]}"
|
|
ul_style = f"{ul_style} {HtmlLogConfig.STYLE[log_result]}"
|
|
html_header.set('class', div_style)
|
|
html_container.set('class', ul_style)
|