diff options
| author | Craig Jennings <c@cjennings.net> | 2025-11-14 02:35:00 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-11-14 02:35:00 -0600 |
| commit | 0febc3bb65462fd95a75387c2ec97ffa374efc00 (patch) | |
| tree | 95ff3ba5c3ab2da2a889530432d75e69ed993efa /tests/test-video-audio-recording-ffmpeg-functions.el | |
| parent | 9d55ed149e100b4fb3ef6f5a79d263dcb26ce835 (diff) | |
Revert "checking in modified/removed tests and other misc changes"
This reverts commit 9d55ed149e100b4fb3ef6f5a79d263dcb26ce835.
Diffstat (limited to 'tests/test-video-audio-recording-ffmpeg-functions.el')
| -rw-r--r-- | tests/test-video-audio-recording-ffmpeg-functions.el | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/tests/test-video-audio-recording-ffmpeg-functions.el b/tests/test-video-audio-recording-ffmpeg-functions.el new file mode 100644 index 00000000..e82614e2 --- /dev/null +++ b/tests/test-video-audio-recording-ffmpeg-functions.el @@ -0,0 +1,361 @@ +;;; test-video-audio-recording-ffmpeg-functions.el --- Tests for ffmpeg recording functions -*- lexical-binding: t; -*- + +;;; Commentary: +;; Unit tests for cj/ffmpeg-record-video, cj/ffmpeg-record-audio, +;; cj/video-recording-stop, and cj/audio-recording-stop functions. +;; Tests process creation, sentinel attachment, and cleanup. + +;;; Code: + +(require 'ert) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub directory variables +(defvar video-recordings-dir "/tmp/video-recordings/") +(defvar audio-recordings-dir "/tmp/audio-recordings/") + +;; Now load the actual production module +(require 'video-audio-recording) + +;;; Setup and Teardown + +(defun test-ffmpeg-setup () + "Reset all variables before each test." + (setq cj/video-recording-ffmpeg-process nil) + (setq cj/audio-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 0.5)) + +(defun test-ffmpeg-teardown () + "Clean up after each test." + (when cj/video-recording-ffmpeg-process + (ignore-errors (delete-process cj/video-recording-ffmpeg-process))) + (when cj/audio-recording-ffmpeg-process + (ignore-errors (delete-process cj/audio-recording-ffmpeg-process))) + (setq cj/video-recording-ffmpeg-process nil) + (setq cj/audio-recording-ffmpeg-process nil) + (setq cj/recording-mic-device nil) + (setq cj/recording-system-device nil)) + +;;; Video Recording - Normal Cases + +(ert-deftest test-video-audio-recording-ffmpeg-record-video-normal-creates-process () + "Test that video recording creates a process." + (test-ffmpeg-setup) + (unwind-protect + (let ((process-created nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (setq process-created t) + (make-process :name "fake-video" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-video video-recordings-dir) + (should process-created) + (should cj/video-recording-ffmpeg-process))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-video-normal-attaches-sentinel () + "Test that video recording attaches sentinel to process." + (test-ffmpeg-setup) + (unwind-protect + (let ((sentinel-attached nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (make-process :name "fake-video" :command '("sleep" "1000")))) + ((symbol-function 'set-process-sentinel) + (lambda (_proc sentinel) + (should (eq sentinel #'cj/recording-process-sentinel)) + (setq sentinel-attached t)))) + (cj/ffmpeg-record-video video-recordings-dir) + (should sentinel-attached))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-video-normal-updates-modeline () + "Test that video recording triggers modeline update." + (test-ffmpeg-setup) + (unwind-protect + (let ((update-called nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (make-process :name "fake-video" :command '("sleep" "1000")))) + ((symbol-function 'force-mode-line-update) + (lambda (&optional _all) (setq update-called t)))) + (cj/ffmpeg-record-video video-recordings-dir) + (should update-called))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-video-normal-uses-device-settings () + "Test that video recording uses configured devices and volume settings." + (test-ffmpeg-setup) + (unwind-protect + (let ((command nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer cmd) + (setq command cmd) + (make-process :name "fake-video" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-video video-recordings-dir) + (should (string-match-p "test-mic-device" command)) + (should (string-match-p "test-monitor-device" command)) + (should (string-match-p "2\\.0" command)) ; mic boost + (should (string-match-p "0\\.5" command)))) ; system volume + (test-ffmpeg-teardown))) + +;;; Audio Recording - Normal Cases + +(ert-deftest test-video-audio-recording-ffmpeg-record-audio-normal-creates-process () + "Test that audio recording creates a process." + (test-ffmpeg-setup) + (unwind-protect + (let ((process-created nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (setq process-created t) + (make-process :name "fake-audio" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-audio audio-recordings-dir) + (should process-created) + (should cj/audio-recording-ffmpeg-process))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-audio-normal-attaches-sentinel () + "Test that audio recording attaches sentinel to process." + (test-ffmpeg-setup) + (unwind-protect + (let ((sentinel-attached nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (make-process :name "fake-audio" :command '("sleep" "1000")))) + ((symbol-function 'set-process-sentinel) + (lambda (_proc sentinel) + (should (eq sentinel #'cj/recording-process-sentinel)) + (setq sentinel-attached t)))) + (cj/ffmpeg-record-audio audio-recordings-dir) + (should sentinel-attached))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-audio-normal-updates-modeline () + "Test that audio recording triggers modeline update." + (test-ffmpeg-setup) + (unwind-protect + (let ((update-called nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (make-process :name "fake-audio" :command '("sleep" "1000")))) + ((symbol-function 'force-mode-line-update) + (lambda (&optional _all) (setq update-called t)))) + (cj/ffmpeg-record-audio audio-recordings-dir) + (should update-called))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-audio-normal-creates-m4a-file () + "Test that audio recording creates .m4a file." + (test-ffmpeg-setup) + (unwind-protect + (let ((command nil)) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer cmd) + (setq command cmd) + (make-process :name "fake-audio" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-audio audio-recordings-dir) + (should (string-match-p "\\.m4a" command)))) + (test-ffmpeg-teardown))) + +;;; Stop Functions - Normal Cases + +(ert-deftest test-video-audio-recording-video-stop-normal-interrupts-process () + "Test that stopping video recording interrupts the process." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000"))) + (interrupt-called nil)) + (setq cj/video-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'interrupt-process) + (lambda (_proc) (setq interrupt-called t)))) + (cj/video-recording-stop) + (should interrupt-called)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-video-stop-normal-clears-variable () + "Test that stopping video recording clears the process variable." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000")))) + (setq cj/video-recording-ffmpeg-process fake-process) + (cj/video-recording-stop) + (should (null cj/video-recording-ffmpeg-process)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-video-stop-normal-updates-modeline () + "Test that stopping video recording updates modeline." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000"))) + (update-called nil)) + (setq cj/video-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'force-mode-line-update) + (lambda (&optional _all) (setq update-called t)))) + (cj/video-recording-stop) + (should update-called)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-audio-stop-normal-interrupts-process () + "Test that stopping audio recording interrupts the process." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))) + (interrupt-called nil)) + (setq cj/audio-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'interrupt-process) + (lambda (_proc) (setq interrupt-called t)))) + (cj/audio-recording-stop) + (should interrupt-called)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-audio-stop-normal-clears-variable () + "Test that stopping audio recording clears the process variable." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000")))) + (setq cj/audio-recording-ffmpeg-process fake-process) + (cj/audio-recording-stop) + (should (null cj/audio-recording-ffmpeg-process)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +;;; Boundary Cases + +(ert-deftest test-video-audio-recording-video-stop-boundary-no-process-displays-message () + "Test that stopping when no video recording shows message." + (test-ffmpeg-setup) + (unwind-protect + (let ((message-text nil)) + (setq cj/video-recording-ffmpeg-process nil) + (cl-letf (((symbol-function 'message) + (lambda (fmt &rest args) (setq message-text (apply #'format fmt args))))) + (cj/video-recording-stop) + (should (string-match-p "No video recording" message-text)))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-audio-stop-boundary-no-process-displays-message () + "Test that stopping when no audio recording shows message." + (test-ffmpeg-setup) + (unwind-protect + (let ((message-text nil)) + (setq cj/audio-recording-ffmpeg-process nil) + (cl-letf (((symbol-function 'message) + (lambda (fmt &rest args) (setq message-text (apply #'format fmt args))))) + (cj/audio-recording-stop) + (should (string-match-p "No audio recording" message-text)))) + (test-ffmpeg-teardown))) + +;;; Error Cases + +(ert-deftest test-video-audio-recording-video-stop-error-interrupt-process-fails () + "Test that video stop handles interrupt-process failure gracefully." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000"))) + (error-raised nil)) + (setq cj/video-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'interrupt-process) + (lambda (_proc) (error "Interrupt failed")))) + ;; Should handle the error without crashing + (condition-case err + (cj/video-recording-stop) + (error (setq error-raised t))) + ;; Error should propagate (function doesn't catch it) + (should error-raised)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-audio-stop-error-interrupt-process-fails () + "Test that audio stop handles interrupt-process failure gracefully." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))) + (error-raised nil)) + (setq cj/audio-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'interrupt-process) + (lambda (_proc) (error "Interrupt failed")))) + ;; Should handle the error without crashing + (condition-case err + (cj/audio-recording-stop) + (error (setq error-raised t))) + ;; Error should propagate (function doesn't catch it) + (should error-raised)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-video-stop-error-dead-process-raises-error () + "Test that video stop raises error if process is already dead. +This documents current behavior - interrupt-process on dead process errors. +The sentinel should clear the variable before this happens in practice." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000")))) + (setq cj/video-recording-ffmpeg-process fake-process) + ;; Kill process before calling stop + (delete-process fake-process) + (sit-for 0.1) + ;; Calling stop on dead process raises error + (should-error (cj/video-recording-stop))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-audio-stop-error-dead-process-raises-error () + "Test that audio stop raises error if process is already dead. +This documents current behavior - interrupt-process on dead process errors. +The sentinel should clear the variable before this happens in practice." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000")))) + (setq cj/audio-recording-ffmpeg-process fake-process) + ;; Kill process before calling stop + (delete-process fake-process) + (sit-for 0.1) + ;; Calling stop on dead process raises error + (should-error (cj/audio-recording-stop))) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-video-boundary-skips-if-already-recording () + "Test that video recording skips if already in progress." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-video" :command '("sleep" "1000"))) + (start-called nil)) + (setq cj/video-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (setq start-called t) + (make-process :name "fake-video2" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-video video-recordings-dir) + ;; Should NOT start a new process + (should-not start-called)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(ert-deftest test-video-audio-recording-ffmpeg-record-audio-boundary-skips-if-already-recording () + "Test that audio recording skips if already in progress." + (test-ffmpeg-setup) + (unwind-protect + (let ((fake-process (make-process :name "test-audio" :command '("sleep" "1000"))) + (start-called nil)) + (setq cj/audio-recording-ffmpeg-process fake-process) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buffer _command) + (setq start-called t) + (make-process :name "fake-audio2" :command '("sleep" "1000"))))) + (cj/ffmpeg-record-audio audio-recordings-dir) + ;; Should NOT start a new process + (should-not start-called)) + (delete-process fake-process)) + (test-ffmpeg-teardown))) + +(provide 'test-video-audio-recording-ffmpeg-functions) +;;; test-video-audio-recording-ffmpeg-functions.el ends here |
