Move internal code-coverage tool to use qa-tools public repo
- CI scripts to use qa-tools repository rather
than test-definitions.
- Consolidate functions to access qa-tools in a
file (qa-code-coverage.sh).
- Refactoring in merge reports script.
Signed-off-by: Saul Romero <saul.romero@arm.com>
Change-Id: I1b447273b216d739bcfcfeddf469a8f4f1c2b16b
diff --git a/script/qa-code-coverage.sh b/script/qa-code-coverage.sh
new file mode 100644
index 0000000..4fc0d9a
--- /dev/null
+++ b/script/qa-code-coverage.sh
@@ -0,0 +1,264 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Include variables and functions to be used by these scripts
+source "$CI_ROOT/utils.sh"
+################################################################################
+# CI VARIABLES:
+# workspace, warehouse, artefacts
+# GLOBAL VARIABLES:
+# OUTDIR, PROJECT, FALLBACK_PLUGIN_URL, FALLBACK_FILES, PLUGIN_BINARY
+################################################################################
+# Defining constants
+GERRIT_URL=${GERRIT_URL:-https://gerrit.oss.arm.com}
+QA_REPO_USER=jenkins_auto
+QA_REPO_INTERNAL=${QA_REPO_INTERNAL:-https://${QA_REPO_USER}:${QA_REPO_TOKEN}@git.gitlab.arm.com/tooling/qa-tools-internal.git}
+QA_REPO_PUBLIC=${QA_REPO_PUBLIC:-https://git.gitlab.arm.com/tooling/qa-tools.git}
+QA_REPO_NAME=qa-tools
+# Internal globals
+CODE_COVERAGE_FOLDER="${OUTDIR:-$workspace}/qa-code-coverage"
+DEBUG_FOLDER=${artefacts}/debug
+RELEASE_FOLDER=${artefacts}/release
+TRACE_FILE_PREFIX=covtrace
+CONFIG_JSON=${CODE_COVERAGE_FOLDER}/configuration_file.json
+INTERMEDIATE_LAYER_FILE=${CODE_COVERAGE_FOLDER}/intermediate_layer.json
+INFO_FILE=${CODE_COVERAGE_FOLDER}/coverage.info
+REPORT_FOLDER=${CODE_COVERAGE_FOLDER}/lcov
+
+if echo "$JENKINS_URL" | grep -q "oss.arm.com"; then
+ QA_REPO=${QA_REPO_PUBLIC}
+ QA_REFSPEC=${QA_REFSPEC:-master}
+else
+ QA_REPO="https://review.trustedfirmware.org/ci/qa-tools"
+ QA_REFSPEC="openci"
+fi
+
+
+################################################################################
+# Deploy qa-tools into the current directory
+# GLOBALS:
+# QA_REPO, QA_REPO_NAME, QA_REFSPEC
+# ARGUMENTS:
+# None
+# OUTPUTS:
+# Clones the qa-tools repo from the global variables with the given
+# commit hash.
+# RETURN:
+# 0 if succeeds, non-zero on error.
+################################################################################
+deploy_qa_tools() {
+ git clone "${QA_REPO}" ${QA_REPO_NAME}
+ cd ${QA_REPO_NAME} && git checkout "${QA_REFSPEC}" && cd ..
+}
+
+
+################################################################################
+# Builds or downloads the QA Code Coverage Tool
+# GLOBALS:
+# CODE_COVERAGE_FOLDER, QA_REPO, QA_REPO_NAME, QA_REFSPEC, FALLBACK_PLUGIN_URL
+# ARGUMENTS:
+# None
+# OUTPUTS:
+# Creates coverage folder and builds/downloads there the plugin binaries.
+# It exports the binary plugin location to coverage_trace_plugin.
+# RETURN:
+# 0 if succeeds, non-zero on error.
+################################################################################
+build_tool() {
+ echo "Building QA Code coverage tool..."
+ PLUGIN_BINARY="${FALLBACK_FILES%%,*}" # The first in the list of the binary files
+ local PVLIB_HOME="warehouse/SysGen/PVModelLib/$model_version/$model_build/external"
+ local LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CODE_COVERAGE_FOLDER
+ mkdir -p ${CODE_COVERAGE_FOLDER}
+ pushd "${CODE_COVERAGE_FOLDER}"
+ deploy_qa_tools
+ local cc_source=$(find . -type f -name 'coverage_trace.cc')
+ local fallback="wget -q ${FALLBACK_PLUGIN_URL}/{$FALLBACK_FILES}"
+ echo "Warehouse=${warehouse}"
+ eval "$fallback"
+ ls -al
+ export coverage_trace_plugin="${CODE_COVERAGE_FOLDER}/${PLUGIN_BINARY}"
+ popd
+}
+
+ ################################################################################
+ # Creates configuration file for intermediate layer generation
+ # GLOBALS:
+ # PROJECT, CONFIG_JSON, INTERMEDIATE_LAYER_FILE, CODE_COVERAGE_FOLDER
+ # ARGUMENTS:
+ # $1 Folder where are the elf/axf files.
+ # $2 List of elf/axf file names.
+ # $3 Path for trace files.
+ # $4 Root folder name where all the repos are cloned.
+ # OUTPUTS:
+ # Creates coverage folder and builds/downloads there the plugin binaries.
+ # RETURN:
+ # 0 if succeeds, non-zero on error.
+ ################################################################################
+create_config_json() {
+ set +e
+ if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
+ then
+ cat << END
+Missing argument at '${FUNCNAME[0]}'.
+USAGE:
+ create_config_json ' Glob binaries' 'Glob trace files' 'Repos root folder name'
+ Example:
+ create_config_json 'bl1.elf bl2.elf' 'tf'
+END
+ exit 1
+ fi
+ local ELF_FOLDER=$1
+ local dwarf_array=($2)
+ local TRACE_FOLDER=$3
+ local root_repos_foolder="${4:-$workspace}"
+ local scm_sources=""
+
+ # Obtaining binaries from array
+ bin_section=""
+ for index in "${!dwarf_array[@]}"
+ do
+ local elf_file="${ELF_FOLDER}/${dwarf_array[$index]}"
+ cp "$elf_file" ${CODE_COVERAGE_FOLDER}/.
+ read -r -d '' bin_section << EOM
+${bin_section}
+ {
+ "name": "$elf_file",
+ "traces": [
+ "${TRACE_FOLDER}/${TRACE_FILE_PREFIX:-covtrace}-*.log"
+ ]
+ }
+EOM
+ if [ $index -lt $((${#dwarf_array[@]} - 1)) ];then
+ bin_section="${bin_section},"
+ fi
+ done
+
+ if [ "$PROJECT" = "SCP" ]; then
+ read -r -d '' scm_sources << EOM
+ [
+ {
+ "type": "git",
+ "URL": "$CC_SCP_URL",
+ "COMMIT": "$CC_SCP_COMMIT",
+ "REFSPEC": "$CC_SCP_REFSPEC",
+ "LOCATION": "scp"
+ },
+ {
+ "type": "git",
+ "URL": "$CC_CMSIS_URL",
+ "COMMIT": "$CC_CMSIS_COMMIT",
+ "REFSPEC": "$CC_CMSIS_REFSPEC",
+ "LOCATION": "scp/contrib/cmsis/git"
+ }
+ ]
+EOM
+elif [ "$PROJECT" = "TF-A" ]; then
+ read -r -d '' scm_sources << EOM
+ [
+ {
+ "type": "git",
+ "URL": "$CC_TRUSTED_FIRMWARE_URL",
+ "COMMIT": "$CC_TRUSTED_FIRMWARE_COMMIT",
+ "REFSPEC": "$CC_TRUSTED_FIRMWARE_REFSPEC",
+ "LOCATION": "trusted_firmware"
+ },
+ {
+ "type": "http",
+ "URL": "$mbedtls_archive",
+ "COMPRESSION": "xz",
+ "EXTRA_PARAMS": "--strip-components=1",
+ "LOCATION": "mbedtls"
+ }
+ ]
+EOM
+ else
+ echo "SCM sources not provided for project '${PROJECT}'"
+ exit 1
+ fi
+local metadata="\"BUILD_CONFIG\": \"${BUILD_CONFIG}\", \"RUN_CONFIG\": \"${RUN_CONFIG}\""
+cat <<EOF > "${CONFIG_JSON}"
+{
+ "configuration":
+ {
+ "remove_workspace": true,
+ "include_assembly": true
+ },
+ "parameters":
+ {
+ "objdump": "${OBJDUMP}",
+ "readelf": "${READELF}",
+ "sources": $scm_sources,
+ "workspace": "${root_repos_foolder}",
+ "output_file": "${INTERMEDIATE_LAYER_FILE}",
+ "metadata": {$metadata}
+ },
+ "elfs": [
+ ${bin_section}
+ ]
+}
+EOF
+
+}
+
+################################################################################
+# Creates intermediate layer json file with trace coverage data.
+#
+# Creates a configuration JSON file to be the input for the intermediate
+# layer file creation.
+# GLOBALS:
+# TRACE_FILE_PREFIX, CODE_COVERAGE_FOLDER
+# ARGUMENTS:
+# $1 Location of trace files.
+# $2 Location of elf/axf files.
+# $3 List of binaries to be checked the traces.
+# $4 Root folder name where all the repos are cloned.
+# OUTPUTS:
+# A configuration JSON file.
+# An intermediate layer JSON file.
+# RETURN:
+# 0 if succeeds, non-zero on error.
+################################################################################
+create_intermediate_layer() {
+ local TRACE_FOLDER="$1"
+ local ELF_FOLDER="$2"
+ local LIST_OF_BINARIES="$3"
+ local root_repos_foolder="$4"
+
+ # Copying trace files into the qa-tools executables folder
+ if [ $(ls -1 ${TRACE_FOLDER}/${TRACE_FILE_PREFIX}-* 2>/dev/null | wc -l) != 0 ]; then
+ cp ${TRACE_FOLDER}/${TRACE_FILE_PREFIX}-* ${CODE_COVERAGE_FOLDER}/.
+ else
+ echo "Trace files not present, aborting reports..."
+ ls -al ${TRACE_FOLDER}
+ exit -1
+ fi
+ create_config_json "${ELF_FOLDER}" "${LIST_OF_BINARIES}" "${TRACE_FOLDER}" "$root_repos_foolder"
+ python3 ${CODE_COVERAGE_FOLDER}/qa-tools/coverage-tool/coverage-reporting/intermediate_layer.py \
+ --config-json ${CONFIG_JSON}
+
+}
+
+
+################################################################################
+# Creates LCOV coverage report.
+# GLOBALS:
+# CODE_COVERAGE_FOLDER, workspace, INTERMEDIATE_LAYER_FILE, INFO_FILE,
+# REPORT_FOLDER
+# ARGUMENTS:
+# None
+# OUTPUTS:
+# A coverage info file.
+# LCOV HTML coverage report.
+# RETURN:
+# 0 if succeeds, non-zero on error.
+################################################################################
+create_coverage_report() {
+ python3 ${CODE_COVERAGE_FOLDER}/qa-tools/coverage-tool/coverage-reporting/generate_info_file.py \
+ --workspace ${workspace} --json ${INTERMEDIATE_LAYER_FILE} --info ${INFO_FILE}
+ genhtml --branch-coverage ${INFO_FILE} --output-directory ${REPORT_FOLDER}
+}