Add report tools for report stage at SI pipeline
diff --git a/report-tools/generate_report.py b/report-tools/generate_report.py
index 7c70050..53087c1 100644
--- a/report-tools/generate_report.py
+++ b/report-tools/generate_report.py
@@ -12,7 +12,13 @@
import argparse
import os
import logging
-import time
+import subprocess
+import sys
+import json
+from adaptors.sql.yaml_parser import YAMLParser
+import glob
+
+HTML_TEMPLATE = "html.tar.gz"
class TCReport(object):
@@ -55,13 +61,13 @@
# {report properties}
try:
with open(report_file) as f:
- full_report = yaml.full_load(f)
+ full_report = yaml.load(f)
self._report_name, \
self.report = list(full_report.items())[0]
- except Exception as e:
+ except Exception as ex:
logging.exception(
f"Exception loading existing report '{report_file}'")
- raise Exception(e)
+ raise ex
else:
self.report = {'metadata': metadata,
'test-environments': test_environments,
@@ -69,6 +75,7 @@
'target': target,
'test-suites': test_suites
}
+ self.report_file = report_file
def dump(self, file_name):
"""
@@ -181,7 +188,7 @@
break
p = pattern.match(rest[0])
if p:
- id = p.groupdict()['id'].replace(" ", "_")
+ id = re.sub("[ :]+", "_", p.groupdict()['id'])
status = p.groupdict()['status']
if not id:
print("Warning: missing 'id'")
@@ -230,6 +237,40 @@
def metadata(self, metadata):
self.report['metadata'] = metadata
+ @property
+ def target(self):
+ return self.report['target']
+
+ @target.setter
+ def target(self, target):
+ self.report['target'] = target
+
+ def merge_into(self, other):
+ """
+ Merge one report object with this.
+
+ :param other: Report object to be merged to this
+ :return:
+ """
+ try:
+ if not self.report_name or self.report_name == "Not-defined":
+ self.report_name = other.report_name
+ if self.report_name != other.report_name:
+ logging.warning(
+ f'Report name \'{other.report_name}\' does not match '
+ f'original report name')
+ # Merge metadata where 'other' report will overwrite common key
+ # values
+ self.metadata.update(other.metadata)
+ self.target.update(other.target)
+ self.test_config['test-assets'].update(other.test_config['test'
+ '-assets'])
+ self.test_environments.update(other.test_environments)
+ self.test_suites.update(other.test_suites)
+ except Exception as ex:
+ logging.exception("Failed to merge reports")
+ raise ex
+
class KvDictAppendAction(argparse.Action):
"""
@@ -244,7 +285,8 @@
(k, v) = value.split("=", 2)
except ValueError as ex:
raise \
- argparse.ArgumentError(self, f"Could not parse argument '{values[0]}' as k=v format")
+ argparse.ArgumentError(self,
+ f"Could not parse argument '{values[0]}' as k=v format")
d[k] = v
setattr(args, self.dest, d)
@@ -308,8 +350,20 @@
# Get the test results
results = {}
if _args.type == 'ptest-report':
+ results_pattern = None
+ suite = _args.suite or _args.test_suite_name
+ if suite == "optee-test":
+ results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (?P<id>.+ .+) " \
+ r"- (?P<description>.+)"
+ elif suite == "kernel-selftest":
+ results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (" \
+ r"?P<description>selftests): (?P<id>.+: .+)"
+ else:
+ logging.error(f"Suite type uknown or not defined:'{suite}'")
+ sys.exit(-1)
+
results = TCReport.process_ptest_results(lava_log,
- results_pattern=_args.results_pattern)
+ results_pattern=results_pattern)
if _args.report_name:
_report.report_name = _args.report_name
_report.parse_fvp_model_version(lava_log)
@@ -321,13 +375,53 @@
metadata=metadata)
+def merge_reports(reportObj, list_reports):
+ """
+ Function to merge a list of yaml report files into a report object
+
+ :param reportObj: Instance of an initial report object to merge the reports
+ :param list_reports: List of yaml report files or file patterns
+ :return: Updated report object
+ """
+ for report_pattern in list_reports:
+ for report_file in glob.glob(report_pattern):
+ to_merge = TCReport(report_file=report_file)
+ reportObj.merge_into(to_merge)
+ return reportObj
+
+
+def generate_html(report_obj, user_args):
+ """
+ Generate html output for the given report_file
+
+ :param report_obj: report object
+ :param user_args: Arguments from user
+ :return: Nothing
+ """
+ script_path = os.path.dirname(sys.argv[0])
+ report_file = user_args.report
+ try:
+ with open(script_path + "/html/js/reporter.js", "a") as write_file:
+ for key in args.html_output:
+ print(f'\nSetting html var "{key}"...')
+ write_file.write(f"\nlet {key}='{args.html_output[key]}'")
+ j = json.dumps({report_obj.report_name: report_obj.report},
+ indent=4)
+ write_file.write(f"\nlet textReport=`\n{j}\n`")
+ subprocess.run(f'cp -f {report_file} {script_path}/html/report.yaml',
+ shell=True)
+ except subprocess.CalledProcessError as ex:
+ logging.exception("Error at generating html")
+ raise ex
+
+
if __name__ == '__main__':
# Defining logger
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
- logging.FileHandler("log_parser_{}.log".format(time.time())),
+ logging.FileHandler("debug.log"),
logging.StreamHandler()
])
"""
@@ -347,11 +441,10 @@
default='ptest-report')
group_results.add_argument('--report-name', type=str, help='Report name',
default="")
- group_results.add_argument('--results-pattern', type=str,
- help='Regex pattern to extract test results',
- default=r"(?P<status>(PASS|FAIL|SKIP)): ("
- r"?P<id>.+ .+) - ( "
- r"?P<description>.+)")
+ group_results.add_argument("--suite", required=False,
+ default=None,
+ help="Suite type. If not defined takes the "
+ "suite name value")
test_env = parser.add_argument_group("Test environments")
test_env.add_argument('--test-env-name', type=str,
help='Test environment type')
@@ -416,9 +509,31 @@
default=None,
help="File with key-value pairs lines i.e"
"key1=value1\nkey2=value2")
+
+ parser.add_argument("--list",
+ nargs="+",
+ default={},
+ help="List of report files.")
+ parser.add_argument("--html-output",
+ required=False,
+ nargs="*",
+ action=KvDictAppendAction,
+ default={},
+ metavar="KEY=VALUE",
+ help="Set a number of key-value pairs i.e. key=value"
+ "(do not put spaces before or after the = "
+ "sign). "
+ "If a value contains spaces, you should define "
+ "it with double quotes: "
+ "Valid keys: title, logo_img, logo_href.")
+ parser.add_argument("--sql-output",
+ required=False,
+ action="store_true",
+ help='Sql output produced from the report file')
args = parser.parse_args()
report = None
+
# Check if report exists (that can be overwritten) or is a new report
if os.path.exists(args.report) and not args.new_report:
report = TCReport(report_file=args.report) # load existing report
@@ -451,6 +566,14 @@
report.add_test_asset(args.test_asset_name,
merge_dicts(args.test_asset_values,
import_env(args.test_asset_env)))
-
- # Dump the report object as a yaml report
+ elif args.command == "merge-reports":
+ report = merge_reports(report, args.list)
report.dump(args.report)
+ if args.html_output:
+ generate_html(report, args)
+
+ if args.sql_output:
+ yaml_obj = YAMLParser(args.report)
+ yaml_obj.create_table()
+ yaml_obj.parse_file()
+ yaml_obj.update_test_config_table()