1ced56a00Sopenharmony_ci#!/bin/bash 2ced56a00Sopenharmony_ci# SPDX-License-Identifier: MIT 3ced56a00Sopenharmony_ci# Copyright 2020 Google LLC 4ced56a00Sopenharmony_ci# 5ced56a00Sopenharmony_ci# Use of this source code is governed by an MIT-style 6ced56a00Sopenharmony_ci# license that can be found in the LICENSE file or at 7ced56a00Sopenharmony_ci# https://opensource.org/licenses/MIT. 8ced56a00Sopenharmony_ci# 9ced56a00Sopenharmony_ci# 10ced56a00Sopenharmony_ci# Test script for fsverity-utils. Runs 'make check' in lots of configurations, 11ced56a00Sopenharmony_ci# runs static analysis, and does a few other tests. 12ced56a00Sopenharmony_ci# 13ced56a00Sopenharmony_ci# Note: for more test coverage, in addition to running this script, also build 14ced56a00Sopenharmony_ci# fsverity-utils into a kvm-xfstests test appliance and run 15ced56a00Sopenharmony_ci# 'kvm-xfstests -c ext4,f2fs -g verity' 16ced56a00Sopenharmony_ci 17ced56a00Sopenharmony_ciset -e -u -o pipefail 18ced56a00Sopenharmony_cicd "$(dirname "$0")/.." 19ced56a00Sopenharmony_ci 20ced56a00Sopenharmony_cilog() 21ced56a00Sopenharmony_ci{ 22ced56a00Sopenharmony_ci echo "[$(date)] $*" 1>&2 23ced56a00Sopenharmony_ci} 24ced56a00Sopenharmony_ci 25ced56a00Sopenharmony_cifail() 26ced56a00Sopenharmony_ci{ 27ced56a00Sopenharmony_ci echo "FAIL: $*" 1>&2 28ced56a00Sopenharmony_ci exit 1 29ced56a00Sopenharmony_ci} 30ced56a00Sopenharmony_ci 31ced56a00Sopenharmony_ciTMPDIR=$(mktemp -d -t libfsverity_test.XXXXXXXXX) 32ced56a00Sopenharmony_citrap 'rm -r "$TMPDIR"' EXIT 33ced56a00Sopenharmony_ci 34ced56a00Sopenharmony_ci# Both stdout and stderr go to log file. 35ced56a00Sopenharmony_ci# Only stderr goes to terminal. 36ced56a00Sopenharmony_ciecho "Starting fsverity-utils tests. See run-tests.log for full output." 37ced56a00Sopenharmony_cirm -f run-tests.log 38ced56a00Sopenharmony_ciexec >> run-tests.log 39ced56a00Sopenharmony_ciexec 2> >(tee -ia run-tests.log 1>&2) 40ced56a00Sopenharmony_ci 41ced56a00Sopenharmony_ciMAKE="make -j$(getconf _NPROCESSORS_ONLN)" 42ced56a00Sopenharmony_ci 43ced56a00Sopenharmony_ciTEST_FUNCS=() 44ced56a00Sopenharmony_ci 45ced56a00Sopenharmony_cistatic_linking_test() 46ced56a00Sopenharmony_ci{ 47ced56a00Sopenharmony_ci log "Build and test with statically linking" 48ced56a00Sopenharmony_ci $MAKE CFLAGS="-Werror" 49ced56a00Sopenharmony_ci if ldd fsverity | grep libfsverity.so; then 50ced56a00Sopenharmony_ci fail "fsverity binary should be statically linked to libfsverity by default" 51ced56a00Sopenharmony_ci fi 52ced56a00Sopenharmony_ci ./fsverity --version 53ced56a00Sopenharmony_ci 54ced56a00Sopenharmony_ci log "Check that all global symbols are prefixed with \"libfsverity_\"" 55ced56a00Sopenharmony_ci if nm libfsverity.a | grep ' T ' | grep -v " libfsverity_"; then 56ced56a00Sopenharmony_ci fail "Some global symbols are not prefixed with \"libfsverity_\"" 57ced56a00Sopenharmony_ci fi 58ced56a00Sopenharmony_ci} 59ced56a00Sopenharmony_ciTEST_FUNCS+=(static_linking_test) 60ced56a00Sopenharmony_ci 61ced56a00Sopenharmony_cidynamic_linking_test() 62ced56a00Sopenharmony_ci{ 63ced56a00Sopenharmony_ci log "Build and test with dynamic linking" 64ced56a00Sopenharmony_ci $MAKE CFLAGS="-Werror" USE_SHARED_LIB=1 check 65ced56a00Sopenharmony_ci if ! ldd fsverity | grep libfsverity.so; then 66ced56a00Sopenharmony_ci fail "fsverity binary should be dynamically linked to libfsverity when USE_SHARED_LIB=1" 67ced56a00Sopenharmony_ci fi 68ced56a00Sopenharmony_ci 69ced56a00Sopenharmony_ci log "Check that all exported symbols are prefixed with \"libfsverity_\"" 70ced56a00Sopenharmony_ci if nm libfsverity.so | grep ' T ' | grep -v " libfsverity_"; then 71ced56a00Sopenharmony_ci fail "Some exported symbols are not prefixed with \"libfsverity_\"" 72ced56a00Sopenharmony_ci fi 73ced56a00Sopenharmony_ci} 74ced56a00Sopenharmony_ciTEST_FUNCS+=(dynamic_linking_test) 75ced56a00Sopenharmony_ci 76ced56a00Sopenharmony_cicplusplus_test() 77ced56a00Sopenharmony_ci{ 78ced56a00Sopenharmony_ci $MAKE CFLAGS="-Werror" libfsverity.so 79ced56a00Sopenharmony_ci log "Test using libfsverity from C++ program" 80ced56a00Sopenharmony_ci cat > "$TMPDIR/test.cc" <<EOF 81ced56a00Sopenharmony_ci#include <libfsverity.h> 82ced56a00Sopenharmony_ci#include <iostream> 83ced56a00Sopenharmony_ciint main() 84ced56a00Sopenharmony_ci{ 85ced56a00Sopenharmony_ci std::cout << libfsverity_get_digest_size(FS_VERITY_HASH_ALG_SHA256) << std::endl; 86ced56a00Sopenharmony_ci} 87ced56a00Sopenharmony_ciEOF 88ced56a00Sopenharmony_ci c++ -Wall -Werror "$TMPDIR/test.cc" -Iinclude -L. -lfsverity -o "$TMPDIR/test" 89ced56a00Sopenharmony_ci [ "$(LD_LIBRARY_PATH=. "$TMPDIR/test")" = "32" ] 90ced56a00Sopenharmony_ci rm "${TMPDIR:?}"/* 91ced56a00Sopenharmony_ci} 92ced56a00Sopenharmony_ciTEST_FUNCS+=(cplusplus_test) 93ced56a00Sopenharmony_ci 94ced56a00Sopenharmony_ciuntracked_files_test() 95ced56a00Sopenharmony_ci{ 96ced56a00Sopenharmony_ci log "Check that build doesn't produce untracked files" 97ced56a00Sopenharmony_ci $MAKE CFLAGS="-Werror" all test_programs 98ced56a00Sopenharmony_ci if git status --short | grep -q '^??'; then 99ced56a00Sopenharmony_ci git status 100ced56a00Sopenharmony_ci fail "Build produced untracked files (check 'git status'). Missing gitignore entry?" 101ced56a00Sopenharmony_ci fi 102ced56a00Sopenharmony_ci} 103ced56a00Sopenharmony_ciTEST_FUNCS+=(untracked_files_test) 104ced56a00Sopenharmony_ci 105ced56a00Sopenharmony_ciuninstall_test() 106ced56a00Sopenharmony_ci{ 107ced56a00Sopenharmony_ci log "Test that 'make uninstall' uninstalls all files" 108ced56a00Sopenharmony_ci make DESTDIR="$TMPDIR" install 109ced56a00Sopenharmony_ci if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" = 0 ]; then 110ced56a00Sopenharmony_ci fail "'make install' didn't install any files" 111ced56a00Sopenharmony_ci fi 112ced56a00Sopenharmony_ci make DESTDIR="$TMPDIR" uninstall 113ced56a00Sopenharmony_ci if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" != 0 ]; then 114ced56a00Sopenharmony_ci fail "'make uninstall' didn't uninstall all files" 115ced56a00Sopenharmony_ci fi 116ced56a00Sopenharmony_ci rm -r "${TMPDIR:?}"/* 117ced56a00Sopenharmony_ci} 118ced56a00Sopenharmony_ciTEST_FUNCS+=(uninstall_test) 119ced56a00Sopenharmony_ci 120ced56a00Sopenharmony_cidash_test() 121ced56a00Sopenharmony_ci{ 122ced56a00Sopenharmony_ci log "Build, install, and uninstall with dash" 123ced56a00Sopenharmony_ci make clean SHELL=/bin/dash 124ced56a00Sopenharmony_ci make DESTDIR="$TMPDIR" SHELL=/bin/dash install 125ced56a00Sopenharmony_ci make DESTDIR="$TMPDIR" SHELL=/bin/dash uninstall 126ced56a00Sopenharmony_ci} 127ced56a00Sopenharmony_ciTEST_FUNCS+=(dash_test) 128ced56a00Sopenharmony_ci 129ced56a00Sopenharmony_cilicense_test() 130ced56a00Sopenharmony_ci{ 131ced56a00Sopenharmony_ci log "Check that all files have license and copyright info" 132ced56a00Sopenharmony_ci list="$TMPDIR/filelist" 133ced56a00Sopenharmony_ci filter_license_info() { 134ced56a00Sopenharmony_ci # files to exclude from license and copyright info checks 135ced56a00Sopenharmony_ci grep -E -v '(\.gitignore|LICENSE|.*\.md|testdata|fsverity_uapi\.h|libfsverity\.pc\.in)' 136ced56a00Sopenharmony_ci } 137ced56a00Sopenharmony_ci git grep -L 'SPDX-License-Identifier: MIT' \ 138ced56a00Sopenharmony_ci | filter_license_info > "$list" || true 139ced56a00Sopenharmony_ci if [ -s "$list" ]; then 140ced56a00Sopenharmony_ci fail "The following files are missing an appropriate SPDX license identifier: $(<"$list")" 141ced56a00Sopenharmony_ci fi 142ced56a00Sopenharmony_ci # For now some people still prefer a free-form license statement, not just SPDX. 143ced56a00Sopenharmony_ci git grep -L 'Use of this source code is governed by an MIT-style' \ 144ced56a00Sopenharmony_ci | filter_license_info > "$list" || true 145ced56a00Sopenharmony_ci if [ -s "$list" ]; then 146ced56a00Sopenharmony_ci fail "The following files are missing an appropriate license statement: $(<"$list")" 147ced56a00Sopenharmony_ci fi 148ced56a00Sopenharmony_ci git grep -L '\<Copyright\>' | filter_license_info > "$list" || true 149ced56a00Sopenharmony_ci if [ -s "$list" ]; then 150ced56a00Sopenharmony_ci fail "The following files are missing a copyright statement: $(<"$list")" 151ced56a00Sopenharmony_ci fi 152ced56a00Sopenharmony_ci rm "$list" 153ced56a00Sopenharmony_ci} 154ced56a00Sopenharmony_ciTEST_FUNCS+=(license_test) 155ced56a00Sopenharmony_ci 156ced56a00Sopenharmony_cigcc_test() 157ced56a00Sopenharmony_ci{ 158ced56a00Sopenharmony_ci log "Build and test with gcc (-O2)" 159ced56a00Sopenharmony_ci $MAKE CC=gcc CFLAGS="-O2 -Werror" check 160ced56a00Sopenharmony_ci 161ced56a00Sopenharmony_ci log "Build and test with gcc (-O3)" 162ced56a00Sopenharmony_ci $MAKE CC=gcc CFLAGS="-O3 -Werror" check 163ced56a00Sopenharmony_ci} 164ced56a00Sopenharmony_ciTEST_FUNCS+=(gcc_test) 165ced56a00Sopenharmony_ci 166ced56a00Sopenharmony_ciclang_test() 167ced56a00Sopenharmony_ci{ 168ced56a00Sopenharmony_ci log "Build and test with clang (-O2)" 169ced56a00Sopenharmony_ci $MAKE CC=clang CFLAGS="-O2 -Werror" check 170ced56a00Sopenharmony_ci 171ced56a00Sopenharmony_ci log "Build and test with clang (-O3)" 172ced56a00Sopenharmony_ci $MAKE CC=clang CFLAGS="-O3 -Werror" check 173ced56a00Sopenharmony_ci} 174ced56a00Sopenharmony_ciTEST_FUNCS+=(clang_test) 175ced56a00Sopenharmony_ci 176ced56a00Sopenharmony_ci32bit_test() 177ced56a00Sopenharmony_ci{ 178ced56a00Sopenharmony_ci log "Build and test with gcc (32-bit)" 179ced56a00Sopenharmony_ci $MAKE CC=gcc CFLAGS="-O2 -Werror -m32" check 180ced56a00Sopenharmony_ci} 181ced56a00Sopenharmony_ciTEST_FUNCS+=(32bit_test) 182ced56a00Sopenharmony_ci 183ced56a00Sopenharmony_cisanitizers_test() 184ced56a00Sopenharmony_ci{ 185ced56a00Sopenharmony_ci log "Build and test with clang + UBSAN" 186ced56a00Sopenharmony_ci $MAKE CC=clang \ 187ced56a00Sopenharmony_ci CFLAGS="-O2 -Werror -fsanitize=undefined -fno-sanitize-recover=undefined" \ 188ced56a00Sopenharmony_ci check 189ced56a00Sopenharmony_ci 190ced56a00Sopenharmony_ci log "Build and test with clang + ASAN" 191ced56a00Sopenharmony_ci $MAKE CC=clang \ 192ced56a00Sopenharmony_ci CFLAGS="-O2 -Werror -fsanitize=address -fno-sanitize-recover=address" \ 193ced56a00Sopenharmony_ci check 194ced56a00Sopenharmony_ci 195ced56a00Sopenharmony_ci log "Build and test with clang + unsigned integer overflow sanitizer" 196ced56a00Sopenharmony_ci $MAKE CC=clang \ 197ced56a00Sopenharmony_ci CFLAGS="-O2 -Werror -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=unsigned-integer-overflow" \ 198ced56a00Sopenharmony_ci check 199ced56a00Sopenharmony_ci 200ced56a00Sopenharmony_ci log "Build and test with clang + CFI" 201ced56a00Sopenharmony_ci $MAKE CC=clang CFLAGS="-O2 -Werror -fsanitize=cfi -flto -fvisibility=hidden" \ 202ced56a00Sopenharmony_ci AR=llvm-ar check 203ced56a00Sopenharmony_ci} 204ced56a00Sopenharmony_ciTEST_FUNCS+=(sanitizers_test) 205ced56a00Sopenharmony_ci 206ced56a00Sopenharmony_civalgrind_test() 207ced56a00Sopenharmony_ci{ 208ced56a00Sopenharmony_ci log "Build and test with valgrind" 209ced56a00Sopenharmony_ci $MAKE TEST_WRAPPER_PROG="valgrind --quiet --error-exitcode=100 --leak-check=full --errors-for-leak-kinds=all" \ 210ced56a00Sopenharmony_ci CFLAGS="-O2 -Werror" check 211ced56a00Sopenharmony_ci} 212ced56a00Sopenharmony_ciTEST_FUNCS+=(valgrind_test) 213ced56a00Sopenharmony_ci 214ced56a00Sopenharmony_ciboringssl_test() 215ced56a00Sopenharmony_ci{ 216ced56a00Sopenharmony_ci log "Build and test using BoringSSL instead of OpenSSL" 217ced56a00Sopenharmony_ci log "-> Building BoringSSL" 218ced56a00Sopenharmony_ci $MAKE boringssl 219ced56a00Sopenharmony_ci log "-> Building fsverity-utils linked to BoringSSL" 220ced56a00Sopenharmony_ci $MAKE CFLAGS="-O2 -Werror" LDFLAGS="-Lboringssl/build/crypto" \ 221ced56a00Sopenharmony_ci CPPFLAGS="-Iboringssl/include" LDLIBS="-lcrypto -lpthread" check 222ced56a00Sopenharmony_ci} 223ced56a00Sopenharmony_ciTEST_FUNCS+=(boringssl_test) 224ced56a00Sopenharmony_ci 225ced56a00Sopenharmony_ciopenssl1_test() 226ced56a00Sopenharmony_ci{ 227ced56a00Sopenharmony_ci log "Build and test using OpenSSL 1.0" 228ced56a00Sopenharmony_ci $MAKE CFLAGS="-O2 -Werror" LDFLAGS="-L/usr/lib/openssl-1.0" \ 229ced56a00Sopenharmony_ci CPPFLAGS="-I/usr/include/openssl-1.0" check 230ced56a00Sopenharmony_ci} 231ced56a00Sopenharmony_ciTEST_FUNCS+=(openssl1_test) 232ced56a00Sopenharmony_ci 233ced56a00Sopenharmony_ciopenssl3_test() 234ced56a00Sopenharmony_ci{ 235ced56a00Sopenharmony_ci log "Build and test using OpenSSL 3.0" 236ced56a00Sopenharmony_ci OSSL3=$HOME/src/openssl/inst/usr/local 237ced56a00Sopenharmony_ci LD_LIBRARY_PATH="$OSSL3/lib64" $MAKE CFLAGS="-O2 -Werror" \ 238ced56a00Sopenharmony_ci LDFLAGS="-L$OSSL3/lib64" CPPFLAGS="-I$OSSL3/include" check 239ced56a00Sopenharmony_ci} 240ced56a00Sopenharmony_ciTEST_FUNCS+=(openssl3_test) 241ced56a00Sopenharmony_ci 242ced56a00Sopenharmony_ciunsigned_char_test() 243ced56a00Sopenharmony_ci{ 244ced56a00Sopenharmony_ci log "Build and test using -funsigned-char" 245ced56a00Sopenharmony_ci $MAKE CFLAGS="-O2 -Werror -funsigned-char" check 246ced56a00Sopenharmony_ci} 247ced56a00Sopenharmony_ciTEST_FUNCS+=(unsigned_char_test) 248ced56a00Sopenharmony_ci 249ced56a00Sopenharmony_cisigned_char_test() 250ced56a00Sopenharmony_ci{ 251ced56a00Sopenharmony_ci log "Build and test using -fsigned-char" 252ced56a00Sopenharmony_ci $MAKE CFLAGS="-O2 -Werror -fsigned-char" check 253ced56a00Sopenharmony_ci} 254ced56a00Sopenharmony_ciTEST_FUNCS+=(signed_char_test) 255ced56a00Sopenharmony_ci 256ced56a00Sopenharmony_ciwindows_build_test() 257ced56a00Sopenharmony_ci{ 258ced56a00Sopenharmony_ci log "Cross-compile for Windows (32-bit)" 259ced56a00Sopenharmony_ci $MAKE CC=i686-w64-mingw32-gcc CFLAGS="-O2 -Werror" 260ced56a00Sopenharmony_ci 261ced56a00Sopenharmony_ci log "Cross-compile for Windows (64-bit)" 262ced56a00Sopenharmony_ci $MAKE CC=x86_64-w64-mingw32-gcc CFLAGS="-O2 -Werror" 263ced56a00Sopenharmony_ci} 264ced56a00Sopenharmony_ciTEST_FUNCS+=(windows_build_test) 265ced56a00Sopenharmony_ci 266ced56a00Sopenharmony_cisparse_test() 267ced56a00Sopenharmony_ci{ 268ced56a00Sopenharmony_ci log "Run sparse" 269ced56a00Sopenharmony_ci ./scripts/run-sparse.sh 270ced56a00Sopenharmony_ci} 271ced56a00Sopenharmony_ciTEST_FUNCS+=(sparse_test) 272ced56a00Sopenharmony_ci 273ced56a00Sopenharmony_ciclang_analyzer_test() 274ced56a00Sopenharmony_ci{ 275ced56a00Sopenharmony_ci log "Run clang static analyzer" 276ced56a00Sopenharmony_ci scan-build --status-bugs make CFLAGS="-O2 -Werror" all test_programs 277ced56a00Sopenharmony_ci} 278ced56a00Sopenharmony_ciTEST_FUNCS+=(clang_analyzer_test) 279ced56a00Sopenharmony_ci 280ced56a00Sopenharmony_cishellcheck_test() 281ced56a00Sopenharmony_ci{ 282ced56a00Sopenharmony_ci log "Run shellcheck" 283ced56a00Sopenharmony_ci shellcheck scripts/*.sh 1>&2 284ced56a00Sopenharmony_ci} 285ced56a00Sopenharmony_ciTEST_FUNCS+=(shellcheck_test) 286ced56a00Sopenharmony_ci 287ced56a00Sopenharmony_citest_exists() 288ced56a00Sopenharmony_ci{ 289ced56a00Sopenharmony_ci local tst=$1 290ced56a00Sopenharmony_ci local func 291ced56a00Sopenharmony_ci for func in "${TEST_FUNCS[@]}"; do 292ced56a00Sopenharmony_ci if [ "${tst}_test" = "$func" ]; then 293ced56a00Sopenharmony_ci return 0 294ced56a00Sopenharmony_ci fi 295ced56a00Sopenharmony_ci done 296ced56a00Sopenharmony_ci return 1 297ced56a00Sopenharmony_ci} 298ced56a00Sopenharmony_ci 299ced56a00Sopenharmony_ciif [[ $# == 0 ]]; then 300ced56a00Sopenharmony_ci for func in "${TEST_FUNCS[@]}"; do 301ced56a00Sopenharmony_ci eval "$func" 302ced56a00Sopenharmony_ci done 303ced56a00Sopenharmony_cielse 304ced56a00Sopenharmony_ci for tst; do 305ced56a00Sopenharmony_ci if ! test_exists "$tst"; then 306ced56a00Sopenharmony_ci echo 1>&2 "Unknown test: $tst" 307ced56a00Sopenharmony_ci exit 2 308ced56a00Sopenharmony_ci fi 309ced56a00Sopenharmony_ci done 310ced56a00Sopenharmony_ci for tst; do 311ced56a00Sopenharmony_ci eval "${tst}_test" 312ced56a00Sopenharmony_ci done 313ced56a00Sopenharmony_cifi 314ced56a00Sopenharmony_ci 315ced56a00Sopenharmony_cilog "All tests passed!" 316