#!/bin/sh
# expects to run as root of a mountns
S_C_G="${S_C_G:-"$PWD/out/build/bin/systemd-crontab-generator"}"
TESTDIR="$PWD/test/"
PATH="/usr/bin:$PATH"

USE_RUN_PARTS="${1:-no}"
echo "USE_RUN_PARTS: $USE_RUN_PARTS"

mount -t tmpfs tmpfs /etc || exit
STATEDIR="${2:-"/var/spool/cron"}"
if [ -d "$STATEDIR" ]; then
	mount -t tmpfs tmpfs "$STATEDIR" || exit
fi


err=0
assert_key() {  # file k v testname
	val="$(grep "^$2=" "$1")"
	[ "${val#"$2="}" = "$3" ] || { err=1; echo "$4: $1: $val != $3" >&2; }
}

assert_ney() {  # file k testname
	val="$(grep "^$2=" "$1")" && { err=1; echo "$3: $1: $val exists" >&2; }
}

assert_dat() {  # file content testname
	printf '%s\n' "$2" | cmp -s - "$1" || { err=1; echo "$3: $(cat "$1") != $2" >&2; }
}

{
	echo 'dummy:x:12:34:dummy:/home/dummy:/bin/sh' > /etc/passwd

	mkdir /etc/cron.d
	printf '%s\n' '# test_path_expansion, test_period_basic'                  \
	              '@daily dummy true'                                         \
	                                                                          \
	              '# test_userpath_expansion'                                 \
	              '@daily dummy ~/fake'                                       \
	                                                                          \
	              '# test_timespec_basic'                                     \
	              '5 6 * * * dummy true'                                      \
	                                                                          \
	              '# test_timespec_slice'                                     \
	              '*/5 * * * * dummy true'                                    \
	                                                                          \
	              '# test_timespec_range'                                     \
	              '1 * * * mon-wed dummy true'                                \
	                                                                          \
	              '# test_substitutions'                                      \
	              'BATCH=1'                                                   \
	              '1 * * * mon-wed dummy echo dev null > /dev/null'           \
	              'BATCH=0'                                                   \
	              '1 * * * mon-wed dummy echo devnull  >/dev/null'            \
	                                                                          \
	              '# test_tz'                                                 \
	              'TZ=Europe/Warsaw'                                          \
	              '1 * * * mon-wed dummy echo in zoneinfo'                    \
	              'TZ=UTC0'                                                   \
	              '1 * * * mon-wed dummy echo valid $TZ, but not in zoneinfo' \
	              'TZ='                                                       \
	                                                                          \
	              '# test_cron_mail_success'                                  \
	              'CRON_MAIL_SUCCESS=always'                                  \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=yes'                                     \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=true'                                    \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=1'                                       \
	              '* * * * * dummy :'                                         \
	                                                                          \
	              'CRON_MAIL_SUCCESS=never'                                   \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=no'                                      \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=false'                                   \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=0'                                       \
	              '* * * * * dummy :'                                         \
	                                                                          \
	              'CRON_MAIL_SUCCESS=inherit'                                 \
	              '* * * * * dummy :'                                         \
	                                                                          \
	              'CRON_MAIL_SUCCESS=nonempty'                                \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_SUCCESS=non-empty'                               \
	              '* * * * * dummy :'                                         \
	                                                                          \
	              '# test_cron_mail_format'                                   \
	              'CRON_MAIL_FORMAT=normal'                                   \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_FORMAT=nometadata'                               \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_FORMAT=inherit'                                  \
	              '* * * * * dummy :'                                         \
	              'CRON_MAIL_FORMAT=no-metadata'                              \
	              '* * * * * dummy :'                                         > /etc/crontab
	printf '%s\n' '# test_MAIL_inherit_default'                               \
	              '* * * * * dummy !'                                         \
	              '# test_MAIL_inherit_partial'                               \
	              'CRON_MAIL_SUCCESS=never'                                   \
	              '* * * * * dummy !'                                         \
	              '# test_MAIL_inherit_explicit'                              \
	              'CRON_MAIL_SUCCESS=inherit'                                 \
	              '* * * * * dummy !'                                         > /etc/cron.d/crondtab


	"$S_C_G" /etc/out
	cd /etc/out || exit

	assert_key cron-crontab-dummy-24edba7d1c50729bdba1f91f44e293f9.service 'ExecStart'  '/usr/bin/true' test_path_expansion
	assert_key cron-crontab-dummy-24edba7d1c50729bdba1f91f44e293f9.timer   'OnCalendar' 'daily'         test_period_basic

	assert_key cron-crontab-dummy-00e11d1caaf3c28c9ca5766d8483ae83.service 'ExecStart'        '/bin/sh /etc/out/cron-crontab-dummy-00e11d1caaf3c28c9ca5766d8483ae83.sh' test_userpath_expansion
	assert_dat cron-crontab-dummy-00e11d1caaf3c28c9ca5766d8483ae83.sh      '/home/dummy/fake'                                                                           test_userpath_expansion

	assert_key cron-crontab-dummy-0.timer   'OnCalendar' '*-*-* 6:5:00'                                 test_timespec_basic
	assert_key cron-crontab-dummy-1.timer   'OnCalendar' '*-*-* *:0,5,10,15,20,25,30,35,40,45,50,55:00' test_timespec_slice
	assert_key cron-crontab-dummy-2.timer   'OnCalendar' 'Mon,Tue,Wed *-*-* *:1:00'                     test_timespec_range

	assert_dat cron-crontab-dummy-3.sh      '/usr/bin/echo dev null' test_substitutions
	assert_dat cron-crontab-dummy-4.sh      '/usr/bin/echo devnull'  test_substitutions
	assert_key cron-crontab-dummy-3.service 'CPUSchedulingPolicy' 'idle' test_substitutions_BATCH
	assert_ney cron-crontab-dummy-4.service 'CPUSchedulingPolicy'        test_substitutions_BATCH

	assert_key cron-crontab-dummy-5.timer   'OnCalendar' 'Mon,Tue,Wed *-*-* *:1:00 Europe/Warsaw'       test_tz  # systemd accepts zones it finds in the zoneinfo file, but only by exact match
	assert_key cron-crontab-dummy-6.timer   'OnCalendar' 'Mon,Tue,Wed *-*-* *:1:00'                     test_tz  # TZ=UTC0 is valid (as is TZ=UTC2), but systemd doesn't accept it as a suffix

	assert_key cron-crontab-dummy-6.service  'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d6\x20nonempty.service'  test_cron_mail_success_default
	assert_key cron-crontab-dummy-6.service  'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d6.service'              test_cron_mail_success_default
	assert_key cron-crontab-dummy-7.service  'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d7.service'              test_cron_mail_success=always
	assert_key cron-crontab-dummy-7.service  'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d7.service'              test_cron_mail_success=always
	assert_key cron-crontab-dummy-8.service  'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d8.service'              test_cron_mail_success=yes
	assert_key cron-crontab-dummy-8.service  'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d8.service'              test_cron_mail_success=yes
	assert_key cron-crontab-dummy-9.service  'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d9.service'              test_cron_mail_success=true
	assert_key cron-crontab-dummy-9.service  'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d9.service'              test_cron_mail_success=true
	assert_key cron-crontab-dummy-10.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d10.service'             test_cron_mail_success=1
	assert_key cron-crontab-dummy-10.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d10.service'             test_cron_mail_success=1
	assert_ney cron-crontab-dummy-11.service 'OnSuccess'                                                                test_cron_mail_success=never
	assert_key cron-crontab-dummy-11.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d11.service'             test_cron_mail_success=never
	assert_ney cron-crontab-dummy-12.service 'OnSuccess'                                                                test_cron_mail_success=no
	assert_key cron-crontab-dummy-12.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d12.service'             test_cron_mail_success=no
	assert_ney cron-crontab-dummy-13.service 'OnSuccess'                                                                test_cron_mail_success=false
	assert_key cron-crontab-dummy-13.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d13.service'             test_cron_mail_success=false
	assert_ney cron-crontab-dummy-14.service 'OnSuccess'                                                                test_cron_mail_success=0
	assert_key cron-crontab-dummy-14.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d14.service'             test_cron_mail_success=0
	assert_key cron-crontab-dummy-15.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d15\x20nonempty.service' test_cron_mail_success=inherit  # same as default at toplevel
	assert_key cron-crontab-dummy-15.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d15.service'             test_cron_mail_success=inherit
	assert_key cron-crontab-dummy-16.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d16\x20nonempty.service' test_cron_mail_success=nonempty
	assert_key cron-crontab-dummy-16.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d16.service'             test_cron_mail_success=nonempty
	assert_key cron-crontab-dummy-17.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d17\x20nonempty.service' test_cron_mail_success=non-empty
	assert_key cron-crontab-dummy-17.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d17.service'             test_cron_mail_success=non-empty
	assert_key cron-crontab-dummy-18.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d18\x20nonempty.service'               test_cron_mail_format=normal
	assert_key cron-crontab-dummy-18.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d18.service'                           test_cron_mail_format=normal
	assert_key cron-crontab-dummy-19.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d19\x20nonempty\x20nometadata.service' test_cron_mail_format=nometadata
	assert_key cron-crontab-dummy-19.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d19\x20nometadata.service'             test_cron_mail_format=nometadata
	assert_key cron-crontab-dummy-20.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d20\x20nonempty.service'               test_cron_mail_format=inherit  # same as default at toplevel
	assert_key cron-crontab-dummy-20.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d20.service'                           test_cron_mail_format=inherit
	assert_key cron-crontab-dummy-21.service 'OnSuccess' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d21\x20nonempty\x20nometadata.service' test_cron_mail_format=no-metadata
	assert_key cron-crontab-dummy-21.service 'OnFailure' 'cron-mail@cron\x2dcrontab\x2ddummy\x2d21\x20nometadata.service'             test_cron_mail_format=no-metadata

	assert_key cron-crondtab-dummy-0.service 'OnSuccess' 'cron-mail@cron\x2dcrondtab\x2ddummy\x2d0\x20nonempty\x20nometadata.service' test_MAIL_inherit_default
	assert_key cron-crondtab-dummy-0.service 'OnFailure' 'cron-mail@cron\x2dcrondtab\x2ddummy\x2d0\x20nometadata.service'             test_MAIL_inherit_default
	assert_ney cron-crondtab-dummy-1.service 'OnSuccess'                                                                              test_MAIL_inherit_partial
	assert_key cron-crondtab-dummy-1.service 'OnFailure' 'cron-mail@cron\x2dcrondtab\x2ddummy\x2d1\x20nometadata.service'             test_MAIL_inherit_partial
	assert_key cron-crondtab-dummy-2.service 'OnSuccess' 'cron-mail@cron\x2dcrondtab\x2ddummy\x2d2\x20nonempty\x20nometadata.service' test_MAIL_inherit_explicit
	assert_key cron-crondtab-dummy-2.service 'OnFailure' 'cron-mail@cron\x2dcrondtab\x2ddummy\x2d2\x20nometadata.service'             test_MAIL_inherit_explicit
}


