aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-30 15:42:56 -0400
committerCraig Jennings <c@cjennings.net>2026-06-30 15:42:56 -0400
commit3cb2790a391e708e9db63dbcd469cfa10afce98e (patch)
tree674f0a57494b482be6c754b60981985835267b75 /tests
parent582ed54ed9a3c600e7e1e68beeea8b16ce1ed613 (diff)
downloaddotemacs-3cb2790a391e708e9db63dbcd469cfa10afce98e.tar.gz
dotemacs-3cb2790a391e708e9db63dbcd469cfa10afce98e.zip
fix(undead-buffers): drop cj/save-some-buffers name collision
Emacs crashed at launch with wrong-number-of-arguments on cj/save-some-buffers, down the startup path (dashboard-only to kill-all-other-buffers to save). Two modules defined a function by that name: custom-buffer-file.el's legible save prompt (arg + pred), installed as an override on save-some-buffers, and undead-buffers.el's older one-arg wrapper that called save-some-buffers internally. custom-buffer-file loads first, undead-buffers second. The one-arg version won the shared symbol, so the override re-entered it with two args. I removed undead-buffers.el's wrapper. cj/kill-all-other-buffers-and-windows now calls the standard save-some-buffers with the undead predicate, which routes through the override when loaded and the built-in otherwise, so undead-buffers no longer depends on custom-buffer-file. The legible override keeps the cj/save-some-buffers name. A regression test loads both modules in launch order and guards the call and the arity so a one-arg shadow can't return.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-undead-buffers--save-some-buffers-override-no-conflict.el34
-rw-r--r--tests/test-undead-buffers-kill-all-other-buffers-and-windows.el17
2 files changed, 44 insertions, 7 deletions
diff --git a/tests/test-undead-buffers--save-some-buffers-override-no-conflict.el b/tests/test-undead-buffers--save-some-buffers-override-no-conflict.el
new file mode 100644
index 000000000..c0dca6e0a
--- /dev/null
+++ b/tests/test-undead-buffers--save-some-buffers-override-no-conflict.el
@@ -0,0 +1,34 @@
+;;; test-undead-buffers--save-some-buffers-override-no-conflict.el --- Regression: save override vs undead -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Regression guard for a launch crash. custom-buffer-file.el installs a
+;; legible `save-some-buffers' override named `cj/save-some-buffers' (arity
+;; arg + pred). undead-buffers.el used to define its own 1-arg
+;; `cj/save-some-buffers' that called `save-some-buffers' internally. In prod
+;; load order (custom-buffer-file before undead-buffers) the 1-arg version won
+;; the symbol, so the override re-entered it with two args and signalled
+;; wrong-number-of-arguments — crashing the kill-all-other-buffers startup path.
+;;
+;; The requires below reproduce that prod order on purpose.
+
+;;; Code:
+
+(require 'ert)
+;; Prod order: override installed first, undead-buffers loaded second.
+(require 'custom-buffer-file)
+(require 'undead-buffers)
+
+(ert-deftest test-undead-buffers-save-override-accepts-predicate ()
+ "Normal: calling `save-some-buffers' with the undead predicate (the
+kill-all-other-buffers path) goes through the legible override without a
+wrong-number-of-arguments crash. No modified file buffers exist in batch, so
+the override returns a count rather than prompting."
+ (should (numberp (save-some-buffers nil #'cj/undead-buffer-p))))
+
+(ert-deftest test-undead-buffers-save-some-buffers-not-arity-shadowed ()
+ "Boundary: `cj/save-some-buffers' must accept the PRED argument the override
+forwards (max arity >= 2), so undead-buffers can't reintroduce a 1-arg shadow."
+ (should (>= (cdr (func-arity #'cj/save-some-buffers)) 2)))
+
+(provide 'test-undead-buffers--save-some-buffers-override-no-conflict)
+;;; test-undead-buffers--save-some-buffers-override-no-conflict.el ends here
diff --git a/tests/test-undead-buffers-kill-all-other-buffers-and-windows.el b/tests/test-undead-buffers-kill-all-other-buffers-and-windows.el
index dcd08e966..36d82add0 100644
--- a/tests/test-undead-buffers-kill-all-other-buffers-and-windows.el
+++ b/tests/test-undead-buffers-kill-all-other-buffers-and-windows.el
@@ -133,23 +133,26 @@
(test-kill-all-other-buffers-and-windows-teardown)))
(ert-deftest test-kill-all-other-buffers-and-windows-should-prompt-for-modified-buffers ()
- "Should call cj/save-some-buffers to handle modified buffers."
+ "Should call save-some-buffers with the undead predicate to handle modified buffers."
(test-kill-all-other-buffers-and-windows-setup)
(unwind-protect
(let ((main (current-buffer))
(file (cj/create-temp-test-file-with-content "original"))
- save-called)
- ;; Mock cj/save-some-buffers to track if it's called
- (cl-letf (((symbol-function 'cj/save-some-buffers)
- (lambda (&optional arg)
- (setq save-called t))))
+ save-called save-pred)
+ ;; Mock save-some-buffers (the standard API the override hooks) to track
+ ;; the call and the predicate passed.
+ (cl-letf (((symbol-function 'save-some-buffers)
+ (lambda (&optional _arg pred &rest _)
+ (setq save-called t
+ save-pred pred))))
(let ((buf (find-file-noselect file)))
(unwind-protect
(progn
(with-current-buffer buf
(insert "modified"))
(cj/kill-all-other-buffers-and-windows)
- (should save-called))
+ (should save-called)
+ (should (eq save-pred #'cj/undead-buffer-p)))
(when (buffer-live-p buf)
(set-buffer-modified-p nil)
(kill-buffer buf))))))