#- # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2025 Michal Scigocki # readonly SYSRC_CONF="${PWD}/sysrc_test.conf" atf_test_case check_variable check_variable_head() { atf_set "descr" "Check rc variable" } check_variable_body() { cat <<- EOF > "${SYSRC_CONF}" test_enable="NO" test_list="item1 item2" test2_list="" EOF atf_check -o inline:"test_enable: NO\n" \ sysrc -f "${SYSRC_CONF}" test_enable atf_check -o inline:"test2_list: \n" \ sysrc -f "${SYSRC_CONF}" test2_list atf_check -o inline:"test_enable: NO\ntest_list: item1 item2\n" \ sysrc -f "${SYSRC_CONF}" test_enable test_list atf_check -e inline:"sysrc: unknown variable 'noexist'\n" \ -s exit:1 sysrc -f "${SYSRC_CONF}" noexist atf_check -e inline:"sysrc: unknown variable 'noexist'\n" \ -s exit:1 -o inline:"test_enable: NO\n" \ sysrc -f "${SYSRC_CONF}" test_enable noexist } atf_test_case set_variable set_variable_head() { atf_set "descr" "Set rc variable" } set_variable_body() { # Previously unset variable atf_check -o inline:"test_enable: -> YES\n" \ sysrc -f "${SYSRC_CONF}" test_enable=YES atf_check -o inline:'test_enable="YES"\n' cat "${SYSRC_CONF}" # Change set variable atf_check -o inline:"test_enable: YES -> YES\n" \ sysrc -f "${SYSRC_CONF}" test_enable=YES atf_check -o inline:'test_enable="YES"\n' cat "${SYSRC_CONF}" atf_check -o inline:"test_enable: YES -> NO\n" \ sysrc -f "${SYSRC_CONF}" test_enable=NO atf_check -o inline:'test_enable="NO"\n' cat "${SYSRC_CONF}" # Set an empty variable atf_check -o inline:"test2_enable: -> \n" \ sysrc -f "${SYSRC_CONF}" test2_enable="" atf_check -o inline:'test_enable="NO"\ntest2_enable=""\n' \ cat "${SYSRC_CONF}" } atf_test_case remove_variable_x_flag remove_variable_x_flag_head() { atf_set "descr" "Remove rc variable (-x flag)" } remove_variable_x_flag_body() { cat <<- EOF > "${SYSRC_CONF}" test1_enable="YES" test2_enable="NO" test3_enable="" EOF atf_check sysrc -f "${SYSRC_CONF}" -x test1_enable atf_check -o inline:'test2_enable="NO"\ntest3_enable=""\n' \ cat "${SYSRC_CONF}" atf_check sysrc -f "${SYSRC_CONF}" -x test2_enable test3_enable atf_check -o empty cat "${SYSRC_CONF}" atf_check -e inline:"sysrc: unknown variable 'noexist'\n"\ -s exit:1 sysrc -f "${SYSRC_CONF}" -x noexist } atf_test_case append_list append_list_head() { atf_set "descr" "Append rc variable to list" } append_list_body() { atf_check -o inline:"test_list: -> item1\n" \ sysrc -f "${SYSRC_CONF}" test_list+=item1 atf_check -o inline:'test_list="item1"\n' cat "${SYSRC_CONF}" atf_check -o inline:"test_list: item1 -> item1\n" \ sysrc -f "${SYSRC_CONF}" test_list+=item1 atf_check -o inline:'test_list="item1"\n' cat "${SYSRC_CONF}" atf_check -o inline:"test_list: item1 -> item1 item2\n" \ sysrc -f "${SYSRC_CONF}" test_list+=item2 atf_check -o inline:'test_list="item1 item2"\n' \ cat "${SYSRC_CONF}" } atf_test_case subtract_list subtract_list_head() { atf_set "descr" "Subtract rc variable from list" } subtract_list_body() { echo 'test_list="item1 item2"' > "${SYSRC_CONF}" atf_check -o inline:"test_list: item1 item2 -> item1\n" \ sysrc -f "${SYSRC_CONF}" test_list-=item2 atf_check -o inline:'test_list="item1"\n' cat "${SYSRC_CONF}" atf_check -o inline:"test_list: item1 -> \n" \ sysrc -f "${SYSRC_CONF}" test_list-=item1 atf_check -o inline:'test_list=""\n' cat "${SYSRC_CONF}" atf_check -o inline:"test_list: -> \n" \ sysrc -f "${SYSRC_CONF}" test_list-=item3 atf_check -o inline:'test_list=""\n' cat "${SYSRC_CONF}" # Subtracting a non-existant rc variable results in an empty variable # being created. This is by design, see sysrc(8). atf_check -s exit:1 grep test2_list "${SYSRC_CONF}" atf_check -o inline:"test2_list: -> \n" \ sysrc -f "${SYSRC_CONF}" test2_list-=item1 atf_check -o inline:'test_list=""\ntest2_list=""\n' \ cat "${SYSRC_CONF}" } atf_test_case multiple_operations multiple_operations_head() { atf_set "descr" "Check performing multiple operations on rc variables" } multiple_operations_body() { atf_check -o inline:"test1_enable: -> YES\ntest1_list: -> item1\n" \ sysrc -f "${SYSRC_CONF}" test1_enable=YES test1_list+=item1 atf_check -o inline:'test1_enable="YES"\ntest1_list="item1"\n' \ cat "${SYSRC_CONF}" # The trailing space on line "^test1_list:" is necessary. cat <<- EOF > expected test1_enable: YES test1_enable: YES -> NO test2_enable: -> YES test1_list: item1 -> test2_list: -> item3 EOF atf_check -s exit:1 -e inline:"sysrc: unknown variable 'noexist'\n" \ -o file:expected sysrc -f "${SYSRC_CONF}" test1_enable \ test1_enable=NO noexist test2_enable=YES test1_list-=item1 \ test2_list+=item3 cat <<- EOF > expected test1_enable="NO" test1_list="" test2_enable="YES" test2_list="item3" EOF atf_check -o file:expected cat "${SYSRC_CONF}" } atf_test_case a_flag a_flag_head() { atf_set "descr" "Verify -a behavior" } a_flag_body() { echo 'test_enable="YES"' > "${SYSRC_CONF}" atf_check -o inline:"test_enable: YES\n" sysrc -f "${SYSRC_CONF}" -a } atf_test_case A_flag cleanup A_flag_head() { atf_set "descr" "Verify -A behavior" } A_flag_body() { RC_DEFAULTS="${PWD}/rc_defaults.conf" echo "rc_conf_files=\"${SYSRC_CONF}\"" > "${RC_DEFAULTS}" echo 'test_enable="NO"' >> "${RC_DEFAULTS}" echo 'test_enable="YES"' > "${SYSRC_CONF}" export RC_DEFAULTS # sysrc is coupled to the "source_rc_confs" sh(1) script function in # /etc/defaults/rc.conf. For this test we use a custom default # rc.conf file that is missing the "source_rc_confs" function, which # causes sysrc to print an error message. While the coupling exists, # we assume the error message is expected behaviour instead of just # ignoring the stderr output to make sure we don't ignore other error # messages in case of future regressions. atf_check -e inline:"/usr/sbin/sysrc: source_rc_confs: not found\n" \ -o inline:"rc_conf_files: ${SYSRC_CONF}\ntest_enable: NO\n" \ sysrc -A # Because "source_rc_confs" does not exist in our custom default # rc.conf file, we cannot get sysrc to load the other SYSRC_CONF file # to compare results. We can only verify that configuration variables # get read from the RC_DEFAULTS file. } A_flag_cleanup() { unset RC_DEFAULTS } atf_test_case c_flag c_flag_head() { atf_set "descr" "Verify -c behavior" } c_flag_body() { echo 'test_enable="NO"' > "${SYSRC_CONF}" echo 'test_list="item1 item2"' >> "${SYSRC_CONF}" # Test if rc variable is set atf_check sysrc -f "${SYSRC_CONF}" -c test_enable atf_check sysrc -f "${SYSRC_CONF}" -c test_list atf_check sysrc -f "${SYSRC_CONF}" -c test_enable test_list atf_check -e inline:"sysrc: unknown variable 'noexist'\n"\ -s exit:1 sysrc -f "${SYSRC_CONF}" -c noexist atf_check -e inline:"sysrc: unknown variable 'noexist'\n"\ -s exit:1 sysrc -f "${SYSRC_CONF}" -c test_enable noexist cat <<- EOF > expected_err sysrc: unknown variable 'noexist1' sysrc: unknown variable 'noexist2' EOF atf_check -e file:expected_err -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c noexist1 noexist2 # Test rc variable assignment atf_check sysrc -f "${SYSRC_CONF}" -c test_enable=NO atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c test_enable=YES atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c noexist=YES # Test appending rc variables atf_check sysrc -f "${SYSRC_CONF}" -c test_list+=item1 atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c test_list+=item3 atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c noexist+=item1 atf_check sysrc -f "${SYSRC_CONF}" -c test_enable=NO test_list+=item1 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=YES test_list+=item1 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=NO test_list+=item3 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=YES test_list+=item3 # Test subracting rc variables atf_check sysrc -f "${SYSRC_CONF}" -c test_list-=item3 atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c test_list-=item1 atf_check -s exit:1 sysrc -f "${SYSRC_CONF}" -c noexist-=item1 atf_check sysrc -f "${SYSRC_CONF}" -c test_enable=NO test_list-=item3 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=YES test_list-=item3 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=NO test_list-=item1 atf_check -s exit:1 \ sysrc -f "${SYSRC_CONF}" -c test_enable=YES test_list-=item1 } atf_test_case d_flag cleanup d_flag_head() { atf_set "descr" "Verify -f behavior" } d_flag_body() { echo 'test_enable="NO" # Test Description' > "${SYSRC_CONF}" export RC_DEFAULTS="${SYSRC_CONF}" atf_check -o inline:'test_enable: Test Description\n' \ sysrc -d test_enable } d_flag_cleanup() { unset RC_DEFAULTS } atf_test_case f_flag f_flag_head() { atf_set "descr" "Verify -f behavior" } f_flag_body() { local sysrc2_conf="${PWD}/sysrc2.conf" echo 'test_list="item1"' > "${sysrc2_conf}" echo 'test_enable="NO"' >> "${sysrc2_conf}" atf_check test ! -f "${SYSRC_CONF}" atf_check -e inline:"sysrc: unknown variable 'noexist'\n" \ -s exit:1 sysrc -f "${SYSRC_CONF}" noexist atf_check test ! -f "${SYSRC_CONF}" atf_check -o inline:"test_enable: -> YES\n" \ sysrc -f "${SYSRC_CONF}" test_enable=YES atf_check test -f "${SYSRC_CONF}" atf_check -o inline:"test_enable: YES\n" \ sysrc -f "${SYSRC_CONF}" test_enable # -f file order impacts final settings atf_check -o inline:"test_enable: YES\n" \ sysrc -f "${sysrc2_conf}" -f "${SYSRC_CONF}" test_enable atf_check -o inline:"test_enable: NO\n" \ sysrc -f "${SYSRC_CONF}" -f "${sysrc2_conf}" test_enable atf_check -o inline:"test_enable: YES\ntest_list: item1\n" \ sysrc -f "${sysrc2_conf}" -f "${SYSRC_CONF}" -a } atf_test_case F_flag F_flag_head() { atf_set "descr" "Verify -F behavior" } F_flag_body() { local sysrc2_conf="${PWD}/sysrc2.conf" echo 'test_list="item1"' > "${sysrc2_conf}" echo 'test_enable="NO"' > "${SYSRC_CONF}" atf_check -o inline:"test_enable: ${SYSRC_CONF}\n" \ sysrc -f "${SYSRC_CONF}" -F test_enable atf_check -o inline:"test_list: ${sysrc2_conf}\n" \ sysrc -f "${sysrc2_conf}" -F test_list cat <<- EOF > expected test_enable: ${SYSRC_CONF} test_list: ${sysrc2_conf} EOF atf_check -o file:expected sysrc -f "${SYSRC_CONF}" \ -f ${sysrc2_conf} -F test_enable test_list } atf_init_test_cases() { atf_add_test_case check_variable atf_add_test_case set_variable atf_add_test_case remove_variable_x_flag atf_add_test_case append_list atf_add_test_case subtract_list atf_add_test_case multiple_operations atf_add_test_case a_flag atf_add_test_case A_flag atf_add_test_case c_flag atf_add_test_case d_flag atf_add_test_case f_flag atf_add_test_case F_flag }