summaryrefslogtreecommitdiff
path: root/tests/test-video-audio-recording-process-sentinel.el
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-video-audio-recording-process-sentinel.el')
-rw-r--r--tests/test-video-audio-recording-process-sentinel.el190
1 files changed, 190 insertions, 0 deletions
diff --git a/tests/test-video-audio-recording-process-sentinel.el b/tests/test-video-audio-recording-process-sentinel.el
new file mode 100644
index 00000000..37a7f94d
--- /dev/null
+++ b/tests/test-video-audio-recording-process-sentinel.el
@@ -0,0 +1,190 @@
+;;; test-video-audio-recording-process-sentinel.el --- Tests for cj/recording-process-sentinel -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Unit tests for cj/recording-process-sentinel function.
+;; Tests process cleanup and modeline update when recording processes exit.
+
+;;; Code:
+
+(require 'ert)
+
+;; Stub dependencies before loading the module
+(defvar cj/custom-keymap (make-sparse-keymap)
+ "Stub keymap for testing.")
+
+;; Now load the actual production module
+(require 'video-audio-recording)
+
+;;; Setup and Teardown
+
+(defun test-sentinel-setup ()
+ "Reset process variables before each test."
+ (setq cj/audio-recording-ffmpeg-process nil)
+ (setq cj/video-recording-ffmpeg-process nil))
+
+(defun test-sentinel-teardown ()
+ "Clean up process variables after each test."
+ (setq cj/audio-recording-ffmpeg-process nil)
+ (setq cj/video-recording-ffmpeg-process nil))
+
+;;; Normal Cases
+
+(ert-deftest test-video-audio-recording-process-sentinel-normal-audio-exit-clears-variable ()
+ "Test that sentinel clears audio process variable when process exits."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock process-status to return 'exit
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'exit)))
+ ;; Call sentinel with exit status
+ (cj/recording-process-sentinel fake-process "finished\n")
+ ;; Variable should be cleared
+ (should (null cj/audio-recording-ffmpeg-process))))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-normal-video-exit-clears-variable ()
+ "Test that sentinel clears video process variable when process exits."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-video" :command '("sh" "-c" "exit 0"))))
+ (setq cj/video-recording-ffmpeg-process fake-process)
+ ;; Mock process-status to return 'exit
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'exit)))
+ ;; Call sentinel with exit status
+ (cj/recording-process-sentinel fake-process "finished\n")
+ ;; Variable should be cleared
+ (should (null cj/video-recording-ffmpeg-process))))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-normal-signal-status-clears-variable ()
+ "Test that sentinel clears variable on signal status (killed)."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ (delete-process fake-process)
+ ;; Call sentinel with signal status
+ (cj/recording-process-sentinel fake-process "killed\n")
+ ;; Variable should be cleared
+ (should (null cj/audio-recording-ffmpeg-process)))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-normal-modeline-update-called ()
+ "Test that sentinel triggers modeline update."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0")))
+ (update-called nil))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock force-mode-line-update to track if it's called
+ (cl-letf (((symbol-function 'force-mode-line-update)
+ (lambda (&optional _all) (setq update-called t))))
+ (cj/recording-process-sentinel fake-process "finished\n")
+ (should update-called)))
+ (test-sentinel-teardown)))
+
+;;; Boundary Cases
+
+(ert-deftest test-video-audio-recording-process-sentinel-boundary-run-status-ignored ()
+ "Test that sentinel ignores processes in 'run status (still running)."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock process-status to return 'run
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'run)))
+ (cj/recording-process-sentinel fake-process "run")
+ ;; Variable should NOT be cleared
+ (should (eq fake-process cj/audio-recording-ffmpeg-process)))
+ (delete-process fake-process))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-boundary-open-status-ignored ()
+ "Test that sentinel ignores processes in 'open status."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'open)))
+ (cj/recording-process-sentinel fake-process "open")
+ ;; Variable should NOT be cleared
+ (should (eq fake-process cj/audio-recording-ffmpeg-process)))
+ (delete-process fake-process))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-boundary-event-trimmed ()
+ "Test that event string is trimmed in message."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0")))
+ (message-text nil))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock message to capture output
+ (cl-letf (((symbol-function 'message)
+ (lambda (fmt &rest args) (setq message-text (apply #'format fmt args)))))
+ (cj/recording-process-sentinel fake-process " finished \n")
+ ;; Message should contain trimmed event
+ (should (string-match-p "finished" message-text))
+ ;; Should not have extra whitespace
+ (should-not (string-match-p " finished " message-text))))
+ (test-sentinel-teardown)))
+
+;;; Error Cases
+
+(ert-deftest test-video-audio-recording-process-sentinel-error-unknown-process-ignored ()
+ "Test that sentinel handles unknown process (not audio or video) gracefully."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-unknown" :command '("sh" "-c" "exit 0")))
+ (audio-proc (make-process :name "test-audio" :command '("sleep" "1000")))
+ (video-proc (make-process :name "test-video" :command '("sleep" "1000"))))
+ (setq cj/audio-recording-ffmpeg-process audio-proc)
+ (setq cj/video-recording-ffmpeg-process video-proc)
+ ;; Call sentinel with unknown process
+ (cj/recording-process-sentinel fake-process "finished\n")
+ ;; Audio and video variables should NOT be cleared
+ (should (eq audio-proc cj/audio-recording-ffmpeg-process))
+ (should (eq video-proc cj/video-recording-ffmpeg-process))
+ (delete-process audio-proc)
+ (delete-process video-proc))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-error-nil-event-handled ()
+ "Test that sentinel handles nil event string gracefully."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock process-status to return 'exit
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'exit)))
+ ;; Should not crash with nil event (string-trim will error, but that's caught)
+ ;; The function uses string-trim without protection, so this will error
+ ;; Testing that it doesn't crash means we expect an error
+ (should-error
+ (cj/recording-process-sentinel fake-process nil))))
+ (test-sentinel-teardown)))
+
+(ert-deftest test-video-audio-recording-process-sentinel-error-empty-event-handled ()
+ "Test that sentinel handles empty event string gracefully."
+ (test-sentinel-setup)
+ (unwind-protect
+ (let ((fake-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0"))))
+ (setq cj/audio-recording-ffmpeg-process fake-process)
+ ;; Mock process-status to return 'exit
+ (cl-letf (((symbol-function 'process-status)
+ (lambda (_proc) 'exit)))
+ ;; Empty string is fine - string-trim handles it
+ ;; No error should be raised
+ (cj/recording-process-sentinel fake-process "")
+ ;; Variable should be cleared
+ (should (null cj/audio-recording-ffmpeg-process))))
+ (test-sentinel-teardown)))
+
+(provide 'test-video-audio-recording-process-sentinel)
+;;; test-video-audio-recording-process-sentinel.el ends here