blob: 630bf5f31566bf63bfa7713e2ec09268e15d82e3 [file] [log] [blame]
Leonardo Sandoval9dfdd1b2020-08-06 17:08:11 -05001#!/usr/bin/env bash
Zelalem1af7a7b2020-08-04 17:34:32 -05002#
Saul Romerocacda172023-03-10 14:23:41 +00003# Copyright (c) 2019-2023, Arm Limited. All rights reserved.
Zelalem1af7a7b2020-08-04 17:34:32 -05004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
Saul Romerocacda172023-03-10 14:23:41 +00008set -x
Zelalem1af7a7b2020-08-04 17:34:32 -05009REPORT_JSON=$1
10REPORT_HTML=$2
Paul Sokolovsky301710a2022-02-21 14:56:33 +030011
Gary Morrison999a9d72022-03-14 18:29:06 -050012if echo "$JENKINS_URL" | grep -q "oss.arm.com"; then
Saul Romerocacda172023-03-10 14:23:41 +000013 ARTIFACT_PATH='artifact/html/qa-code-coverage'
14 INFO_PATH='coverage.info'
15 JSON_PATH='intermediate_layer.json'
Paul Sokolovsky301710a2022-02-21 14:56:33 +030016else
Saul Romerocacda172023-03-10 14:23:41 +000017 ARTIFACT_PATH='artifact'
18 INFO_PATH='trace_report/coverage.info'
19 JSON_PATH='config_file.json'
Paul Sokolovsky301710a2022-02-21 14:56:33 +030020fi
21
Zelalem1af7a7b2020-08-04 17:34:32 -050022#################################################################
23# Create json file for input to the merge.sh for Code Coverage
24# Globals:
25# REPORT_JSON: Json file for SCP and TF ci gateway test results
Saul Romerocacda172023-03-10 14:23:41 +000026# MERGE_CONFIGURATION: Json file to be used as input to the merge.sh
Zelalem1af7a7b2020-08-04 17:34:32 -050027# Arguments:
28# None
29# Outputs:
30# Print number of files to be merged
31################################################################
32create_merge_cfg() {
33python3 - << EOF
34import json
35import os
Saul Romero568f5d72023-11-29 11:58:34 +000036import re
Zelalem1af7a7b2020-08-04 17:34:32 -050037
38server = os.getenv("JENKINS_URL", "https://jenkins.oss.arm.com/")
39merge_json = {} # json object
40_files = []
41with open("$REPORT_JSON") as json_file:
42 data = json.load(json_file)
43merge_number = 0
44test_results = data['test_results']
45test_files = data['test_files']
46for index, build_number in enumerate(test_results):
Saul Romerocacda172023-03-10 14:23:41 +000047 if ("bmcov" in test_files[index] or
48 "code-coverage" in test_files[index]) and test_results[build_number] == "SUCCESS":
Zelalem1af7a7b2020-08-04 17:34:32 -050049 merge_number += 1
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030050 base_url = "{}job/{}/{}/{}".format(
51 server, data['job'], build_number, "$ARTIFACT_PATH")
Saul Romero568f5d72023-11-29 11:58:34 +000052 _group_test_config = re.match(f'^[0-9%]*(?:${TEST_GROUPS}%)?(.+?)\.test', test_files[index])
53 tf_configuration = _group_test_config.groups()[0] if _group_test_config else 'N/A'
Zelalem1af7a7b2020-08-04 17:34:32 -050054 _files.append( {'id': build_number,
55 'config': {
56 'type': 'http',
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030057 'origin': "{}/{}".format(
58 base_url, "$JSON_PATH")
Zelalem1af7a7b2020-08-04 17:34:32 -050059 },
60 'info': {
61 'type': 'http',
Paul Sokolovskydd04dea2022-02-21 13:40:43 +030062 'origin': "{}/{}".format(
63 base_url, "$INFO_PATH")
Saul Romero568f5d72023-11-29 11:58:34 +000064 },
65 'tf-configuration': tf_configuration
Zelalem1af7a7b2020-08-04 17:34:32 -050066 })
67merge_json = { 'files' : _files }
Saul Romerocacda172023-03-10 14:23:41 +000068with open("$MERGE_CONFIGURATION", 'w') as outfile:
69 json.dump(merge_json, outfile, indent=4)
Zelalem1af7a7b2020-08-04 17:34:32 -050070print(merge_number)
71EOF
72}
73
Saul Romerocacda172023-03-10 14:23:41 +000074generate_header() {
75 local cov_html=${OUTDIR}/${COVERAGE_FOLDER}/index.html
76 local out_report=$1
Zelalem1af7a7b2020-08-04 17:34:32 -050077python3 - << EOF
78import re
Saul Romerocacda172023-03-10 14:23:41 +000079import json
Zelalem1af7a7b2020-08-04 17:34:32 -050080cov_html="$cov_html"
81out_report = "$out_report"
Saul Romerocacda172023-03-10 14:23:41 +000082confs = ""
83with open("$REPORT_JSON") as json_file:
84 data = json.load(json_file)
Saul Romerocacda172023-03-10 14:23:41 +000085
Zelalem1af7a7b2020-08-04 17:34:32 -050086with open(cov_html, "r") as f:
87 html_content = f.read()
88items = ["Lines", "Functions", "Branches"]
89s = """
Saul Romerocacda172023-03-10 14:23:41 +000090<style>
91.dropbtn {
92 background-color: #04AA6D;
93 color: white;
94 padding: 16px;
95 font-size: 16px;
96 border: none;
97}
98
99/* The container <div> - needed to position the dropdown content */
100.dropdown {
101 position: relative;
102 display: inline-block;
103}
104
105/* Dropdown Content (Hidden by Default) */
106.dropdown-content {
107 display: none;
108 position: absolute;
109 background-color: #f1f1f1;
110 min-width: 160px;
111 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
112 z-index: 1;
113}
114
115/* Links inside the dropdown */
116.dropdown-content a {
117 color: black;
118 padding: 12px 16px;
119 text-decoration: none;
120 display: block;
121}
122
123/* Change color of dropdown links on hover */
124.dropdown-content a:hover {background-color: #ddd;}
125
126/* Show the dropdown menu on hover */
127.dropdown:hover .dropdown-content {display: block;}
128
129/* Change the background color of the dropdown button when the dropdown content is shown */
130.dropdown:hover .dropbtn {background-color: #3e8e41;}
131</style>
Zelalem1af7a7b2020-08-04 17:34:32 -0500132 <div id="div-cov">
133 <hr>
134 <table id="table-cov">
135 <tbody>
136 <tr>
137 <td>Type</td>
138 <td>Hit</td>
139 <td>Total</td>
140 <td>Coverage</td>
141 </tr>
142"""
143for item in items:
144 data = re.findall(r'<td class="headerItem">{}:</td>\n\s+<td class="headerCovTableEntry">(.+?)</td>\n\s+<td class="headerCovTableEntry">(.+?)</td>\n\s+'.format(item),
145 html_content, re.DOTALL)
146 if data is None:
147 continue
148 hit, total = data[0]
149 cov = round(float(hit)/float(total) * 100.0, 2)
150 color = "success"
151 if cov < 90:
152 color = "unstable"
153 if cov < 75:
154 color = "failure"
155 s = s + """
156 <tr>
157 <td>{}</td>
158 <td>{}</td>
159 <td>{}</td>
160 <td class='{}'>{} %</td>
161 </tr>
162""".format(item, hit, total, color, cov)
163s = s + """
164 </tbody>
165 </table>
166 <p>
Saul Romero568f5d72023-11-29 11:58:34 +0000167 <button onclick="window.open('artifact/${jenkins_archive_folder}/${COVERAGE_FOLDER}/index.html','_blank');">Total Coverage Report (${#list_of_merged_builds[@]} out of ${number_of_files_to_merge})</button>
Zelalem1af7a7b2020-08-04 17:34:32 -0500168 </p>
169 </div>
Saul Romerocacda172023-03-10 14:23:41 +0000170
Zelalem1af7a7b2020-08-04 17:34:32 -0500171<script>
172 document.getElementById('tf-report-main').appendChild(document.getElementById("div-cov"));
173</script>
Saul Romerocacda172023-03-10 14:23:41 +0000174
Zelalem1af7a7b2020-08-04 17:34:32 -0500175"""
176with open(out_report, "a") as f:
177 f.write(s)
178EOF
179}
Saul Romero568f5d72023-11-29 11:58:34 +0000180
181generate_cols() {
182 echo "List of merged build ids:${list_of_merged_builds[@]}"
183python3 - << EOF
184merged_ids=[int(i) for i in "${list_of_merged_builds[@]}".split()]
185s = """
186
187 <script>
188 window.onload = function() {
189 """ + f"const mergedIds={merged_ids}" + """
190 document.querySelector('#tf-report-main table').querySelectorAll("tr").forEach((row,i) => {
191 const cell = document.createElement(i ? "td" : "th")
192 const button = document.createElement("button")
193 button.textContent = "Report"
194 if (i) {
195 merged = false
196 if (q = row.querySelector('td.success a.buildlink')) {
197 href = q.href
198 buildId = href.split("/").at(-2)
199 if (mergedIds.include(buildId)) {
200 cell.classList.add("success")
201 const url = href.replace('console', 'artifact/trace_report/index.html')
202 button.addEventListener('click', () => {
203 window.open(url, "_blank")
204 })
205 cell.appendChild(button)
206 merged = true
207 }
208 }
209 if (!merged) {
210 cell.innerText = "N/A"
211 cell.classList.add("failure")
212 }
213 }
214 else {
215 cell.innerText = "Code Coverage"
216 }
217 row.appendChild(cell)
218 })
219 }
220 </script>
221"""
222with open("$1", "a") as f:
223 f.write(s)
224EOF
225}
226
227
Zelalem1af7a7b2020-08-04 17:34:32 -0500228OUTDIR=""
229index=""
230case "$TEST_GROUPS" in
231 scp*)
232 project="scp"
Saul Romerocacda172023-03-10 14:23:41 +0000233 jenkins_archive_folder=reports;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500234 tf*)
235 project="trusted_firmware"
Saul Romerocacda172023-03-10 14:23:41 +0000236 jenkins_archive_folder=merge/outdir;;
Saul Romero82bcfb02023-06-27 16:24:13 +0100237 spm*)
238 project="hafnium"
239 jenkins_archive_folder=merge/outdir;;
Zelalem1af7a7b2020-08-04 17:34:32 -0500240 *)
241 exit 0;;
242esac
Saul Romerocacda172023-03-10 14:23:41 +0000243OUTDIR=${WORKSPACE}/${jenkins_archive_folder}
244source "$CI_ROOT/script/qa-code-coverage.sh"
245export MERGE_CONFIGURATION="$OUTDIR/merge_configuration.json"
246COVERAGE_FOLDER=lcov
247cd $WORKSPACE
248deploy_qa_tools
249cd -
Zelalem1af7a7b2020-08-04 17:34:32 -0500250mkdir -p $OUTDIR
251pushd $OUTDIR
Saul Romerocacda172023-03-10 14:23:41 +0000252 number_of_files_to_merge=$(create_merge_cfg)
Saul Romero568f5d72023-11-29 11:58:34 +0000253 echo "Merging from $number_of_files_to_merge code coverage reports..."
Zelalem1af7a7b2020-08-04 17:34:32 -0500254 # Only merge when more than 1 test result
Saul Romerocacda172023-03-10 14:23:41 +0000255 if [ "$number_of_files_to_merge" -lt 2 ] ; then
256 echo "Only one file to merge."
Zelalem1af7a7b2020-08-04 17:34:32 -0500257 exit 0
258 fi
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300259
Saul Romero568f5d72023-11-29 11:58:34 +0000260 source ${WORKSPACE}/qa-tools/coverage-tool/coverage-reporting/merge.sh \
261 -j $MERGE_CONFIGURATION -l ${OUTDIR}/${COVERAGE_FOLDER} -w $WORKSPACE -c
Paul Sokolovsky227f2cc2021-12-21 10:58:26 +0300262
Saul Romero568f5d72023-11-29 11:58:34 +0000263 merged_status && generate_header ${REPORT_HTML}
264 generate_cols ${REPORT_HTML}
Zelalem1af7a7b2020-08-04 17:34:32 -0500265 cp ${REPORT_HTML} $OUTDIR
Saul Romero568f5d72023-11-29 11:58:34 +0000266
Zelalem1af7a7b2020-08-04 17:34:32 -0500267popd