#!/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


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

assert_ney() {  # file k testname
	val="$(grep "^$2=" "$1")" && { err=1; echo "$4: $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

	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'                                      \
	              '1 * * * mon-wed dummy echo dev null > /dev/null'           \
	              '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='                                                       > /etc/crontab

	"$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-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
}


{
	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 '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
