saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 1 | ############################################################################## |
| 2 | |
| 3 | # Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. |
| 4 | |
| 5 | # |
| 6 | |
| 7 | # SPDX-License-Identifier: BSD-3-Clause |
| 8 | |
| 9 | ############################################################################## |
| 10 | import re |
| 11 | import yaml |
| 12 | import argparse |
| 13 | import os |
| 14 | import logging |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 15 | import subprocess |
| 16 | import sys |
| 17 | import json |
| 18 | from adaptors.sql.yaml_parser import YAMLParser |
| 19 | import glob |
| 20 | |
| 21 | HTML_TEMPLATE = "html.tar.gz" |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 22 | |
| 23 | |
| 24 | class TCReport(object): |
| 25 | """ |
| 26 | Class definition for objects to build report files in a |
| 27 | pipeline stage |
| 28 | """ |
| 29 | STATUS_VALUES = ["PASS", "FAIL", "SKIP"] |
| 30 | |
| 31 | def __init__(self, metadata=None, test_environments=None, |
| 32 | test_configuration=None, target=None, |
| 33 | test_suites=None, report_file=None): |
| 34 | """ |
| 35 | Constructor for the class. Initialise the report object and loads |
| 36 | an existing report(yaml) if defined. |
| 37 | |
| 38 | :param metadata: Initial metadata report object |
| 39 | :param test_environments: Initial test environment object |
| 40 | :param test_configuration: Initial test configuration object |
| 41 | :param target: Initial target object |
| 42 | :param test_suites: Initial test suites object |
| 43 | :param report_file: If defined then an existing yaml report is loaded |
| 44 | as the initial report object |
| 45 | """ |
| 46 | if test_suites is None: |
| 47 | test_suites = {} |
| 48 | if target is None: |
| 49 | target = {} |
| 50 | if test_configuration is None: |
| 51 | test_configuration = {'test-assets': {}} |
| 52 | if test_environments is None: |
| 53 | test_environments = {} |
| 54 | if metadata is None: |
| 55 | metadata = {} |
| 56 | self._report_name = "Not-defined" |
| 57 | # Define if is a new report or an existing report |
| 58 | if report_file: |
| 59 | # The structure of the report must follow: |
| 60 | # - report name: |
| 61 | # {report properties} |
| 62 | try: |
| 63 | with open(report_file) as f: |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 64 | full_report = yaml.load(f) |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 65 | self._report_name, \ |
| 66 | self.report = list(full_report.items())[0] |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 67 | except Exception as ex: |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 68 | logging.exception( |
| 69 | f"Exception loading existing report '{report_file}'") |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 70 | raise ex |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 71 | else: |
| 72 | self.report = {'metadata': metadata, |
| 73 | 'test-environments': test_environments, |
| 74 | 'test-config': test_configuration, |
| 75 | 'target': target, |
| 76 | 'test-suites': test_suites |
| 77 | } |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 78 | self.report_file = report_file |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 79 | |
| 80 | def dump(self, file_name): |
| 81 | """ |
| 82 | Method that dumps the report object with the report name as key in |
| 83 | a yaml format in a given file. |
| 84 | |
| 85 | :param file_name: File name to dump the yaml report |
| 86 | :return: Nothing |
| 87 | """ |
| 88 | with open(file_name, 'w') as f: |
| 89 | yaml.dump({self._report_name: self.report}, f) |
| 90 | |
| 91 | @property |
| 92 | def test_suites(self): |
| 93 | return self.report['test-suites'] |
| 94 | |
| 95 | @test_suites.setter |
| 96 | def test_suites(self, value): |
| 97 | self.test_suites = value |
| 98 | |
| 99 | @property |
| 100 | def test_environments(self): |
| 101 | return self.report['test-environments'] |
| 102 | |
| 103 | @test_environments.setter |
| 104 | def test_environments(self, value): |
| 105 | self.test_environments = value |
| 106 | |
| 107 | @property |
| 108 | def test_config(self): |
| 109 | return self.report['test-config'] |
| 110 | |
| 111 | @test_config.setter |
| 112 | def test_config(self, value): |
| 113 | self.test_config = value |
| 114 | |
| 115 | def add_test_suite(self, name: str, test_results, metadata=None): |
| 116 | """ |
| 117 | Public method to add a test suite object to a report object. |
| 118 | |
| 119 | :param name: Unique test suite name |
| 120 | :param test_results: Object with the tests results |
| 121 | :param metadata: Metadata object for the test suite |
| 122 | """ |
| 123 | if metadata is None: |
| 124 | metadata = {} |
| 125 | if name in self.test_suites: |
| 126 | logging.error("Duplicated test suite:{}".format(name)) |
| 127 | else: |
| 128 | self.test_suites[name] = {'test-results': test_results, |
| 129 | 'metadata': metadata} |
| 130 | |
| 131 | def add_test_environment(self, name: str, values=None): |
| 132 | """ |
| 133 | Public method to add a test environment object to a report object. |
| 134 | |
| 135 | :param name: Name (key) of the test environment object |
| 136 | :param values: Object assigned to the test environment object |
| 137 | :return: Nothing |
| 138 | """ |
| 139 | if values is None: |
| 140 | values = {} |
| 141 | self.test_environments[name] = values |
| 142 | |
| 143 | def add_test_asset(self, name: str, values=None): |
| 144 | """ |
| 145 | Public method to add a test asset object to a report object. |
| 146 | |
| 147 | :param name: Name (key) of the test asset object |
| 148 | :param values: Object assigned to the test asset object |
| 149 | :return: Nothing |
| 150 | """ |
| 151 | if values is None: |
| 152 | values = {} |
| 153 | if 'test-assets' not in self.test_config: |
| 154 | self.test_config['test-assets'] = {} |
| 155 | self.test_config['test-assets'][name] = values |
| 156 | |
| 157 | @staticmethod |
| 158 | def process_ptest_results(lava_log_string="", |
| 159 | results_pattern=r"(?P<status>(" |
| 160 | r"PASS|FAIL|SKIP)): (" |
| 161 | r"?P<id>.+)"): |
| 162 | """ |
| 163 | Method that process ptest-runner results from a lava log string and |
| 164 | converts them to a test results object. |
| 165 | |
| 166 | :param lava_log_string: Lava log string |
| 167 | :param results_pattern: Regex used to capture the test results |
| 168 | :return: Test results object |
| 169 | """ |
| 170 | pattern = re.compile(results_pattern) |
| 171 | if 'status' not in pattern.groupindex or \ |
| 172 | 'id' not in pattern.groupindex: |
| 173 | raise Exception( |
| 174 | "Status and/or id must be defined in the results pattern") |
| 175 | results = {} |
| 176 | lines = lava_log_string.split("\n") |
| 177 | it = iter(lines) |
| 178 | stop_found = False |
| 179 | for line in it: |
| 180 | fields = line.split(" ", 1) |
| 181 | if len(fields) > 1 and fields[1] == "START: ptest-runner": |
| 182 | for report_line in it: |
| 183 | timestamp, *rest = report_line.split(" ", 1) |
| 184 | if not rest: |
| 185 | continue |
| 186 | if rest[0] == "STOP: ptest-runner": |
| 187 | stop_found = True |
| 188 | break |
| 189 | p = pattern.match(rest[0]) |
| 190 | if p: |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 191 | id = re.sub("[ :]+", "_", p.groupdict()['id']) |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 192 | status = p.groupdict()['status'] |
| 193 | if not id: |
| 194 | print("Warning: missing 'id'") |
| 195 | elif status not in TCReport.STATUS_VALUES: |
| 196 | print("Warning: Status unknown") |
| 197 | elif id in results: |
| 198 | print("Warning: duplicated id") |
| 199 | else: |
| 200 | metadata = {k: p.groupdict()[k] |
| 201 | for k in p.groupdict().keys() |
| 202 | if k not in ('id', 'status')} |
| 203 | results[id] = {'status': status, |
| 204 | 'metadata': metadata} |
| 205 | break |
| 206 | if not stop_found: |
Monalisa Jena | 1542682 | 2021-12-02 16:40:55 +0530 | [diff] [blame] | 207 | logging.warning("End of ptest-runner not found") |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 208 | return results |
| 209 | |
| 210 | def parse_fvp_model_version(self, lava_log_string): |
| 211 | """ |
| 212 | Obtains the FVP model and version from a lava log string. |
| 213 | |
| 214 | :param lava_log_string: Lava log string |
| 215 | :return: Tuple with FVP model and version |
| 216 | """ |
| 217 | result = re.findall(r"opt/model/(.+) --version", lava_log_string) |
| 218 | model = "" if not result else result[0] |
| 219 | result = re.findall(r"Fast Models \[(.+?)\]\n", lava_log_string) |
| 220 | version = "" if not result else result[0] |
| 221 | self.report['target'] = {'platform': model, 'version': version} |
| 222 | return model, version |
| 223 | |
| 224 | @property |
| 225 | def report_name(self): |
| 226 | return self._report_name |
| 227 | |
| 228 | @report_name.setter |
| 229 | def report_name(self, value): |
| 230 | self._report_name = value |
| 231 | |
| 232 | @property |
| 233 | def metadata(self): |
| 234 | return self.report['metadata'] |
| 235 | |
| 236 | @metadata.setter |
| 237 | def metadata(self, metadata): |
| 238 | self.report['metadata'] = metadata |
| 239 | |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 240 | @property |
| 241 | def target(self): |
| 242 | return self.report['target'] |
| 243 | |
| 244 | @target.setter |
| 245 | def target(self, target): |
| 246 | self.report['target'] = target |
| 247 | |
| 248 | def merge_into(self, other): |
| 249 | """ |
| 250 | Merge one report object with this. |
| 251 | |
| 252 | :param other: Report object to be merged to this |
| 253 | :return: |
| 254 | """ |
| 255 | try: |
| 256 | if not self.report_name or self.report_name == "Not-defined": |
| 257 | self.report_name = other.report_name |
| 258 | if self.report_name != other.report_name: |
| 259 | logging.warning( |
| 260 | f'Report name \'{other.report_name}\' does not match ' |
| 261 | f'original report name') |
| 262 | # Merge metadata where 'other' report will overwrite common key |
| 263 | # values |
| 264 | self.metadata.update(other.metadata) |
| 265 | self.target.update(other.target) |
| 266 | self.test_config['test-assets'].update(other.test_config['test' |
| 267 | '-assets']) |
| 268 | self.test_environments.update(other.test_environments) |
| 269 | self.test_suites.update(other.test_suites) |
| 270 | except Exception as ex: |
| 271 | logging.exception("Failed to merge reports") |
| 272 | raise ex |
saurom01 | 8e7c54d | 2021-12-06 14:44:52 +0000 | [diff] [blame] | 273 | |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 274 | |
| 275 | class KvDictAppendAction(argparse.Action): |
| 276 | """ |
| 277 | argparse action to split an argument into KEY=VALUE form |
| 278 | on the first = and append to a dictionary. |
| 279 | """ |
| 280 | |
| 281 | def __call__(self, parser, args, values, option_string=None): |
| 282 | d = getattr(args, self.dest) or {} |
| 283 | for value in values: |
| 284 | try: |
| 285 | (k, v) = value.split("=", 2) |
| 286 | except ValueError as ex: |
| 287 | raise \ |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 288 | argparse.ArgumentError(self, |
| 289 | f"Could not parse argument '{values[0]}' as k=v format") |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 290 | d[k] = v |
| 291 | setattr(args, self.dest, d) |
| 292 | |
| 293 | |
| 294 | def read_metadata(metadata_file): |
| 295 | """ |
| 296 | Function that returns a dictionary object from a KEY=VALUE lines file. |
| 297 | |
| 298 | :param metadata_file: Filename with the KEY=VALUE pairs |
| 299 | :return: Dictionary object with key and value pairs |
| 300 | """ |
| 301 | if not metadata_file: |
| 302 | return {} |
| 303 | with open(metadata_file) as f: |
| 304 | d = dict([line.strip().split("=", 1) for line in f]) |
| 305 | return d |
| 306 | |
| 307 | |
| 308 | def import_env(env_names): |
| 309 | """ |
| 310 | Function that matches a list of regex expressions against all the |
| 311 | environment variables keys and returns an object with the matched key |
| 312 | and the value of the environment variable. |
| 313 | |
| 314 | :param env_names: List of regex expressions to match env keys |
| 315 | :return: Object with the matched env variables |
| 316 | """ |
| 317 | env_list = list(os.environ.keys()) |
| 318 | keys = [] |
| 319 | for expression in env_names: |
| 320 | r = re.compile(expression) |
| 321 | keys = keys + list(filter(r.match, env_list)) |
| 322 | d = {key: os.environ[key] for key in keys} |
| 323 | return d |
| 324 | |
| 325 | |
| 326 | def merge_dicts(*dicts): |
| 327 | """ |
| 328 | Function to merge a list of dictionaries. |
| 329 | |
| 330 | :param dicts: List of dictionaries |
| 331 | :return: A merged dictionary |
| 332 | """ |
| 333 | merged = {} |
| 334 | for d in dicts: |
| 335 | merged.update(d) |
| 336 | return merged |
| 337 | |
| 338 | |
| 339 | def process_lava_log(_report, _args): |
| 340 | """ |
| 341 | Function to adapt user arguments to process test results and add properties |
| 342 | to the report object. |
| 343 | |
| 344 | :param _report: Report object |
| 345 | :param _args: User arguments |
| 346 | :return: Nothing |
| 347 | """ |
| 348 | with open(_args.lava_log, "r") as f: |
| 349 | lava_log = f.read() |
| 350 | # Get the test results |
| 351 | results = {} |
| 352 | if _args.type == 'ptest-report': |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 353 | results_pattern = None |
| 354 | suite = _args.suite or _args.test_suite_name |
| 355 | if suite == "optee-test": |
| 356 | results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (?P<id>.+ .+) " \ |
| 357 | r"- (?P<description>.+)" |
| 358 | elif suite == "kernel-selftest": |
| 359 | results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (" \ |
| 360 | r"?P<description>selftests): (?P<id>.+: .+)" |
Mohan Kumari Munivenkatappa | c6928c7 | 2021-06-10 08:34:32 +0000 | [diff] [blame] | 361 | elif suite == "ltp": |
Mohan Kumari Munivenkatappa | d86f662 | 2021-08-05 09:18:48 +0000 | [diff] [blame] | 362 | results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (?P<id>.+)" |
Riju Arya | d183f7f | 2021-09-03 08:40:24 +0000 | [diff] [blame] | 363 | elif suite == "pm-qa": |
Riju Arya | ef59191 | 2021-09-09 12:51:53 +0000 | [diff] [blame] | 364 | results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (?P<id>.+)" \ |
Riju Arya | d183f7f | 2021-09-03 08:40:24 +0000 | [diff] [blame] | 365 | r"- (?P<description>.+)" |
Monalisa Jena | 1542682 | 2021-12-02 16:40:55 +0530 | [diff] [blame] | 366 | elif suite == "scmi": |
| 367 | results_pattern = r"(?P<status>(PASS|FAIL|SKIP)): (?P<id>.+)" |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 368 | else: |
| 369 | logging.error(f"Suite type uknown or not defined:'{suite}'") |
| 370 | sys.exit(-1) |
| 371 | |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 372 | results = TCReport.process_ptest_results(lava_log, |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 373 | results_pattern=results_pattern) |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 374 | if _args.report_name: |
| 375 | _report.report_name = _args.report_name |
| 376 | _report.parse_fvp_model_version(lava_log) |
| 377 | metadata = {} |
| 378 | if _args.metadata_pairs or _args.metadata_env or _args.metadata_file: |
| 379 | metadata = _args.metadata_pairs or import_env( |
| 380 | _args.metadata_env) or read_metadata(_args.metadata_file) |
| 381 | _report.add_test_suite(_args.test_suite_name, test_results=results, |
| 382 | metadata=metadata) |
| 383 | |
| 384 | |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 385 | def merge_reports(reportObj, list_reports): |
| 386 | """ |
| 387 | Function to merge a list of yaml report files into a report object |
| 388 | |
| 389 | :param reportObj: Instance of an initial report object to merge the reports |
| 390 | :param list_reports: List of yaml report files or file patterns |
| 391 | :return: Updated report object |
| 392 | """ |
| 393 | for report_pattern in list_reports: |
| 394 | for report_file in glob.glob(report_pattern): |
| 395 | to_merge = TCReport(report_file=report_file) |
| 396 | reportObj.merge_into(to_merge) |
| 397 | return reportObj |
| 398 | |
| 399 | |
| 400 | def generate_html(report_obj, user_args): |
| 401 | """ |
| 402 | Generate html output for the given report_file |
| 403 | |
| 404 | :param report_obj: report object |
| 405 | :param user_args: Arguments from user |
| 406 | :return: Nothing |
| 407 | """ |
| 408 | script_path = os.path.dirname(sys.argv[0]) |
| 409 | report_file = user_args.report |
| 410 | try: |
| 411 | with open(script_path + "/html/js/reporter.js", "a") as write_file: |
| 412 | for key in args.html_output: |
| 413 | print(f'\nSetting html var "{key}"...') |
| 414 | write_file.write(f"\nlet {key}='{args.html_output[key]}'") |
| 415 | j = json.dumps({report_obj.report_name: report_obj.report}, |
| 416 | indent=4) |
| 417 | write_file.write(f"\nlet textReport=`\n{j}\n`") |
| 418 | subprocess.run(f'cp -f {report_file} {script_path}/html/report.yaml', |
| 419 | shell=True) |
| 420 | except subprocess.CalledProcessError as ex: |
| 421 | logging.exception("Error at generating html") |
| 422 | raise ex |
| 423 | |
| 424 | |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 425 | if __name__ == '__main__': |
| 426 | # Defining logger |
| 427 | logging.basicConfig( |
| 428 | level=logging.INFO, |
| 429 | format="%(asctime)s [%(levelname)s] %(message)s", |
| 430 | handlers=[ |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 431 | logging.FileHandler("debug.log"), |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 432 | logging.StreamHandler() |
| 433 | ]) |
| 434 | """ |
| 435 | The main aim of this script is to be called with different options to build |
| 436 | a report object that can be dumped into a yaml format |
| 437 | """ |
| 438 | parser = argparse.ArgumentParser(description='Generic yaml report for TC') |
| 439 | parser.add_argument("--report", "-r", help="Report filename") |
| 440 | parser.add_argument("-f", help="Force new report", action='store_true', |
| 441 | dest='new_report') |
| 442 | parser.add_argument("command", help="Command: process-results") |
| 443 | group_results = parser.add_argument_group("Process results") |
| 444 | group_results.add_argument('--test-suite-name', type=str, |
| 445 | help='Test suite name') |
| 446 | group_results.add_argument('--lava-log', type=str, help='Lava log file') |
| 447 | group_results.add_argument('--type', type=str, help='Type of report log', |
| 448 | default='ptest-report') |
| 449 | group_results.add_argument('--report-name', type=str, help='Report name', |
| 450 | default="") |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 451 | group_results.add_argument("--suite", required=False, |
| 452 | default=None, |
| 453 | help="Suite type. If not defined takes the " |
| 454 | "suite name value") |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 455 | test_env = parser.add_argument_group("Test environments") |
| 456 | test_env.add_argument('--test-env-name', type=str, |
| 457 | help='Test environment type') |
| 458 | test_env.add_argument("--test-env-values", |
| 459 | nargs="+", |
| 460 | action=KvDictAppendAction, |
| 461 | default={}, |
| 462 | metavar="KEY=VALUE", |
| 463 | help="Set a number of key-value pairs " |
| 464 | "(do not put spaces before or after the = " |
| 465 | "sign). " |
| 466 | "If a value contains spaces, you should define " |
| 467 | "it with double quotes: " |
| 468 | 'key="Value with spaces". Note that ' |
| 469 | "values are always treated as strings.") |
| 470 | test_env.add_argument("--test-env-env", |
| 471 | nargs="+", |
| 472 | default={}, |
| 473 | help="Import environment variables values with the " |
| 474 | "given name.") |
| 475 | parser.add_argument("--metadata-pairs", |
| 476 | nargs="+", |
| 477 | action=KvDictAppendAction, |
| 478 | default={}, |
| 479 | metavar="KEY=VALUE", |
| 480 | help="Set a number of key-value pairs " |
| 481 | "(do not put spaces before or after the = sign). " |
| 482 | "If a value contains spaces, you should define " |
| 483 | "it with double quotes: " |
| 484 | 'key="Value with spaces". Note that ' |
| 485 | "values are always treated as strings.") |
| 486 | |
| 487 | test_config = parser.add_argument_group("Test config") |
| 488 | test_config.add_argument('--test-asset-name', type=str, |
| 489 | help='Test asset type') |
| 490 | test_config.add_argument("--test-asset-values", |
| 491 | nargs="+", |
| 492 | action=KvDictAppendAction, |
| 493 | default={}, |
| 494 | metavar="KEY=VALUE", |
| 495 | help="Set a number of key-value pairs " |
| 496 | "(do not put spaces before or after the = " |
| 497 | "sign). " |
| 498 | "If a value contains spaces, you should " |
| 499 | "define " |
| 500 | "it with double quotes: " |
| 501 | 'key="Value with spaces". Note that ' |
| 502 | "values are always treated as strings.") |
| 503 | test_config.add_argument("--test-asset-env", |
| 504 | nargs="+", |
| 505 | default=None, |
| 506 | help="Import environment variables values with " |
| 507 | "the given name.") |
| 508 | |
| 509 | parser.add_argument("--metadata-env", |
| 510 | nargs="+", |
| 511 | default=None, |
| 512 | help="Import environment variables values with the " |
| 513 | "given name.") |
| 514 | parser.add_argument("--metadata-file", |
| 515 | type=str, |
| 516 | default=None, |
| 517 | help="File with key-value pairs lines i.e" |
| 518 | "key1=value1\nkey2=value2") |
saurom01 | 8e7c54d | 2021-12-06 14:44:52 +0000 | [diff] [blame] | 519 | |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 520 | parser.add_argument("--list", |
| 521 | nargs="+", |
| 522 | default={}, |
| 523 | help="List of report files.") |
| 524 | parser.add_argument("--html-output", |
| 525 | required=False, |
| 526 | nargs="*", |
| 527 | action=KvDictAppendAction, |
| 528 | default={}, |
| 529 | metavar="KEY=VALUE", |
| 530 | help="Set a number of key-value pairs i.e. key=value" |
| 531 | "(do not put spaces before or after the = " |
| 532 | "sign). " |
| 533 | "If a value contains spaces, you should define " |
| 534 | "it with double quotes: " |
| 535 | "Valid keys: title, logo_img, logo_href.") |
| 536 | parser.add_argument("--sql-output", |
| 537 | required=False, |
| 538 | action="store_true", |
| 539 | help='Sql output produced from the report file') |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 540 | |
| 541 | args = parser.parse_args() |
| 542 | report = None |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 543 | |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 544 | # Check if report exists (that can be overwritten) or is a new report |
| 545 | if os.path.exists(args.report) and not args.new_report: |
| 546 | report = TCReport(report_file=args.report) # load existing report |
| 547 | else: |
| 548 | report = TCReport() |
| 549 | |
| 550 | # Possible list of commands: |
| 551 | # process-results: To parse test results from stream into a test suite obj |
| 552 | if args.command == "process-results": |
| 553 | # Requires the test suite name and the log file, lava by the time being |
| 554 | if not args.test_suite_name: |
| 555 | parser.error("Test suite name required") |
| 556 | elif not args.lava_log: |
| 557 | parser.error("Lava log file required") |
| 558 | process_lava_log(report, args) |
| 559 | # set-report-metadata: Set the report's metadata |
| 560 | elif args.command == "set-report-metadata": |
| 561 | # Various options to load metadata into the report object |
| 562 | report.metadata = merge_dicts(args.metadata_pairs, |
| 563 | read_metadata(args.metadata_file), |
| 564 | import_env(args.metadata_env)) |
| 565 | # add-test-environment: Add a test environment to the report's object |
| 566 | elif args.command == "add-test-environment": |
| 567 | # Various options to load environment data into the report object |
| 568 | report.add_test_environment(args.test_env_name, |
| 569 | merge_dicts(args.test_env_values, |
| 570 | import_env(args.test_env_env))) |
| 571 | # add-test-asset: Add a test asset into the report's object (test-config) |
| 572 | elif args.command == "add-test-asset": |
| 573 | report.add_test_asset(args.test_asset_name, |
| 574 | merge_dicts(args.test_asset_values, |
| 575 | import_env(args.test_asset_env))) |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 576 | elif args.command == "merge-reports": |
| 577 | report = merge_reports(report, args.list) |
saul-romero-arm | 1c97ecc | 2021-04-08 12:09:19 +0000 | [diff] [blame] | 578 | report.dump(args.report) |
saul-romero-arm | ce968d6 | 2021-05-18 15:01:12 +0000 | [diff] [blame] | 579 | if args.html_output: |
| 580 | generate_html(report, args) |
| 581 | |
| 582 | if args.sql_output: |
| 583 | yaml_obj = YAMLParser(args.report) |
| 584 | yaml_obj.create_table() |
| 585 | yaml_obj.parse_file() |
| 586 | yaml_obj.update_test_config_table() |