tests: Embed test framework within OCL repository
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
0
test/functional/test-framework/log/__init__.py
Normal file
0
test/functional/test-framework/log/__init__.py
Normal file
78
test/functional/test-framework/log/base_log.py
Normal file
78
test/functional/test-framework/log/base_log.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from enum import Enum
|
||||
from re import sub
|
||||
|
||||
|
||||
class BaseLogResult(Enum):
|
||||
DEBUG = 10
|
||||
PASSED = 11
|
||||
WORKAROUND = 12
|
||||
WARNING = 13
|
||||
SKIPPED = 14
|
||||
FAILED = 15
|
||||
EXCEPTION = 16
|
||||
BLOCKED = 17
|
||||
CRITICAL = 18
|
||||
|
||||
|
||||
def escape(msg):
|
||||
return sub(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', '', msg)
|
||||
|
||||
|
||||
class BaseLog():
|
||||
def __init__(self, begin_message=None):
|
||||
self.__begin_msg = begin_message
|
||||
self.__result = BaseLogResult.PASSED
|
||||
|
||||
def __enter__(self):
|
||||
if self.__begin_msg is not None:
|
||||
self.begin(self.__begin_msg)
|
||||
else:
|
||||
self.begin("Start BaseLog ...")
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.end()
|
||||
|
||||
def __try_to_set_new_result(self, new_result):
|
||||
if new_result.value > self.__result.value:
|
||||
self.__result = new_result
|
||||
|
||||
def begin(self, message):
|
||||
pass
|
||||
|
||||
def debug(self, message):
|
||||
pass
|
||||
|
||||
def info(self, message):
|
||||
pass
|
||||
|
||||
def workaround(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.WORKAROUND)
|
||||
|
||||
def warning(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.WARNING)
|
||||
|
||||
def skip(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.SKIPPED)
|
||||
|
||||
def error(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.FAILED)
|
||||
|
||||
def blocked(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.BLOCKED)
|
||||
|
||||
def exception(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.EXCEPTION)
|
||||
|
||||
def critical(self, message):
|
||||
self.__try_to_set_new_result(BaseLogResult.CRITICAL)
|
||||
|
||||
def end(self):
|
||||
return self.__result
|
||||
|
||||
def get_result(self):
|
||||
return self.__result
|
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.base_log import BaseLogResult, BaseLog
|
||||
from log.group.html_group_log import HtmlGroupLog
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class HtmlChapterGroupLog(HtmlGroupLog):
|
||||
SET_RESULT = {
|
||||
BaseLogResult.PASSED: BaseLog.info,
|
||||
BaseLogResult.WORKAROUND: BaseLog.workaround,
|
||||
BaseLogResult.WARNING: BaseLog.warning,
|
||||
BaseLogResult.SKIPPED: BaseLog.skip,
|
||||
BaseLogResult.FAILED: BaseLog.error,
|
||||
BaseLogResult.BLOCKED: BaseLog.blocked,
|
||||
BaseLogResult.EXCEPTION: BaseLog.exception,
|
||||
BaseLogResult.CRITICAL: BaseLog.critical}
|
||||
|
||||
def __init__(self, html_base, cfg, begin_msg=None, id='ch0'):
|
||||
super().__init__(HtmlChapterGroupLog._factory, html_base, cfg, begin_msg, id)
|
||||
|
||||
@staticmethod
|
||||
def _factory(html_base, cfg, begin_msg, id):
|
||||
return HtmlChapterGroupLog(html_base, cfg, begin_msg, id)
|
||||
|
||||
def end_dir_group(self, ref_group):
|
||||
group = super().end_group()
|
||||
ref_container_id = ref_group._container.get('id')
|
||||
group._header.set('ondblclick', f"chapterClick('{ref_container_id}')")
|
||||
|
||||
def set_result(self, result):
|
||||
if self._successor is not None:
|
||||
self._successor.set_result(result)
|
||||
HtmlChapterGroupLog.SET_RESULT[result](self, "set result")
|
||||
|
||||
def end(self):
|
||||
result = super().end()
|
||||
exe_time = (datetime.now() - self._start_time).seconds
|
||||
self._cfg.group_chapter_end(exe_time, self._header, self._container, result)
|
||||
return result
|
139
test/functional/test-framework/log/group/html_group_log.py
Normal file
139
test/functional/test-framework/log/group/html_group_log.py
Normal file
@@ -0,0 +1,139 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from datetime import datetime
|
||||
from log.base_log import BaseLog, BaseLogResult
|
||||
|
||||
|
||||
class HtmlGroupLog(BaseLog):
|
||||
def __init__(self, constructor, html_base_element, cfg, begin_message, id_):
|
||||
super().__init__(begin_message)
|
||||
self._successor = None
|
||||
self.__factory = constructor
|
||||
self.__log_main_store = html_base_element
|
||||
self._id = id_
|
||||
self._container = None
|
||||
self._header = None
|
||||
self.__msg_idx = 0
|
||||
self._start_time = datetime.now()
|
||||
self._cfg = cfg
|
||||
self._header_msg_type = type(begin_message)
|
||||
|
||||
def begin(self, message):
|
||||
policy = self._cfg.get_policy(type(message))
|
||||
self._header, self._container = policy.group_begin(self._id, message, self.__log_main_store)
|
||||
super().begin(message)
|
||||
|
||||
def get_step_id(self):
|
||||
if self._successor is not None:
|
||||
return self._successor.get_step_id()
|
||||
else:
|
||||
return f'step.{self._id}.{self.__msg_idx}'
|
||||
|
||||
def __add_test_step(self, message, result=BaseLogResult.PASSED):
|
||||
policy = self._cfg.get_policy(type(message))
|
||||
policy.standard(self.get_step_id(), message, result, self._container)
|
||||
self.__msg_idx += 1
|
||||
|
||||
def get_main_log_store(self):
|
||||
return self.__log_main_store
|
||||
|
||||
def start_group(self, message):
|
||||
self._header_msg_type = type(message)
|
||||
if self._successor is not None:
|
||||
result = self._successor.start_group(message)
|
||||
else:
|
||||
new_id = f"{self._id}.{self.__msg_idx}"
|
||||
self.__msg_idx += 1
|
||||
self._successor = self.__factory(self._container, self._cfg, message, new_id)
|
||||
self._successor.begin(message)
|
||||
result = self._successor
|
||||
return result
|
||||
|
||||
def end_group(self):
|
||||
if self._successor is not None:
|
||||
if self._successor._successor is None:
|
||||
self._successor.end()
|
||||
result = self._successor
|
||||
self._successor = None
|
||||
else:
|
||||
result = self._successor.end_group()
|
||||
else:
|
||||
self.end()
|
||||
result = self
|
||||
return result
|
||||
|
||||
def debug(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.debug(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.DEBUG)
|
||||
return super().debug(message)
|
||||
|
||||
def info(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.info(message)
|
||||
else:
|
||||
self.__add_test_step(message)
|
||||
super().info(message)
|
||||
|
||||
def workaround(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.workaround(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.WORKAROUND)
|
||||
super().workaround(message)
|
||||
|
||||
def warning(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.warning(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.WARNING)
|
||||
super().warning(message)
|
||||
|
||||
def skip(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.skip(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.SKIPPED)
|
||||
super().skip(message)
|
||||
|
||||
def error(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.error(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.FAILED)
|
||||
super().error(message)
|
||||
|
||||
def blocked(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.blocked(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.BLOCKED)
|
||||
super().blocked(message)
|
||||
|
||||
def critical(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.critical(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.CRITICAL)
|
||||
super().critical(message)
|
||||
|
||||
def exception(self, message):
|
||||
if self._successor is not None:
|
||||
self._successor.exception(message)
|
||||
else:
|
||||
self.__add_test_step(message, BaseLogResult.EXCEPTION)
|
||||
super().exception(message)
|
||||
|
||||
def end(self):
|
||||
return super().end()
|
||||
|
||||
def get_current_group(self):
|
||||
if self._successor is not None:
|
||||
result = self._successor.get_current_group()
|
||||
else:
|
||||
result = self
|
||||
return result
|
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.group.html_group_log import HtmlGroupLog
|
||||
|
||||
|
||||
class HtmlIterationGroupLog(HtmlGroupLog):
|
||||
def __init__(self, html_base, cfg, begin_msg, id='itg0'):
|
||||
super().__init__(HtmlIterationGroupLog._factory, html_base, cfg, begin_msg, id)
|
||||
|
||||
@staticmethod
|
||||
def _factory(html_base, cfg, begin_msg, id):
|
||||
return HtmlIterationGroupLog(html_base, cfg, begin_msg, id)
|
||||
|
||||
def end(self):
|
||||
result = super().end()
|
||||
self._cfg.group_end(self._id, self._header, self._container, result)
|
||||
return result
|
102
test/functional/test-framework/log/html_file_item_log.py
Normal file
102
test/functional/test-framework/log/html_file_item_log.py
Normal file
@@ -0,0 +1,102 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.html_file_log import HtmlFileLog
|
||||
from log.group.html_chapter_group_log import HtmlChapterGroupLog
|
||||
from log.group.html_iteration_group_log import HtmlIterationGroupLog
|
||||
from datetime import datetime
|
||||
from lxml.etree import Element
|
||||
|
||||
|
||||
class HtmlFileItemLog(HtmlFileLog):
|
||||
def __init__(self, html_file_path, test_title, cfg, iteration_title="Test summary"):
|
||||
super().__init__(html_file_path, test_title)
|
||||
root = self.get_root()
|
||||
self._log_items_store = root.xpath('/html/body')[0]
|
||||
self._idx = 0
|
||||
self._log_chapters_store = root.xpath('/html/body/section[@id="iteration-chapters"]')[0]
|
||||
self._chapter_group = HtmlChapterGroupLog(self._log_chapters_store, cfg, test_title)
|
||||
self._main_group = HtmlIterationGroupLog(self._log_items_store, cfg, test_title)
|
||||
self._start_time = datetime.now()
|
||||
iteration_title_node = root.xpath('/html/body/a/h1')[0]
|
||||
iteration_title_node.text = iteration_title
|
||||
self._config = cfg
|
||||
self._fail_container = root.xpath('/html/body/div/select[@id="error-list-selector"]')[0]
|
||||
|
||||
def __add_error(self, msg_idx, msg, error_class):
|
||||
fail_element = Element('option', value=msg_idx)
|
||||
fail_element.set('class', error_class)
|
||||
fail_element.text = msg
|
||||
self._fail_container.append(fail_element)
|
||||
|
||||
def start_iteration(self, message):
|
||||
super().begin(message)
|
||||
|
||||
def get_result(self):
|
||||
return self._main_group.get_result()
|
||||
|
||||
def begin(self, message):
|
||||
self._chapter_group.begin(message)
|
||||
self._main_group.begin(message)
|
||||
|
||||
def debug(self, message):
|
||||
self._main_group.debug(message)
|
||||
|
||||
def info(self, message):
|
||||
self._main_group.info(message)
|
||||
|
||||
def workaround(self, message):
|
||||
self._main_group.workaround(message)
|
||||
|
||||
def warning(self, message):
|
||||
self._main_group.warning(message)
|
||||
|
||||
def skip(self, message):
|
||||
self._main_group.skip(message)
|
||||
|
||||
def error(self, message):
|
||||
msg_idx = self._main_group.get_step_id()
|
||||
self.__add_error(msg_idx, message, "fail")
|
||||
self._main_group.error(message)
|
||||
|
||||
def blocked(self, message):
|
||||
msg_idx = self._main_group.get_step_id()
|
||||
self.__add_error(msg_idx, message, "blocked")
|
||||
self._main_group.blocked(message)
|
||||
|
||||
def exception(self, message):
|
||||
msg_idx = self._main_group.get_step_id()
|
||||
self.__add_error(msg_idx, message, "exception")
|
||||
self._main_group.exception(message)
|
||||
|
||||
def critical(self, message):
|
||||
msg_idx = self._main_group.get_step_id()
|
||||
self.__add_error(msg_idx, message, "critical")
|
||||
self._main_group.critical(message)
|
||||
|
||||
def start_group(self, message):
|
||||
self._chapter_group.start_group(message)
|
||||
self._main_group.start_group(message)
|
||||
|
||||
def end_group(self):
|
||||
ref_group = self._main_group.get_current_group()
|
||||
self._chapter_group.set_result(ref_group.get_result())
|
||||
self._main_group.end_group()
|
||||
self._chapter_group.end_dir_group(ref_group)
|
||||
|
||||
def end_all_groups(self):
|
||||
while self._main_group._successor is not None:
|
||||
self.end_group()
|
||||
|
||||
def end(self):
|
||||
while self._main_group._successor is not None:
|
||||
self.end_group()
|
||||
self.end_group()
|
||||
time_result = datetime.now() - self._start_time
|
||||
time_node = self.get_root().xpath('/html/body/div[@class="iteration-execution-time"]')[0]
|
||||
status_node = self.get_root().xpath('/html/body/div[@class="iteration-status"]')[0]
|
||||
self._config.end_iteration_func(
|
||||
time_node, status_node, time_result.total_seconds(), self.get_result())
|
||||
super().end()
|
29
test/functional/test-framework/log/html_file_log.py
Normal file
29
test/functional/test-framework/log/html_file_log.py
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.base_log import BaseLog
|
||||
from lxml.html import fromstring
|
||||
from lxml.html import tostring
|
||||
|
||||
|
||||
class HtmlFileLog(BaseLog):
|
||||
def __init__(self, file_path, title):
|
||||
super().__init__(title)
|
||||
self.__path = file_path
|
||||
with open(file_path) as file_stream:
|
||||
self.__root = fromstring(file_stream.read())
|
||||
node_list = self.__root.xpath('/html/head/title')
|
||||
node_list[0].text = title
|
||||
|
||||
def get_path(self):
|
||||
return self.__path
|
||||
|
||||
def get_root(self):
|
||||
return self.__root
|
||||
|
||||
def end(self):
|
||||
with open(self.__path, "wb") as file:
|
||||
x = tostring(self.__root)
|
||||
file.write(x)
|
13
test/functional/test-framework/log/html_iteration_log.py
Normal file
13
test/functional/test-framework/log/html_iteration_log.py
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.html_file_item_log import HtmlFileItemLog
|
||||
|
||||
|
||||
class HtmlIterationLog(HtmlFileItemLog):
|
||||
def __init__(self, test_title, iteration_title, config):
|
||||
self.iteration_closed: bool = False
|
||||
html_file = config.create_iteration_file()
|
||||
super().__init__(html_file, test_title, config, iteration_title)
|
204
test/functional/test-framework/log/html_log_config.py
Normal file
204
test/functional/test-framework/log/html_log_config.py
Normal file
@@ -0,0 +1,204 @@
|
||||
#
|
||||
# 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)
|
126
test/functional/test-framework/log/html_log_manager.py
Normal file
126
test/functional/test-framework/log/html_log_manager.py
Normal file
@@ -0,0 +1,126 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
|
||||
from log.base_log import BaseLog, escape
|
||||
from log.html_iteration_log import HtmlIterationLog
|
||||
from log.html_log_config import HtmlLogConfig
|
||||
from log.html_main_log import HtmlMainLog
|
||||
from log.html_setup_log import HtmlSetupLog
|
||||
|
||||
|
||||
class HtmlLogManager(BaseLog):
|
||||
def __init__(self, begin_message=None, log_config=None):
|
||||
super().__init__(begin_message)
|
||||
self._config = HtmlLogConfig() if log_config is None else log_config
|
||||
self._main = None
|
||||
self._log_setup = None
|
||||
self._log_iterations = []
|
||||
self._current_log = None
|
||||
self._files_path = None
|
||||
|
||||
def __add(self, msg):
|
||||
pass
|
||||
|
||||
def begin(self, message):
|
||||
self._files_path = self._config.create_html_test_log(message)
|
||||
self._main = HtmlMainLog(message, self._config)
|
||||
self._log_setup = HtmlSetupLog(message, config=self._config)
|
||||
self._current_log = self._log_setup
|
||||
self._main.begin(message)
|
||||
self._current_log.begin(message)
|
||||
self.__add("begin: " + message)
|
||||
|
||||
@property
|
||||
def base_dir(self):
|
||||
return self._files_path
|
||||
|
||||
def get_result(self):
|
||||
log_result = self._log_setup.get_result()
|
||||
for iteration in self._log_iterations:
|
||||
if log_result.value < iteration.get_result().value:
|
||||
log_result = iteration.get_result()
|
||||
return log_result
|
||||
|
||||
def end(self):
|
||||
self._log_setup.end()
|
||||
self._main.end_setup_iteration(self._log_setup.get_result())
|
||||
log_result = self.get_result()
|
||||
self._main.end(log_result)
|
||||
self.__add("end")
|
||||
|
||||
def add_build_info(self, message):
|
||||
self._main.add_build_info(escape(message))
|
||||
|
||||
def start_iteration(self, message):
|
||||
message = escape(message)
|
||||
self._log_iterations.append(HtmlIterationLog(message, message, self._config))
|
||||
self._main.start_iteration(self._config.get_iteration_id())
|
||||
self._current_log = self._log_iterations[-1]
|
||||
self._current_log.begin(message)
|
||||
self._log_setup.start_iteration(message)
|
||||
self.__add("start_iteration: " + message)
|
||||
|
||||
def end_iteration(self):
|
||||
self._current_log.end()
|
||||
self._main.end_iteration(self._current_log.get_result())
|
||||
self._log_setup.end_iteration(self._current_log.get_result())
|
||||
self._current_log.iteration_closed = True
|
||||
self._current_log = self._log_setup
|
||||
self.__add("end_iteration: ")
|
||||
return self._current_log
|
||||
|
||||
def debug(self, message):
|
||||
self._current_log.debug(escape(message))
|
||||
self.__add("debug: " + message)
|
||||
|
||||
def info(self, message):
|
||||
self._current_log.info(escape(message))
|
||||
self.__add("info: " + message)
|
||||
|
||||
def workaround(self, message):
|
||||
self._current_log.workaround(escape(message))
|
||||
self.__add(": " + message)
|
||||
|
||||
def warning(self, message):
|
||||
self._current_log.warning(escape(message))
|
||||
self.__add(": " + message)
|
||||
|
||||
def skip(self, message):
|
||||
self._current_log.skip(escape(message))
|
||||
self.__add("warning: " + message)
|
||||
|
||||
def error(self, message):
|
||||
self._current_log.error(escape(message))
|
||||
self.__add("error: " + message)
|
||||
|
||||
def blocked(self, message):
|
||||
self._current_log.blocked(escape(message))
|
||||
self.__add(f'blocked: {message}')
|
||||
self.end_all_groups()
|
||||
|
||||
def exception(self, message):
|
||||
self._current_log.exception(escape(message))
|
||||
self.__add("exception: " + message)
|
||||
self.end_all_groups()
|
||||
|
||||
def critical(self, message):
|
||||
self._current_log.critical(escape(message))
|
||||
self.__add("critical: " + message)
|
||||
self.end_all_groups()
|
||||
|
||||
def start_group(self, message):
|
||||
self._current_log.start_group(escape(message))
|
||||
self.__add("start_group: " + message)
|
||||
|
||||
def end_group(self):
|
||||
self._current_log.end_group()
|
||||
self.__add("end_group")
|
||||
|
||||
def end_all_groups(self):
|
||||
for iteration in reversed(self._log_iterations):
|
||||
if not iteration.iteration_closed:
|
||||
self.end_iteration()
|
||||
self._current_log.end_all_groups()
|
53
test/functional/test-framework/log/html_main_log.py
Normal file
53
test/functional/test-framework/log/html_main_log.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.html_file_log import HtmlFileLog
|
||||
from lxml.etree import Element
|
||||
|
||||
|
||||
class HtmlMainLog(HtmlFileLog):
|
||||
def __init__(self, title, config):
|
||||
super().__init__(config.get_main_file_path(), title)
|
||||
self._config = config
|
||||
self.__current_iteration_id = None
|
||||
root = self.get_root()
|
||||
test_title_div = root.xpath('/html/body/div/div/div/div[@class="sidebar-test-title"]')[0]
|
||||
test_title_div.text = title
|
||||
self.__build_information_set = root.xpath(
|
||||
'/html/body/div/div/div/div[@id="sidebar-tested-build"]')[0]
|
||||
|
||||
def add_build_info(self, message):
|
||||
build_info = Element("div")
|
||||
build_info.text = message
|
||||
self.__build_information_set.append(build_info)
|
||||
|
||||
def start_iteration(self, iteration_id):
|
||||
self.__current_iteration_id = iteration_id
|
||||
|
||||
def end_iteration(self):
|
||||
pass
|
||||
|
||||
def end_iteration(self, iteration_result):
|
||||
root = self.get_root()
|
||||
iteration_selector_div = root.xpath('/html/body/div/div/div[@id="iteration-selector"]')
|
||||
iteration_selector_select = root.xpath(
|
||||
'/html/body/div/div/select[@id="sidebar-iteration-list"]')[0]
|
||||
self._config.end_iteration(iteration_selector_div,
|
||||
iteration_selector_select,
|
||||
self.__current_iteration_id,
|
||||
iteration_result)
|
||||
|
||||
def end_setup_iteration(self, result):
|
||||
root = self.get_root()
|
||||
iteration_selector_div = root.xpath('/html/body/div/div/div[@id="iteration-selector"]')[0]
|
||||
iteration_selector_select = root.xpath(
|
||||
'/html/body/div/div/select[@id="sidebar-iteration-list"]')[0]
|
||||
self._config.end_setup_iteration(iteration_selector_div, iteration_selector_select, result)
|
||||
|
||||
def end(self, result):
|
||||
root = self.get_root()
|
||||
test_status_div = root.xpath('/html/body/div/div/div/div[@class="sidebar-test-status"]')
|
||||
self._config.end_main_log(test_status_div, result)
|
||||
super().end()
|
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.base_log import BaseLogResult
|
||||
from lxml.etree import Element
|
||||
from datetime import datetime
|
||||
from log.presentation_policy import PresentationPolicy
|
||||
from log.html_log_config import HtmlLogConfig
|
||||
|
||||
|
||||
def std_log_entry(msg_id, msg, log_result, html_node):
|
||||
test_step = Element('li')
|
||||
style = 'test-step'
|
||||
if log_result != BaseLogResult.PASSED:
|
||||
style = f"{style} {HtmlLogConfig.STYLE[log_result]}"
|
||||
test_step.set('class', style)
|
||||
test_time = Element('div')
|
||||
test_time.set('class', 'ts-time')
|
||||
test_time_txt = Element('a', name=msg_id)
|
||||
time = datetime.now()
|
||||
test_time_txt.text = f"{str(time.hour).zfill(2)}:" \
|
||||
f"{str(time.minute).zfill(2)}:{str(time.second).zfill(2)}"
|
||||
test_time.append(test_time_txt)
|
||||
test_step.append(test_time)
|
||||
test_msg = Element('div')
|
||||
test_msg.set('class', 'ts-msg')
|
||||
test_msg.text = msg
|
||||
test_step.append(test_msg)
|
||||
html_node.append(test_step)
|
||||
|
||||
|
||||
def group_log_begin(msg_id, msg, html_node):
|
||||
element = Element("div")
|
||||
sub_element = Element('a', name=msg_id)
|
||||
sub_element.text = msg
|
||||
element.append(sub_element)
|
||||
html_node.append(element)
|
||||
ul_set = Element('ul', id=f'ul_{msg_id}')
|
||||
html_node.append(ul_set)
|
||||
return element, ul_set
|
||||
|
||||
|
||||
html_policy = PresentationPolicy(std_log_entry, group_log_begin)
|
34
test/functional/test-framework/log/html_setup_log.py
Normal file
34
test/functional/test-framework/log/html_setup_log.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from log.html_file_item_log import HtmlFileItemLog
|
||||
from log.base_log import BaseLogResult
|
||||
|
||||
|
||||
class HtmlSetupLog(HtmlFileItemLog):
|
||||
|
||||
LOG_RESULT = {
|
||||
BaseLogResult.PASSED: HtmlFileItemLog.info,
|
||||
BaseLogResult.WORKAROUND: HtmlFileItemLog.workaround,
|
||||
BaseLogResult.WARNING: HtmlFileItemLog.warning,
|
||||
BaseLogResult.SKIPPED: HtmlFileItemLog.skip,
|
||||
BaseLogResult.FAILED: HtmlFileItemLog.error,
|
||||
BaseLogResult.BLOCKED: HtmlFileItemLog.blocked,
|
||||
BaseLogResult.EXCEPTION: HtmlFileItemLog.exception,
|
||||
BaseLogResult.CRITICAL: HtmlFileItemLog.critical}
|
||||
|
||||
def __init__(self, test_title, config, iteration_title="Test summary"):
|
||||
html_file_path = config.get_setup_file_path()
|
||||
super().__init__(html_file_path, test_title, config, iteration_title)
|
||||
self._last_iteration_title = ''
|
||||
|
||||
def start_iteration(self, message):
|
||||
self._last_iteration_title = message
|
||||
|
||||
def end_iteration(self, iteration_result):
|
||||
HtmlSetupLog.LOG_RESULT[iteration_result](self, self._last_iteration_title)
|
||||
|
||||
def end(self):
|
||||
super().end()
|
220
test/functional/test-framework/log/logger.py
Normal file
220
test/functional/test-framework/log/logger.py
Normal file
@@ -0,0 +1,220 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime
|
||||
from threading import Lock
|
||||
|
||||
import portalocker
|
||||
|
||||
from log.html_log_config import HtmlLogConfig
|
||||
from log.html_log_manager import HtmlLogManager
|
||||
from log.html_presentation_policy import html_policy
|
||||
from test_utils.output import Output
|
||||
from test_utils.singleton import Singleton
|
||||
|
||||
|
||||
def create_log(log_base_path, test_module, additional_args=None):
|
||||
Log.setup()
|
||||
log_cfg = HtmlLogConfig(base_dir=log_base_path,
|
||||
presentation_policy=html_policy)
|
||||
log = Log(log_config=log_cfg)
|
||||
test_name = 'TestNameError'
|
||||
error_msg = None
|
||||
try:
|
||||
test_name = test_module
|
||||
if additional_args:
|
||||
test_name += f"__{'_'.join(additional_args)}"
|
||||
except Exception as ex:
|
||||
error_msg = f'Detected some problems during calculating test name: {ex}'
|
||||
finally:
|
||||
log.begin(test_name)
|
||||
print(f"\n<LogFile>{os.path.join(log.base_dir, 'main.html')}</LogFile>")
|
||||
if error_msg:
|
||||
log.exception(error_msg)
|
||||
return log
|
||||
|
||||
|
||||
class Log(HtmlLogManager, metaclass=Singleton):
|
||||
logger = None
|
||||
LOG_FORMAT = '%(asctime)s %(levelname)s:\t%(message)s'
|
||||
DATE_FORMAT = "%Y/%m/%d %H:%M:%S"
|
||||
command_id = 0
|
||||
lock = Lock()
|
||||
|
||||
@classmethod
|
||||
def destroy(cls):
|
||||
del cls._instances[cls]
|
||||
|
||||
@classmethod
|
||||
def setup(cls):
|
||||
|
||||
# Get handle to root logger.
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
# Set paramiko log level to warning
|
||||
logging.getLogger('paramiko').setLevel(logging.WARNING)
|
||||
|
||||
# Create Handlers.
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
|
||||
# Set logging level on handlers.
|
||||
stdout_handler.setLevel(logging.DEBUG)
|
||||
|
||||
# Set log formatting on each handler.
|
||||
formatter = logging.Formatter(Log.LOG_FORMAT, Log.DATE_FORMAT)
|
||||
stdout_handler.setFormatter(formatter)
|
||||
|
||||
# Attach handlers to root logger.
|
||||
logger.handlers = []
|
||||
logger.addHandler(stdout_handler)
|
||||
cls.logger = logger
|
||||
logger.info("Logger successfully initialized.")
|
||||
|
||||
@contextmanager
|
||||
def step(self, message):
|
||||
self.step_info(message)
|
||||
super(Log, self).start_group(message)
|
||||
if Log.logger:
|
||||
Log.logger.info(message)
|
||||
yield
|
||||
super(Log, self).end_group()
|
||||
|
||||
@contextmanager
|
||||
def group(self, message):
|
||||
self.start_group(message)
|
||||
yield
|
||||
self.end_group()
|
||||
|
||||
def add_build_info(self, msg):
|
||||
super(Log, self).add_build_info(msg)
|
||||
if Log.logger:
|
||||
Log.logger.info(msg)
|
||||
|
||||
def info(self, msg):
|
||||
super(Log, self).info(msg)
|
||||
if Log.logger:
|
||||
Log.logger.info(msg)
|
||||
|
||||
def debug(self, msg):
|
||||
super(Log, self).debug(msg)
|
||||
if Log.logger:
|
||||
Log.logger.debug(msg)
|
||||
|
||||
def error(self, msg):
|
||||
super(Log, self).error(msg)
|
||||
if Log.logger:
|
||||
Log.logger.error(msg)
|
||||
|
||||
def blocked(self, msg):
|
||||
super(Log, self).blocked(msg)
|
||||
if Log.logger:
|
||||
Log.logger.fatal(msg)
|
||||
|
||||
def exception(self, msg):
|
||||
super(Log, self).exception(msg)
|
||||
if Log.logger:
|
||||
Log.logger.exception(msg)
|
||||
|
||||
def critical(self, msg):
|
||||
super(Log, self).critical(msg)
|
||||
if Log.logger:
|
||||
Log.logger.fatal(msg)
|
||||
|
||||
def workaround(self, msg):
|
||||
super(Log, self).workaround(msg)
|
||||
if Log.logger:
|
||||
Log.logger.warning(msg)
|
||||
|
||||
def warning(self, msg):
|
||||
super(Log, self).warning(msg)
|
||||
if Log.logger:
|
||||
Log.logger.warning(msg)
|
||||
|
||||
def get_new_command_id(self):
|
||||
self.lock.acquire()
|
||||
command_id = self.command_id
|
||||
self.command_id += 1
|
||||
self.lock.release()
|
||||
return command_id
|
||||
|
||||
def write_to_command_log(self, message):
|
||||
super(Log, self).debug(message)
|
||||
command_log_path = os.path.join(self.base_dir, "dut_info", 'commands.log')
|
||||
timestamp = datetime.now().strftime('%Y-%m-%d_%H:%M:%S:%f')
|
||||
with portalocker.Lock(command_log_path, "ab+") as command_log:
|
||||
line_to_write = f"[{timestamp}] {message}\n"
|
||||
command_log.write(line_to_write.encode())
|
||||
|
||||
def write_command_to_command_log(self, command, command_id, info=None):
|
||||
added_info = "" if info is None else f"[{info}] "
|
||||
self.write_to_command_log(f"{added_info}Command id: {command_id}\n{command}")
|
||||
|
||||
def write_output_to_command_log(self, output: Output, command_id):
|
||||
if output is not None:
|
||||
line_to_write = f"Command id: {command_id}\n\texit code: {output.exit_code}\n" \
|
||||
f"\tstdout: {output.stdout}\n" \
|
||||
f"\tstderr: {output.stderr}\n\n\n"
|
||||
self.write_to_command_log(line_to_write)
|
||||
else:
|
||||
self.write_to_command_log(f"Command id: {command_id}\n\tNone output.")
|
||||
|
||||
def step_info(self, step_name):
|
||||
from core.test_run import TestRun
|
||||
decorator = "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n"
|
||||
message = f"\n\n\n{decorator}{step_name}\n\n{decorator}\n"
|
||||
|
||||
try:
|
||||
serial_monitor = TestRun.plugin_manager.get_plugin("serial_monitor")
|
||||
serial_monitor.send_to_serial(message)
|
||||
except (KeyError, AttributeError):
|
||||
pass
|
||||
self.write_to_command_log(message)
|
||||
|
||||
def get_additional_logs(self):
|
||||
from core.test_run import TestRun
|
||||
from test_tools.fs_utils import check_if_file_exists
|
||||
messages_log = "/var/log/messages"
|
||||
if not check_if_file_exists(messages_log):
|
||||
messages_log = "/var/log/syslog"
|
||||
log_files = {"messages.log": messages_log,
|
||||
"dmesg.log": "/tmp/dmesg"}
|
||||
extra_logs = TestRun.config.get("extra_logs", {})
|
||||
log_files.update(extra_logs)
|
||||
|
||||
TestRun.executor.run(f"dmesg > {log_files['dmesg.log']}")
|
||||
|
||||
for log_name, log_source_path in log_files.items():
|
||||
try:
|
||||
log_destination_path = os.path.join(
|
||||
self.base_dir, f"dut_info", TestRun.dut.ip, log_name
|
||||
)
|
||||
TestRun.executor.rsync_from(log_source_path, log_destination_path)
|
||||
except Exception as e:
|
||||
TestRun.LOGGER.warning(
|
||||
f"There was a problem during gathering {log_name} log.\n{str(e)}"
|
||||
)
|
||||
|
||||
def generate_summary(self, item, meta):
|
||||
import json
|
||||
summary_path = os.path.join(self.base_dir, 'info.json')
|
||||
with open(summary_path, "w+") as summary:
|
||||
data = {
|
||||
'module': os.path.relpath(item.fspath, os.getcwd()),
|
||||
'function': item.name,
|
||||
'meta': meta,
|
||||
'status': self.get_result().name,
|
||||
'path': os.path.normpath(self.base_dir),
|
||||
'stage_status': {
|
||||
'setup': getattr(item, "rep_setup", {}),
|
||||
'call': getattr(item, "rep_call", {}),
|
||||
'teardown': getattr(item, "rep_teardown", {})
|
||||
}
|
||||
}
|
||||
json.dump(data, summary)
|
21
test/functional/test-framework/log/presentation_policy.py
Normal file
21
test/functional/test-framework/log/presentation_policy.py
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# Copyright(c) 2019-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
|
||||
class PresentationPolicy:
|
||||
def __init__(self, standard_log, group_begin_func):
|
||||
self.standard = standard_log
|
||||
self.group_begin = group_begin_func
|
||||
|
||||
|
||||
def std_log_entry(msg_id, msg, log_result, html_node):
|
||||
pass
|
||||
|
||||
|
||||
def group_log_begin(msg_id, msg, html_node):
|
||||
return html_node, html_node
|
||||
|
||||
|
||||
null_policy = PresentationPolicy(std_log_entry, group_log_begin)
|
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Copyright(c) 2019-2021 Intel Corporation
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>[title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="../main.css"/>
|
||||
<script src="../main.js"></script>
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body onload="onLoadDocument();">
|
||||
<div class="floating">
|
||||
<b>View: </b>
|
||||
<select id="mode-selector" onchange="selectMode();">
|
||||
<option style="background-color: white; color: black;" value="info">Info</option>
|
||||
<option style="background-color: white; color: black" value="debug">Debug</option>
|
||||
</select>
|
||||
<b>Errors: </b>
|
||||
<button onclick="previousError()"><</button>
|
||||
<select id="error-list-selector" onchange="errorSelected('error-list-selector')">
|
||||
<option value="top" class="empty">-empty-</option>
|
||||
</select>
|
||||
<button onclick="nextError()">></button>
|
||||
</div>
|
||||
<br/>
|
||||
<a name="top"><h1 class="iteration-title" style="border-bottom: 4px solid rgba(255, 0, 0, 1)">[title]</h1></a>
|
||||
<div class="iteration-status">Iteration status: [status]</div>
|
||||
<div class="iteration-execution-time">Execution time: [time] [s]</div>
|
||||
<section class="iteration-chapters" id="iteration-chapters">
|
||||
<h2>Groups:</h2>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
@@ -0,0 +1,37 @@
|
||||
<!--
|
||||
Copyright(c) 2019-2021 Intel Corporation
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Setup</title>
|
||||
<link rel="stylesheet" type="text/css" href="../main.css"/>
|
||||
<meta charset="UTF-8"/>
|
||||
<script src="../main.js"></script>
|
||||
</head>
|
||||
<body onload="onLoadDocument();">
|
||||
<div class="floating">
|
||||
<b>View: </b>
|
||||
<select id="mode-selector" onchange="selectMode();">
|
||||
<option style="background-color: white; color: black;" value="info">Info</option>
|
||||
<option style="background-color: white; color: black" value="debug">Debug</option>
|
||||
</select>
|
||||
<b>Errors: </b>
|
||||
<button onclick="previousError()"><</button>
|
||||
<select id="error-list-selector" onchange="errorSelected('error-list-selector')">
|
||||
<option value="top">-empty-</option>
|
||||
</select>
|
||||
<button onclick="nextError()">></button>
|
||||
</div>
|
||||
<br/>
|
||||
<a name="top">
|
||||
<h1 class="iteration-title" style="border-bottom: 4px solid rgba(255, 0, 0, 1)">Test summary</h1>
|
||||
</a>
|
||||
<div class="iteration-status">Iteration status: [STATUS]</div>
|
||||
<div class="iteration-execution-time">Execution time: [time] [s]</div>
|
||||
<section class="iteration-chapters" id="iteration-chapters">
|
||||
<h2>Groups:</h2>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
383
test/functional/test-framework/log/template/main.css
Normal file
383
test/functional/test-framework/log/template/main.css
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
Copyright(c) 2019-2021 Intel Corporation
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #F0F0F0;
|
||||
font-family: Calibri;
|
||||
color: black;
|
||||
}
|
||||
|
||||
div { display: block; }
|
||||
|
||||
h2 { margin: 0; padding: 0; }
|
||||
h4 { margin: 0; padding: 0; }
|
||||
|
||||
div.meta-container {
|
||||
margin-left: 502px;
|
||||
min-width: 500px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
div.main-layaut {
|
||||
float: right;
|
||||
width: 100%;
|
||||
background-color: #FDFDFD;
|
||||
height: 100vh;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
float: left;
|
||||
width: 500px;
|
||||
height: 100vh;
|
||||
margin-left: -502px;
|
||||
border: 4px;
|
||||
background-color: #F0F0F0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
text-align: center;
|
||||
color: white;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
div.sidebar-hide {
|
||||
padding: 3px;
|
||||
height: 20px;
|
||||
margin: 5px auto;
|
||||
font-family: Consolas;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
text-shadow: 1px 1px 3px black;
|
||||
background-color: rgb(40,80,180);
|
||||
cursor: default;
|
||||
border: 2px solid silver;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
div.sidebar-show { color: balck; height: 50%; }
|
||||
|
||||
div.sidebar-test { overflow-x: hidden; overflow-y: hidden;}
|
||||
|
||||
div.sidebar-test-title {
|
||||
padding: 10px;
|
||||
height: 40px;
|
||||
margin: 5px auto;
|
||||
background-color: rgb(40,80,180);
|
||||
font-size: 100%;
|
||||
border: 2px solid silver;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
div.sidebar-test-status {
|
||||
padding: 3px;
|
||||
height: 20px;
|
||||
background-color: green;
|
||||
border: 2px solid silver;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
div.sidebar-tested-build {
|
||||
color: black;
|
||||
border-radius: 25px;
|
||||
width: 80%;
|
||||
margin: 5px auto;
|
||||
padding: 25px;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid silver;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.sidebar-test-iteration {
|
||||
padding: 3px;
|
||||
height: 20px;
|
||||
margin: 5px auto;
|
||||
font-family: Consolas;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
text-shadow: 1px 1px 3px black;
|
||||
background-color: rgb(40,80,180);
|
||||
cursor: default;
|
||||
border: 2px solid silver;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.debug { display: none; }
|
||||
|
||||
select.sidebar-iteration-list {
|
||||
margin: 5px auto;
|
||||
background-color: white;
|
||||
color: black;
|
||||
width: 90%;
|
||||
}
|
||||
select.warning { background-color: #ff0; color: black; }
|
||||
select.workaround { background-color: #fff8dc; color: black; }
|
||||
select.skip { background-color: silver; color: black; }
|
||||
select.fail { background-color: red; color: white; }
|
||||
select.blocked { background-color: #7030a0; color: white; }
|
||||
select.exception { background-color: #e29517; color: white; }
|
||||
select.critical { background-color: #002060; color: white; }
|
||||
|
||||
option {
|
||||
background-color: green;
|
||||
color: white;
|
||||
margin: 2px;
|
||||
}
|
||||
option.warning { background-color: #ff0; color: black; }
|
||||
option.workaround { background-color: #fff8dc; color: black; }
|
||||
option.skip { background-color: silver; color: black; }
|
||||
option.error { background-color: red; color: white; }
|
||||
option.blocked { background-color: #7030a0; color: white; }
|
||||
option.exception { background-color: #e29517; color: white; }
|
||||
select.critical { background-color: #002060; color: white; }
|
||||
|
||||
a.iteration-selector {
|
||||
border: 2px solid silver;
|
||||
border-radius: 40px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
display: table-cell;
|
||||
color: white;
|
||||
background-color: green;
|
||||
text-shadow: 0 0 3px black;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
line-height: 1em;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
a.warning { background-color: #ff0; }
|
||||
a.workaround { background-color: #fff8dc; }
|
||||
a.skip { background-color: silver; }
|
||||
a.fail { background-color: red; }
|
||||
a.exception { background-color: #e29517; }
|
||||
a.blocked { background-color: #7030a0; }
|
||||
a.critical { background-color: #002060; }
|
||||
a.selected { border: 2px solid black; }
|
||||
|
||||
select.error-list-selector { background-color: silver; }
|
||||
|
||||
div.test-chapter-step {
|
||||
margin: 4px auto;
|
||||
border-style: solid;
|
||||
border-color: #8CB9AE;
|
||||
border-radius: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.sidebar-copyright {
|
||||
position: absolute;
|
||||
background-color: #DDD;
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
color: #888;
|
||||
bottom: 0;
|
||||
font-size: 12px;
|
||||
font-family: Consolas;
|
||||
}
|
||||
|
||||
div.floating {
|
||||
right: 0;
|
||||
border: 3px solid silver;
|
||||
width: 40%;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
position: fixed;
|
||||
background-color : #F0F0F0;
|
||||
border-bottom: 1px solid #999;
|
||||
z-index: 999;
|
||||
color: #333;
|
||||
box-shadow: 0 0px 6px gray;
|
||||
}
|
||||
|
||||
h1 {
|
||||
display: block;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.iteration-selector {
|
||||
margin: 5px auto;
|
||||
}
|
||||
|
||||
div.iteration-status {
|
||||
padding: 3px;
|
||||
height: 20px;
|
||||
background-color: green;
|
||||
border: 2px solid silver;
|
||||
border-radius: 25px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1.iteration-title { text-align: center; }
|
||||
|
||||
div.iteration-execution-time { text-align: center; }
|
||||
|
||||
section.iteration-chapters {
|
||||
border-radius: 25px;
|
||||
width: 80%;
|
||||
margin: 10px auto;
|
||||
padding: 25px;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid silver;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
ul.iteration-content {
|
||||
list-style-type: none;
|
||||
border-left-color: green;
|
||||
border-left-style: solid;
|
||||
margin: 0px;
|
||||
}
|
||||
ul.warning { border-left-color: #ff0; }
|
||||
ul.workaround { border-left-color: #fff8dc; }
|
||||
ul.skip { border-left-color: silver; }
|
||||
ul.fail { border-left-color: red; }
|
||||
ul.blocked { border-left-color: #7030a0; }
|
||||
ul.critical { border-left-color: #002060; }
|
||||
ul.exception { border-left-color: #e29517; }
|
||||
|
||||
li.iteration-content {
|
||||
border-color: rgba(192, 192, 192, 1);
|
||||
background-color: rgba(238, 238, 238, 1);
|
||||
display: block;
|
||||
margin: 2px auto;
|
||||
border: 1px solid #C0C0C0;
|
||||
padding: 3px 6px;
|
||||
font-family: Calibri;
|
||||
font-size: 16px;
|
||||
line-height: 1.15em;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
border-left-color: green;
|
||||
border-left-style: solid;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
div.test-group-step {
|
||||
color: black;
|
||||
background-color: #8CB9AE;
|
||||
border: 1px solid #5C8880;
|
||||
font-size: 18px;
|
||||
letter-spacing: 2px;
|
||||
cursor: pointer;
|
||||
margin: 4px;
|
||||
border-radius: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
div.warning { background-color: #ff0; color: black; }
|
||||
div.workaround { background-color: #fff8dc; color: black; }
|
||||
div.skip { background-color: silver; color: black; }
|
||||
div.fail { background-color: red; color: white; }
|
||||
div.blocked { background-color: #7030a0; color: white; }
|
||||
div.critical { background-color: #002060; color: white; }
|
||||
div.exception { background-color: #e29517; color: white; }
|
||||
|
||||
a.top-marker { cursor: pointer; float: right; }
|
||||
|
||||
a.top-time-marker {
|
||||
word-wrap: break-word;
|
||||
float: right;
|
||||
}
|
||||
|
||||
li.test-step {
|
||||
color: black;
|
||||
border-color: rgba(192, 192, 192, 1);
|
||||
background-color: rgba(238, 238, 238, 1);
|
||||
display: block;
|
||||
margin: 4px auto;
|
||||
border: 1px solid #C0C0C0;
|
||||
padding: 3px 6px;
|
||||
font-family: Calibri;
|
||||
font-size: 16px;
|
||||
line-height: 1.15em;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
border-left-color: green;
|
||||
border-left-style: solid;
|
||||
border-radius: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px
|
||||
}
|
||||
li.warning { background-color: #ff0; border-left-color: #ff0; }
|
||||
li.workaround { background-color: #fff8dc; border-left-color: #fff8dc; }
|
||||
li.skip { background-color: silver; border-left-color: silver; }
|
||||
li.fail {
|
||||
background-color: red;
|
||||
border-left-color: red;
|
||||
color: white;
|
||||
}
|
||||
li.blocked {
|
||||
background-color: #7030a0;
|
||||
border-left-color: #7030a0;
|
||||
color: white;
|
||||
}
|
||||
li.exception {
|
||||
background-color: #e29517;
|
||||
border-left-color: #e29517;
|
||||
color: white;
|
||||
}
|
||||
|
||||
li.critical {
|
||||
background-color: #002060;
|
||||
border-left-color: #002060;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.ts-iteration {
|
||||
float: left;
|
||||
margin: 2px auto;
|
||||
border: 1px solid silver;
|
||||
padding: 3px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.ts-total-time {
|
||||
margin: 2px auto;
|
||||
border: 1px solid silver;
|
||||
padding: 3px 3px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.ts-time {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
margin: 2px auto;
|
||||
border: 1px solid #A7A7A7;
|
||||
padding: 3px 3px;
|
||||
}
|
||||
|
||||
div.ts-msg {
|
||||
font-size: 16px;
|
||||
font-family: Courier;
|
||||
margin: 2px auto;
|
||||
border: 1px solid #A7A7A7;
|
||||
padding: 3px 3px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
44
test/functional/test-framework/log/template/main.html
Normal file
44
test/functional/test-framework/log/template/main.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
Copyright(c) 2019-2021 Intel Corporation
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>[test title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="main.css">
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="meta-container">
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-test" id="sidebar-test">
|
||||
<div class="sidebar-show" style="display:none" onclick="sidebarCtrl('sidebar-hide', 'sidebar-show')">>></div>
|
||||
<div class="sidebar-test-title">Test title: </div>
|
||||
<div class="sidebar-test-status">Test status: </div>
|
||||
<div class="sidebar-tested-build" id="sidebar-tested-build">
|
||||
<h2>Build:</h2>
|
||||
</div>
|
||||
<div class="sidebar-hide" id=sidebar-hide" onclick="sidebarCtrl('sidebar-hide', 'sidebar-show')"><<</div>
|
||||
<div class="sidebar-show" style="display:none" onclick="sidebarCtrl('sidebar-hide', 'sidebar-show')">>></div>
|
||||
</div>
|
||||
<div class="sidebar-test-iteration">Executed iterations:</div>
|
||||
<select id="sidebar-iteration-list" class="sidebar-iteration-list" onchange="selectIterationFromSelect()" onclick="clickSelectIteration()">
|
||||
<option value="M">Setup</option>
|
||||
</select>
|
||||
<div id="iteration-selector">
|
||||
<a class="iteration-selector" onclick="selectIteration('M')">M</a>
|
||||
</div>
|
||||
<div class="sidebar-copyright" id="sidebar-copyright">
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
<br>
|
||||
Copyright © 2015-2021 Intel Corporation
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-layaut">
|
||||
<iframe id="main-view" src="iterations/setup.html" width="100%" height="99%"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
223
test/functional/test-framework/log/template/main.js
Normal file
223
test/functional/test-framework/log/template/main.js
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Copyright(c) 2019-2021 Intel Corporation
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
function onLoadDocument() {
|
||||
hideDebug();
|
||||
}
|
||||
|
||||
function selectMode() {
|
||||
var selector = document.getElementById('mode-selector');
|
||||
if (selector.value.includes('info')) {
|
||||
hideDebug();
|
||||
} else {
|
||||
showDebug();
|
||||
}
|
||||
}
|
||||
|
||||
function hideDebug() {
|
||||
var debugTestStepArray = document.getElementsByTagName('li');
|
||||
for (i = 0; i < debugTestStepArray.length; i ++) {
|
||||
if(debugTestStepArray[i].className.includes('debug')) {
|
||||
debugTestStepArray[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showDebug() {
|
||||
var debugTestStepArray = document.getElementsByTagName('li');
|
||||
for (i = 0; i < debugTestStepArray.length; i ++) {
|
||||
if(debugTestStepArray[i].className.includes('debug')) {
|
||||
debugTestStepArray[i].style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sidebarCtrl(ctrlHideId, ctrlShowClass) {
|
||||
var metaContainer = document.getElementsByClassName("meta-container")[0];
|
||||
var sidebar = document.getElementsByClassName('sidebar')[0];
|
||||
var sidebarTest = document.getElementById('sidebar-test');
|
||||
var ctrlHide = document.getElementById(ctrlHideId);
|
||||
var ctrlShowSet = document.getElementsByClassName(ctrlShowClass);
|
||||
|
||||
if(sidebar.style.width.includes('15px')) {
|
||||
showSidebar(metaContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest);
|
||||
} else {
|
||||
hideSidebar(metaContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest);
|
||||
}
|
||||
}
|
||||
|
||||
function showSidebar(mContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest) {
|
||||
sidebar.style.cursor = 'default';
|
||||
mContainer.style.marginLeft = '';
|
||||
sidebarTest.style.width = '';
|
||||
sidebarTest.style.height = '';
|
||||
sidebar.style.height = '';
|
||||
sidebar.style.marginLeft = '';
|
||||
sidebar.style.width = '';
|
||||
var i;
|
||||
for (i = 0; i < sidebarTest.children.length; i++) {
|
||||
sidebarTest.children[i].style.display = '';
|
||||
}
|
||||
document.getElementById('iteration-selector').style.display = '';
|
||||
document.getElementById('sidebar-iteration-list').style.display = '';
|
||||
document.getElementById('sidebar-copyright').style.display = '';
|
||||
for(i = 0; i < ctrlShowSet.length; i ++) {
|
||||
ctrlShowSet[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function hideSidebar(mContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest) {
|
||||
document.getElementById('iteration-selector').style.display = 'none';
|
||||
document.getElementById('sidebar-iteration-list').style.display = 'none';
|
||||
document.getElementById('sidebar-copyright').style.display = 'none';
|
||||
var i;
|
||||
for (i = 0; i < sidebarTest.children.length; i++) {
|
||||
sidebarTest.children[i].style.display = 'none';
|
||||
}
|
||||
sidebarTest.style.display = '';
|
||||
for(i = 0; i < ctrlShowSet.length; i ++) {
|
||||
ctrlShowSet[i].style.display = '';
|
||||
ctrlShowSet[i].style.color = 'black';
|
||||
}
|
||||
sidebar.style.width = '15px';
|
||||
sidebar.style.marginLeft = '-15px';
|
||||
sidebar.style.height = '100%';
|
||||
sidebarTest.style.height = '100%';
|
||||
sidebarTest.style.width = '100%';
|
||||
mContainer.style.marginLeft = '16px';
|
||||
sidebar.style.cursor = 'pointer';
|
||||
}
|
||||
|
||||
function previousError() {
|
||||
var errorSelector = document.getElementById("error-list-selector");
|
||||
if (errorSelector.length > 1) {
|
||||
var id = errorSelector.selectedIndex;
|
||||
if (id - 1 > 0) {
|
||||
errorSelector.selectedIndex = (id - 1);
|
||||
} else {
|
||||
errorSelector.selectedIndex = (errorSelector.length - 1);
|
||||
}
|
||||
errorSelected('error-list-selector');
|
||||
}
|
||||
}
|
||||
|
||||
function nextError() {
|
||||
var errorSelector = document.getElementById("error-list-selector");
|
||||
if (errorSelector.length > 1) {
|
||||
var id = errorSelector.selectedIndex;
|
||||
if (id + 1 < errorSelector.length) {
|
||||
errorSelector.selectedIndex = (id + 1);
|
||||
} else {
|
||||
errorSelector.selectedIndex = 1;
|
||||
}
|
||||
errorSelected('error-list-selector');
|
||||
}
|
||||
}
|
||||
|
||||
function selectIterationFromSelect() {
|
||||
var element = document.getElementById("sidebar-iteration-list");
|
||||
loadDocument(element.value);
|
||||
updateIterationSelector(element);
|
||||
}
|
||||
|
||||
function clickSelectIteration() {
|
||||
var element = document.getElementById("sidebar-iteration-list");
|
||||
for (i = 0; i < element.length; i ++) {
|
||||
option = element[i];
|
||||
var cls = option.getAttribute('class');
|
||||
switch(cls) {
|
||||
case "warning":
|
||||
option.style.backgroundColor = "yellow";
|
||||
option.style.color = "black";
|
||||
break;
|
||||
case "skip":
|
||||
option.style.backgroundColor = "silver";
|
||||
option.style.color = "black";
|
||||
break;
|
||||
case "fail":
|
||||
option.style.backgroundColor = "red";
|
||||
option.style.color = "white";
|
||||
break;
|
||||
case "exception":
|
||||
option.style.backgroundColor = "blueviolet";
|
||||
option.style.color = "white";
|
||||
break;
|
||||
default:
|
||||
option.style.backgroundColor = "white";
|
||||
option.style.color = "black";
|
||||
break;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
function selectIteration(iteration) {
|
||||
var selectElement = document.getElementById("sidebar-iteration-list");
|
||||
var docId = loadDocument(iteration);
|
||||
selectElement.selectedIndex = docId;
|
||||
updateIterationSelector(selectElement);
|
||||
}
|
||||
|
||||
function loadDocument(fileId) {
|
||||
var result = 0;
|
||||
if(fileId == 'M') {
|
||||
document.getElementById("main-view").src = "iterations/setup.html";
|
||||
} else {
|
||||
var id = pad(fileId, 3);
|
||||
document.getElementById("main-view").src = "iterations/iteration_" + id + ".html";
|
||||
result = parseInt(fileId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function updateIterationSelector(element) {
|
||||
var index = element.selectedIndex
|
||||
var option_class = element[index].getAttribute('class')
|
||||
if (option_class != null) {
|
||||
element.setAttribute('class', "sidebar-iteration-list " + option_class);
|
||||
} else {
|
||||
element.setAttribute('class', "sidebar-iteration-list");
|
||||
}
|
||||
}
|
||||
|
||||
function errorSelected(selectorId) {
|
||||
var newLocation = document.getElementById(selectorId).value;
|
||||
window.location.hash = newLocation;
|
||||
}
|
||||
|
||||
function pad(strNumber, padding) {
|
||||
while((strNumber.length + 1) <= padding) {
|
||||
strNumber = "0" + strNumber;
|
||||
}
|
||||
return strNumber;
|
||||
}
|
||||
|
||||
function showHide(id) {
|
||||
var ulElement = document.getElementById(id);
|
||||
if(ulElement.style.display == 'none') {
|
||||
ulElement.style.display = '';
|
||||
} else {
|
||||
ulElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function chapterClick(id) {
|
||||
var id_array = id.split('.');
|
||||
var node_id = "";
|
||||
var i = 0;
|
||||
var destinationElement = document.getElementById(id);
|
||||
if (destinationElement.style.display == 'none') {
|
||||
do {
|
||||
node_id += id_array[i];
|
||||
var ele = document.getElementById(node_id);
|
||||
ele.style.display = '';
|
||||
node_id += '.';
|
||||
i += 1;
|
||||
} while (i < id_array.length);
|
||||
window.location = '#' + id;
|
||||
} else {
|
||||
destinationElement.style.display = 'none';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user