aboutsummaryrefslogtreecommitdiff
path: root/tests/test-undead-buffers--warnings-undead.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-08-25 05:28:25 -0600
committerCraig Jennings <c@cjennings.net>2026-08-25 05:28:25 -0600
commit638310601a39e7f9ade59ea85794a21167905f31 (patch)
tree59ebb07880634aaf2084cf4917b09aadc1cd7068 /tests/test-undead-buffers--warnings-undead.el
parentac1d034d09dd37305e84d08438fef268ed8173bc (diff)
downloaddotemacs-638310601a39e7f9ade59ea85794a21167905f31.tar.gz
dotemacs-638310601a39e7f9ade59ea85794a21167905f31.zip
fix(startup): keep *Warnings* alive so 31.1's first frame is Wayland
Emacs 31.1's warnings.el defers daemon-startup warnings into a one-shot after-make-frame-functions closure that holds the *Warnings* buffer object and displays it on the first client frame. The startup sweep in cj/dashboard-only killed that buffer first. On the first emacsclient -c of every session, display-buffer then signaled inside make-frame and server.el answered -window-system-unsupported. emacsclient silently retried on $DISPLAY, and the frame opened on XWayland behind the pgtk "unsupported under X" dialog. Only that first frame was affected, which made it look like a display problem rather than a config one. I added *Warnings* to cj/undead-buffer-list so the sweep buries it instead, the same choice desktop.el makes in desktop-clear-preserve-buffers. Two things follow. C-x k on *Warnings* now buries it. A startup that produced warnings shows them on the first frame, because the deferred closure finally has a live buffer. As a backstop, cj/warning--display-buffer-if-live wraps warning--display-buffer so a dead buffer (or a name that resolves to none) is skipped rather than passed on. That function only exists from Emacs 31, and advising the undefined symbol on 30.2 is harmless. The new tests pin *Warnings* to the undead list and check the sweep leaves it live. The guard tests cover live and dead buffers plus names that do and don't resolve, and run the real 31.x function on a dead buffer.
Diffstat (limited to 'tests/test-undead-buffers--warnings-undead.el')
-rw-r--r--tests/test-undead-buffers--warnings-undead.el63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/test-undead-buffers--warnings-undead.el b/tests/test-undead-buffers--warnings-undead.el
new file mode 100644
index 00000000..858dbf76
--- /dev/null
+++ b/tests/test-undead-buffers--warnings-undead.el
@@ -0,0 +1,63 @@
+;;; test-undead-buffers--warnings-undead.el --- *Warnings* survives the buffer sweep -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Emacs 31.1's warnings.el defers daemon-startup warnings into a one-shot
+;; `after-make-frame-functions' closure that holds the *Warnings* buffer
+;; object and displays it on the first client frame. Killing that buffer
+;; during startup leaves the closure holding a dead buffer, `display-buffer'
+;; then signals inside `make-frame', server.el reports the window system as
+;; unsupported, and emacsclient silently retries on $DISPLAY -- the first
+;; frame of the session lands on XWayland instead of Wayland.
+;;
+;; `cj/dashboard-only' on `emacs-startup-hook' runs
+;; `cj/kill-all-other-buffers-and-windows', which is exactly such a sweep.
+;; These tests pin *Warnings* to the undead list so the sweep buries it
+;; instead of killing it. Error-path coverage of the predicate itself (a nil
+;; or non-string name) lives in test-undead-buffers--buffer-undead-p.el.
+
+;;; Code:
+
+(require 'ert)
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'undead-buffers)
+
+;;; Normal Cases
+
+(ert-deftest test-undead-buffers-warnings-is-undead-by-default ()
+ "Normal: the module's default list makes *Warnings* bury-only."
+ (should (member "*Warnings*" cj/undead-buffer-list))
+ (should (cj/--buffer-undead-p "*Warnings*")))
+
+(ert-deftest test-undead-buffers-warnings-survives-kill-all-other-buffers ()
+ "Normal: the startup sweep buries *Warnings* rather than killing it.
+This is the sweep `cj/dashboard-only' runs from `emacs-startup-hook'."
+ (delete-other-windows)
+ (unwind-protect
+ (let* ((main (current-buffer))
+ (existing (get-buffer "*Warnings*"))
+ (warnings (or existing (get-buffer-create "*Warnings*")))
+ (victim (generate-new-buffer "*test-sweep-victim*")))
+ (unwind-protect
+ (progn
+ (cj/kill-all-other-buffers-and-windows)
+ (should (buffer-live-p main))
+ (should (buffer-live-p warnings))
+ (should-not (buffer-live-p victim)))
+ (when (buffer-live-p victim) (kill-buffer victim))
+ ;; Only remove what this test created. `kill-buffer' the function
+ ;; is not the remapped command, so the undead list doesn't apply.
+ (when (and (not existing) (buffer-live-p warnings))
+ (kill-buffer warnings))))
+ (delete-other-windows)))
+
+;;; Boundary Cases
+
+(ert-deftest test-undead-buffers-warnings-match-is-exact ()
+ "Boundary: only the exact name is undead; a uniquified *Warnings*<2> is not.
+The list matches exact names, so a second warnings buffer made by
+`generate-new-buffer' is an ordinary buffer to the sweep."
+ (should-not (cj/--buffer-undead-p "*Warnings*<2>"))
+ (should-not (cj/--buffer-undead-p " *Warnings*")))
+
+(provide 'test-undead-buffers--warnings-undead)
+;;; test-undead-buffers--warnings-undead.el ends here