Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
Leandro Belli | 6e0c446 | 2024-12-12 18:46:37 +0000 | [diff] [blame] | 3 | # Copyright (c) 2019-2024 Arm Limited. All rights reserved. |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 4 | # |
| 5 | # SPDX-License-Identifier: BSD-3-Clause |
| 6 | # |
| 7 | |
| 8 | # After lava job is dispatched, its results will be collected in |
| 9 | # $WORKSPACE/job_results.yaml file. Parse that file, and exit from this script |
| 10 | # with the respective exit status |
| 11 | |
| 12 | import argparse |
| 13 | import os |
| 14 | import sys |
| 15 | import yaml |
| 16 | |
| 17 | |
| 18 | def report_job_failure(): |
| 19 | job_url = os.environ["JOB_URL"] |
| 20 | build_number = os.environ["BUILD_NUMBER"] |
| 21 | print() |
| 22 | print("Job failed!") |
| 23 | print("See " + "/".join([job_url.rstrip("/"), build_number, "artifact", |
| 24 | "job_output.log"])) |
| 25 | print() |
| 26 | sys.exit(1) |
| 27 | |
| 28 | |
| 29 | def report_job_success(): |
| 30 | print() |
| 31 | print("Job success.") |
| 32 | print() |
| 33 | sys.exit(0) |
| 34 | |
Joel Goddard | 3e09183 | 2021-03-30 10:29:47 +0100 | [diff] [blame] | 35 | def scmi_parse_phase(results, case, special_case, expected_skip_count): |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 36 | pass_count = 0 |
| 37 | fail_count = 0 |
| 38 | false_fail_count = 0 |
Joel Goddard | 3e09183 | 2021-03-30 10:29:47 +0100 | [diff] [blame] | 39 | skip_count = 0 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 40 | |
| 41 | for phase in results: |
| 42 | if phase["metadata"]["definition"] == case: |
| 43 | if phase["metadata"]["result"] == "pass": |
| 44 | pass_count += 1 |
Joel Goddard | 3e09183 | 2021-03-30 10:29:47 +0100 | [diff] [blame] | 45 | elif phase["metadata"]["result"] == "skip": |
| 46 | skip_count += 1 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 47 | else: |
| 48 | if special_case != "" and phase["metadata"]["case"] == special_case: |
| 49 | false_fail_count += 1 |
| 50 | else: |
| 51 | fail_count += 1 |
| 52 | |
| 53 | print(case) |
| 54 | print("pass_count " + str(pass_count)) |
| 55 | print("fail_count " + str(fail_count)) |
| 56 | if special_case != "": |
| 57 | print("false_fail_count " + str(false_fail_count)) |
Joel Goddard | 3e09183 | 2021-03-30 10:29:47 +0100 | [diff] [blame] | 58 | print("skip_count " + str(skip_count) + " out of expected " + str(expected_skip_count)) |
| 59 | if (fail_count > 0) or (skip_count > expected_skip_count): |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 60 | report_job_failure() |
| 61 | |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 62 | def parse_cmd_line(): |
| 63 | parser = argparse.ArgumentParser(description="Parse results from LAVA. " |
| 64 | "The results must be provided as a YAML file.") |
| 65 | parser.add_argument("--payload-type", default="linux", type=str, |
| 66 | help="Type of payload that was used in the test (default: %(default)s)") |
| 67 | parser.add_argument("--file", |
| 68 | default=os.path.join(os.environ["WORKSPACE"], "job_results.yaml"), |
| 69 | type=str, help="YAML file to parse (default: %(default)s)") |
| 70 | args = parser.parse_args() |
| 71 | return args |
| 72 | |
| 73 | |
| 74 | args = parse_cmd_line() |
| 75 | |
| 76 | with open(args.file) as fd: |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 77 | results = yaml.safe_load(fd) |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 78 | |
| 79 | # Iterate through results. Find the element whose name is "job" in the |
| 80 | # "lava" suite. It contains the result of the overall LAVA run. |
| 81 | for phase in results: |
| 82 | if phase["name"] == "job" and phase["suite"] == "lava": |
| 83 | break |
| 84 | else: |
| 85 | raise Exception("Couldn't find 'job' phase in 'lava' suite in results") |
| 86 | |
| 87 | if phase["result"] != "pass": |
| 88 | report_job_failure() |
| 89 | |
| 90 | # If we've simply booted to the Linux shell prompt then we don't need to |
| 91 | # further analyze the results from LAVA. |
| 92 | if args.payload_type == "linux": |
| 93 | report_job_success() |
| 94 | |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 95 | # If we've run TFTF or SCMI tests instead, then do some further parsing. |
| 96 | elif args.payload_type == "tftf": |
| 97 | session = "TFTF" |
| 98 | suite = "tftf" |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 99 | else: |
| 100 | raise Exception("Payload not defined") |
| 101 | |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 102 | # Then count the number of tests that failed/skipped. |
| 103 | test_failures = 0 |
| 104 | test_skips = 0 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 105 | for phase in filter(lambda p: p["suite"] == suite, results): |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 106 | metadata = phase["metadata"] |
| 107 | testcase_name = metadata["case"] |
| 108 | testcase_result = metadata["result"] |
| 109 | if testcase_result == "fail": |
| 110 | test_failures += 1 |
| 111 | print("=> FAILED: " + testcase_name) |
| 112 | elif testcase_result == "skip": |
| 113 | test_skips += 1 |
| 114 | print(" SKIPPED: " + testcase_name) |
| 115 | |
| 116 | # Print a test summary |
| 117 | print() |
| 118 | if test_failures == 0 and test_skips == 0: |
| 119 | print("All tests passed.") |
| 120 | else: |
| 121 | print("{} tests failed; {} skipped. All other tests passed.".format( |
| 122 | test_failures, test_skips)) |
| 123 | |
| 124 | if test_failures == 0: |
| 125 | report_job_success() |
| 126 | else: |
| 127 | report_job_failure() |