aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/status/test-statusctl.sh
blob: 38da27cd2ac401a8a01fa3058fdc5beaf708dcd2 (plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/bin/bash
#
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# The one runnable check for statusctl. It points XDG_RUNTIME_DIR at a
# temporary directory, so nothing here touches the live modes.
#
# Usage: ./test-statusctl.sh   (exit 0 = all passed)

set -u

here="$(cd "$(dirname "$0")" && pwd)"
ctl="$here/statusctl"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
export XDG_RUNTIME_DIR="$tmp"

pass=0
fail=0

check() {
    local label="$1" want="$2" got="$3"
    if [[ "$want" == "$got" ]]; then
        printf 'ok   %s\n' "$label"
        pass=$((pass + 1))
    else
        printf 'FAIL %s: want %q, got %q\n' "$label" "$want" "$got"
        fail=$((fail + 1))
    fi
}

# A mode with no file reads as off.
check "missing file reads 0" "0" "$("$ctl" dnd get)"

# set writes the file and get reads it back.
"$ctl" dnd set 1
check "set 1 writes the file" "1" "$(cat "$tmp/status.dnd" | tr -d '[:space:]')"
check "get after set 1" "1" "$("$ctl" dnd get)"

# toggle flips it.
"$ctl" dnd toggle
check "toggle from 1" "0" "$("$ctl" dnd get)"
"$ctl" dnd toggle
check "toggle from 0" "1" "$("$ctl" dnd get)"

# set 0 writes rather than removing, so a reader sees an explicit off.
"$ctl" dnd set 0
check "set 0 writes the file" "0" "$("$ctl" dnd get)"

# nolock is a mode like any other: the mechanism is generic, this only pins
# that the name is accepted by the mode list.
"$ctl" nolock set 1
check "nolock set 1" "1" "$("$ctl" nolock get)"
"$ctl" nolock toggle
check "nolock toggle" "0" "$("$ctl" nolock get)"

# An unknown mode is an error, not a silent success: a typo must not look
# like a mode that is off.
"$ctl" nosuch get >/dev/null 2>&1
check "unknown mode exits non-zero" "1" "$?"

# watch prints a line on change, and the class reflects the value. The
# atomic write arrives as a rename, which is why the watch needs moved_to.
out="$tmp/watch.out"
"$ctl" presentation watch > "$out" 2>/dev/null &
watcher=$!
sleep 0.3
"$ctl" presentation set 1
sleep 0.5
kill "$watcher" 2>/dev/null
wait "$watcher" 2>/dev/null
check "watch reports activated" "1" "$(grep -c '"class": *"activated"' "$out")"

# A missing file is the off state, so the absent-file watch reports off rather
# than a distinct warning: a fresh session has no file until something writes
# one, and that is the normal state.
rm -f "$tmp/status.presentation"
out2="$tmp/watch2.out"
"$ctl" presentation watch > "$out2" 2>/dev/null &
watcher2=$!
sleep 0.5
kill "$watcher2" 2>/dev/null
wait "$watcher2" 2>/dev/null
check "watch reports deactivated when absent" "1" "$(grep -c '"class": *"deactivated"' "$out2")"

# A running game is reported as its own state, not as plain activated: the
# widget draws a different icon and the tooltip says why the mode is on.
rm -f "$tmp/status.presentation"
printf '1\n' > "$tmp/status.gaming"
out3="$tmp/watch3.out"
"$ctl" presentation watch > "$out3" 2>/dev/null &
watcher3=$!
sleep 0.5
kill "$watcher3" 2>/dev/null
wait "$watcher3" 2>/dev/null
check "watch reports gaming" "1" "$(grep -c '"class": *"gaming"' "$out3")"

# The gaming file is the shell's, so presentation's own file stays off and
# `get` keeps reporting the manual half rather than the OR.
check "get reads the manual half" "0" "$("$ctl" presentation get)"

# Toggling while a game runs is refused: the detector would reassert it, so a
# write here would not stick.
"$ctl" presentation toggle 2>/dev/null
check "toggle refused while gaming" "1" "$?"
check "toggle wrote nothing" "0" "$("$ctl" presentation get)"

# The refusal is specific to presentation; another mode toggles normally with
# a game running.
"$ctl" dnd set 0
"$ctl" dnd toggle
check "dnd toggles while gaming" "1" "$("$ctl" dnd get)"

# A game ending redraws the widget, which is why the watch follows
# status.gaming as well as its own file.
out4="$tmp/watch4.out"
"$ctl" presentation watch > "$out4" 2>/dev/null &
watcher4=$!
sleep 0.3
printf '0\n' > "$tmp/status.gaming.tmp"
mv -f "$tmp/status.gaming.tmp" "$tmp/status.gaming"
sleep 0.5
kill "$watcher4" 2>/dev/null
wait "$watcher4" 2>/dev/null
check "game ending redraws" "1" "$(grep -c '"class": *"deactivated"' "$out4")"

printf '\n%d passed, %d failed\n' "$pass" "$fail"
[[ "$fail" -eq 0 ]]