Compare commits

..
105 Commits
Author SHA1 Message Date
theupriser 737882c213 test: unit tests of steam-shortcuts.py and steamify-notifier.py
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-03 13:18:15 +02:00
theupriser 0e63b931ea test: the helpers read Steamify's lib list from steamify.sh instead of their own copy 2026-10-03 12:53:40 +02:00
theupriser 3bcbdf3d98 test: menu-test.sh, a golden-output test of the menu rules, the plan and the app's JSON (REPO points at the checkout) 2026-10-03 11:19:01 +02:00
theupriser 9dbf05ab9c docs: steamify-branch-cleanup: a released release/X.Y.Z branch is deleted once a tag or main contains it 2026-10-02 14:41:40 +02:00
theupriser 86a44d7e68 docs: CHANGELOG 0.5.0: the full test run, the ISO pipeline, tests moved here, the 2.11.0 test results 2026-10-02 14:06:35 +02:00
theupriser d540dd2310 test: vmstate reports Steam's autostart entry (silent/plain/none) instead of the old unit 2026-10-02 09:28:05 +02:00
theupriser f7625f5882 test: the Steamify unit tests and the NVIDIA hardware test move here from steamify-cachyos (REPO points at the checkout) 2026-10-02 07:53:25 +02:00
theupriser b4d6c23129 notes: Steamify 2.10.0 2026-10-01 21:05:27 +02:00
theupriser 7a313a96ee tests: nvidia suite (fake NVIDIA PC), controller block, name-based menu rows; get-iso.sh uses CachyOS's own mirror and resumes; notes 2026-10-01 21:03:20 +02:00
theupriser 9e8e05e99b nvidia: Plasma session with Big Picture autostart works 2026-10-01 18:33:24 +02:00
theupriser b95ccb686d nvidia: TTY-only KWin stutters, Big Picture in Plasma is perfect 2026-10-01 18:26:25 +02:00
theupriser dabc43ded6 nvidia: direct scanout confirmed as the cause, a Plasma-less KWin session works 2026-10-01 18:11:32 +02:00
theupriser a253ff15cd nvidia: results of the hardware test on the RTX 5080 PC 2026-10-01 18:02:17 +02:00
theupriser c8a6a2cef5 docs: nvidia/: TODO, research and test instructions for the NVIDIA fix (moved here from the steamify-cachyos branch); AGENTS.md: feature notes live in this repo 2026-10-01 15:38:51 +02:00
theupriser 1aff67612d docs: the ISO repo's PRs and vmisobuild.sh target master (feat/steamify is gone) 2026-10-01 15:36:34 +02:00
theupriser b2fc992745 feat: vmtest.sh runs the plain-PC install check (generic) for every loader; vmprogress.sh knows the new jobs 2026-09-30 14:47:40 +02:00
theupriser 90fe42da5f docs: TESTPLAN results: the official 2.9.6 ISO, 341 pass, 0 fail 2026-09-30 14:45:20 +02:00
theupriser 5146dd1109 fix: the waitssh comment broke the one-line function (syntax error) 2026-09-30 14:38:34 +02:00
theupriser b840eb3697 fix: vmbootloadertest.sh waits up to 15 minutes for the first ssh (a first boot is slow with five VMs at once) 2026-09-30 14:38:19 +02:00
theupriser 5ea436efc5 docs: MAX_PARALLEL=5 ran fine on the 9800X3D (TODO R2 done, comments) 2026-09-30 13:47:52 +02:00
theupriser f33d3bf491 docs: TODO: CI tests dropped (they run locally), the quick install test, new open items 2026-09-30 13:46:43 +02:00
theupriser 32db035e9b docs: the steamify-iso-release skill: dispatch-started build, steamify_ref, build badge and its secrets, replaced tags, parallel jobs on the runner 2026-09-30 13:04:08 +02:00
theupriser cfba222439 docs: the steamify-iso-release skill: daily names, kind input, replacement and retention, sync by workflow, always master 2026-09-30 11:37:14 +02:00
theupriser 76b162d7e1 feat: show progress while the tests run (install and steamify.sh heartbeats, unbuffered output) 2026-09-30 10:51:24 +02:00
theupriser da263529e9 fix: vminstall.sh is headless in CI (no display for QEMU's GTK window) 2026-09-30 10:30:01 +02:00
theupriser f604e10b3e feat: vmbootloadertest.sh --quick [--generic]: a Steam Machine gets all its items and modules, a plain PC none 2026-09-30 10:12:35 +02:00
theupriser 19ea677cf7 fix: vmbootloadertest.sh --quick installs on a VM that reports Steam Machine hardware 2026-09-30 10:11:00 +02:00
theupriser ca0cf43919 fix: vminstall.sh: show the QEMU, serial and install logs when the install fails 2026-09-30 10:07:43 +02:00
theupriser 7b7715ab07 fix: vminstall.sh removes the read-only ISO files it extracted (failed as a non-root host) 2026-09-30 09:50:28 +02:00
theupriser 8ef247e596 fix: the VM's ssh key is looked up at every call (a clean host failed the first-boot check: common.sh was sourced before the key existed) 2026-09-30 09:43:05 +02:00
theupriser 1db4693e3c feat: vmbootloadertest.sh --quick: only what the ISO's install must get right (B1-B5) 2026-09-30 09:38:30 +02:00
theupriser 6190abadfc fix: a test that aborts fails (exit status of the piped block), vminstall reads the ISO with bsdtar (no loop partitions in CI containers) 2026-09-30 09:02:16 +02:00
theupriser 4cb253b41c ci: sync the git.upriser.nl mirror on every branch and tag 2026-09-30 08:54:35 +02:00
theupriser 7b0147f065 feat: VM_INSTALL_MEM sets the RAM of the installer VM only 2026-09-30 08:25:07 +02:00
theupriser f35df9c4d3 feat(ci): sync the git.upriser.nl mirror on every push to main and every tag
GitHub workflow calls the mirror-sync API so the Gitea build starts at once instead of at the mirror's 10 minute interval (secrets GIT_UPRISER_URL, GIT_UPRISER_TOKEN; retried; skipped on Gitea itself). The steamify-iso-release skill uses the renamed secret and workflows.
2026-09-30 08:11:24 +02:00
theupriser 85657a3183 docs: rename the local ISO checkout to steamify-cachyos-live-iso
- scripts and skills use ../steamify-cachyos-live-iso
- TODO item 4: the ISO comes from the git.upriser.nl release
2026-09-30 07:47:37 +02:00
theupriser 92bf3f0b19 docs: use the renamed steamify-cachyos-live-iso repo in vmtest-remote.sh and TODO
- vmtest-remote.sh: name the ISO repo checkout steamify-cachyos-live-iso
- TODO.md: gh run download points at theupriser/steamify-cachyos-live-iso
2026-09-30 07:45:35 +02:00
theupriser b07ff5f99b docs: skills and AGENTS.md after 2026-09-29: the ISO release pipeline (new skill), boot entry check and install gotchas, monitor rules, freeing WSL disk, deleting merged branches 2026-09-29 23:05:29 +02:00
theupriser 2daf83b013 docs: wsl-build-host: a hand-built ISO is named local (releases come from a GitHub tag) 2026-09-29 22:19:51 +02:00
theupriser d8c7670c53 fix: boot check: the power-off fix is loaded, or was tried at boot and refused (journal); it grepped dmesg for systemd's error, which only sometimes lands there 2026-09-29 20:17:27 +02:00
theupriser 58b233c20b docs: full run with Steamify release/2.9.1: 341 pass; the CEC driver cache done 2026-09-29 19:46:08 +02:00
theupriser b6e801664a fix: test prelude sets SCRIPT_DIR (the libs read patches/ from it); hw block 50 checks every run for errors 2026-09-29 19:24:25 +02:00
theupriser fa01c19ba1 fix: hw block 50: the private cache folder is readable like /var/cache/steamify (mktemp's 700 hid it from the user) 2026-09-29 19:22:16 +02:00
theupriser f356cc3f74 feat: hw block 50: the CEC driver cache (new pin downloads and removes the old file, cache hit, damaged file replaced), offline via file:// 2026-09-29 19:19:52 +02:00
theupriser 0824e78249 feat: the VMs share the host's cache for Steamify's own downloads (/var/cache/steamify: the CEC driver once for every VM, GitHub rate-limits it) 2026-09-29 19:16:45 +02:00
theupriser 48edfc53c5 docs: B1 boot entry check and the ISO's /var/log fix done; CEC driver download (GitHub 429) as the next item 2026-09-29 19:09:16 +02:00
theupriser 36bd85cce6 docs: TODO: WSL starting with Windows is not Steamify's work (removed R1d) 2026-09-29 18:58:10 +02:00
theupriser 4670b296dc docs: TODO: R1d (WSL with Windows) left for now 2026-09-29 18:57:57 +02:00
theupriser b6082c0322 fix: vminstall.sh stops waiting as soon as the live system reports a failed install (it waited 90 minutes) 2026-09-29 18:48:27 +02:00
theupriser ebf9e3c267 fix: vmprogress.sh reports a failed install (it stayed at 'install' for 18 minutes) 2026-09-29 18:48:14 +02:00
theupriser ade5566174 feat: B1 check: booted through the loader's own EFI boot entry (BootCurrent, a real partition), after every reboot in the boot loader test 2026-09-29 18:13:16 +02:00
theupriser 6729d61ea8 docs: the first full run on the PC (328 pass, 18 min): TESTPLAN, TODO, AGENTS, wsl-build-host; vmsuite.sh writes its summary into its log 2026-09-29 18:05:10 +02:00
theupriser 5f97f1334c fix: vmprogress.sh: only a new step, a finished job or a FAIL is a change (not every PASS) 2026-09-29 17:50:41 +02:00
theupriser c6578103a3 docs: progress-report: a stopped local command leaves its remote loop running (known_hosts during an install) 2026-09-29 17:31:35 +02:00
theupriser 97f68a8065 fix: vmprogress.sh: a new install percentage alone is no change (one line per stage) 2026-09-29 17:23:42 +02:00
theupriser 3a0d9f98d8 feat: progress-report skill and scripts/vmprogress.sh (a status line per change); referenced from the other skills and AGENTS.md 2026-09-29 17:07:52 +02:00
theupriser fd1b916023 feat: vmview.py: a window with a headless VM's screen (QMP screendump every 2 s, view only) 2026-09-29 17:05:17 +02:00
theupriser b6a7b30092 fix: vminstall.sh sets up the ISO's loop device under a lock (parallel installs collided) 2026-09-29 16:28:19 +02:00
theupriser 314bac87e7 fix: vminstall.sh in parallel: a poweroff that drops ssh is no failure, wait only for its own VM 2026-09-29 16:17:53 +02:00
theupriser dea5f9d715 fix: vminstall.sh never makes root the guest user (WSL runs as root): theupriser then 2026-09-29 15:49:29 +02:00
theupriser a576b734c7 docs: wsl-build-host skill, vminstall.sh without udisks (WSL), AGENTS.md/TODO WSL notes corrected
The WSL box has a desktop after all (WSLg windows on Windows), closing the
Arch window shuts it down, and vminstall.sh loop-mounts the ISO with losetup
as root when udisksctl is missing (R1c).
2026-09-29 15:40:03 +02:00
theupriser 105ac638ee docs: AGENTS.md: state, where the tests run (PC, WSL2) and the ISO problems found 2026-09-29 15:31:57 +02:00
theupriser d231aec125 docs: the agent hand-off file is AGENTS.md (was CLAUDE.md) 2026-09-29 15:29:49 +02:00
theupriser 5b3e246629 docs: CLAUDE.md: this repo takes pushes straight to main 2026-09-29 15:29:08 +02:00
theupriser f24ff3927e feat: faster and parallel tests, a remote runner, and a CLAUDE.md hand-off
vmsuite.sh: the ssh-ready snapshot becomes one base image, every block gets a new qcow2 overlay
(no snapshot restore), each suite has its own VM directory and ssh port (2301-2305, boot loaders
2401-2403), the host's package cache is bound over pacman's, VM_MEM defaults to 4G for tests
(run.sh VM_MEM, default 8G). vmtest.sh runs up to MAX_PARALLEL=3 jobs at once, slowest first.
scripts/vmtest-remote.sh runs vmtest.sh on another machine (the PC) over ssh and prints the
summary. CLAUDE.md and the branch cleanup skill now live in the repo.

Not proven as a whole: three VMs at once and the base image work, but a complete parallel run to
the end has not finished yet (P1/P2 in TODO.md); the remote runner and WSL2 are untried (R1-R2).
2026-09-29 15:26:57 +02:00
theupriser b895e28181 feat: vmtest.sh runs everything: boot loaders plus the cli, menu, hw, installer and toggles suites
vmtest.sh [--install] [--window] [--screen] [boot|loader|suite...], a detached screen
session with --screen, the summary in ~/vms/last-test.txt, the rows that need a person
listed as SKIP. New: the installer suite (R2.1), the toggles suite (R1.8) and H3 (BIOS
dry-run, per-block '# env:' for the VM start). vmsuite.sh and vmbootloadertest.sh are
executable again.
2026-09-29 14:41:37 +02:00
theupriser 0a12c0e4c6 feat: the hw suite (H1, H4, H5, R1.7 CEC) and host-side suite blocks
vmsuite.sh runs NN-name.host.sh blocks on the host (reboot, scripts/vmcec.sh) with
prelude-host.sh; every block that applies Steamify says so first (INFO) so the shared
console is not silent for minutes. 68 checks pass.
2026-09-29 14:12:39 +02:00
theupriser fcffceb941 feat: the menu suite (R1.1-R1.6, R1.10) and one shared log Konsole for every test run
Scripted menu input and Steamify's own status functions, journals free of duplicates,
--backend status as JSON, an older item shown as (update). The test scripts append to
$TEST_LOG and share one Konsole (common.sh view_start) instead of opening one each;
vmsuite.sh streams its output (sed -u). 36 checks pass.
2026-09-29 13:53:35 +02:00
theupriser ea1207580f feat: vmsuite.sh and the cli suite: G1-G3, F1-F7 of TESTPLAN.md as unattended checks
Each block in share/vmtest/<suite>/ starts from a fresh ssh-ready snapshot, gets a
Plasma session environment over ssh (the theme item needs one) and prints PASS/FAIL
lines. ONLY=<prefix> runs one block. 55 checks pass on the plain CachyOS VM.
2026-09-29 11:45:02 +02:00
theupriser 38a50ab57d docs: vm-install skill, TESTPLAN section B and TODO for the boot loader test and the full automated suite 2026-09-29 11:23:50 +02:00
theupriser ed12ecb57d feat: vmtest.sh: the boot loader test for every loader the ISO advertises
One VM per loader, Steam Machine (--fremont): Steamify's state as its menu sees it,
OS name untouched, loader identity, the DKMS modules for every kernel, Steamify's
loader-specific code (hdmi_remove_boot_param), a kernel update, and a reboot into
each of the two kernels. Headless by default with a log Konsole (--window shows
the VMs). Fails when an advertised loader has no test. Limine 41, systemd-boot 40,
GRUB 40 checks pass.
2026-09-29 11:23:50 +02:00
theupriser 8ea75424b0 feat: vminstall.sh installs any boot loader and the Steamify ISO's Steamify step, with a package cache
VM_BOOTLOADER=limine|systemd-boot|grub, VM_STEAMIFY (steamify-install runs after
the headless installer, like Calamares does), VM_CACHE (host pacman cache shared
as 9p, default ~/vms/pkg-cache). run.sh --headless / VM_HEADLESS=1: no window.

Fixes found on the way: the live script deadlocked on is-system-running (it is
the running kernel-command-line.service) and now waits for pacman-init; the post
script kept forcing the Plasma login over Steamify's gaming-mode SDDM, gave
systemd-boot no timeout/default (it waited in the menu for ever), and left ufw
blocking the host's ssh; the first-boot check wanted plasmashell in gaming mode.
2026-09-29 11:23:50 +02:00
theupriser e435577b5c docs: steam-machine-iso: vmreset.sh also stops the ISO VM 2026-09-28 18:27:52 +02:00
theupriser 104d1dac44 fix: vmreset.sh works when the VM lives in the repo itself (cp of run.sh onto itself failed) 2026-09-28 18:27:27 +02:00
theupriser 8b0c168711 docs: steam-machine-iso: read an installed VM's disk while it runs; serial output 2026-09-28 18:12:18 +02:00
theupriser d0c551d23a docs: steam-machine-iso: one log Konsole for every build 2026-09-28 17:45:00 +02:00
theupriser 728f329ebc docs: steam-machine-iso: a package cache for the podman ISO build 2026-09-28 17:42:37 +02:00
theupriser 332fdca4c2 fix: qmptype.py types > < ? { } 2026-09-28 17:37:51 +02:00
theupriser 92c1e58f55 feat: vmisobuild.sh and the steam-machine-iso skill run build-calamares-modules.sh 2026-09-28 16:41:22 +02:00
theupriser 36d1e6d326 docs: note token-cheap ISO-VM testing (serial log, no screenshot polling) 2026-09-28 15:35:25 +02:00
theupriser c5ac00faf6 docs: packagechooser multi-select needs Shift/Ctrl-click 2026-09-28 13:45:09 +02:00
theupriser 107f8f4076 docs: steam-machine-iso: run Calamares in its own Konsole tab; watch for the live keyboard layout switching away from US 2026-09-28 13:42:23 +02:00
theupriser 1c1bc55a62 docs: correction - packagechooser mode:optionalmultiple DOES multi-select (verified from global storage, not misleading label text) 2026-09-28 13:30:09 +02:00
theupriser 6df107d578 docs: packagechooserq isn't installed on this Calamares build; packagechooser's mode:optionalmultiple is single-select regardless; QMP/Calamares live-testing gotchas 2026-09-28 13:24:36 +02:00
theupriser 6840044038 docs: ISO builds use 75% of host cores, not all-but-2 2026-09-28 13:04:04 +02:00
theupriser 32499b1c01 docs: TESTPLAN: 2.8.0 --defaults --list tested 2026-09-28 12:44:50 +02:00
theupriser b1e9a273a3 feat: vmisobuild.sh (ISO build in the VM, package cache per VM), vmisoboot.sh (ISO VM for Calamares), qmpshot.py/qmpclick.py; run.sh VM_CACHE/VM_CPUS/VM_NOGL/VM_PORT 2026-09-28 11:40:21 +02:00
theupriser 9706066269 docs: TESTPLAN: 2.7.0's Steam Machine checks carried over from 2.6.0 (code unchanged) 2026-09-28 10:56:17 +02:00
theupriser 7a0a216327 docs: 2.7.0 regression results on the new VM; the first login's app is the newest release 2026-09-28 10:53:44 +02:00
theupriser 4adc018654 docs: vminstallsim.sh example uses --options 2026-09-28 10:08:27 +02:00
theupriser ac8f77cf4a feat: scripts/vminstall.sh installs an ssh-ready test VM unattended; TESTPLAN.md; vm-install skill 2026-09-28 10:07:13 +02:00
theupriser 0f57d86bae docs: steam-machine-iso: one build at a time; vminstallsim.sh passes --defaults options 2026-09-27 22:00:32 +02:00
theupriser 46e039809e docs: steam-machine-iso: build-live-modules.sh in the build, the ISO's new name 2026-09-27 21:26:45 +02:00
theupriser 379f1c7f7f docs: steam-machine-iso: the Steamify step is added by calamares-online.sh 2026-09-27 20:06:26 +02:00
theupriser 471332e20f docs: steam-machine-iso: live-session quirks; scripts/qmptype.py types into the VM 2026-09-27 20:01:41 +02:00
theupriser 8ce2917c0f docs: steam-machine-iso: the harmless chown error, the ISO test VM 2026-09-27 19:54:30 +02:00
theupriser 9a4653b6d3 feat: steam-machine-iso skill (ISO build in podman on the Steam Machine, installer simulation, first-login test) and scripts/vminstallsim.sh 2026-09-27 19:53:23 +02:00
theupriser 3b7b685667 VM on the Steam Machine: Arch OVMF paths, visible tests, and the steam-machine-testing skill 2026-09-27 17:00:10 +02:00
theupriser 7a0443e131 docs: VM skill up to date with the menu (sub-options, HDMI-CEC, kernel pin) and today's pitfalls 2026-09-25 13:07:02 +02:00
theupriser 8d5a659c89 docs: The test VM needs an x86_64 Linux host 2026-09-25 13:05:15 +02:00
theupriser 6d992c83c7 chore: Remove the Windows scripts; the test VM runs on Linux 2026-09-25 13:04:20 +02:00
theupriser 974cea7cf4 docs: run.sh --amd (venus on the AMD iGPU); gaming mode can't render in the VM, all tried 2026-09-25 12:54:27 +02:00
theupriser 19b6ba4d97 feat: vmcec.sh tests HDMI-CEC against a fake TV; vmwake.sh wakes the VM over QMP
run.sh opens a QMP socket; the skill documents the CEC test and its gotchas.
2026-09-25 11:14:00 +02:00
theupriser 788d345a9d docs: VM skill: menu with sub-options, HDMI-CEC and faking it with vivid 2026-09-25 09:12:12 +02:00
theupriser 10357b2d52 Merge pull request #1 from theupriser/feat/visible-vm-runs
Feat/visible vm runs
2026-09-24 13:09:16 +02:00
53 changed files with 480 additions and 223 deletions

No files matched your search

-2
View File
@@ -22,7 +22,6 @@ share/*
!share/vminstall-post.sh !share/vminstall-post.sh
!share/bootloader-test/ !share/bootloader-test/
!share/vmtest/ !share/vmtest/
!share/uitest/
# Belt and braces, anywhere in the tree # Belt and braces, anywhere in the tree
*.iso *.iso
@@ -35,4 +34,3 @@ share/*
*.tmp *.tmp
host-keys.pub host-keys.pub
__pycache__/ __pycache__/
!share/golden/
-4
View File
@@ -4,10 +4,6 @@ All notable changes, per version and per commit. Versions follow
[Semantic Versioning](https://semver.org/) and were numbered from the start [Semantic Versioning](https://semver.org/) and were numbered from the start
of the history. of the history.
## Unreleased
- **feat: `share/golden/`: a no-VM sandbox (bubblewrap, fake `/etc` `/sys` `$HOME`, shim `pacman` `systemctl` `sudo` `uname` `modinfo`) and golden `--backend status` and apply `plan` output of the bash 2.11.1 backend for an AMD PC, an NVIDIA PC and a Steam Machine; `record.sh` records, `record.sh check` compares (the Go refactor's safety net)**
## 0.5.0 - 2026-10-02 ## 0.5.0 - 2026-10-02
The whole automated test (boot loaders plus suites), the Steamify ISO pipeline, The whole automated test (boot loaders plus suites), the Steamify ISO pipeline,
+1 -1
View File
@@ -5,7 +5,7 @@
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; } pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
cd /mnt || exit 1 cd /mnt || exit 1
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier; do for lib in $(grep -oP '^for lib in \K.*(?=; do$)' steamify.sh); do
# shellcheck source=/dev/null # shellcheck source=/dev/null
. "lib/$lib.sh" 2>/dev/null . "lib/$lib.sh" 2>/dev/null
done done
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming","boot"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming","single"]}
-1
View File
@@ -1 +0,0 @@
{"version":"2.12.0","firstRun":true,"steamMachine":false,"kernel":"7.0.0-fixture-cachyos","pinnedKernel":"7.1.6-1","cecDevices":"","leds":0,"bios":null,"items":[{"id":"gaming","label":"SteamOS conversion","hint":"boot into gaming mode, Steam on the desktop","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"boot","label":"Boot into the desktop instead of gaming mode","hint":"","kind":"choice","parent":"gaming","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"silent","label":"Start Steam silently in desktop mode","hint":"in the tray at login on the desktop, no window","kind":"toggle","parent":"gaming","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"glyphs","label":"Install Steam Deck/Machine icons","hint":"Deck button icons in gaming mode","kind":"toggle","parent":"gaming","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"theme","label":"Install SteamOS theme","hint":"Vapor look (cachyos-vapor)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"single","label":"Single user mode","hint":"no password, lock screen or log out (SDDM)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"launcher","label":"Steamify shortcut","hint":"the app on the desktop, Steamify Terminal in the launcher","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"notify","label":"Update notifications","hint":"a notification when there's a new Steamify, never updates by itself","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"extended_controller_support","label":"Extended controller support","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","kind":"toggle","parent":"","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"cec","label":"HDMI-CEC","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","kind":"toggle","parent":"","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true}]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["nvidia","bigpicture"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["single"]}
@@ -1 +0,0 @@
{"version":"2.12.0","firstRun":true,"steamMachine":false,"kernel":"7.0.0-fixture-cachyos","pinnedKernel":"7.1.6-1","cecDevices":"","leds":0,"bios":null,"items":[{"id":"nvidia","label":"Gaming on NVIDIA","hint":"Steam on the desktop, started at login","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"bigpicture","label":"Steam starts in Big Picture","hint":"the controller-friendly Steam (untick: Steam's normal window)","kind":"toggle","parent":"nvidia","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"nvsilent","label":"Start Steam silently","hint":"in the tray at login, no window (untick: Steam's normal window)","kind":"toggle","parent":"nvidia","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"theme","label":"Install SteamOS theme","hint":"Vapor look (cachyos-vapor)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"single","label":"Single user mode","hint":"no password, lock screen or log out (SDDM)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"launcher","label":"Steamify shortcut","hint":"the app on the desktop, Steamify Terminal in the launcher","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"notify","label":"Update notifications","hint":"a notification when there's a new Steamify, never updates by itself","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"extended_controller_support","label":"Extended controller support","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","kind":"toggle","parent":"","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"cec","label":"HDMI-CEC","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","kind":"toggle","parent":"","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true}]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming","boot"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":[]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["machine","poweroff"]}
@@ -1 +0,0 @@
{"event":"plan","disable":[],"enable":["gaming","single"]}
@@ -1 +0,0 @@
{"version":"2.12.0","firstRun":true,"steamMachine":true,"kernel":"7.0.0-fixture-cachyos","pinnedKernel":"7.1.6-1","cecDevices":"","leds":0,"bios":{"current":"unknown","newest":"","selectable":false,"dryRun":false},"items":[{"id":"gaming","label":"SteamOS conversion","hint":"boot into gaming mode, Steam on the desktop","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"boot","label":"Boot into the desktop instead of gaming mode","hint":"","kind":"choice","parent":"gaming","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"silent","label":"Start Steam silently in desktop mode","hint":"in the tray at login on the desktop, no window","kind":"toggle","parent":"gaming","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"glyphs","label":"Install Steam Deck/Machine icons","hint":"Deck button icons in gaming mode","kind":"toggle","parent":"gaming","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"theme","label":"Install SteamOS theme","hint":"Vapor look (cachyos-vapor)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"single","label":"Single user mode","hint":"no password, lock screen or log out (SDDM)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"launcher","label":"Steamify shortcut","hint":"the app on the desktop, Steamify Terminal in the launcher","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"notify","label":"Update notifications","hint":"a notification when there's a new Steamify, never updates by itself","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"extended_controller_support","label":"Extended controller support","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","kind":"toggle","parent":"","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":true},{"id":"cec","label":"HDMI-CEC","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"machine","label":"Steam Machine support","hint":"LED bar driver, hardware settings in Steam","kind":"toggle","parent":"","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"poweroff","label":"Power-off fix","hint":"the Steam Machine stays off after shutting down","kind":"toggle","parent":"machine","needs":"","on":false,"wanted":true,"update":false,"new":false,"selectable":true},{"id":"bios","label":"Update BIOS","hint":"now unknown, newest unknown (offline?)","kind":"action","parent":"machine","needs":"","on":false,"wanted":false,"update":false,"new":false,"selectable":false}]}
@@ -1,3 +0,0 @@
NAME="CachyOS Linux"
ID=cachyos
ID_LIKE=arch
-2
View File
@@ -1,2 +0,0 @@
sddm
plasma-desktop
@@ -1 +0,0 @@
PRIME B650
@@ -1 +0,0 @@
ASUSTeK
@@ -1,3 +0,0 @@
NAME="CachyOS Linux"
ID=cachyos
ID_LIKE=arch
-1
View File
@@ -1 +0,0 @@
nvidia_drm
-3
View File
@@ -1,3 +0,0 @@
sddm
plasma-desktop
nvidia-utils
@@ -1 +0,0 @@
PRIME B650
@@ -1 +0,0 @@
ASUSTeK
@@ -1 +0,0 @@
0x030000
@@ -1 +0,0 @@
0x10de
@@ -1,3 +0,0 @@
NAME="CachyOS Linux"
ID=cachyos
ID_LIKE=arch
@@ -1,2 +0,0 @@
sddm
plasma-desktop
@@ -1 +0,0 @@
Fremont
@@ -1 +0,0 @@
Valve
-33
View File
@@ -1,33 +0,0 @@
#!/bin/bash
# Record what the bash backend (steamify.sh in $REPO) prints, per fixture, into share/golden/expected/.
# share/golden/record.sh record all | share/golden/record.sh check compare with the recorded files
set -uo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
export REPO="${REPO:-$here/../../../steamify-cachyos}"; REPO="$(cd "$REPO" && pwd)"
backend="${BACKEND:-bash $REPO/steamify.sh}"
mode="${1:-record}"; failures=0; work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT
# case name -> backend arguments
# status: the whole output. plan-*: only the first line of the apply stream (the plan event, where the rules live);
# the steps after it need the real system (the VM suite), they are not stable with a fake sudo.
cases=("status:--backend status"
"plan-gaming:--backend apply gaming"
"plan-gaming-desktop:--backend apply --boot desktop gaming boot"
"plan-single:--backend apply single"
"plan-poweroff:--backend apply poweroff"
"plan-nothing:--backend apply"
"plan-nvidia:--backend apply nvidia bigpicture")
for fixture in "$here"/fixtures/*/; do
name="$(basename "$fixture")"
for entry in "${cases[@]}"; do
label="${entry%%:*}"; arguments="${entry#*:}"
expected="$here/expected/$name.$label.json"; mkdir -p "$here/expected"
if [[ "$label" == plan-* ]]; then # the plan event comes first; then the steps run for real, so stop after a moment
timeout -s KILL 5 "$here/sandbox.sh" "$fixture" $backend $arguments > "$work/stream" 2>&1
actual="$(head -n 1 "$work/stream")"
else actual="$("$here/sandbox.sh" "$fixture" $backend $arguments 2>&1)"; fi
if [[ "$mode" == record ]]; then printf '%s\n' "$actual" > "$expected"; echo "recorded $expected"
elif ! diff -u "$expected" <(printf '%s\n' "$actual"); then echo "FAIL $name $label"; failures=$((failures+1))
else echo "PASS $name $label"; fi
done
done
exit $failures
-32
View File
@@ -1,32 +0,0 @@
#!/bin/bash
# Run a command in a throw-away copy of a machine described by a fixture folder (no VM, no root).
# share/golden/sandbox.sh <fixture> <command>...
# <fixture>/etc/**, <fixture>/sys/**, <fixture>/usr/** : files shown at those places (the rest of /etc and /sys is empty)
# <fixture>/home/ : the user's home (fresh copy each run)
# <fixture>/packages, enabled-units, active-units : answers of the fake pacman and systemctl (shims/)
# <fixture>/env : optional VAR=value lines for the command
# Needs bubblewrap. $GOLDEN_LOG collects the writes the shims were asked to make.
set -euo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
fixture="$(cd "${1:?usage: $0 <fixture> <command>...}" && pwd)"; shift
work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT
mkdir -p "$work/home" "$work/fixture"
cp -a "$fixture/." "$work/fixture/"
[[ -d "$fixture/home" ]] && cp -a "$fixture/home/." "$work/home/"
arguments=(--die-with-parent --unshare-pid --ro-bind / / --dev /dev --proc /proc --tmpfs /tmp --tmpfs /sys --tmpfs /etc
--bind "$work/home" "$HOME" --bind "$work/fixture" /mnt --ro-bind "$here/shims" /media)
[[ -n "${REPO:-}" ]] && arguments+=(--ro-bind "$REPO" "$REPO")
for keep in passwd group nsswitch.conf ld.so.cache ld.so.conf ld.so.conf.d localtime alternatives resolv.conf hostname; do
[[ -e "/etc/$keep" ]] && arguments+=(--ro-bind "/etc/$keep" "/etc/$keep")
done
for root in etc sys; do
[[ -d "$fixture/$root" ]] || continue
while IFS= read -r -d '' file; do
arguments+=(--ro-bind "$work/fixture/${file#"$fixture/"}" "/${file#"$fixture/"}")
done < <(find "$fixture/$root" -type f -print0)
done
environment=(--setenv FIXTURE /mnt --setenv PATH "/media:$PATH" --setenv GOLDEN_LOG "${GOLDEN_LOG:-/mnt/writes.log}")
[[ -f "$fixture/env" ]] && while IFS= read -r line; do
[[ "$line" == *=* ]] && environment+=(--setenv "${line%%=*}" "${line#*=}")
done < "$fixture/env"
exec bwrap "${arguments[@]}" "${environment[@]}" "$@"
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
# Fake modinfo: modules listed in $FIXTURE/modules exist.
for module in "$@"; do [[ "$module" == -* ]] || grep -qx -- "$module" "$FIXTURE/modules" 2>/dev/null || exit 1; done
-10
View File
@@ -1,10 +0,0 @@
#!/bin/bash
# Fake pacman for the golden sandbox: the installed packages are listed in $FIXTURE/packages (one name per line).
# Only the queries the status code makes: -Q/-Qq <pkg>, -T <pkg>..., -Qi <pkg>. Writes (-S, -U, -R) are logged and succeed.
list="$FIXTURE/packages"; touch "$list" 2>/dev/null
case "$1" in
-T) shift; for package in "$@"; do grep -qx -- "$package" "$list" || echo "$package"; done; [[ $# -gt 0 ]] ;;
-Q|-Qq|-Qi|-Qs) shift; status=0; for package in "$@"; do [[ "$package" == -* ]] && continue; grep -qx -- "$package" "$list" || status=1; done; exit $status ;;
-Ss|-Si) exit 1 ;;
*) echo "pacman $*" >> "${GOLDEN_LOG:-/dev/null}"; exit 0 ;;
esac
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
# Fake sudo: logs the command and succeeds; nothing runs.
while [[ "$1" == -* ]]; do shift; done
echo "sudo $*" >> "${GOLDEN_LOG:-/dev/null}"
-13
View File
@@ -1,13 +0,0 @@
#!/bin/bash
# Fake systemctl: enabled units listed in $FIXTURE/enabled-units, active ones in $FIXTURE/active-units.
# Queries answer from those lists; everything else is logged and succeeds.
verb=""; units=()
for argument in "$@"; do
[[ "$argument" == -* ]] && continue
if [[ -z "$verb" ]]; then verb="$argument"; else units+=("$argument"); fi
done
case "$verb" in
is-enabled) for unit in "${units[@]}"; do grep -qx -- "$unit" "$FIXTURE/enabled-units" 2>/dev/null || { echo disabled; exit 1; }; done; echo enabled ;;
is-active) for unit in "${units[@]}"; do grep -qx -- "$unit" "$FIXTURE/active-units" 2>/dev/null || { echo inactive; exit 3; }; done; echo active ;;
*) echo "systemctl $*" >> "${GOLDEN_LOG:-/dev/null}"; exit 0 ;;
esac
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
if [[ "$1" == -r ]]; then echo 7.0.0-fixture-cachyos; else command uname "$@"; fi
-42
View File
@@ -1,42 +0,0 @@
import sys, os, importlib.machinery, importlib.util, json
os.environ["QT_QPA_PLATFORM"] = "offscreen"
sys.argv = ["steamify-ui"]
loader = importlib.machinery.SourceFileLoader("ui", sys.argv[0] if False else os.environ["UI"])
spec = importlib.util.spec_from_loader("ui", loader); ui = importlib.util.module_from_spec(spec); loader.exec_module(ui)
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtCore import QTimer, QObject, QMetaObject, Q_ARG, Qt
app = QGuiApplication(sys.argv)
backend = ui.Backend(ui.find_script()); pad = ui.Gamepad(); engine = QQmlApplicationEngine()
engine.setInitialProperties({"backend": backend, "gamepad": pad, "fullscreen": False, "fromSteam": False, "iconUrl": ""})
engine.load(os.path.join(ui.HERE, "qml", "Main.qml"))
assert engine.rootObjects(), "QML did not load"
root = engine.rootObjects()[0]; backend.refresh()
def find_state():
for o in root.findChildren(QObject):
if o.property("want") is not None and o.property("resolution") is not None: return o
state = None
def step():
global state
state = find_state(); assert state, "no AppState"
def want(): return {k for k, v in state.property("want").toVariant().items() if v} if hasattr(state.property("want"),"toVariant") else {k for k,v in state.property("want").items() if v}
def toggle(i): QMetaObject.invokeMethod(state, "toggle", Qt.DirectConnection, Q_ARG("QVariant", i))
def vis():
r = state.property("resolution"); r = r.toVariant() if hasattr(r,"toVariant") else r
return set(r["visible"])
def plan():
r = state.property("resolution"); r = r.toVariant() if hasattr(r,"toVariant") else r
return [(p["id"], p["action"]) for p in r["plan"]]
print("start want", want(), "plan", plan(), "canApply", state.property("canApply"))
assert want() == {"theme"}
toggle("single"); print("after single", want(), plan())
assert want() == {"theme", "single", "gaming"} and plan() == [("gaming","on"),("single","on")]
assert "silent" in vis() and "poweroff" not in vis()
toggle("machine"); print("after machine", want(), vis())
assert "poweroff" in want() and "poweroff" in vis()
toggle("gaming"); print("after gaming off", want())
assert want() == {"theme", "machine", "poweroff"}
assert state.property("canApply") is True
print("UI OK"); app.quit()
QTimer.singleShot(4000, step)
sys.exit(app.exec())
@@ -1,30 +0,0 @@
# Go core (REFACTOR-2.12 phase 0/1): `steamify --backend apply` through the Go binary must emit the
# same event stream as the bash backend: enable two small items, then turn them off again, once with
# each backend, in the same VM. Needs the binary built in the repo (make build -> bin/steamify).
GO=/mnt/bin/steamify
[[ -x $GO ]] || { fail "no $GO (run make build in steamify-cachyos)"; exit 0; }
export STEAMIFY_NO_DOWNLOAD=1
backend_run() { # backend_run <label> <command...>: the event stream of one apply, log lines dropped
# Only the structure (plan, start, done, finished): the log lines of the first run hold pacman's install output, which the
# second run on the same machine does not repeat.
"$@" 2>&1 < /dev/null | sed 's/\x1b\[[0-9;]*m//g' | grep -v '^{"event":"log"'
}
status_json() { "$@" --backend status 2>/dev/null; }
info "status through both backends"
bash_status=$(bash /mnt/steamify.sh --backend status 2>/dev/null); go_status=$($GO --backend status 2>/dev/null)
[[ -n $bash_status && "$bash_status" == "$go_status" ]] && pass "status identical" || fail "status differs"
for step in "launcher notify" ""; do
# shellcheck disable=SC2086
bash_events=$(backend_run bash /mnt/steamify.sh --backend apply $step)
# put the machine back for the Go run
# shellcheck disable=SC2086
if [[ -n $step ]]; then backend_run bash /mnt/steamify.sh --backend apply >/dev/null; else backend_run bash /mnt/steamify.sh --backend apply launcher notify >/dev/null; fi
# shellcheck disable=SC2086
go_events=$(backend_run $GO --backend apply $step)
label="apply ${step:-nothing (turn off)}"
if [[ "$bash_events" == "$go_events" ]]; then pass "$label: same event stream ($(wc -l <<< "$bash_events") lines)"
else fail "$label: streams differ: $(diff <(echo "$bash_events") <(echo "$go_events") | head -6 | tr '\n' '|')"; fi
done
grep -q '"finished"' <<< "$go_events" && pass "Go run finished" || fail "no finished event: $(tail -n 2 <<< "$go_events")"
+1 -1
View File
@@ -6,7 +6,7 @@ pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }; skip() { echo "SKIP $*";
sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
cd /mnt || exit 1 cd /mnt || exit 1
export SCRIPT_DIR=/mnt # steamify.sh sets it; the libs alone read patches/ and services/ from it export SCRIPT_DIR=/mnt # steamify.sh sets it; the libs alone read patches/ and services/ from it
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh nvidia controllers cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier; do for lib in $(grep -oP '^for lib in \K.*(?=; do$)' steamify.sh); do
# shellcheck source=/dev/null # shellcheck source=/dev/null
. "lib/$lib.sh" 2>/dev/null . "lib/$lib.sh" 2>/dev/null
done done
+170
View File
@@ -0,0 +1,170 @@
== pc first run
wanted: gaming glyphs theme single launcher notify
disable:
enable: gaming glyphs theme single launcher notify
== pc first run, untick gaming
wanted: theme launcher notify
disable:
enable: theme launcher notify
== pc single on
wanted: gaming theme single launcher notify
disable:
enable: gaming theme single launcher notify
== pc single then gaming off
wanted: theme launcher notify
disable:
enable: theme launcher notify
== pc boot desktop
wanted: gaming boot glyphs theme single launcher notify
disable:
enable: gaming boot glyphs theme single launcher notify
== pc boot desktop then gaming off
wanted: theme launcher notify
disable:
enable: theme launcher notify
== pc silent only
wanted: gaming silent glyphs theme single launcher notify
disable:
enable: gaming silent glyphs theme single launcher notify
== pc all on, theme off
wanted: gaming boot silent glyphs single launcher notify
disable: theme
enable: gaming silent notify
== pc launcher off
wanted:
disable: launcher
enable:
== pc steamgame on without launcher
wanted: theme launcher steamgame notify
disable:
enable: theme launcher steamgame notify
== machine first run
wanted: gaming glyphs theme single launcher steamgame notify vram cec machine poweroff
disable:
enable: gaming glyphs theme single launcher steamgame notify vram cec machine poweroff
== machine silent hidden until boot desktop
wanted: gaming silent glyphs theme single launcher notify vram machine
disable:
enable: gaming silent glyphs theme single launcher notify vram machine
== machine boot desktop keeps silent
wanted: gaming boot silent glyphs theme single launcher notify vram machine
disable:
enable: gaming boot silent glyphs theme single launcher notify vram machine
== machine off
wanted: gaming glyphs theme single launcher notify vram
disable: poweroff machine
enable: gaming glyphs theme single launcher notify vram
== machine poweroff off
wanted: gaming glyphs theme single launcher notify vram machine
disable: poweroff
enable: gaming glyphs theme single launcher notify vram machine
== machine poweroff on brings machine
wanted: gaming glyphs theme single launcher notify vram machine poweroff
disable:
enable: gaming glyphs theme single launcher notify vram machine poweroff
== machine kpin removal
wanted: gaming glyphs theme single launcher notify vram machine poweroff
disable: kpin
enable: gaming glyphs theme single launcher notify vram machine poweroff
== nvidia first run
wanted: nvidia bigpicture theme single launcher notify
disable:
enable: nvidia bigpicture theme single launcher notify
== nvidia bigpicture off
wanted: nvidia theme single launcher notify
disable: bigpicture
enable: nvidia theme single launcher notify
== nvidia nvsilent on
wanted: nvidia nvsilent theme single launcher notify
disable: bigpicture
enable: nvidia nvsilent theme single launcher notify
== nvidia nvsilent then bigpicture
wanted: nvidia bigpicture theme single launcher notify
disable:
enable: nvidia bigpicture theme single launcher notify
== nvidia off
wanted: theme single launcher notify
disable: nvsilent bigpicture nvidia
enable: theme single launcher notify
== nvidia single
wanted: nvidia bigpicture theme launcher notify
disable:
enable: nvidia bigpicture theme launcher notify
== nvidia gaming already on
wanted: nvidia theme launcher notify
disable: gaming
enable: nvidia theme launcher notify
== outdated features
wanted: gaming glyphs theme single launcher notify
disable:
enable: gaming glyphs single launcher notify
== reapply (a)
wanted: gaming glyphs theme single launcher notify
disable:
enable: gaming glyphs theme single launcher notify
== backend_apply single
{"event":"plan","disable":[],"enable":["gaming","single"]}
== backend_apply boot
{"event":"plan","disable":[],"enable":[]}
== backend_apply poweroff
{"event":"plan","disable":[],"enable":["machine","poweroff"]}
== backend_apply silent
{"event":"plan","disable":[],"enable":["gaming","silent"]}
== backend_apply kpin
{"event":"plan","disable":[],"enable":[]}
== backend_apply gaming boot
{"event":"plan","disable":[],"enable":["gaming","boot"]}
== backend_apply launcher steamgame
{"event":"plan","disable":[],"enable":["launcher","steamgame"]}
== backend_apply nvidia bigpicture
{"event":"plan","disable":[],"enable":["nvidia","bigpicture"]}
== backend_apply nvidia nvsilent
{"event":"plan","disable":[],"enable":["nvidia","nvsilent"]}
== backend_apply nvidia bigpicture nvsilent
{"event":"plan","disable":[],"enable":["nvidia","bigpicture"]}
== backend_apply nvidia single
{"event":"plan","disable":[],"enable":["single"]}
== backend_apply nvidia boot
{"event":"plan","disable":[],"enable":[]}
== defaults_list []
{"hideWhen":"","hint":"boot into gaming mode, Steam on the desktop","id":"gaming","kind":"toggle","label":"SteamOS conversion","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"","id":"boot","kind":"choice","label":"Boot into the desktop instead of gaming mode","needs":"","on":false,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"in the tray at login on the desktop, no window","id":"silent","kind":"toggle","label":"Start Steam silently in desktop mode","needs":"","on":false,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"Deck button icons in gaming mode","id":"glyphs","kind":"toggle","label":"Install Steam Deck/Machine icons","needs":"","on":true,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","on":false,"parent":"","selectable":true}
{"hideWhen":"","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","on":false,"parent":"","selectable":true}
== backend_status []
{"bios":null,"firstRun":true,"items":[{"hint":"boot into gaming mode, Steam on the desktop","id":"gaming","kind":"toggle","label":"SteamOS conversion","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"","id":"boot","kind":"choice","label":"Boot into the desktop instead of gaming mode","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":false},{"hint":"in the tray at login on the desktop, no window","id":"silent","kind":"toggle","label":"Start Steam silently in desktop mode","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":false},{"hint":"Deck button icons in gaming mode","id":"glyphs","kind":"toggle","label":"Install Steam Deck/Machine icons","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":true},{"hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":false},{"hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":false}],"pinnedKernel":"7.1.6-1","steamMachine":false,"version":"0.0.0"}
== defaults_list [fremont steam vram]
{"hideWhen":"","hint":"boot into gaming mode, Steam on the desktop","id":"gaming","kind":"toggle","label":"SteamOS conversion","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"","id":"boot","kind":"choice","label":"Boot into the desktop instead of gaming mode","needs":"","on":false,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"in the tray at login on the desktop, no window","id":"silent","kind":"toggle","label":"Start Steam silently in desktop mode","needs":"","on":false,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"Deck button icons in gaming mode","id":"glyphs","kind":"toggle","label":"Install Steam Deck/Machine icons","needs":"","on":true,"parent":"gaming","selectable":true}
{"hideWhen":"","hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"Steamify in your Steam library, for the controller and gaming mode","id":"steamgame","kind":"toggle","label":"Add as non-Steam game","needs":"","on":true,"parent":"launcher","selectable":true}
{"hideWhen":"","hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","on":false,"parent":"","selectable":true}
{"hideWhen":"","hint":"the game in front keeps its VRAM, background apps make room","id":"vram","kind":"toggle","label":"VRAM booster","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"LED bar driver, hardware settings in Steam","id":"machine","kind":"toggle","label":"Steam Machine support","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"the Steam Machine stays off after shutting down","id":"poweroff","kind":"toggle","label":"Power-off fix","needs":"","on":true,"parent":"machine","selectable":true}
== backend_status [fremont steam vram]
{"bios":null,"firstRun":true,"items":[{"hint":"boot into gaming mode, Steam on the desktop","id":"gaming","kind":"toggle","label":"SteamOS conversion","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"","id":"boot","kind":"choice","label":"Boot into the desktop instead of gaming mode","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":false},{"hint":"in the tray at login on the desktop, no window","id":"silent","kind":"toggle","label":"Start Steam silently in desktop mode","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":false},{"hint":"Deck button icons in gaming mode","id":"glyphs","kind":"toggle","label":"Install Steam Deck/Machine icons","needs":"","new":false,"on":false,"parent":"gaming","selectable":true,"update":false,"wanted":true},{"hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"Steamify in your Steam library, for the controller and gaming mode","id":"steamgame","kind":"toggle","label":"Add as non-Steam game","needs":"","new":false,"on":false,"parent":"launcher","selectable":true,"update":false,"wanted":true},{"hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":false},{"hint":"the game in front keeps its VRAM, background apps make room","id":"vram","kind":"toggle","label":"VRAM booster","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"LED bar driver, hardware settings in Steam","id":"machine","kind":"toggle","label":"Steam Machine support","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"the Steam Machine stays off after shutting down","id":"poweroff","kind":"toggle","label":"Power-off fix","needs":"","new":false,"on":false,"parent":"machine","selectable":true,"update":false,"wanted":true}],"pinnedKernel":"7.1.6-1","steamMachine":true,"version":"0.0.0"}
== defaults_list [nvidia steam]
{"hideWhen":"","hint":"Steam on the desktop, started at login","id":"nvidia","kind":"toggle","label":"Gaming on NVIDIA","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"the controller-friendly Steam (untick: Steam's normal window)","id":"bigpicture","kind":"toggle","label":"Steam starts in Big Picture","needs":"","on":true,"parent":"nvidia","selectable":true}
{"hideWhen":"bigpicture","hint":"in the tray at login, no window (untick: Steam's normal window)","id":"nvsilent","kind":"toggle","label":"Start Steam silently","needs":"","on":false,"parent":"nvidia","selectable":true}
{"hideWhen":"","hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","on":true,"parent":"","selectable":true}
{"hideWhen":"","hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","on":false,"parent":"","selectable":true}
{"hideWhen":"","hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","on":false,"parent":"","selectable":true}
== backend_status [nvidia steam]
{"bios":null,"firstRun":true,"items":[{"hint":"Steam on the desktop, started at login","id":"nvidia","kind":"toggle","label":"Gaming on NVIDIA","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"the controller-friendly Steam (untick: Steam's normal window)","id":"bigpicture","kind":"toggle","label":"Steam starts in Big Picture","needs":"","new":false,"on":false,"parent":"nvidia","selectable":true,"update":false,"wanted":true},{"hint":"in the tray at login, no window (untick: Steam's normal window)","id":"nvsilent","kind":"toggle","label":"Start Steam silently","needs":"","new":false,"on":false,"parent":"nvidia","selectable":true,"update":false,"wanted":false},{"hint":"Vapor look (cachyos-vapor)","id":"theme","kind":"toggle","label":"Install SteamOS theme","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"no password, lock screen or log out (SDDM)","id":"single","kind":"toggle","label":"Single user mode","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"the app on the desktop, Steamify Terminal in the launcher","id":"launcher","kind":"toggle","label":"Steamify shortcut","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"a notification when there's a new Steamify, never updates by itself","id":"notify","kind":"toggle","label":"Update notifications","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":true},{"hint":"Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)","id":"extended_controller_support","kind":"toggle","label":"Extended controller support","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":false},{"hint":"use Steam with the TV remote, TV on/off with the PC (experimental)","id":"cec","kind":"toggle","label":"HDMI-CEC","needs":"","new":false,"on":false,"parent":"","selectable":true,"update":false,"wanted":false}],"pinnedKernel":"7.1.6-1","steamMachine":false,"version":"0.0.0"}
+135
View File
@@ -0,0 +1,135 @@
#!/bin/bash
# Golden-output test for the menu rules (lib/menu.sh, lib/backend.sh): what
# toggling does to WANTED, what plan_changes picks, and the JSON the app and
# the installer read. Hardware and package state are stubbed, so no root, VM
# or hardware is needed.
# bash tests/menu-test.sh compare with menu-test.golden
# bash tests/menu-test.sh --update rewrite the golden file (review the diff!)
# The Steamify checkout (REPO, default: the steamify-cachyos next to this repo)
REPO="${REPO:-$(cd "$(dirname "$0")/../../steamify-cachyos" && pwd)}"; HERE="$(cd "$(dirname "$0")" && pwd)"; cd "$REPO" || exit 1
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
SCRIPT_DIR="$PWD"; HOME="$T/home"; mkdir -p "$HOME"
VERSION=0.0.0
for lib in $(grep -oP '^for lib in \K.*(?=; do$)' steamify.sh); do
source "lib/$lib.sh"
done
info() { :; }; ok() { :; }; warn() { :; }; err() { :; }
# From the entry point.
RESTART_FOR_LOGIN=false; restart_needed() { return 1; }
# Hardware profile and what is "on", set per scenario.
HW=""; ON=""
has() { [[ " $HW " == *" $1 "* ]]; }
nvidia_present() { has nvidia; }
nvidia_available() { has nvidia; }
bigpicture_available() { has nvidia; }
machine_available() { has fremont; }
detect_valve_fremont() { has fremont; }
vram_available() { has vram; }
vram_selectable() { return 0; }
steamgame_available() { has steam; }
kpin_available() { has fremont && [[ " $ON " == *" kpin "* ]]; }
hdmi_available() { return 1; }
bios_available() { return 1; }
bios_selectable() { return 1; }
cec_repair() { return 1; }
launcher_repair() { return 1; }
bios_lookup_newest() { :; }
kernel_overview() { :; }
os_version_refresh() { :; }
for c in "${COMPONENTS[@]}"; do
eval "${c}_status() { [[ \" \$ON \" == *\" $c \"* ]]; }"
done
show() {
# show <label>: WANTED as the ticked ids, then the plan.
local c w=""
for c in "${COMPONENTS[@]}"; do [[ "${WANTED[$c]:-0}" == 1 ]] && w+=" $c"; done
echo "$1"
echo " wanted:$w"
plan_changes
echo " disable: ${TO_DISABLE[*]:-}"
echo " enable: ${TO_ENABLE[*]:-}"
}
scenario() {
# scenario <name> <hardware> <on> [toggle...]
local name="$1"; HW="$2"; ON="$3"; shift 3
rm -rf "$STATE_DIR"; REAPPLY=false
detect_components
local t
for t in "$@"; do toggle_component "$t"; done
show "== $name"
}
run() {
scenario "pc first run" "" ""
scenario "pc first run, untick gaming" "" "" gaming
scenario "pc single on" "" "" gaming single
scenario "pc single then gaming off" "" "" single gaming
scenario "pc boot desktop" "" "" boot
scenario "pc boot desktop then gaming off" "" "" boot gaming
scenario "pc silent only" "" "gaming" silent
scenario "pc all on, theme off" "" "gaming boot silent theme glyphs single launcher steamgame notify" theme
scenario "pc launcher off" "" "launcher steamgame" launcher
scenario "pc steamgame on without launcher" "steam" "" gaming launcher steamgame
scenario "machine first run" "fremont steam vram" ""
scenario "machine silent hidden until boot desktop" "fremont steam vram" "gaming silent"
scenario "machine boot desktop keeps silent" "fremont steam vram" "gaming silent" boot
scenario "machine off" "fremont steam vram" "gaming machine poweroff" machine
scenario "machine poweroff off" "fremont steam vram" "gaming machine poweroff" poweroff
scenario "machine poweroff on brings machine" "fremont steam vram" "gaming" poweroff
scenario "machine kpin removal" "fremont steam vram" "gaming machine poweroff kpin"
scenario "nvidia first run" "nvidia steam" ""
scenario "nvidia bigpicture off" "nvidia steam" "nvidia bigpicture" bigpicture
scenario "nvidia nvsilent on" "nvidia steam" "nvidia bigpicture" nvsilent
scenario "nvidia nvsilent then bigpicture" "nvidia steam" "nvidia" nvsilent bigpicture
scenario "nvidia off" "nvidia steam" "nvidia bigpicture nvsilent" nvidia
scenario "nvidia single" "nvidia steam" "" single
scenario "nvidia gaming already on" "nvidia steam" "gaming" gaming
# Feature versions: an old record is ticked and re-applied.
HW=""; ON="gaming theme"; rm -rf "$STATE_DIR"; REAPPLY=false
state_set features gaming 2.1.0; state_set features theme 2.1.0
detect_components; show "== outdated features"
REAPPLY=true; ON="gaming theme launcher"; detect_components; show "== reapply (a)"
REAPPLY=false
# The app's own rules (backend_apply's normalisation) go through the same plan.
HW="fremont steam vram"; ON=""; rm -rf "$STATE_DIR"
detect_components
local sel
for sel in "single" "boot" "poweroff" "silent" "kpin" "gaming boot" "launcher steamgame"; do
echo "== backend_apply $sel"
backend_sudo() { return 0; }
backend_run_component() { return 0; }
# shellcheck disable=SC2086
backend_apply $sel | jq -c 'select(.event == "plan")'
done
HW="nvidia steam"; ON=""; detect_components
for sel in "bigpicture" "nvsilent" "bigpicture nvsilent" "single" "boot"; do
echo "== backend_apply nvidia $sel"
# shellcheck disable=SC2086
backend_apply $sel | jq -c 'select(.event == "plan")'
done
# JSON for the app and the installer page.
local hw
for hw in "" "fremont steam vram" "nvidia steam"; do
HW="$hw"; ON=""; rm -rf "$STATE_DIR"; detect_components
echo "== defaults_list [$hw]"
defaults_list | jq -S -c '.[]'
echo "== backend_status [$hw]"
backend_status | jq -S -c 'del(.kernel, .cecDevices, .leds)'
done
}
if [[ "${1:-}" == --update ]]; then
run > "$HERE/menu-test.golden" 2>&1
echo "wrote $HERE/menu-test.golden ($(wc -l < "$HERE/menu-test.golden") lines)"
elif diff -u "$HERE/menu-test.golden" <(run 2>&1); then
echo "ok menu rules, plan and JSON match the golden file"
else
echo "FAIL menu rules changed (diff above; --update if intended)"; exit 1
fi
+161
View File
@@ -0,0 +1,161 @@
"""Unit tests of the Python helpers in steamify-cachyos/patches (stdlib only).
Run through tests/python-test.sh (REPO = the Steamify checkout), or:
REPO=../steamify-cachyos python3 -m unittest tests/patches_test.py -v
"""
import contextlib
import importlib.util
import io
import os
import struct
import tempfile
import unittest
from unittest import mock
REPO = os.environ.get("REPO") or os.path.join(os.path.dirname(__file__), "..", "..", "steamify-cachyos")
def load(name, filename):
spec = importlib.util.spec_from_file_location(name, os.path.join(REPO, "patches", filename))
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
shortcuts = load("steam_shortcuts", "steam-shortcuts.py")
notifier = load("steamify_notifier", "steamify-notifier.py")
class VdfTests(unittest.TestCase):
def test_roundtrip(self):
root = [("shortcuts", [("0", [("appid", 123), ("AppName", "A"), ("tags", [])])])]
self.assertEqual(shortcuts.parse(shortcuts.dump(root)), root)
def test_empty_data_is_an_empty_list(self):
self.assertEqual(shortcuts.parse(b""), [("shortcuts", [])])
def test_unknown_type_is_an_error(self):
with self.assertRaises(ValueError):
shortcuts.parse(b"\x07key\0")
def test_ints_are_unsigned_32_bit(self):
data = shortcuts.dump([("n", -1)])
self.assertEqual(struct.unpack_from("<I", data, 3)[0], 0xFFFFFFFF)
def test_keys_match_regardless_of_case(self):
entry = [("AppName", "x")]
self.assertEqual(shortcuts.get(entry, "appname"), "x")
shortcuts.put(entry, "APPNAME", "y")
self.assertEqual(entry, [("AppName", "y")])
def test_ours(self):
exe = "/home/u/.local/share/steamify/bin/run-app"
self.assertTrue(shortcuts.ours([("Exe", f'"{exe}"')], exe))
# An older install's start script counts as ours: updated, not doubled.
self.assertTrue(shortcuts.ours([("Exe", '"/home/u/.local/share/cachyos-gamescope-boot/bin/run-app"')], exe))
self.assertFalse(shortcuts.ours([("Exe", '"/usr/bin/other"')], exe))
self.assertFalse(shortcuts.ours([("Exe", '"/home/u/games/run-app"')], exe))
class ShortcutsCommandTests(unittest.TestCase):
def setUp(self):
self.dir = tempfile.TemporaryDirectory()
self.addCleanup(self.dir.cleanup)
self.vdf = os.path.join(self.dir.name, "userdata", "1", "config", "shortcuts.vdf")
self.exe = "/home/u/.local/share/steamify/bin/run-app"
def run_cmd(self, *args):
out = io.StringIO()
with contextlib.redirect_stdout(out), contextlib.redirect_stderr(io.StringIO()):
rc = shortcuts.main(["steam-shortcuts.py", *args])
return rc, out.getvalue().strip()
def entries(self):
return shortcuts.shortcuts(shortcuts.load(self.vdf))
def test_add_creates_the_file_and_an_entry(self):
rc, out = self.run_cmd("add", self.vdf, "Steamify", self.exe, "/icon.png", "steamify.desktop")
self.assertEqual(rc, 0)
self.assertTrue(out.startswith("added "))
(_, entry), = self.entries()
self.assertEqual(shortcuts.get(entry, "AppName"), "Steamify")
self.assertEqual(shortcuts.get(entry, "Exe"), f'"{self.exe}"')
# Steam's id for a shortcut has the top bit set.
self.assertGreaterEqual(shortcuts.get(entry, "appid"), 0x80000000)
self.assertEqual(out, f"added {shortcuts.get(entry, 'appid')}")
def test_add_twice_updates_instead_of_doubling(self):
self.run_cmd("add", self.vdf, "Steamify", self.exe, "/a.png", "a.desktop")
rc, out = self.run_cmd("add", self.vdf, "Steamify 2", self.exe, "/b.png", "b.desktop")
self.assertTrue(out.startswith("updated "))
entries = self.entries()
self.assertEqual(len(entries), 1)
self.assertEqual(shortcuts.get(entries[0][1], "AppName"), "Steamify 2")
self.assertEqual(shortcuts.get(entries[0][1], "icon"), "/b.png")
def test_other_entries_are_kept(self):
self.run_cmd("add", self.vdf, "Other", "/usr/bin/other", "", "")
self.run_cmd("add", self.vdf, "Steamify", self.exe, "", "")
self.assertEqual(len(self.entries()), 2)
self.assertEqual([k for k, _ in self.entries()], ["0", "1"])
def test_find(self):
self.assertEqual(self.run_cmd("find", self.vdf, self.exe)[0], 1)
_, out = self.run_cmd("add", self.vdf, "Steamify", self.exe, "", "")
rc, found = self.run_cmd("find", self.vdf, self.exe)
self.assertEqual((rc, found), (0, out.split()[1]))
def test_remove_by_appid_renumbers(self):
self.run_cmd("add", self.vdf, "Other", "/usr/bin/other", "", "")
_, out = self.run_cmd("add", self.vdf, "Steamify", self.exe, "", "")
self.assertEqual(self.run_cmd("remove", self.vdf, out.split()[1])[0], 0)
entries = self.entries()
self.assertEqual([k for k, _ in entries], ["0"])
self.assertEqual(shortcuts.get(entries[0][1], "AppName"), "Other")
def test_remove_of_nothing_leaves_the_file_alone(self):
self.run_cmd("add", self.vdf, "Steamify", self.exe, "", "")
with open(self.vdf, "rb") as f:
before = f.read()
self.assertEqual(self.run_cmd("remove", self.vdf, "999")[0], 0)
with open(self.vdf, "rb") as f:
self.assertEqual(f.read(), before)
def test_unknown_command(self):
self.assertEqual(self.run_cmd("bogus", self.vdf)[0], 2)
class NotifierTests(unittest.TestCase):
def test_version(self):
self.assertEqual(notifier.version("v2.11.1"), (2, 11, 1))
self.assertEqual(notifier.version("2.9.0"), (2, 9, 0))
self.assertIsNone(notifier.version("nightly"))
def test_versions_compare_as_numbers(self):
self.assertGreater(notifier.version("2.10.0"), notifier.version("2.9.0"))
def pending(self, new, seen="", skipped=""):
values = {"seen": seen, "skipped": skipped}
with mock.patch.object(notifier, "state", lambda key: values[key]):
return notifier.pending(new)
def test_newer_than_seen(self):
self.assertTrue(self.pending("2.12.0", seen="2.11.1"))
def test_same_or_older_is_not_pending(self):
self.assertFalse(self.pending("2.11.1", seen="2.11.1"))
self.assertFalse(self.pending("2.9.0", seen="2.11.1"))
def test_skipped_version_is_not_pending(self):
self.assertFalse(self.pending("2.12.0", seen="2.11.1", skipped="2.12.0"))
def test_nothing_seen_yet(self):
self.assertTrue(self.pending("2.12.0", seen=""))
def test_unparsable_tag_is_not_pending(self):
# A release tag like "nightly" must not crash the daily check.
self.assertFalse(self.pending("nightly", seen="2.11.1"))
if __name__ == "__main__":
unittest.main()
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# Unit tests of the Python helpers in steamify-cachyos/patches (steam-shortcuts.py,
# steamify-notifier.py). No root, VM or hardware needed: bash tests/python-test.sh
# The Steamify checkout (REPO, default: the steamify-cachyos next to this repo)
REPO="${REPO:-$(cd "$(dirname "$0")/../../steamify-cachyos" && pwd)}"
export REPO
cd "$(dirname "$0")/.." || exit 1
if python3 -B -m unittest tests/patches_test.py 2>&1 | tail -n 25 | tee /dev/stderr | grep -q '^OK'; then
echo "ok Python helpers"
else
echo "FAIL Python helpers"; exit 1
fi