diff --git a/tests/check.sh b/tests/check.sh index b6352415..71fc244a 100644 --- a/tests/check.sh +++ b/tests/check.sh @@ -9,50 +9,104 @@ set -eu -o pipefail readonly APPARMORD="apparmor.d" +readonly HEADERS=( + "# apparmor.d - Full set of apparmor profiles" + "# Copyright (C) " + "# SPDX-License-Identifier: GPL-2.0-only" +) + +_die() { + echo " ✗ $*" + exit 1 +} _ensure_header() { local file="$1" - headers=( - "# apparmor.d - Full set of apparmor profiles" - "# Copyright (C) " - "# SPDX-License-Identifier: GPL-2.0-only" - ) - for header in "${headers[@]}"; do + for header in "${HEADERS[@]}"; do if ! grep -q "^$header" "$file"; then - echo "$file does not contain '$header'" - exit 1 + _die "$file does not contain '$header'" fi done } +_ensure_indentation() { + local file="$1" + local in_profile=false + local first_line_after_profile=true + local line_number=0 + + while IFS= read -r line; do + line_number=$((line_number + 1)) + + if [[ "$line" =~ $'\t' ]]; then + _die "$file:$line_number: tabs are not allowed." + fi + + if [[ "$line" =~ ^profile ]]; then + in_profile=true + first_line_after_profile=true + + elif $in_profile; then + if $first_line_after_profile; then + local leading_spaces="${line%%[! ]*}" + local num_spaces=${#leading_spaces} + if ((num_spaces != 2)); then + _die "$file: profile must have a two-space indentation." + fi + first_line_after_profile=false + + else + local leading_spaces="${line%%[! ]*}" + local num_spaces=${#leading_spaces} + + if ((num_spaces % 2 != 0)); then + ok=false + for offset in 5 11; do + num_spaces=$((num_spaces - offset)) + if ((num_spaces < 0)); then + break + fi + if ((num_spaces % 2 == 0)); then + ok=true + break + fi + done + + if ! $ok; then + _die "$file:$line_number: invalid indentation." + fi + fi + fi + fi + done <"$file" +} + _ensure_include() { local file="$1" local include="$2" if ! grep -q "^ *${include}$" "$file"; then - echo "$file does not contain '$include'" - exit 1 + _die "$file does not contain '$include'" fi } _ensure_abi() { local file="$1" if ! grep -q "^ *abi ," "$file"; then - echo "$file does not contain 'abi ,'" - exit 1 + _die "$file does not contain 'abi ,'" fi } _ensure_vim() { local file="$1" if ! grep -q "^# vim:syntax=apparmor" "$file"; then - echo "$file does not contain '# vim:syntax=apparmor'" - exit 1 + _die "$file does not contain '# vim:syntax=apparmor'" fi } check_profiles() { - echo "⋅ Checking if all profiles contain:" + echo " ⋅ Checking if all profiles contain:" echo " - apparmor.d header & license" + echo " - Check indentation: 2 spaces" echo " - 'abi ,'" echo " - 'profile '" echo " - 'include if exists '" @@ -67,19 +121,18 @@ check_profiles() { name="${name/.apparmor.d/}" include="include if exists " _ensure_header "$file" + _ensure_indentation "$file" _ensure_include "$file" "$include" _ensure_abi "$file" _ensure_vim "$file" if ! grep -q "^profile $name" "$file"; then - echo "$name does not contain 'profile $name'" - exit 1 + _die "$name does not contain 'profile $name'" fi mapfile -t subrofiles < <(grep "^ *profile*" "$file" | awk '{print $2}') for subprofile in "${subrofiles[@]}"; do include="include if exists " if ! grep -q "^ *${include}$" "$file"; then - echo "$name: $name//$subprofile does not contain '$include'" - exit 1 + _die "$name: $name//$subprofile does not contain '$include'" fi done done @@ -87,8 +140,9 @@ check_profiles() { } check_abstractions() { - echo "⋅ Checking if all abstractions contain:" + echo " ⋅ Checking if all abstractions contain:" echo " - apparmor.d header & license" + echo " - Check indentation: 2 spaces" echo " - 'abi ,'" echo " - 'include if exists '" echo " - vim:syntax=apparmor" @@ -103,12 +157,12 @@ check_abstractions() { root="${dir/${APPARMORD}\/abstractions\//}" include="include if exists " _ensure_header "$file" + _ensure_indentation "$file" _ensure_include "$file" "$include" _ensure_abi "$file" _ensure_vim "$file" done done - } check_profiles