summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-02-03 08:57:10 -0600
committerCraig Jennings <c@cjennings.net>2026-02-03 08:57:10 -0600
commitcebb70fd5799f0bb9eaa7c14747408095619fc08 (patch)
tree4d7a36f380cf1dfb7f2f62b80bd668de81079ac9 /tests
parent3c9f31b2f1249a2f5911a300ad48a894443d3009 (diff)
test(video-recording): add process cleanup tests
Unit tests verify pkill wf-recorder is called: - On Wayland video stop (to kill orphan wf-recorder) - On Wayland video start (to clean previous orphans) - NOT called on X11 (only relevant for Wayland pipeline) Integration tests (tagged :integration :wayland) verify actual cleanup: - No orphan processes after stop - Start cleans up existing orphans - Multiple start/stop cycles don't accumulate orphans
Diffstat (limited to 'tests')
-rw-r--r--tests/test-video-audio-recording-process-cleanup.el229
1 files changed, 229 insertions, 0 deletions
diff --git a/tests/test-video-audio-recording-process-cleanup.el b/tests/test-video-audio-recording-process-cleanup.el
new file mode 100644
index 00000000..10b17f2c
--- /dev/null
+++ b/tests/test-video-audio-recording-process-cleanup.el
@@ -0,0 +1,229 @@
+;;; test-video-audio-recording-process-cleanup.el --- Tests for recording process cleanup -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Tests that verify proper cleanup of recording processes, especially
+;; wf-recorder on Wayland which can become orphaned if not explicitly killed.
+;;
+;; Unit tests verify pkill is called at the right times.
+;; Integration tests verify no orphan processes remain after stop.
+
+;;; Code:
+
+(require 'ert)
+
+;; Stub dependencies before loading the module
+(defvar cj/custom-keymap (make-sparse-keymap)
+ "Stub keymap for testing.")
+
+(defvar video-recordings-dir "/tmp/video-recordings/")
+
+;; Now load the actual production module
+(require 'video-audio-recording)
+
+;;; Setup and Teardown
+
+(defun test-cleanup-setup ()
+ "Reset all variables before each test."
+ (setq cj/video-recording-ffmpeg-process nil)
+ (setq cj/recording-mic-device "test-mic-device")
+ (setq cj/recording-system-device "test-monitor-device")
+ (setq cj/recording-mic-boost 2.0)
+ (setq cj/recording-system-volume 1.0))
+
+(defun test-cleanup-teardown ()
+ "Clean up after each test."
+ (when cj/video-recording-ffmpeg-process
+ (ignore-errors (delete-process cj/video-recording-ffmpeg-process)))
+ (setq cj/video-recording-ffmpeg-process nil)
+ (setq cj/recording-mic-device nil)
+ (setq cj/recording-system-device nil))
+
+;;; Unit Tests - Verify pkill is called
+
+(ert-deftest test-video-recording-stop-wayland-calls-pkill-wf-recorder ()
+ "Test that stopping video on Wayland calls pkill to kill wf-recorder."
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000")))
+ (pkill-called nil)
+ (pkill-args nil))
+ (setq cj/video-recording-ffmpeg-process fake-process)
+ (cl-letf (((symbol-function 'cj/recording--wayland-p) (lambda () t))
+ ((symbol-function 'call-process)
+ (lambda (program &rest args)
+ (when (equal program "pkill")
+ (setq pkill-called t)
+ (setq pkill-args args))
+ 0))
+ ((symbol-function 'interrupt-process) (lambda (_proc) nil)))
+ (cj/video-recording-stop)
+ (should pkill-called)
+ ;; Should call: pkill -INT wf-recorder
+ (should (member "-INT" pkill-args))
+ (should (member "wf-recorder" pkill-args)))
+ (ignore-errors (delete-process fake-process)))
+ (test-cleanup-teardown)))
+
+(ert-deftest test-video-recording-stop-x11-does-not-call-pkill ()
+ "Test that stopping video on X11 does NOT call pkill wf-recorder."
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000")))
+ (pkill-called nil))
+ (setq cj/video-recording-ffmpeg-process fake-process)
+ (cl-letf (((symbol-function 'cj/recording--wayland-p) (lambda () nil))
+ ((symbol-function 'call-process)
+ (lambda (program &rest _args)
+ (when (equal program "pkill")
+ (setq pkill-called t))
+ 0))
+ ((symbol-function 'interrupt-process) (lambda (_proc) nil)))
+ (cj/video-recording-stop)
+ ;; Should NOT call pkill on X11
+ (should-not pkill-called))
+ (ignore-errors (delete-process fake-process)))
+ (test-cleanup-teardown)))
+
+(ert-deftest test-video-recording-start-wayland-kills-orphans ()
+ "Test that starting video on Wayland kills orphan wf-recorder processes."
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((pkill-called nil)
+ (pkill-args nil))
+ (cl-letf (((symbol-function 'cj/recording--wayland-p) (lambda () t))
+ ((symbol-function 'cj/recording--check-wf-recorder) (lambda () t))
+ ((symbol-function 'call-process)
+ (lambda (program &rest args)
+ (when (equal program "pkill")
+ (setq pkill-called t)
+ (setq pkill-args args))
+ 0))
+ ((symbol-function 'start-process-shell-command)
+ (lambda (_name _buffer _command)
+ (make-process :name "fake-video" :command '("sleep" "1000")))))
+ (cj/ffmpeg-record-video video-recordings-dir)
+ ;; Should call pkill to clean up orphans before starting
+ (should pkill-called)
+ (should (member "-INT" pkill-args))
+ (should (member "wf-recorder" pkill-args))))
+ (test-cleanup-teardown)))
+
+(ert-deftest test-video-recording-start-x11-does-not-kill-orphans ()
+ "Test that starting video on X11 does NOT call pkill."
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((pkill-called nil))
+ (cl-letf (((symbol-function 'cj/recording--wayland-p) (lambda () nil))
+ ((symbol-function 'call-process)
+ (lambda (program &rest _args)
+ (when (equal program "pkill")
+ (setq pkill-called t))
+ 0))
+ ((symbol-function 'start-process-shell-command)
+ (lambda (_name _buffer _command)
+ (make-process :name "fake-video" :command '("sleep" "1000")))))
+ (cj/ffmpeg-record-video video-recordings-dir)
+ ;; Should NOT call pkill on X11
+ (should-not pkill-called)))
+ (test-cleanup-teardown)))
+
+;;; Integration Tests - Verify actual process cleanup
+;;; These tests require wf-recorder to be installed and a Wayland session
+
+(defun test-cleanup--count-wf-recorder-processes ()
+ "Count running wf-recorder processes."
+ (let ((output (shell-command-to-string "pgrep -c wf-recorder 2>/dev/null || echo 0")))
+ (string-to-number (string-trim output))))
+
+(defun test-cleanup--get-wf-recorder-pids ()
+ "Get list of wf-recorder PIDs."
+ (let ((output (shell-command-to-string "pgrep wf-recorder 2>/dev/null")))
+ (when (and output (not (string-empty-p (string-trim output))))
+ (mapcar #'string-to-number (split-string (string-trim output) "\n")))))
+
+(ert-deftest test-integration-video-recording-no-orphan-wf-recorder-after-stop ()
+ "Test that no wf-recorder processes remain after stopping recording.
+This is an integration test that requires wf-recorder and Wayland."
+ :tags '(:integration :wayland)
+ (skip-unless (executable-find "wf-recorder"))
+ (skip-unless (cj/recording--wayland-p))
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((initial-count (test-cleanup--count-wf-recorder-processes)))
+ ;; Start recording
+ (cj/ffmpeg-record-video video-recordings-dir)
+ (sit-for 1.0) ; Let it start
+
+ ;; Should have at least one wf-recorder running
+ (should (> (test-cleanup--count-wf-recorder-processes) initial-count))
+
+ ;; Stop recording
+ (cj/video-recording-stop)
+ (sit-for 1.0) ; Let cleanup complete
+
+ ;; Should be back to initial count (no orphans)
+ (should (= (test-cleanup--count-wf-recorder-processes) initial-count)))
+ (test-cleanup-teardown)
+ ;; Extra cleanup in case test failed mid-way
+ (ignore-errors (call-process "pkill" nil nil nil "-INT" "wf-recorder"))))
+
+(ert-deftest test-integration-video-recording-start-cleans-orphans ()
+ "Test that starting a recording cleans up any orphan wf-recorder processes.
+This is an integration test that requires wf-recorder and Wayland."
+ :tags '(:integration :wayland)
+ (skip-unless (executable-find "wf-recorder"))
+ (skip-unless (cj/recording--wayland-p))
+ (test-cleanup-setup)
+ (unwind-protect
+ (progn
+ ;; Create an orphan wf-recorder (simulating a crash)
+ (start-process "orphan-wf" nil "wf-recorder" "-c" "libx264" "-m" "matroska" "-f" "/dev/null")
+ (sit-for 0.5)
+
+ (let ((orphan-pids (test-cleanup--get-wf-recorder-pids)))
+ (should orphan-pids) ; Verify orphan was created
+
+ ;; Start recording - should clean up orphan
+ (cj/ffmpeg-record-video video-recordings-dir)
+ (sit-for 1.0)
+
+ ;; The orphan PIDs should no longer exist
+ (let ((current-pids (test-cleanup--get-wf-recorder-pids)))
+ ;; Old orphan should be gone (new recording process may exist)
+ (dolist (orphan-pid orphan-pids)
+ ;; Check if old orphan is still in current pids
+ ;; It's OK if there's a NEW wf-recorder, just not the orphan
+ (let ((still-running (member orphan-pid current-pids)))
+ (should-not still-running))))
+
+ ;; Clean up the recording we started
+ (cj/video-recording-stop)
+ (sit-for 0.5)))
+ (test-cleanup-teardown)
+ ;; Extra cleanup
+ (ignore-errors (call-process "pkill" nil nil nil "-INT" "wf-recorder"))))
+
+(ert-deftest test-integration-video-recording-multiple-start-stop-cycles ()
+ "Test that multiple recording cycles don't accumulate orphan processes.
+This is an integration test that requires wf-recorder and Wayland."
+ :tags '(:integration :wayland)
+ (skip-unless (executable-find "wf-recorder"))
+ (skip-unless (cj/recording--wayland-p))
+ (test-cleanup-setup)
+ (unwind-protect
+ (let ((initial-count (test-cleanup--count-wf-recorder-processes)))
+ ;; Do 3 start/stop cycles
+ (dotimes (_ 3)
+ (cj/ffmpeg-record-video video-recordings-dir)
+ (sit-for 0.5)
+ (cj/video-recording-stop)
+ (sit-for 0.5))
+
+ ;; Should be back to initial count - no accumulated orphans
+ (should (= (test-cleanup--count-wf-recorder-processes) initial-count)))
+ (test-cleanup-teardown)
+ ;; Extra cleanup
+ (ignore-errors (call-process "pkill" nil nil nil "-INT" "wf-recorder"))))
+
+(provide 'test-video-audio-recording-process-cleanup)
+;;; test-video-audio-recording-process-cleanup.el ends here