File: TEST-53-TIMER.RandomizedDelaySec-persistent.sh

package info (click to toggle)
systemd 259.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 113,388 kB
  • sloc: ansic: 727,211; xml: 121,125; python: 36,732; sh: 34,990; cpp: 946; makefile: 278; awk: 102; lisp: 13; sed: 1
file content (67 lines) | stat: -rwxr-xr-x 2,676 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Persistent timers (i.e. timers with Persitent=yes) save their last trigger timestamp to a persistent
# storage (a stamp file), which is loaded during subsequent boots. As mentioned in the man page, such timers
# should be still affected by RandomizedDelaySec= during boot even if they already elapsed and would be then
# triggered immediately.
#
# This behavior was, however, broken by [0], which stopped rebasing the to-be next elapse timestamps
# unconditionally and left that only for timers that have neither last trigger nor inactive exit timestamps
# set, since rebasing is needed only during boot. This holds for regular timers during boot, but not for
# persistent ones, since the last trigger timestamp is loaded from a persistent storage.
#
# Provides coverage for:
#   - https://github.com/systemd/systemd/issues/39739
#
# [0] bdb8e584f4509de0daebbe2357d23156160c3a90
#
set -eux
set -o pipefail

# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/util.sh

UNIT_NAME="timer-RandomizedDelaySec-persistent-$RANDOM"
STAMP_FILE="/var/lib/systemd/timers/stamp-$UNIT_NAME.timer"

# Setup
cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=12h
EOF

cat >"/run/systemd/system/$UNIT_NAME.service" <<\EOF
[Service]
ExecStart=echo "Service ran at $(date)"
EOF

systemctl daemon-reload

# Create timer's state file with an old-enough timestamp (~2 days ago), so it'd definitely elapse if the next
# elapse timestamp wouldn't get rebased
mkdir -p "$(dirname "$STAMP_FILE")"
touch -d "2 days ago" "$STAMP_FILE"
stat "$STAMP_FILE"
SAVED_LAST_TRIGGER_S="$(stat --format="%Y" "$STAMP_FILE")"

# Start the timer and verify that its last trigger timestamp didn't change
#
# The last trigger timestamp should get rebased before it gets used as a base for the next elapse timestamp
# (since it pre-dates the machine boot time). This should then add a RandomizedDelaySec= to the rebased
# timestamp and the timer unit should not get triggered immediately after starting.
systemctl start "$UNIT_NAME.timer"
systemctl status "$UNIT_NAME.timer"

TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec --value "$UNIT_NAME.timer")"
TIMER_LAST_TRIGGER_S="$(date --date="$TIMER_LAST_TRIGGER" "+%s")"
: "The timer should not be triggered immediately, hence the last trigger timestamp should not change"
assert_eq "$SAVED_LAST_TRIGGER_S" "$TIMER_LAST_TRIGGER_S"

# Cleanup
systemctl stop "$UNIT_NAME".{timer,service}
systemctl clean --what=state "$UNIT_NAME.timer"
rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
systemctl daemon-reload