hwdb: fix screen rotation for EXO Wings 2in1 w1125 (#36283)
[systemd.io.git] / test / units / TEST-45-TIMEDATE.sh
blob420ebefd017d9b423e49c6102f1baa4ac62b84cd
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
4 set -eux
5 set -o pipefail
7 # shellcheck source=test/units/test-control.sh
8 . "$(dirname "$0")"/test-control.sh
9 # shellcheck source=test/units/util.sh
10 . "$(dirname "$0")"/util.sh
12 testcase_timedatectl() {
13 timedatectl --no-pager --help
14 timedatectl --version
16 timedatectl
17 timedatectl --no-ask-password
18 timedatectl status --machine=testuser@.host
19 timedatectl status
20 timedatectl show
21 timedatectl show --all
22 timedatectl show -p NTP
23 timedatectl show -p NTP --value
24 timedatectl list-timezones
26 if ! systemd-detect-virt -qc; then
27 systemctl enable --runtime --now systemd-timesyncd
28 timedatectl timesync-status
29 timedatectl show-timesync
33 restore_timezone() {
34 if [[ -f /tmp/timezone.bak ]]; then
35 mv /tmp/timezone.bak /etc/timezone
36 else
37 rm -f /etc/timezone
41 testcase_timezone() {
42 local ORIG_TZ=
44 # Debian/Ubuntu specific file
45 if [[ -f /etc/timezone ]]; then
46 mv /etc/timezone /tmp/timezone.bak
49 trap restore_timezone RETURN
51 if [[ -L /etc/localtime ]]; then
52 ORIG_TZ=$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')
53 echo "original tz: $ORIG_TZ"
56 echo 'timedatectl works'
57 assert_in "Local time:" "$(timedatectl --no-pager)"
59 echo 'change timezone'
60 assert_eq "$(timedatectl --no-pager set-timezone Europe/Kyiv 2>&1)" ""
61 assert_eq "$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')" "Europe/Kyiv"
62 if [[ -f /etc/timezone ]]; then
63 assert_eq "$(cat /etc/timezone)" "Europe/Kyiv"
65 assert_in "Time zone: Europe/Kyiv \(EES*T, \+0[0-9]00\)" "$(timedatectl)"
67 if [[ -n "$ORIG_TZ" ]]; then
68 echo 'reset timezone to original'
69 assert_eq "$(timedatectl set-timezone "$ORIG_TZ" 2>&1)" ""
70 assert_eq "$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')" "$ORIG_TZ"
71 if [[ -f /etc/timezone ]]; then
72 assert_eq "$(cat /etc/timezone)" "$ORIG_TZ"
77 restore_adjtime() {
78 if [[ -e /etc/adjtime.bak ]]; then
79 mv /etc/adjtime.bak /etc/adjtime
80 else
81 rm /etc/adjtime
85 check_adjtime_not_exist() {
86 if [[ -e /etc/adjtime ]]; then
87 echo "/etc/adjtime unexpectedly exists." >&2
88 exit 1
92 testcase_adjtime() {
93 # test setting UTC vs. LOCAL in /etc/adjtime
94 if [[ -e /etc/adjtime ]]; then
95 mv /etc/adjtime /etc/adjtime.bak
98 trap restore_adjtime RETURN
100 echo 'no adjtime file'
101 rm -f /etc/adjtime
102 timedatectl set-local-rtc 0
103 check_adjtime_not_exist
104 timedatectl set-local-rtc 1
105 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
107 LOCAL"
108 timedatectl set-local-rtc 0
109 check_adjtime_not_exist
111 echo 'UTC set in adjtime file'
112 printf '0.0 0 0\n0\nUTC\n' >/etc/adjtime
113 timedatectl set-local-rtc 0
114 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
116 UTC"
117 timedatectl set-local-rtc 1
118 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
120 LOCAL"
122 echo 'non-zero values in adjtime file'
123 printf '0.1 123 0\n0\nLOCAL\n' >/etc/adjtime
124 timedatectl set-local-rtc 0
125 assert_eq "$(cat /etc/adjtime)" "0.1 123 0
127 UTC"
128 timedatectl set-local-rtc 1
129 assert_eq "$(cat /etc/adjtime)" "0.1 123 0
131 LOCAL"
133 echo 'fourth line adjtime file'
134 printf '0.0 0 0\n0\nLOCAL\nsomethingelse\n' >/etc/adjtime
135 timedatectl set-local-rtc 0
136 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
139 somethingelse"
140 timedatectl set-local-rtc 1
141 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
143 LOCAL
144 somethingelse"
146 echo 'no final newline in adjtime file'
147 printf '0.0 0 0\n0\nUTC' >/etc/adjtime
148 timedatectl set-local-rtc 0
149 check_adjtime_not_exist
150 printf '0.0 0 0\n0\nUTC' >/etc/adjtime
151 timedatectl set-local-rtc 1
152 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
154 LOCAL"
156 echo 'only one line in adjtime file'
157 printf '0.0 0 0\n' >/etc/adjtime
158 timedatectl set-local-rtc 0
159 check_adjtime_not_exist
160 printf '0.0 0 0\n' >/etc/adjtime
161 timedatectl set-local-rtc 1
162 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
164 LOCAL"
166 echo 'only one line in adjtime file, no final newline'
167 printf '0.0 0 0' >/etc/adjtime
168 timedatectl set-local-rtc 0
169 check_adjtime_not_exist
170 printf '0.0 0 0' >/etc/adjtime
171 timedatectl set-local-rtc 1
172 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
174 LOCAL"
176 echo 'only two lines in adjtime file'
177 printf '0.0 0 0\n0\n' >/etc/adjtime
178 timedatectl set-local-rtc 0
179 check_adjtime_not_exist
180 printf '0.0 0 0\n0\n' >/etc/adjtime
181 timedatectl set-local-rtc 1
182 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
184 LOCAL"
186 echo 'only two lines in adjtime file, no final newline'
187 printf '0.0 0 0\n0' >/etc/adjtime
188 timedatectl set-local-rtc 0
189 check_adjtime_not_exist
190 printf '0.0 0 0\n0' >/etc/adjtime
191 timedatectl set-local-rtc 1
192 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
194 LOCAL"
196 echo 'unknown value in 3rd line of adjtime file'
197 printf '0.0 0 0\n0\nFOO\n' >/etc/adjtime
198 timedatectl set-local-rtc 0
199 check_adjtime_not_exist
200 printf '0.0 0 0\n0\nFOO\n' >/etc/adjtime
201 timedatectl set-local-rtc 1
202 assert_eq "$(cat /etc/adjtime)" "0.0 0 0
204 LOCAL"
207 assert_ntp() {
208 local value="${1:?}"
210 for _ in {0..9}; do
211 [[ "$(busctl get-property org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 NTP)" == "b $value" ]] && return 0
212 sleep .5
213 done
215 return 1
218 assert_timedated_signal() {
219 local timestamp="${1:?}"
220 local value="${2:?}"
221 local args=(-q -n 1 --since="$timestamp" -p info -t busctl)
223 journalctl --sync
225 for _ in {0..9}; do
226 if journalctl "${args[@]}" --grep .; then
227 [[ "$(journalctl "${args[@]}" -o cat | jq -r '.payload.data[1].NTP.data')" == "$value" ]];
228 return 0
231 sleep .5
232 done
234 return 1
237 assert_timesyncd_state() {
238 local state="${1:?}"
240 for _ in {0..9}; do
241 [[ "$(systemctl show systemd-timesyncd.service -P ActiveState)" == "$state" ]] && return 0
242 sleep .5
243 done
245 return 1
248 testcase_ntp() {
249 # timesyncd has ConditionVirtualization=!container by default; drop/mock that for testing
250 if systemd-detect-virt --container --quiet; then
251 systemctl disable --quiet --now systemd-timesyncd
252 mkdir -p /run/systemd/system/systemd-timesyncd.service.d
253 cat >/run/systemd/system/systemd-timesyncd.service.d/container.conf <<EOF
254 [Unit]
255 ConditionVirtualization=
257 [Service]
258 Type=simple
259 AmbientCapabilities=
260 ExecStart=
261 ExecStart=sleep infinity
263 systemctl daemon-reload
266 systemd-run --unit busctl-monitor.service --service-type=notify \
267 busctl monitor --json=short --match="type=signal,sender=org.freedesktop.timedate1,member=PropertiesChanged,path=/org/freedesktop/timedate1"
269 : 'Disable NTP'
270 ts="$(date +"%F %T.%6N")"
271 timedatectl set-ntp false
272 assert_timedated_signal "$ts" "false"
273 assert_timesyncd_state "inactive"
274 assert_ntp "false"
275 assert_rc 3 systemctl is-active --quiet systemd-timesyncd
277 : 'Enable NTP'
278 ts="$(date +"%F %T.%6N")"
279 timedatectl set-ntp true
280 assert_timedated_signal "$ts" "true"
281 assert_ntp "true"
282 assert_timesyncd_state "active"
283 assert_rc 0 systemctl is-active --quiet systemd-timesyncd
285 : 'Re-disable NTP'
286 ts="$(date +"%F %T.%6N")"
287 timedatectl set-ntp false
288 assert_timedated_signal "$ts" "false"
289 assert_ntp "false"
290 assert_rc 3 systemctl is-active --quiet systemd-timesyncd
292 systemctl stop busctl-monitor.service
293 rm -rf /run/systemd/system/systemd-timesyncd.service.d/
294 systemctl daemon-reload
297 assert_timesyncd_signal() {
298 local timestamp="${1:?}"
299 local property="${2:?}"
300 local value="${3:?}"
301 local args=(-q --since="$timestamp" -p info -t busctl)
303 journalctl --sync
305 for _ in {0..9}; do
306 if journalctl "${args[@]}" --grep .; then
307 [[ "$(journalctl "${args[@]}" -o cat | jq -r ".payload.data[1].$property.data | join(\" \")")" == "$value" ]];
308 return 0
311 sleep .5
312 done
314 return 1
317 assert_networkd_ntp() {
318 local interface="${1:?}"
319 local value="${2:?}"
320 # Go through the array of NTP servers and for each entry do:
321 # - if the entry is an IPv4 address, join the Address array into a dot separated string
322 # - if the entry is a server address, select it unchanged
323 # These steps produce an array of strings, that is then joined into a space-separated string
324 # Note: this doesn't support IPv6 addresses, since converting them to a string is a bit more
325 # involved than a simple join(), but let's leave that to another time
326 local expr='[.NTP[] | (select(.Family == 2).Address | join(".")), select(has("Server")).Server] | join(" ")'
328 [[ "$(networkctl status "$interface" --json=short | jq -r "$expr")" == "$value" ]]
331 testcase_timesyncd() {
332 if systemd-detect-virt -cq; then
333 echo "This test case requires a VM, skipping..."
334 return 0
337 if ! command -v networkctl >/dev/null; then
338 echo "This test requires systemd-networkd, skipping..."
339 return 0
342 # Create a dummy interface managed by networkd, so we can configure link NTP servers
343 mkdir -p /run/systemd/network/
344 cat >/etc/systemd/network/10-ntp99.netdev <<EOF
345 [NetDev]
346 Name=ntp99
347 Kind=dummy
349 cat >/etc/systemd/network/10-ntp99.network <<EOF
350 [Match]
351 Name=ntp99
353 [Network]
354 Address=10.0.0.1/24
357 systemctl unmask systemd-timesyncd systemd-networkd
358 systemctl restart systemd-timesyncd
359 systemctl restart systemd-networkd
360 networkctl status ntp99
362 systemd-run --unit busctl-monitor.service --service-type=notify \
363 busctl monitor --json=short --match="type=signal,sender=org.freedesktop.timesync1,member=PropertiesChanged,path=/org/freedesktop/timesync1"
365 # LinkNTPServers
367 # Single IP
368 ts="$(date +"%F %T.%6N")"
369 timedatectl ntp-servers ntp99 10.0.0.1
370 assert_networkd_ntp ntp99 10.0.0.1
371 assert_timesyncd_signal "$ts" LinkNTPServers 10.0.0.1
372 # Setting NTP servers to the same value shouldn't emit a PropertiesChanged signal
373 ts="$(date +"%F %T.%6N")"
374 timedatectl ntp-servers ntp99 10.0.0.1
375 assert_networkd_ntp ntp99 10.0.0.1
376 (! assert_timesyncd_signal "$ts" LinkNTPServers 10.0.0.1)
377 # Multiple IPs
378 ts="$(date +"%F %T.%6N")"
379 timedatectl ntp-servers ntp99 10.0.0.1 192.168.0.99
380 assert_networkd_ntp ntp99 "10.0.0.1 192.168.0.99"
381 assert_timesyncd_signal "$ts" LinkNTPServers "10.0.0.1 192.168.0.99"
382 # Multiple IPs + servers
383 ts="$(date +"%F %T.%6N")"
384 timedatectl ntp-servers ntp99 10.0.0.1 192.168.0.99 foo.localhost foo 10.11.12.13
385 assert_networkd_ntp ntp99 "10.0.0.1 192.168.0.99 foo.localhost foo 10.11.12.13"
386 assert_timesyncd_signal "$ts" LinkNTPServers "10.0.0.1 192.168.0.99 foo.localhost foo 10.11.12.13"
388 # RuntimeNTPServers
390 # There's no user-facing API that allows changing this property (afaik), so let's
391 # call SetRuntimeNTPServers() directly to test things out. The inner workings should
392 # be exactly the same as in the previous case, so do just one test to make sure
393 # things work
394 ts="$(date +"%F %T.%6N")"
395 busctl call org.freedesktop.timesync1 /org/freedesktop/timesync1 org.freedesktop.timesync1.Manager \
396 SetRuntimeNTPServers as 4 "10.0.0.1" foo "192.168.99.1" bar
397 servers="$(busctl get-property org.freedesktop.timesync1 /org/freedesktop/timesync1 org.freedesktop.timesync1.Manager RuntimeNTPServers)"
398 [[ "$servers" == 'as 4 "10.0.0.1" "foo" "192.168.99.1" "bar"' ]]
399 assert_timesyncd_signal "$ts" RuntimeNTPServers "10.0.0.1 foo 192.168.99.1 bar"
401 # Cleanup
402 systemctl stop systemd-networkd systemd-timesyncd
403 rm -f /run/systemd/network/ntp99.*
406 run_testcases
408 touch /testok