{
	rm -r /etc/cron.d
	printf '%s\n' 'root:x:0:0:root:/root:/bin/sh' 'eroot:x:0:0:root:/root:/bin/ed' > /etc/passwd
	cp "${TESTDIR}crontab" /etc
	mkdir /etc/cron.daily
	echo id > /etc/cron.daily/id

	"$S_C_G" /etc/out2
	cd /etc/out2 || exit

	assert_key cron-crontab-henry-0.service 'User'              'henry'                                           henry-unknown-user
	assert_key cron-crontab-henry-0.service 'Requires'          'systemd-user-sessions.service'                   henry-unknown-user
	assert_ney cron-crontab-henry-0.service 'RequiresMountsFor'                                                   henry-unknown-user
	assert_key cron-crontab-henry-0.service 'OnFailure'         'cron-mail@cron\x2dcrontab\x2dhenry\x2d0.service' onfailure_escaped
	assert_key cron-crontab-henry-0.service 'Description'       '[Cron] "1 2 3 4 5 henry echo 0=Vasárnap 1=Hétfő 2=Kedd 3=Szerda 4=Csütörtök 5=Péntek 6=Szombat"' henry-the-hungarian

	assert_key cron-crontab-henry-0.timer   'OnCalendar'       'Fri *-4-3 2:1:00'              henry\'s-calendar

	assert_dat cron-crontab-henry-0.sh      '/usr/bin/echo 0=Vasárnap 1=Hétfő 2=Kedd 3=Szerda 4=Csütörtök 5=Péntek 6=Szombat' henry\'s-hungarian-program
}
test_test_crontab_common() {
	assert_key cron-crontab-root-0.service  'User'              'root'                                          root-special
	assert_ney cron-crontab-root-0.service  'Requires'                                                          root-special
	assert_ney cron-crontab-root-0.service  'RequiresMountsFor'                                                 root-special
	assert_key cron-crontab-root-0.timer    'OnCalendar'        '*-*-* *:0,5,10,15,20,25,30,35,40,45,50,55:00'  root-slashed-calendar
	assert_key cron-crontab-root-0.service  'ExecStart'         '/usr/bin/true'                                 root-truexec


	assert_key cron-crontab-eroot-0.service 'User'              'eroot'                                         eroot-known-user
	assert_key cron-crontab-eroot-0.service 'Requires'          'systemd-user-sessions.service'                 eroot-known-user
	assert_key cron-crontab-eroot-0.service 'RequiresMountsFor' '/root'                                         eroot-known-user
	assert_key cron-crontab-eroot-0.timer   'OnCalendar'        'Mon,Tue,Wed,Thu,Fri *-*-* 0:0:00'              eroot-mon-fri-\ \ -00

	assert_key cron-crontab-root-1.timer    'Description'       '[Timer] "00  0 * * 0-3 root echo test US mode"' root-US-mode-timer
	assert_key cron-crontab-root-1.timer    'OnCalendar'        'Sun,Mon,Tue,Wed *-*-* 0:0:00'                   root-US-mode-timer
	assert_key cron-crontab-root-2.timer    'Description'       '[Timer] "0 0 * * 4-7 root echo test EU mode"'   root-EU-mode-timer
	assert_key cron-crontab-root-2.timer    'OnCalendar'        'Thu,Fri,Sat,Sun *-*-* 0:0:00'                   root-EU-mode-timer

	assert_key cron-crontab-root-79873eb1181afcc4e7f8c0cde4c8bd1a.timer 'Description' '[Timer] "@daily root ls"' root-@daily
	assert_key cron-crontab-root-79873eb1181afcc4e7f8c0cde4c8bd1a.timer 'OnCalendar'  '*-*-* 3:0:0'              root-@daily
	assert_key cron-crontab-root-79873eb1181afcc4e7f8c0cde4c8bd1a.timer 'Persistent'  'true'                     root-@daily

if [ "$USE_RUN_PARTS" = 'no' ]
then
	assert_key cron-daily-id.service  'Description'       '[Cron] "/etc/cron.daily/id"'              /etc/cron.daily
	assert_key cron-daily-id.service  'ExecStartPre'      '-/usr/libexec/systemd-cron/boot_delay 10' /etc/cron.daily    # hourly.daily = 2nd, *5min for each longer one
	assert_key cron-daily-id.service  'ExecStart'         '/etc/cron.daily/id'                       /etc/cron.daily
	assert_key cron-daily-id.timer    'OnCalendar'        '*-*-* 5:10:0'                             /etc/cron.daily
	assert_key cron-daily-id.timer    'Persistent'        'true'                                     /etc/cron.daily
fi
}
test_test_crontab_common

