diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 09:37:12 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 09:37:12 -0500 |
| commit | b83865a65eb744f6d36c1c672a4d83a59d6383f8 (patch) | |
| tree | 02619079973580147ccf2cf2e7e4567b7d69e022 /tests | |
| parent | 14195e10b01fec3d9ded6e664a416c5cf3d33cc9 (diff) | |
| download | emacs-wttrin-b83865a65eb744f6d36c1c672a4d83a59d6383f8.tar.gz emacs-wttrin-b83865a65eb744f6d36c1c672a4d83a59d6383f8.zip | |
fix(ci): rewrite mode-init-order test and retry deps install
Two CI failures from the first run, neither a real bug in production code.
The Emacs-snapshot job failed on
`test-wttrin-mode-initialization-order-normal-mode-before-buffer-local-vars-calls-mode-first`.
The original test mocked the `set' primitive to detect when
`xterm-color--state' was first set. That worked on the byte-code path some
older Emacs versions used, but `setq-local' doesn't go through the `set'
function on Emacs master, so the mock never fired and the assertion read nil.
The test was already brittle in isolation locally too.
Rewrote the test to use `advice-add :before' on `wttrin-mode' and
`make-local-variable'. Both are ordinary advisable functions, and
`make-local-variable' is on the code path for every form that defines a
buffer-local binding (`setq-local', `defvar-local', etc.) so the observation
holds across Emacs versions. Renamed the test to drop "calls-mode-first"
and use "mode-runs-before-xterm-color-state-binding" since that's what the
new advice actually observes.
The Emacs 26.3 job failed with a transient DNS error from elpa.gnu.org
during `make deps'. Wrapped the install step in a 3-attempt retry with a
15-second backoff so a runner-side network blip doesn't fail the build.
Applied to all three jobs (test, lint, coverage) since they all hit the
same archives.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-wttrin-mode-initialization-order.el | 89 |
1 files changed, 47 insertions, 42 deletions
diff --git a/tests/test-wttrin-mode-initialization-order.el b/tests/test-wttrin-mode-initialization-order.el index 1def5f0..6554b64 100644 --- a/tests/test-wttrin-mode-initialization-order.el +++ b/tests/test-wttrin-mode-initialization-order.el @@ -5,19 +5,46 @@ ;;; Commentary: ;; This test verifies that wttrin--display-weather initializes wttrin-mode -;; BEFORE setting buffer-local variables. This prevents kill-all-local-variables -;; (called by derived modes) from wiping out important state like xterm-color--state. +;; BEFORE making `xterm-color--state' buffer-local. This prevents +;; kill-all-local-variables (called by derived modes) from wiping out +;; important state. ;; ;; Bug context: On fresh Emacs launch, weather displayed with no colors because ;; xterm-color--state was set buffer-local BEFORE wttrin-mode was called, and ;; wttrin-mode's kill-all-local-variables wiped it out. +;; +;; Earlier versions of this file mocked the `set' primitive to observe the +;; ordering. That was fragile because `setq-local' doesn't always go through +;; the `set' function -- the byte-code path differs across Emacs versions, and +;; on Emacs master the mock missed the assignment entirely. This rewrite uses +;; `advice-add' on `wttrin-mode' and `make-local-variable', both of which are +;; ordinary advisable functions guaranteed to be invoked on every code path +;; that defines a buffer-local binding. ;;; Code: (require 'ert) +(require 'cl-lib) (require 'wttrin) (require 'testutil-wttrin) +(defvar test-wttrin--init-events nil + "Ordered list of init events captured during the order test. +Each entry is `mode' or `xterm-color', recorded by advice on +`wttrin-mode' and `make-local-variable' respectively. Reset before +each test run.") + +(defun test-wttrin--record-mode-call (&rest _args) + "Advice that records a `mode' event when `wttrin-mode' runs." + (push 'mode test-wttrin--init-events)) + +(defun test-wttrin--record-mlv-call (symbol &rest _args) + "Advice that records an `xterm-color' event when SYMBOL is the target. +Only triggers for `xterm-color--state' so unrelated buffer-local +declarations don't pollute the timeline." + (when (eq symbol 'xterm-color--state) + (push 'xterm-color test-wttrin--init-events))) + ;;; Setup and Teardown (defun test-wttrin-mode-init-setup () @@ -34,50 +61,28 @@ ;;; Tests -(ert-deftest test-wttrin-mode-initialization-order-normal-mode-before-buffer-local-vars-calls-mode-first () - "Test that wttrin-mode is activated before setting buffer-local variables. - -This test verifies the fix for the color rendering bug where xterm-color--state -was wiped by kill-all-local-variables. +(ert-deftest test-wttrin-mode-initialization-order-normal-mode-runs-before-xterm-color-state-binding () + "Verify wttrin-mode runs before xterm-color--state is made buffer-local. -The test strategy: -1. Advise wttrin-mode to record when it's called -2. Advise setq-local to record when buffer-local vars are set -3. Call wttrin--display-weather -4. Verify wttrin-mode was called BEFORE any buffer-local vars were set" +If `make-local-variable' for `xterm-color--state' ran first, the subsequent +`wttrin-mode' call would invoke `kill-all-local-variables' and wipe the +state, leaving the rendered buffer without ANSI colors. Observing the +ordering directly catches a regression that re-introduces the bug even if +the outcome test happens to pass on a particular Emacs version." (test-wttrin-mode-init-setup) + (setq test-wttrin--init-events nil) + (advice-add 'wttrin-mode :before #'test-wttrin--record-mode-call) + (advice-add 'make-local-variable :before #'test-wttrin--record-mlv-call) (unwind-protect (testutil-wttrin-with-clean-weather-buffer - (let ((mode-called-at nil) - (first-setq-local-at nil) - (call-counter 0)) - - ;; Advise to track when wttrin-mode is called - (cl-letf (((symbol-function 'wttrin-mode) - (let ((orig-fn (symbol-function 'wttrin-mode))) - (lambda () - (setq mode-called-at (cl-incf call-counter)) - (funcall orig-fn)))) - - ;; Advise to track first buffer-local variable set - ((symbol-function 'set) - (let ((orig-fn (symbol-function 'set))) - (lambda (symbol value) - ;; Track xterm-color--state specifically - (when (and (eq symbol 'xterm-color--state) - (null first-setq-local-at)) - (setq first-setq-local-at (cl-incf call-counter))) - (funcall orig-fn symbol value))))) - - (wttrin--display-weather "Paris" "Test weather data") - - ;; Verify mode was called - (should mode-called-at) - ;; Verify buffer-local var was set - (should first-setq-local-at) - ;; Critical: mode must be called BEFORE buffer-local var - (should (< mode-called-at first-setq-local-at))))) - + (wttrin--display-weather "Paris" "Test weather data") + (let ((order (nreverse test-wttrin--init-events))) + (should (memq 'mode order)) + (should (memq 'xterm-color order)) + (should (< (cl-position 'mode order) + (cl-position 'xterm-color order))))) + (advice-remove 'wttrin-mode #'test-wttrin--record-mode-call) + (advice-remove 'make-local-variable #'test-wttrin--record-mlv-call) (test-wttrin-mode-init-teardown))) (ert-deftest test-wttrin-mode-initialization-order-normal-xterm-color-state-survives-mode-init () |
