diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-10 16:36:47 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-10 16:36:47 -0500 |
| commit | 3c64dac1b98049d475be838294349326c32248ae (patch) | |
| tree | 626917ca3660d34b48195a77123b1def3d418282 /tests/test-chime-validation-retry.el | |
| parent | 0772736d2bca36472f623d5258784f41db9b4f9a (diff) | |
| download | chime-3c64dac1b98049d475be838294349326c32248ae.tar.gz chime-3c64dac1b98049d475be838294349326c32248ae.zip | |
feat: tighten chime runtime validation and tooltip behavior
Diffstat (limited to 'tests/test-chime-validation-retry.el')
| -rw-r--r-- | tests/test-chime-validation-retry.el | 574 |
1 files changed, 261 insertions, 313 deletions
diff --git a/tests/test-chime-validation-retry.el b/tests/test-chime-validation-retry.el index 70188bc..a2765f4 100644 --- a/tests/test-chime-validation-retry.el +++ b/tests/test-chime-validation-retry.el @@ -20,37 +20,21 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) +(require 'testutil-general (expand-file-name "testutil-general.el")) +(require 'testutil-time (expand-file-name "testutil-time.el")) +(require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup and Teardown -(defvar test-chime-validation-retry--original-max-retries nil - "Original value of chime--validation-max-retries for restoration.") - -(defvar test-chime-validation-retry--original-agenda-files nil - "Original value of org-agenda-files for restoration.") - -(defun test-chime-validation-retry-setup () - "Set up test environment before each test." - ;; Save original values - (setq test-chime-validation-retry--original-max-retries chime--validation-max-retries) - (setq test-chime-validation-retry--original-agenda-files org-agenda-files) - - ;; Reset validation state - (setq chime--validation-done nil) - (setq chime--validation-retry-count 0) - - ;; Set predictable defaults - (setq chime--validation-max-retries 3)) - -(defun test-chime-validation-retry-teardown () - "Clean up test environment after each test." - ;; Restore original values - (setq chime--validation-max-retries test-chime-validation-retry--original-max-retries) - (setq org-agenda-files test-chime-validation-retry--original-agenda-files) - - ;; Reset validation state - (setq chime--validation-done nil) - (setq chime--validation-retry-count 0)) +(defmacro test-chime-validation-retry--with-state (&rest body) + "Run BODY with isolated validation retry state." + (declare (indent 0)) + `(with-chime-config + chime--validation-max-retries 3 + org-agenda-files nil + (let ((chime--validation-done nil) + (chime--validation-retry-count 0)) + ,@body))) ;;; Normal Cases - Retry Behavior @@ -60,35 +44,32 @@ When org-agenda-files is empty on the first check, chime should show a friendly waiting message instead of immediately displaying the full error. This accommodates async org-agenda-files initialization." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Empty org-agenda-files to trigger validation failure - (setq org-agenda-files nil) - - ;; Capture message output - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages))) - ;; Mock fetch to prevent actual agenda processing - ((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; Call chime-check - (chime-check) - - ;; Should show waiting message - (should (= chime--validation-retry-count 1)) - (should-not chime--validation-done) - (should (cl-some (lambda (msg) - (string-match-p "Waiting for org-agenda-files" msg)) - messages)) - ;; Should NOT show error message - (should-not (cl-some (lambda (msg) - (string-match-p "Configuration errors detected" msg)) - messages))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Empty org-agenda-files to trigger validation failure + (setq org-agenda-files nil) + + ;; Capture message output + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages))) + ;; Mock fetch to prevent actual agenda processing + ((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; Call chime-check + (chime-check) + + ;; Should show waiting message + (should (= chime--validation-retry-count 1)) + (should-not chime--validation-done) + (should (cl-some (lambda (msg) + (string-match-p "Waiting for org-agenda-files" msg)) + messages)) + ;; Should NOT show error message + (should-not (cl-some (lambda (msg) + (string-match-p "Configuration errors detected" msg)) + messages)))))) (ert-deftest test-chime-validation-retry-normal-success-resets-counter () "Test successful validation after retry resets counter to zero. @@ -96,83 +77,74 @@ error. This accommodates async org-agenda-files initialization." When validation succeeds on a retry attempt, the retry counter should be reset to 0, allowing fresh retry attempts if validation fails again later (e.g., after mode restart)." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Simulate one failed attempt - (setq chime--validation-retry-count 1) + (test-chime-validation-retry--with-state + ;; Simulate one failed attempt + (setq chime--validation-retry-count 1) - ;; Set valid org-agenda-files - (setq org-agenda-files '("/tmp/test.org")) + ;; Set valid org-agenda-files + (setq org-agenda-files '("/tmp/test.org")) - ;; Mock fetch to prevent actual agenda processing - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) + ;; Mock fetch to prevent actual agenda processing + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) - ;; Call chime-check - should succeed - (chime-check) + ;; Call chime-check - should succeed + (chime-check) - ;; Counter should be reset - (should (= chime--validation-retry-count 0)) - ;; Validation marked as done - (should chime--validation-done))) - (test-chime-validation-retry-teardown))) + ;; Counter should be reset + (should (= chime--validation-retry-count 0)) + ;; Validation marked as done + (should chime--validation-done)))) (ert-deftest test-chime-validation-retry-normal-multiple-retries-increment () "Test multiple validation failures increment counter correctly. Each validation failure should increment the retry counter by 1, allowing the system to track how many retries have been attempted." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Empty org-agenda-files - (setq org-agenda-files nil) - - ;; Mock fetch - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil)) - ((symbol-function 'message) - (lambda (&rest args) nil))) - - ;; First attempt - (chime-check) - (should (= chime--validation-retry-count 1)) - - ;; Second attempt - (chime-check) - (should (= chime--validation-retry-count 2)) - - ;; Third attempt - (chime-check) - (should (= chime--validation-retry-count 3)))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Empty org-agenda-files + (setq org-agenda-files nil) + + ;; Mock fetch + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil)) + ((symbol-function 'message) + (lambda (&rest args) nil))) + + ;; First attempt + (chime-check) + (should (= chime--validation-retry-count 1)) + + ;; Second attempt + (chime-check) + (should (= chime--validation-retry-count 2)) + + ;; Third attempt + (chime-check) + (should (= chime--validation-retry-count 3))))) (ert-deftest test-chime-validation-retry-normal-successful-validation-proceeds () "Test successful validation proceeds with event checking. When validation passes, chime-check should proceed to fetch and process events normally." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Valid org-agenda-files - (setq org-agenda-files '("/tmp/test.org")) - - ;; Track if fetch was called - (let ((fetch-called nil)) - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) - (setq fetch-called t)))) - - ;; Call chime-check - (chime-check) - - ;; Should proceed to fetch - (should fetch-called) - (should chime--validation-done) - (should (= chime--validation-retry-count 0))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Valid org-agenda-files + (setq org-agenda-files '("/tmp/test.org")) + + ;; Track if fetch was called + (let ((fetch-called nil)) + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) + (setq fetch-called t)))) + + ;; Call chime-check + (chime-check) + + ;; Should proceed to fetch + (should fetch-called) + (should chime--validation-done) + (should (= chime--validation-retry-count 0)))))) ;;; Boundary Cases - Edge Conditions @@ -182,159 +154,144 @@ process events normally." When chime--validation-max-retries is set to 0, validation failures should immediately show the full error message without any retry attempts." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Set max retries to 0 - (setq chime--validation-max-retries 0) - - ;; Empty org-agenda-files - (setq org-agenda-files nil) - - ;; Capture message output - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages))) - ((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; Call chime-check - (chime-check) - - ;; Counter incremented - (should (= chime--validation-retry-count 1)) - ;; Should show error, not waiting message - (should (cl-some (lambda (msg) - (string-match-p "Configuration errors detected" msg)) - messages)) - (should-not (cl-some (lambda (msg) - (string-match-p "Waiting for" msg)) - messages))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Set max retries to 0 + (setq chime--validation-max-retries 0) + + ;; Empty org-agenda-files + (setq org-agenda-files nil) + + ;; Capture message output + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages))) + ((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; Call chime-check + (chime-check) + + ;; Counter incremented + (should (= chime--validation-retry-count 1)) + ;; Should show error, not waiting message + (should (cl-some (lambda (msg) + (string-match-p "Configuration errors detected" msg)) + messages)) + (should-not (cl-some (lambda (msg) + (string-match-p "Waiting for" msg)) + messages)))))) (ert-deftest test-chime-validation-retry-boundary-max-retries-one () "Test max-retries=1 allows one retry before showing error. First attempt should show waiting message, second attempt should show full error." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Set max retries to 1 - (setq chime--validation-max-retries 1) - - ;; Empty org-agenda-files - (setq org-agenda-files nil) - - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; First attempt - should show waiting - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check) - (should (= chime--validation-retry-count 1)) - (should (cl-some (lambda (msg) - (string-match-p "Waiting for" msg)) - messages)))) - - ;; Second attempt - should show error - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check) - (should (= chime--validation-retry-count 2)) - (should (cl-some (lambda (msg) - (string-match-p "Configuration errors detected" msg)) - messages)))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Set max retries to 1 + (setq chime--validation-max-retries 1) + + ;; Empty org-agenda-files + (setq org-agenda-files nil) + + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; First attempt - should show waiting + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check) + (should (= chime--validation-retry-count 1)) + (should (cl-some (lambda (msg) + (string-match-p "Waiting for" msg)) + messages)))) + + ;; Second attempt - should show error + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check) + (should (= chime--validation-retry-count 2)) + (should (cl-some (lambda (msg) + (string-match-p "Configuration errors detected" msg)) + messages))))))) (ert-deftest test-chime-validation-retry-boundary-exactly-at-threshold () "Test behavior exactly at max-retries threshold. The (retry_count + 1)th attempt should show the error message." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Default max retries = 3 - (setq chime--validation-max-retries 3) - (setq org-agenda-files nil) - - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; Attempts 1-3: waiting messages - (dotimes (_ 3) - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check) - (should (cl-some (lambda (msg) - (string-match-p "Waiting for" msg)) - messages))))) - - ;; Attempt 4: should show error - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check) - (should (= chime--validation-retry-count 4)) - (should (cl-some (lambda (msg) - (string-match-p "Configuration errors detected" msg)) - messages)))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Default max retries = 3 + (setq chime--validation-max-retries 3) + (setq org-agenda-files nil) + + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; Attempts 1-3: waiting messages + (dotimes (_ 3) + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check) + (should (cl-some (lambda (msg) + (string-match-p "Waiting for" msg)) + messages))))) + + ;; Attempt 4: should show error + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check) + (should (= chime--validation-retry-count 4)) + (should (cl-some (lambda (msg) + (string-match-p "Configuration errors detected" msg)) + messages))))))) (ert-deftest test-chime-validation-retry-boundary-stop-resets-counter () "Test chime--stop resets retry counter to zero. When chime-mode is stopped, the retry counter should be reset to allow fresh retry attempts on next start." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Simulate some failed attempts - (setq chime--validation-retry-count 5) - (setq chime--validation-done nil) + (test-chime-validation-retry--with-state + ;; Simulate some failed attempts + (setq chime--validation-retry-count 5) + (setq chime--validation-done nil) - ;; Call stop - (chime--stop) + ;; Call stop + (chime--stop) - ;; Counter should be reset - (should (= chime--validation-retry-count 0)) - (should-not chime--validation-done)) - (test-chime-validation-retry-teardown))) + ;; Counter should be reset + (should (= chime--validation-retry-count 0)) + (should-not chime--validation-done))) (ert-deftest test-chime-validation-retry-boundary-empty-agenda-files () "Test empty org-agenda-files list triggers retry. An empty list should be treated the same as nil - both should trigger validation failure and retry." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - ;; Empty list (not nil) - (setq org-agenda-files '()) - - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages))) - ((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; Should trigger retry - (chime-check) - (should (= chime--validation-retry-count 1)) - (should (cl-some (lambda (msg) - (string-match-p "Waiting for" msg)) - messages))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + ;; Empty list (not nil) + (setq org-agenda-files '()) + + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages))) + ((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; Should trigger retry + (chime-check) + (should (= chime--validation-retry-count 1)) + (should (cl-some (lambda (msg) + (string-match-p "Waiting for" msg)) + messages)))))) ;;; Error Cases - Failure Scenarios @@ -343,85 +300,76 @@ trigger validation failure and retry." After max retries exceeded, the full validation error should be displayed with all error details in the *Messages* buffer." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - (setq chime--validation-max-retries 2) - (setq org-agenda-files nil) - - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil))) - - ;; Exhaust retries - (dotimes (_ 3) - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check)))) - - ;; Verify error message on next attempt - (let ((messages nil)) - (cl-letf (((symbol-function 'message) - (lambda (format-string &rest args) - (push (apply #'format format-string args) messages)))) - (chime-check) - ;; Should show error message (detailed error with retry count goes to *Messages* buffer via chime--log-silently) - (should (cl-some (lambda (msg) - (string-match-p "Configuration errors detected" msg)) - messages)))))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + (setq chime--validation-max-retries 2) + (setq org-agenda-files nil) + + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil))) + + ;; Exhaust retries + (dotimes (_ 3) + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check)))) + + ;; Verify error message on next attempt + (let ((messages nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (push (apply #'format format-string args) messages)))) + (chime-check) + ;; Should show error message (detailed error with retry count goes to *Messages* buffer via chime--log-silently) + (should (cl-some (lambda (msg) + (string-match-p "Configuration errors detected" msg)) + messages))))))) (ert-deftest test-chime-validation-retry-error-persistent-failure () "Test validation failure persisting through all retries. If org-agenda-files remains empty through all retry attempts, validation should never be marked as done." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - (setq chime--validation-max-retries 3) - (setq org-agenda-files nil) - - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil)) - ((symbol-function 'message) - (lambda (&rest args) nil))) - - ;; Multiple attempts, all failing - (dotimes (_ 10) - (chime-check) - ;; Should never mark as done - (should-not chime--validation-done)) - - ;; Counter keeps incrementing - (should (= chime--validation-retry-count 10)))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + (setq chime--validation-max-retries 3) + (setq org-agenda-files nil) + + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil)) + ((symbol-function 'message) + (lambda (&rest args) nil))) + + ;; Multiple attempts, all failing + (dotimes (_ 10) + (chime-check) + ;; Should never mark as done + (should-not chime--validation-done)) + + ;; Counter keeps incrementing + (should (= chime--validation-retry-count 10))))) (ert-deftest test-chime-validation-retry-error-counter-large-value () "Test retry counter handles large values without overflow. The retry counter should continue incrementing correctly even with many retry attempts, ensuring no integer overflow issues." - (test-chime-validation-retry-setup) - (unwind-protect - (progn - (setq chime--validation-max-retries 1000) - (setq org-agenda-files nil) - - (cl-letf (((symbol-function 'chime--fetch-and-process) - (lambda (callback) nil)) - ((symbol-function 'message) - (lambda (&rest args) nil))) - - ;; Many attempts - (dotimes (i 100) - (chime-check) - (should (= chime--validation-retry-count (1+ i)))) - - ;; Should still be counting correctly - (should (= chime--validation-retry-count 100)))) - (test-chime-validation-retry-teardown))) + (test-chime-validation-retry--with-state + (setq chime--validation-max-retries 1000) + (setq org-agenda-files nil) + + (cl-letf (((symbol-function 'chime--fetch-and-process) + (lambda (callback) nil)) + ((symbol-function 'message) + (lambda (&rest args) nil))) + + ;; Many attempts + (dotimes (i 100) + (chime-check) + (should (= chime--validation-retry-count (1+ i)))) + + ;; Should still be counting correctly + (should (= chime--validation-retry-count 100))))) (provide 'test-chime-validation-retry) ;;; test-chime-validation-retry.el ends here |
