summaryrefslogtreecommitdiff
path: root/script/qa-code-coverage.sh
blob: e5961b0b21cfe9ae242c16d13542056ce0639e14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
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_TOOLS_REPO:-$QA_REPO_PUBLIC}
  QA_REFSPEC=${QA_TOOLS_BRANCH:-master}
else
  QA_REPO=${QA_TOOLS_REPO:-"https://review.trustedfirmware.org/ci/qa-tools"}
  QA_REFSPEC=${QA_TOOLS_BRANCH:-"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}
}