{
	iconv() { command iconv -f utf-8 -t iso-8859-2; }
	iconv < "${TESTDIR}crontab" > /etc/crontab

	"$S_C_G" /etc/out3
	cd /etc/out3 || exit

	# All the same except Description (escaped) and program (not escaped)
	assert_key cron-crontab-henry-0.service 'User'             'henry'                         henry-unknown-user-iconv
	assert_key cron-crontab-henry-0.service 'Requires'         'systemd-user-sessions.service' henry-unknown-user-iconv
	assert_ney cron-crontab-henry-0.service 'RequiresMountsFor'                                henry-unknown-user-iconv
	assert_key cron-crontab-henry-0.service 'Description'      '[Cron] "1 2 3 4 5 henry echo 0=Vas\xe1rnap 1=H\xe9tf\xf5 2=Kedd 3=Szerda 4=Cs\xfct\xf6rt\xf6k 5=P\xe9ntek 6=Szombat"' henry-the-hungarian-iconv

	assert_key cron-crontab-henry-0.timer   'OnCalendar'       'Fri *-4-3 2:1:00'              henry\'s-calendar-iconv

	assert_dat cron-crontab-henry-0.sh      "$(echo '/usr/bin/echo 0=Vasárnap 1=Hétfő 2=Kedd 3=Szerda 4=Csütörtök 5=Péntek 6=Szombat' | iconv)" henry\'s-hungarian-program-iconv
}
test_test_crontab_common

exit $err
