aboutsummaryrefslogtreecommitdiff
path: root/tests/test-chime-validation-retry.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-10 16:36:47 -0500
committerCraig Jennings <c@cjennings.net>2026-05-10 16:36:47 -0500
commit3c64dac1b98049d475be838294349326c32248ae (patch)
tree626917ca3660d34b48195a77123b1def3d418282 /tests/test-chime-validation-retry.el
parent0772736d2bca36472f623d5258784f41db9b4f9a (diff)
downloadchime-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.el574
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