Subject: 29.0.50; [PATCH] Add test coverage for overlay modification hooks

From: Matt Armstrong <[email-masked]>
Date: Thu, 11 Aug 2022 21:32:40 -0700

I noticed there was no explicit test against the overlay modification
hook boundary conditions.  The attached patch adds some, which might be
nice to have if a person (possibly me) someday optimizes overlay
performance with a change in data structure.

In writing this I was surprised to learn that the hooks do not behave
differently if the overlay is `front-advance' or `rear-advance', so this
is explicitly tested.

>From 9083709cbe12ab97b795bcac8343f9d11f2929b7 Mon Sep 17 00:00:00 2001
From: Matt Armstrong <[email-masked]>
Date: Thu, 11 Aug 2022 21:11:36 -0700
Subject: [PATCH] Add test coverage for overlay modification hooks

* test/src/buffer-tests.el: (overlay-modification-hooks) new
ert-deftest.
---
 test/src/buffer-tests.el | 66 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 3c6a9208ff..ee25b43f9e 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -22,6 +22,72 @@
 (require 'ert)
 (require 'ert-x)
 (require 'cl-lib)
+(require 'pcase)
+
+(ert-deftest overlay-modification-hooks ()
+  "Test the `modification-hooks' overlay property.
+
+This also tests `insert-in-front-hooks' and `insert-behind-hooks'."
+  ;; Perform operation against the given needle (a position or string)
+  ;; and expect the `modification-hook', `insert-in-front-hooks' and
+  ;; `insert-behind-hooks' to be called with the given arguments.  All
+  ;; tests are performed against the same fixed buffer and overlay.
+  (pcase-dolist (`(,operation
+                   ,needle
+                   ,expected-insert-in-front-calls
+                   ,expected-modification-calls
+                   ,expected-insert-behind-calls)
+                 '((insert 1 nil nil nil)
+                   (insert 2 ((nil 2 2) (t 2 3 0)) nil nil)
+                   (insert 3 nil ((nil 3 3) (t 3 4 0)) nil)
+                   (insert 4 nil nil ((nil 4 4) (t 4 5 0)))
+                   (insert 5 nil nil nil)
+                   (replace "1" nil nil nil)
+                   (replace "2" nil ((nil 2 3) (t 2 3 1)) nil)
+                   (replace "3" nil ((nil 3 4) (t 3 4 1)) nil)
+                   (replace "4" nil nil nil)
+                   (replace "12" nil ((nil 1 3) (t 1 2 2)) nil)
+                   (replace "23" nil ((nil 2 4) (t 2 3 2)) nil)
+                   (replace "34" nil ((nil 3 5) (t 3 4 2)) nil)
+                   (replace "123" nil ((nil 1 4) (t 1 2 3)) nil)
+                   (replace "234" nil ((nil 2 5) (t 2 3 3)) nil)
+                   (replace "1234" nil ((nil 1 5) (t 1 2 4)) nil)))
+    ;; All three hooks ignore the overlay's `front-advance' and
+    ;; `rear-advance' option, so test ways and expect the same result.
+    (dolist (advance '(nil t))
+      (with-temp-buffer
+        (insert "1234")
+        (let (modification-calls insert-in-front-calls insert-behind-calls
+              (overlay (make-overlay 2 4 nil advance advance)))
+          (overlay-put overlay
+                       'modification-hooks
+                       (list (lambda (ov &rest args)
+                               (should inhibit-modification-hooks)
+                               (should (eq ov overlay))
+                               (push args modification-calls))))
+          (overlay-put overlay
+                       'insert-in-front-hooks
+                       (list (lambda (ov &rest args)
+                               (should inhibit-modification-hooks)
+                               (should (eq ov overlay))
+                               (push args insert-in-front-calls))))
+          (overlay-put overlay
+                       'insert-behind-hooks
+                       (list (lambda (ov &rest args)
+                               (should inhibit-modification-hooks)
+                               (should (eq ov overlay))
+                               (push args insert-behind-calls))))
+          (pcase-exhaustive operation
+            (`insert (goto-char needle)
+                     (insert "x"))
+            (`replace (goto-char (point-min))
+                      (replace-string needle "x")))
+          (should (equal (reverse insert-in-front-calls)
+                         expected-insert-in-front-calls))
+          (should (equal (reverse modification-calls)
+                         expected-modification-calls))
+          (should (equal (reverse insert-behind-calls)
+                         expected-insert-behind-calls)))))))
 
 (ert-deftest overlay-modification-hooks-message-other-buf ()
   "Test for bug#21824.
-- 
2.35.1