From f176e2dd23fb59d846827382d74ade19edc1bf83 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Mon, 15 May 2023 09:21:50 +0300 Subject: [PATCH 01/14] feature: unit/bash/execute_tests: allow to enable bats features - by default parallel execution if `parallel` available - by default print output on failure - add --verbose --quiet - add --debug - add --parallel / --no-parallel - any other parameter provided to bats --- tests/unit/bash/execute_tests.sh | 72 +++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/tests/unit/bash/execute_tests.sh b/tests/unit/bash/execute_tests.sh index adb14638428..73cbb31637d 100755 --- a/tests/unit/bash/execute_tests.sh +++ b/tests/unit/bash/execute_tests.sh @@ -1,10 +1,70 @@ #!/bin/bash -PYTHON_EXECUTABLE="$1" -TESTS_ROOT="$2" -TESTDIR="$3" -OUTDIR="$4" +set -epu -mkdir -p "$OUTDIR" +usage() { + printf "Usage: %s [OPTIONS] PYTHON_EXECUTABLE TESTS_ROOT TESTDIR OUTDIR [bats opts]" "${0##/}" + printf " %s [--help]" "${0##/}" + printf "\nOPTIONS\n" + printf " --verbose\n" + printf " --quiet\n" + printf " --debug\n" + printf " --parallel | --no-parallel\n" + printf " --\n" +} -PYTHONPATH="$TESTS_ROOT/.." ${PYTHON_EXECUTABLE} "$TESTS_ROOT/../build-scripts/expand_jinja.py" --outdir "$OUTDIR" $TESTDIR/*.jinja && bats "$OUTDIR" +OPT_debug=0 +OPT_parallel=0 +if [[ -x /usr/bin/parallel ]]; then + OPT_parallel=1 +fi + +OPT_verbose=1 +while (( $# )); do + case "$1" in + --verbose) (( OPT_verbose++, 1 )); shift ;; + --quiet) OPT_verbose=0; shift ;; + --debug) set -x; OPT_debug=1; shift ;; + + --parallel) OPT_parallel=1; shift ;; + --no[_-]parallel) OPT_parallel=0; shift ;; + + --help) usage; exit 2 ;; + --) shift; break ;; + + *) break ;; + esac +done + +PYTHON_EXECUTABLE="$1"; shift +TESTS_ROOT="$1"; shift +TESTDIR="$1"; shift +OUTDIR="$1"; shift + +mkdir -p "${OUTDIR}" + +bats_opts=() + +if (( OPT_parallel )); then + bats_opts+=(--jobs "$(nproc)") +fi + +if (( OPT_verbose > 1 )); then + bats_opts+=(--verbose-run) +elif (( OPT_verbose == 1 )); then + bats_opts+=(--print-output-on-failure) +fi + +if (( OPT_debug )); then + bats_opts+=(--no-tempdir-cleanup --trace) +fi + +rc=0 +PYTHONPATH="${TESTS_ROOT}/.." ${PYTHON_EXECUTABLE} \ +"${TESTS_ROOT}/../build-scripts/expand_jinja.py" --outdir "${OUTDIR}" \ + "${TESTDIR}"/*.jinja || rc=$? +if (( rc )); then + >&2 echo "ERROR: expand_jinja.py could not create bats files" + exit "${rc}" +fi +bats "${bats_opts[@]}" "$@" "${OUTDIR}" From 8d3840934643bc246b191e1653be2564c6a565e2 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 11:08:14 +0300 Subject: [PATCH 02/14] fix: bats tests: add set -pu Ensure env is cleaned and do not use unset variables. --- tests/unit/bash/bash_os_linux_conditional.bats.jinja | 2 ++ tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja | 2 ++ tests/unit/bash/test_bash_ensure_ini_config.bats.jinja | 1 + tests/unit/bash/test_bash_replace_or_append.bats.jinja | 1 + tests/unit/bash/test_set_config_file.bats.jinja | 1 + 5 files changed, 7 insertions(+) diff --git a/tests/unit/bash/bash_os_linux_conditional.bats.jinja b/tests/unit/bash/bash_os_linux_conditional.bats.jinja index c7d7c7a53ba..4a6a396cc22 100644 --- a/tests/unit/bash/bash_os_linux_conditional.bats.jinja +++ b/tests/unit/bash/bash_os_linux_conditional.bats.jinja @@ -1,5 +1,7 @@ #!/bin/bash +set -pu + @test "bash_os_linux_conditional - test OS release - RHEL" { os_release_path="$(mktemp)" diff --git a/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja b/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja index b7037be0f31..71557ddbc75 100644 --- a/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja +++ b/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja @@ -1,5 +1,7 @@ #!/bin/bash +set -pu + # Mock the "rpm" command # mocked package: coconut-4.5.17 # The mock is used to avoid the need to have a specific RPM package in a diff --git a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja index 227411ba71d..22c6062607b 100644 --- a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja +++ b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja @@ -1,5 +1,6 @@ #!/bin/bash +set -pu function call_bash_ensure_ini_config { {{{ bash_ensure_ini_config("$1", "$2", "$3", "$4") | indent(4) }}} diff --git a/tests/unit/bash/test_bash_replace_or_append.bats.jinja b/tests/unit/bash/test_bash_replace_or_append.bats.jinja index 138ae4c0f2b..92582d69ded 100644 --- a/tests/unit/bash/test_bash_replace_or_append.bats.jinja +++ b/tests/unit/bash/test_bash_replace_or_append.bats.jinja @@ -1,5 +1,6 @@ #!/bin/bash +set -pu function call_bash_replace_or_append { {{{ bash_replace_or_append("$1", "$2", "$3") | indent(4) }}} diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index d45249b188e..8219313f89b 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -1,5 +1,6 @@ #!/bin/bash +set -pu function call_set_config_file_create_false { {{{ set_config_file("$1", "Compression", "no", False) | indent(4) }}} From d8cec0d94a2e793c5cc01a15eb5c53e59cd4893a Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Thu, 18 May 2023 17:47:39 +0300 Subject: [PATCH 03/14] style: test_set_config_file.bats.jinja: indent, drop tabs --- tests/unit/bash/test_set_config_file.bats.jinja | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index 8219313f89b..43f1fee925b 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -12,8 +12,9 @@ function call_set_config_file { } function call_set_config_file_rsyslog { - {{{ set_config_file(path="$1", - parameter="\$DefaultNetstreamDriver", value="gtls", create=true, separator=" ", separator_regex=" ") }}} + {{{ set_config_file(path="$1", + parameter="\$DefaultNetstreamDriver", value="gtls", + create=true, separator=" ", separator_regex=" ") }}} } @test "Basic value remediation" { From 5d91ba5e1b73643a553f331e3d9684e6808747fd Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Thu, 18 May 2023 17:49:33 +0300 Subject: [PATCH 04/14] style: test_bash_ensure_ini_config --- tests/unit/bash/test_bash_ensure_ini_config.bats.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja index 22c6062607b..c8706b3d201 100644 --- a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja +++ b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja @@ -112,7 +112,7 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - + run diff "pam_cert_auth.conf" <(printf "$expected_output") [ "$status" -eq 0 ] From 586760fe3d589cee6a676bcbe4b867eee740a7f1 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 09:17:57 +0300 Subject: [PATCH 05/14] fix: test_bash_ensure_ini_config: use bats features Use setup to setup common. There is no need to do cleanup when using `$BATS_TEST_TMPDIR`. bats does it for us. This allows tests to be run parallel as resources are not shared between tests. --- .../test_bash_ensure_ini_config.bats.jinja | 34 +++---------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja index c8706b3d201..163bb503c82 100644 --- a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja +++ b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja @@ -6,8 +6,12 @@ function call_bash_ensure_ini_config { {{{ bash_ensure_ini_config("$1", "$2", "$3", "$4") | indent(4) }}} } +setup() { + pushd "${BATS_TEST_TMPDIR}" + mkdir -p sssd_test +} + @test "bash_ensure_ini_config - Basic value remediation" { - mkdir sssd_test printf "[pam]\npam_cert_auth = false\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -15,12 +19,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Value remediation in multiple files" { - mkdir sssd_test printf "[pam]\npam_cert_auth = false\n" > sssd_test/sssd.conf printf "[pam]\npam_cert_auth = false\n" > pam_cert_auth.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -32,13 +33,9 @@ function call_bash_ensure_ini_config { run diff "pam_cert_auth.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm pam_cert_auth.conf - rm -rf sssd_test } @test "bash_ensure_ini_config - No remediation happened" { - mkdir sssd_test printf "[pam]\npam_cert_auth = true\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -46,12 +43,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append section with option to empty file" { - mkdir sssd_test printf "" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -59,8 +53,6 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Create file with section and option" { @@ -70,12 +62,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append option to section" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -83,12 +72,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append option to section when section is substring of option" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf expected_output="[pam]\npam_verbosity = 1\npam_cert_auth = true\n" @@ -96,14 +82,10 @@ function call_bash_ensure_ini_config { call_bash_ensure_ini_config "sssd_test/sssd.conf" "pam" "pam_verbosity" "1" run diff "sssd_test/sssd.conf" <(printf "$expected_output") - - rm -rf sssd_test - [ "$status" -eq 0 ] } @test "bash_ensure_ini_config - Append option to section in multiple files" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf printf "[pam]\n" > pam_cert_auth.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -115,13 +97,9 @@ function call_bash_ensure_ini_config { run diff "pam_cert_auth.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm pam_cert_auth.conf - rm -rf sssd_test } @test "bash_ensure_ini_config - Append section with option to non-empty file" { - mkdir sssd_test printf "[section]\nkey = value\n" > sssd_test/sssd.conf expected_output="[section]\nkey = value\n[pam]\npam_cert_auth = true\n" @@ -129,6 +107,4 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } From 6470bcb250c00373883fb4b00a5806a6a5d74084 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 10:36:48 +0300 Subject: [PATCH 06/14] fix: test_bash_replace_or_append: use bats features Use setup to setup common. There is no need to create special tmpfile and do cleanup as bats does it for us. --- .../test_bash_replace_or_append.bats.jinja | 33 ++++--------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/tests/unit/bash/test_bash_replace_or_append.bats.jinja b/tests/unit/bash/test_bash_replace_or_append.bats.jinja index 92582d69ded..858321239fa 100644 --- a/tests/unit/bash/test_bash_replace_or_append.bats.jinja +++ b/tests/unit/bash/test_bash_replace_or_append.bats.jinja @@ -10,8 +10,13 @@ function call_bash_replace_or_append_w_format { {{{ bash_replace_or_append("$1", "$2", "$3", "$4") | indent(4) }}} } +setup() { + pushd "${BATS_TEST_TMPDIR}" + tmp_file=test.sh + touch "$tmp_file" +} + @test "bash_replace_or_append - Basic value remediation" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space = 5" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -19,12 +24,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - No remediation happened" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space = 2" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -32,12 +34,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key to empty file" { - tmp_file="$(mktemp)" printf "" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -45,12 +44,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key to non-empty file" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_fake = 5" > "$tmp_file" expected_output="kernel.randomize_va_fake = 5\nkernel.randomize_va_space = 2\n" @@ -58,12 +54,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Remediation with format" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space=5" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -71,12 +64,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - No remediation with format" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space=2" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -84,12 +74,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key with format to empty file" { - tmp_file="$(mktemp)" printf "" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -97,12 +84,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key with format to non-empty file" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_fake=5" > "$tmp_file" expected_output="kernel.randomize_va_fake=5\nkernel.randomize_va_space=2\n" @@ -110,12 +94,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Remediate value containing forward slash" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.core_pattern=|/bin/true" > "$tmp_file" expected_output="kernel.core_pattern=|/bin/false\n" @@ -123,6 +104,4 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } From ff36f1a25da301881455a4fce2e2606055c26a39 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 11:08:09 +0300 Subject: [PATCH 07/14] fix: bash_os_linux_conditional: use bats features Use setup to setup common. There is no need to do cleanup as bats does it for us. --- .../unit/bash/bash_os_linux_conditional.bats.jinja | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/unit/bash/bash_os_linux_conditional.bats.jinja b/tests/unit/bash/bash_os_linux_conditional.bats.jinja index 4a6a396cc22..dc8a08c0a69 100644 --- a/tests/unit/bash/bash_os_linux_conditional.bats.jinja +++ b/tests/unit/bash/bash_os_linux_conditional.bats.jinja @@ -2,9 +2,12 @@ set -pu -@test "bash_os_linux_conditional - test OS release - RHEL" { - os_release_path="$(mktemp)" +setup() { + pushd "${BATS_TEST_TMPDIR}" + os_release_path="os-release" +} +@test "bash_os_linux_conditional - test OS release - RHEL" { cat << EOF > "$os_release_path" NAME="Red Hat Enterprise Linux" VERSION="9.2 (Plow)" @@ -44,13 +47,9 @@ EOF ! ( {{{ bash_os_linux_conditional("fedora", "38", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "9.2", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "9.4", "<", "$os_release_path") }}} ) - - rm -rf "$os_release_path" } @test "bash_os_linux_conditional - test OS release - Ubuntu" { - os_release_path="$(mktemp)" - cat << EOF > "$os_release_path" PRETTY_NAME="Ubuntu 22.04.1 LTS" NAME="Ubuntu" @@ -84,6 +83,4 @@ EOF ! ( {{{ bash_os_linux_conditional("fedora", "38", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "22.10", "<", "$os_release_path") }}} ) - - rm -rf "$os_release_path" } From 58ebe168f3b837064fa9f020444022d7f9834baf Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Thu, 18 May 2023 17:56:05 +0300 Subject: [PATCH 08/14] fix: test_set_config_file: add test name prefix This shows test target and there is nice logging. --- .../unit/bash/test_set_config_file.bats.jinja | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index 43f1fee925b..6e5c3ddca58 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -17,7 +17,7 @@ function call_set_config_file_rsyslog { create=true, separator=" ", separator_regex=" ") }}} } -@test "Basic value remediation" { +@test "set_config_file - Basic value remediation" { tmp_file="$(mktemp)" printf "%s\n" "Compression yes" > "$tmp_file" expected_output="Compression no\n" @@ -30,7 +30,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "No remediation happened" { +@test "set_config_file - No remediation happened" { tmp_file="$(mktemp)" printf "%s\n" "Compression no" > "$tmp_file" expected_output="Compression no\n" @@ -43,7 +43,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Multiline file remediation" { +@test "set_config_file - Multiline file remediation" { tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -56,7 +56,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "No remediation on commented line" { +@test "set_config_file - No remediation on commented line" { tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "# Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\n# Compression yes\nPort 22\nCompression no\n" @@ -69,7 +69,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Create if missing" { +@test "set_config_file - Create if missing" { tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -82,7 +82,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Create file if doesn't exist" { +@test "set_config_file - Create file if doesn't exist" { tmp_file="$(mktemp)" rm "$tmp_file" expected_output="Compression no\n" @@ -95,7 +95,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Do not create if missing" { +@test "set_config_file - Do not create if missing" { tmp_file="$(mktemp)" rm "$tmp_file" @@ -106,7 +106,7 @@ function call_set_config_file_rsyslog { } -@test "Case insensitive remediation" { +@test "set_config_file - Case insensitive remediation" { tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -119,7 +119,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Case sensitive remediation" { +@test "set_config_file - Case sensitive remediation" { tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nCOMPRESSION YES\nPort 22\nCompression no\n" @@ -133,7 +133,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Basic Bash remediation" { +@test "set_config_file - Basic Bash remediation" { tmp_file="$(mktemp)" printf "%s\n" "something=foo" > "$tmp_file" expected_output="something='va lue'\n" @@ -147,7 +147,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Variable remediation - preserve dollar and use double quotes" { +@test "set_config_file - Variable remediation - preserve dollar and use double quotes" { tmp_file="$(mktemp)" printf "%s\n" "something=bar" > "$tmp_file" expected_output='something="$value"'"\n" @@ -161,7 +161,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Basic Bash remediation - don't quote" { +@test "set_config_file - Basic Bash remediation - don't quote" { tmp_file="$(mktemp)" printf "%s\n" "something=foo" > "$tmp_file" expected_output="something=va lue\n" @@ -175,7 +175,7 @@ function call_set_config_file_rsyslog { rm "$tmp_file" } -@test "Variable remediation - don't quote" { +@test "set_config_file - Variable remediation - don't quote" { tmp_file="$(mktemp)" printf "%s\n" "something=bar" > "$tmp_file" expected_output='something=$value'"\n" From afd86617f86d99e3e03413466de16b822e720d38 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 11:08:32 +0300 Subject: [PATCH 09/14] fix: test_set_config_file: use bats features Use setup to setup common. There is no need to do cleanup as bats does it for us. Also use bats to output if needed, not implemented inside test. --- .../unit/bash/test_set_config_file.bats.jinja | 52 +++---------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index 6e5c3ddca58..db0d1c3b8d2 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -17,8 +17,13 @@ function call_set_config_file_rsyslog { create=true, separator=" ", separator_regex=" ") }}} } +setup() { + pushd "${BATS_TEST_TMPDIR}" + tmp_file=test.conf + touch "$tmp_file" +} + @test "set_config_file - Basic value remediation" { - tmp_file="$(mktemp)" printf "%s\n" "Compression yes" > "$tmp_file" expected_output="Compression no\n" @@ -26,12 +31,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - No remediation happened" { - tmp_file="$(mktemp)" printf "%s\n" "Compression no" > "$tmp_file" expected_output="Compression no\n" @@ -39,12 +41,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Multiline file remediation" { - tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -52,12 +51,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - No remediation on commented line" { - tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "# Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\n# Compression yes\nPort 22\nCompression no\n" @@ -65,12 +61,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Create if missing" { - tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -78,12 +71,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Create file if doesn't exist" { - tmp_file="$(mktemp)" rm "$tmp_file" expected_output="Compression no\n" @@ -91,12 +81,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Do not create if missing" { - tmp_file="$(mktemp)" rm "$tmp_file" run call_set_config_file_create_false "$tmp_file" @@ -107,7 +94,6 @@ function call_set_config_file_rsyslog { @test "set_config_file - Case insensitive remediation" { - tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -115,90 +101,64 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Case sensitive remediation" { - tmp_file="$(mktemp)" printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nCOMPRESSION YES\nPort 22\nCompression no\n" {{{ set_config_file("$tmp_file", "Compression", "no", True, "", "", False) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Basic Bash remediation" { - tmp_file="$(mktemp)" printf "%s\n" "something=foo" > "$tmp_file" expected_output="something='va lue'\n" {{{ bash_shell_file_set("$tmp_file", "something", "va lue") | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Variable remediation - preserve dollar and use double quotes" { - tmp_file="$(mktemp)" printf "%s\n" "something=bar" > "$tmp_file" expected_output='something="$value"'"\n" {{{ bash_shell_file_set("$tmp_file", "something", '$value') | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Basic Bash remediation - don't quote" { - tmp_file="$(mktemp)" printf "%s\n" "something=foo" > "$tmp_file" expected_output="something=va lue\n" {{{ bash_shell_file_set("$tmp_file", "something", "va lue", no_quotes=true) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - Variable remediation - don't quote" { - tmp_file="$(mktemp)" printf "%s\n" "something=bar" > "$tmp_file" expected_output='something=$value'"\n" {{{ bash_shell_file_set("$tmp_file", "something", '$value', no_quotes=true) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - handle escaped dollar" { - tmp_file="$(mktemp)" printf "%s\n" '$DefaultNetstreamDriver bad' > "$tmp_file" expected_output='$DefaultNetstreamDriver gtls'"\n" call_set_config_file_rsyslog "$tmp_file" run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } From 6bf14a85baff642132b7a54f37e7c26dff17ac73 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Wed, 17 May 2023 21:37:11 +0300 Subject: [PATCH 10/14] improve: test_bash_replace_or_append: more tests --- .../test_bash_replace_or_append.bats.jinja | 869 ++++++++++++++++++ 1 file changed, 869 insertions(+) diff --git a/tests/unit/bash/test_bash_replace_or_append.bats.jinja b/tests/unit/bash/test_bash_replace_or_append.bats.jinja index 858321239fa..856ab3efd23 100644 --- a/tests/unit/bash/test_bash_replace_or_append.bats.jinja +++ b/tests/unit/bash/test_bash_replace_or_append.bats.jinja @@ -105,3 +105,872 @@ setup() { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] } + +@test "bash_replace_or_append - Key prefix remediation" { + printf "kernel.randomize_va_space = 5\nakernel.randomize_va_space = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nakernel.randomize_va_space = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key suffix remediation" { + printf "kernel.randomize_va_space = 5\nkernel.randomize_va_space2 = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nkernel.randomize_va_space2 = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key ending with . remediation" { + skip "Implementation needs to have word_boundary" + printf "kernel.randomize_va_space. = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space. = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space.' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key contains * with remediation" { + skip "Implementation does not quote regexps properly despite skipped_key functionality" + printf "kernel.randomize_va_space. = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space. = 5\nkernel.* = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.*' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Commented remediation" { + printf "kernel.randomize_va_space = 5\n# kernel.randomize_va_space = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n# kernel.randomize_va_space = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case insensitive key remediation" { + printf "KERNEL.RANDOMIZE_VA_SPACE = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case sensitive value remediation" { + printf "kernel.randomize_va_space = FOO\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = foo\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' 'foo' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case insensitive key, remediation happened 3 times" { + printf "kernel.randomize_va_space = foo\nKERNEL.RANDOMIZE_VA_SPACE = 2\nkernel.randomize_va_space = foo\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nkernel.randomize_va_space = 2\nkernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - No file before" { + rm "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Fail if not file" { + skip "bash_replace_or_append does not handle situation where final target is not creatable/readable/writable file" + rm "${tmp_file}" + mkdir -p "${tmp_file}" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Is symlink missing" { + ln -s "${tmp_file}" symlink.sh + rm "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] + [ -L symlink.sh ] + [ -f "${tmp_file}" ] +} + +@test "bash_replace_or_append - Is symlink empty" { + ln -s "${tmp_file}" symlink.sh + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + [ -L symlink.sh ] + [ -f "${tmp_file}" ] + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Is symlink remediation" { + printf "foo\n%s\nbar\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + ln -s "${tmp_file}" symlink.sh + expected_output="foo\nkernel.randomize_va_space = 2\nbar\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + [ -L symlink.sh ] + [ -f "${tmp_file}" ] + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains space" { + tmp_file="${tmp_file} " + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains tab" { + tmp_file="$(printf "\t%s" "${tmp_file}")" + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains newline" { + tmp_file="$(printf "%s\n" "${tmp_file}")" + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test 'bash_replace_or_append - Filename contains \$(touch foo)' { + tmp_file+=$'$(touch foo)' + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [[ ${tmp_file} =~ foo ]] + [ "${status}" -eq 0 ] + [ ! -f foo ] +} + +@test 'bash_replace_or_append - Filename contains \`touch foo\`' { + tmp_file+=$'`touch foo`' + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [[ ${tmp_file} =~ foo ]] + [ "${status}" -eq 0 ] + [ ! -f foo ] +} + +@test "bash_replace_or_append - Remediate value emtpy" { + printf "%s\n" "kernel.core_pattern=|/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern=\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s=%s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediation with format space" { + printf "%s\n" "kernel.randomize_va_space 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - No remediation with format space" { + printf "%s\n" "kernel.randomize_va_space 2" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Append key with format to empty file format space" { + printf "" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Append key with format to non-empty file format space" { + printf "%s\n" "kernel.randomize_va_fake 5" > "${tmp_file}" + expected_output="kernel.randomize_va_fake 5\nkernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing forward slash format space" { + printf "%s\n" "kernel.core_pattern |/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern |/bin/false\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '|/bin/false' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value emtpy format space" { + printf "%s\n" "kernel.core_pattern |/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern \n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value emtpy format tab" { + printf "kernel.core_pattern\t|/bin/true\n" > "${tmp_file}" + expected_output="kernel.core_pattern\t\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s\t%s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously not ending with newline" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously ending with space" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s " + key_fmt="^%s" + value_fmt="%s" + expected_output="${before} \n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously ending with tab" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\t" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\t\n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing newline prefix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\n%s" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing newline suffix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s\n" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple newlines prefix and suffix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\n\n%s\n\n" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt=" %s" + expected_output="${before}\n${key}= ${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s " + expected_output="${before}\n${key}=${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt=" %s " + expected_output="${before}\n${key}= ${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\t%s" + expected_output="${before}\n${key}=\t${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s\t" + expected_output="${before}\n${key}=${value}\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\t\t%s\t\t" + expected_output="${before}\n${key}=\t\t${value}\t\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^ %s" + value_fmt="%s" + expected_output="${before}\n ${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s " + value_fmt="%s" + expected_output="${before}\n${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^ %s " + value_fmt="%s" + expected_output="${before}\n ${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^\t%s" + value_fmt="%s" + expected_output="${before}\n\t${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s\t" + value_fmt="%s" + expected_output="${before}\n${key}\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^\t\t%s\t\t" + value_fmt="%s" + expected_output="${before}\n\t\t${key}\t\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format=' %s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n ${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s =%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s= %s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}= ${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s ' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format=' %s = %s ' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n ${key} = ${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" ' %s = %s ' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='\t%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n\t${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s\t=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=\t%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=\t${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s\t' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value}\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='\t\t%s\t\t=\t\t%s\t\t' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n\t\t${key}\t\t=\t\t${value}\t\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} From f146893bebb5fde8517505b8945616176cfe1020 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Mon, 15 May 2023 22:46:38 +0300 Subject: [PATCH 11/14] feature: bash: add bash_ensure_nl_at_eof Ensure file ends with newline. Follows always symlinks. --- shared/macros/10-bash.jinja | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja index 44642ab1ea8..5a6298da649 100644 --- a/shared/macros/10-bash.jinja +++ b/shared/macros/10-bash.jinja @@ -1465,6 +1465,22 @@ cce="{{{ cce_identifiers['cce'] }}}" {{%- endmacro -%}} +{{# + Ensure file ends with newline + + Do not modify file at all if there already is newline. Always follows + symlinks. + + :param file: file to check +#}} +{{%- macro bash_ensure_nl_at_eof(file) -%}} +{{#- Plain sed '$a\' updates stat even if it dones not change the file. -#}} +if [[ -s "{{{ file }}}" ]] && [[ -n "$(tail -c 1 -- "{{{ file }}}" || true)" ]]; then + LC_ALL=C sed -i --follow-symlinks '$a'\\ "{{{ file }}}" +fi +{{%- endmacro -%}} + + {{# Macro to replace configuration setting in config file or add the configuration setting if it does not exist. From 43393b5b07f716e125bf709fdb11dec5965bfd5a Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 13:19:51 +0300 Subject: [PATCH 12/14] fix: bash_replace_or_append: use bash_ensure_nl_at_eof Moved jinja whitespace trim from end to start as it works best that way. --- shared/macros/10-bash.jinja | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja index 5a6298da649..677a7f0bf75 100644 --- a/shared/macros/10-bash.jinja +++ b/shared/macros/10-bash.jinja @@ -1529,10 +1529,10 @@ if LC_ALL=C grep -q -m 1 -i -e "{{{ key }}}\\>" "{{{ config_file }}}"; then escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output") "${sed_command[@]}" "s/{{{ key }}}\\>.*/$escaped_formatted_output/gi" "{{{ config_file }}}" else - # \n is precaution for case where file ends without trailing newline - {{% if cce_identifiers and 'cce' in cce_identifiers -%}} + {{{ bash_ensure_nl_at_eof(config_file) | indent }}} + {{%- if cce_identifiers and 'cce' in cce_identifiers %}} {{{ set_cce_value() }}} - printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "{{{ config_file }}}" >> "{{{ config_file }}}" + printf '# Per %s: Set %s in %s\n' "${cce}" "${formatted_output}" "{{{ config_file }}}" >> "{{{ config_file }}}" {{%- endif %}} printf '%s\n' "$formatted_output" >> "{{{ config_file }}}" fi From c8928e0cefc64ca10adfd75b937bf2ceaa197637 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Mon, 15 May 2023 22:50:10 +0300 Subject: [PATCH 13/14] change: bash_replace_or_append: drop logic about symlinks I see no point doing extra test. Functionality does not change. It exposes bigger TOCTOU window. And I think all `sed -i` commands should always have `--follow-symlinks`. And also have always LC_ALL=C if there is no other reason why not. --- shared/macros/10-bash.jinja | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja index 677a7f0bf75..f52ae185b41 100644 --- a/shared/macros/10-bash.jinja +++ b/shared/macros/10-bash.jinja @@ -1507,14 +1507,6 @@ fi #}} {{%- macro bash_replace_or_append(config_file, key, value, format='%s = %s') -%}} - -# Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed. -# Otherwise, regular sed command will do. -sed_command=('sed' '-i') -if test -L "{{{ config_file }}}"; then - sed_command+=('--follow-symlinks') -fi - # Strip any search characters in the key arg so that the key can be replaced without # adding any search characters to the config file. stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "{{{ key }}}") @@ -1527,7 +1519,7 @@ printf -v formatted_output "{{{ format }}}" "$stripped_key" "{{{ value }}}" # so if we search for 'setting', 'setting2' won't match. if LC_ALL=C grep -q -m 1 -i -e "{{{ key }}}\\>" "{{{ config_file }}}"; then escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output") - "${sed_command[@]}" "s/{{{ key }}}\\>.*/$escaped_formatted_output/gi" "{{{ config_file }}}" + LC_ALL=C sed -i --follow-symlinks "s/{{{ key }}}\\>.*/$escaped_formatted_output/gi" "{{{ config_file }}}" else {{{ bash_ensure_nl_at_eof(config_file) | indent }}} {{%- if cce_identifiers and 'cce' in cce_identifiers %}} From 628c5fb4825c9c5ca031d7e573573115eef45f74 Mon Sep 17 00:00:00 2001 From: Markus Linnala Date: Tue, 16 May 2023 17:24:13 +0300 Subject: [PATCH 14/14] fix: execute_tests: handle older versions Seems Debian 10 has 0.4.0, so need to disable some features. --- .../bash/bash_os_linux_conditional.bats.jinja | 35 ++++++++++++++++++- tests/unit/bash/execute_tests.sh | 28 ++++++++++++--- .../test_bash_ensure_ini_config.bats.jinja | 35 ++++++++++++++++++- .../test_bash_replace_or_append.bats.jinja | 35 ++++++++++++++++++- .../unit/bash/test_set_config_file.bats.jinja | 35 ++++++++++++++++++- 5 files changed, 160 insertions(+), 8 deletions(-) diff --git a/tests/unit/bash/bash_os_linux_conditional.bats.jinja b/tests/unit/bash/bash_os_linux_conditional.bats.jinja index dc8a08c0a69..c25a4500627 100644 --- a/tests/unit/bash/bash_os_linux_conditional.bats.jinja +++ b/tests/unit/bash/bash_os_linux_conditional.bats.jinja @@ -2,11 +2,44 @@ set -pu +is_old_bats=0 + setup() { - pushd "${BATS_TEST_TMPDIR}" + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 os_release_path="os-release" } +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "bash_os_linux_conditional - test OS release - RHEL" { cat << EOF > "$os_release_path" NAME="Red Hat Enterprise Linux" diff --git a/tests/unit/bash/execute_tests.sh b/tests/unit/bash/execute_tests.sh index 73cbb31637d..1766ddaebb4 100755 --- a/tests/unit/bash/execute_tests.sh +++ b/tests/unit/bash/execute_tests.sh @@ -36,6 +36,23 @@ while (( $# )); do esac done +bats_version="$(bats -v)" || : +case "${bats_version##* }" in + # Debian 10 v0.4.0 + # Usage: bats [-c] [-p | -t] + ""|"0."*|"1.0."*|"1.1."*) + OPT_parallel=0 + OPT_verbose=0 + OPT_debug=0 + ;; + # Ubuntu 22.04 + # Error: Bad command line option '--print-output-on-failure' + "1.2."*|"1.3."*|"1.4."*) + OPT_verbose=0 + OPT_debug=0 + ;; +esac + PYTHON_EXECUTABLE="$1"; shift TESTS_ROOT="$1"; shift TESTDIR="$1"; shift @@ -46,17 +63,20 @@ mkdir -p "${OUTDIR}" bats_opts=() if (( OPT_parallel )); then - bats_opts+=(--jobs "$(nproc)") + bats_opts+=(--jobs "$(nproc)") # 1.2.0 fi if (( OPT_verbose > 1 )); then - bats_opts+=(--verbose-run) + bats_opts+=(--verbose-run) # 1.5.0 elif (( OPT_verbose == 1 )); then - bats_opts+=(--print-output-on-failure) + bats_opts+=(--print-output-on-failure) # 1.5.0 fi if (( OPT_debug )); then - bats_opts+=(--no-tempdir-cleanup --trace) + bats_opts+=( + --no-tempdir-cleanup # 1.4.0 + --trace # 1.5.0 + ) fi rc=0 diff --git a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja index 163bb503c82..b680fc939c0 100644 --- a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja +++ b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja @@ -6,11 +6,44 @@ function call_bash_ensure_ini_config { {{{ bash_ensure_ini_config("$1", "$2", "$3", "$4") | indent(4) }}} } +is_old_bats=0 + setup() { - pushd "${BATS_TEST_TMPDIR}" + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 mkdir -p sssd_test } +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "bash_ensure_ini_config - Basic value remediation" { printf "[pam]\npam_cert_auth = false\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" diff --git a/tests/unit/bash/test_bash_replace_or_append.bats.jinja b/tests/unit/bash/test_bash_replace_or_append.bats.jinja index 856ab3efd23..9df981d4e9b 100644 --- a/tests/unit/bash/test_bash_replace_or_append.bats.jinja +++ b/tests/unit/bash/test_bash_replace_or_append.bats.jinja @@ -10,12 +10,45 @@ function call_bash_replace_or_append_w_format { {{{ bash_replace_or_append("$1", "$2", "$3", "$4") | indent(4) }}} } +is_old_bats=0 + setup() { - pushd "${BATS_TEST_TMPDIR}" + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 tmp_file=test.sh touch "$tmp_file" } +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "bash_replace_or_append - Basic value remediation" { printf "%s\n" "kernel.randomize_va_space = 5" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index db0d1c3b8d2..f989eb5ecb4 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -17,12 +17,45 @@ function call_set_config_file_rsyslog { create=true, separator=" ", separator_regex=" ") }}} } +is_old_bats=0 + setup() { - pushd "${BATS_TEST_TMPDIR}" + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 tmp_file=test.conf touch "$tmp_file" } +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "set_config_file - Basic value remediation" { printf "%s\n" "Compression yes" > "$tmp_file" expected_output="Compression no\n"