]> granicus.if.org Git - libexpat/blob - expat/coverage.sh
19c2625b9bdf848f8c1c0c4c3d238557b40ab1fd
[libexpat] / expat / coverage.sh
1 #! /usr/bin/env bash
2 # Copyright (C) Sebastian Pipping <sebastian@pipping.org>
3 # Licensed under the MIT license
4
5 export PS4='# '
6
7
8 _get_source_dir() {
9     echo "source__${version}"
10 }
11
12
13 _get_build_dir() {
14     local libbsd_part=
15     if ${with_libbsd}; then
16         libbsd_part=__libbsd
17     fi
18
19     local mingw_part=
20     if ${with_mingw}; then
21         mingw_part=__windows
22     fi
23
24     local char_part=
25     if ${with_unsigned_char}; then
26         char_part=__unsigned_char
27     fi
28
29     local xml_attr_part=
30     if ${xml_attr_info_enabled}; then
31         xml_attr_part=__attr_info
32     fi
33
34     echo "build__${version}__unicode_${unicode_enabled}__xml_context_${xml_context}${libbsd_part}${mingw_part}${char_part}${xml_attr_part}"
35 }
36
37
38 _get_coverage_dir() {
39     echo "coverage__${version}"
40 }
41
42
43 _call_cmake() {
44     local cmake_args=()
45
46     ${unicode_enabled} \
47             && cmake_args+=( -DEXPAT_CHAR_TYPE=wchar_t )
48
49     ${xml_attr_info_enabled} \
50             && cmake_args+=( -DEXPAT_ATTR_INFO=ON )
51
52     if [[ ${xml_context} -eq 0 ]]; then
53         cmake_args+=( -DEXPAT_CONTEXT_BYTES=OFF )
54     else
55         cmake_args+=( -DEXPAT_CONTEXT_BYTES=${xml_context} )
56     fi
57
58     ${with_libbsd} && cmake_args+=( -DEXPAT_WITH_LIBBSD=ON )
59     ${with_mingw} && cmake_args+=( -DCMAKE_TOOLCHAIN_FILE="${abs_source_dir}"/cmake/mingw-toolchain.cmake )
60
61     (
62         set -x
63         cmake "${cmake_args[@]}" "$@" . &>> cmake.log
64     )
65 }
66
67
68 _copy_to() {
69     local target_dir="$1"
70     [[ -d "${target_dir}" ]] && return 0
71
72     mkdir "${target_dir}"
73     git archive --format=tar "${version}" | ( cd "${target_dir}" && tar x )
74 }
75
76
77 _copy_missing_mingw_libaries() {
78     # These extra files are copied because
79     # * coverage GCC flags make them needed
80     # * With WINEDLLPATH Wine looks for .dll.so in these folders, not .dll
81     local target="$1"
82     local mingw_gcc_dll_dir="$(dirname "$(ls -1 /usr/lib*/gcc/i686-w64-mingw32/*/libgcc_s_sjlj-1.dll | head -n1)")"
83     for dll in libgcc_s_sjlj-1.dll libstdc++-6.dll; do
84         (
85             set -x
86             ln -s "${mingw_gcc_dll_dir}"/${dll} "${target}"/${dll}
87         )
88     done
89
90     local mingw_pthread_dll="$(ls -1 /usr/i686-w64-mingw32/lib*/libwinpthread-1.dll 2>/dev/null | head -n1)"
91     if [[ -n ${mingw_pthread_dll} ]]; then
92         local mingw_pthread_dll_dir="$(dirname "${mingw_pthread_dll}")"
93         for dll in libwinpthread-1.dll; do
94             source="${mingw_pthread_dll_dir}"/${dll}
95             (
96                 set -x
97                 ln -s "${source}" "${target}"/${dll}
98             )
99         done
100     fi
101
102     for dll in libexpat.dll; do
103         (
104             set -x
105             ln -s "${abs_build_dir}"/${dll} "${target}"/${dll}
106         )
107     done
108 }
109
110
111 _run() {
112     local source_dir="$1"
113     local build_dir="$2"
114     local abs_source_dir="${PWD}/${source_dir}"
115     local abs_build_dir="${PWD}/${build_dir}"
116     local capture_dir=.
117
118     local BASE_FLAGS='-pipe -Wall -Wextra -pedantic -Wno-overlength-strings'
119     BASE_FLAGS+=' --coverage --no-inline'
120
121     ${with_unsigned_char} && BASE_FLAGS="${BASE_FLAGS} -funsigned-char"
122
123     local CFLAGS="-std=c99 ${BASE_FLAGS}"
124     local CXXFLAGS="-std=c++98 ${BASE_FLAGS}"
125
126     (
127         set -e
128         cd "${build_dir}"
129
130         _call_cmake \
131                 -DCMAKE_C_FLAGS="${CFLAGS}" \
132                 -DCMAKE_CXX_FLAGS="${CXXFLAGS}"
133
134         (
135             set -x
136             make &> build.log
137
138             lcov -c -d "${capture_dir}" -i -o "${coverage_info}-zero" &> run.log
139         )
140
141         if ${with_mingw}; then
142             for d in tests xmlwf ; do
143                 mkdir -p "${d}"
144                 _copy_missing_mingw_libaries "${d}"
145             done
146         fi
147
148         set -x
149         make CTEST_OUTPUT_ON_FAILURE=1 test run-xmltest
150
151         lcov -c -d "${capture_dir}" -o "${coverage_info}-test" &>> run.log
152         lcov \
153                 -a "${coverage_info}-zero" \
154                 -a "${coverage_info}-test" \
155                 -o "${coverage_info}-all" \
156                 &>> run.log
157
158         # Make sure that files overlap in report despite different build folders
159         sed "/SF:/ s,${build_dir}/,${source_dir}/," "${coverage_info}-all" > "${coverage_info}"
160     ) |& sed 's,^,  ,'
161     res=${PIPESTATUS[0]}
162
163     if [[ ${res} -eq 0 ]]; then
164         echo PASSED
165     else
166         echo FAILED >&2
167         return 1
168     fi
169 }
170
171
172 _merge_coverage_info() {
173     local coverage_dir="$1"
174     shift
175     local build_dirs=( "$@" )
176
177     mkdir -p "${coverage_dir}"
178     (
179         local lcov_merge_args=()
180         for build_dir in "${build_dirs[@]}"; do
181             lcov_merge_args+=( -a "${build_dir}/${coverage_info}" )
182         done
183         lcov_merge_args+=( -o "${coverage_dir}/${coverage_info}" )
184
185         set -x
186         lcov "${lcov_merge_args[@]}"
187     ) &> "${coverage_dir}/merge.log"
188 }
189
190
191 _render_html_report() {
192     local coverage_dir="$1"
193     genhtml -o "${coverage_dir}" "${coverage_dir}/${coverage_info}" &> "${coverage_dir}/render.log"
194 }
195
196
197 _show_summary() {
198     local coverage_dir="$1"
199     lcov -q -l "${coverage_dir}/${coverage_info}" | grep -v '^\['
200 }
201
202
203 _main() {
204     version="$(git describe --tags)"
205     coverage_info=coverage.info
206
207     local build_dirs=()
208     local source_dir="$(_get_source_dir)"
209     local coverage_dir="$(_get_coverage_dir)"
210
211     _copy_to "${source_dir}"
212
213     _build_case() {
214         local build_dir="$(_get_build_dir)"
215
216         echo "[${build_dir}]"
217         _copy_to "${build_dir}"
218
219         # Make sure we don't need to download xmlts.zip over and over again
220         if [[ ${#build_dirs[*]} -gt 0 ]]; then
221             ln -s "$PWD/${build_dirs[0]}/tests/xmlts.zip" "${build_dir}"/tests/
222         fi
223
224         _run "${source_dir}" "${build_dir}"
225
226         build_dirs+=( "${build_dir}" )
227     }
228
229     # All combinations:
230     with_unsigned_char=false
231     with_libbsd=false
232     for with_mingw in true false ; do
233         for unicode_enabled in true false ; do
234             if ${unicode_enabled} && ! ${with_mingw} ; then
235                 continue
236             fi
237
238             for xml_attr_info_enabled in true false ; do
239                 for xml_context in 0 1024 ; do
240                     _build_case
241                 done
242             done
243         done
244     done
245
246     # Single cases:
247     with_libbsd=true _build_case
248     with_unsigned_char=true _build_case
249
250     echo
251     echo 'Merging coverage files...'
252     _merge_coverage_info "${coverage_dir}" "${build_dirs[@]}"
253
254     echo 'Rendering HTML report...'
255     _render_html_report "${coverage_dir}"
256     echo "--> ${coverage_dir}/index.html"
257
258     echo
259     _show_summary "${coverage_dir}"
260 }
261
262
263 _main