unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Vladimir Kazanov <vekazanov@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: martin rudalics <rudalics@gmx.at>, emacs-devel@gnu.org
Subject: Re: The overlay branch (yet again)
Date: Wed, 4 Dec 2019 11:41:16 +0000	[thread overview]
Message-ID: <CAAs=0-0daXrvurzNt9xJAR6nUbPtT1TDZQuiqVrsFM4VtfaqLQ@mail.gmail.com> (raw)
In-Reply-To: <jwv7e3d81zd.fsf-monnier+emacs@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1199 bytes --]

So here's the first patch containing a few hundred (!!!)
implementation-agnostic overlay tests.

I took all Lisp-level overlay related tests in the feature-noverlay
branch, removed automatically generated ones and a single test that
was aware of the tree-based implementation. This should be a good
basis for any further work related to overlays (and buffers in
general).

I did not add a single line of code, all credit goes to Andreas.

Feel free to request tweaks and additions. Note that I am still in the
process of pushing the papers through corporate bureaucracy. No
problems, I got all the approvals needed but it'll take a week or two
more.

Thanks

On Tue, Dec 3, 2019 at 10:43 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>
> > https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00488.html
> > https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00598.html
> > https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00736.html
>
> At least those links should be in comments somewhere in the code.
>
>
>         Stefan
>


-- 
Yours sincerely,


Vladimir Kazanov


--
С уважением,

Владимир Казанов

[-- Attachment #2: 0001-Include-overlay-tests.patch --]
[-- Type: text/x-patch, Size: 53157 bytes --]

diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 845d41f9d6..1a78960b9d 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -94,4 +94,1212 @@
       (insert "toto")
       (move-overlay ol (point-min) (point-min)))))
 
+
+;; +===================================================================================+
+;; | Overlay test setup
+;; +===================================================================================+
+
+(eval-when-compile
+  (defun make-overlay-test-name (fn x y)
+    (intern (format "test-%s-%s-%s" fn x y))))
+
+(defun unmake-ov-test-name (symbol)
+  (let ((name (if (stringp symbol) symbol (symbol-name symbol))))
+    (when (string-match "\\`test-\\(.*\\)-\\(.*\\)-\\(.*\\)\\'" name)
+      (list (match-string 1 name) (match-string 2 name) (match-string 3 name)))))
+
+(defmacro deftest-make-overlay-1 (id args)
+  (declare (indent 1))
+  `(ert-deftest ,(make-overlay-test-name 'make-overlay 1 id) ()
+     (with-temp-buffer
+       (should ,(cons 'make-overlay args)))))
+
+(defmacro deftest-make-overlay-2 (id args condition)
+  (declare (indent 1))
+  `(ert-deftest ,(make-overlay-test-name 'make-overlay 2 id) ()
+     (with-temp-buffer
+       (should-error
+        ,(cons 'make-overlay args)
+        :type ',condition
+        :exclude-subtypes t))))
+
+(defmacro deftest-overlay-start/end-1 (id start-end-args start-end-should)
+  (declare (indent 1))
+  (cl-destructuring-bind (start end sstart send)
+      (append start-end-args start-end-should)
+    `(ert-deftest ,(make-overlay-test-name 'overlay-start/end 1 id) ()
+       (with-temp-buffer
+         (insert (make-string 9 ?\n))
+         (let ((ov (make-overlay ,start ,end)))
+           (should (equal ,sstart (overlay-start ov)))
+           (should (equal ,send (overlay-end ov))))))))
+
+(defmacro deftest-overlay-buffer-1 (id arg-expr should-expr)
+  (declare (indent 1))
+  `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) ()
+     (with-temp-buffer
+       (should (equal (overlay-buffer (make-overlay 1 1 ,arg-expr))
+                      ,should-expr)))))
+
+(defmacro deftest-overlayp-1 (id arg-expr should-expr)
+  (declare (indent 1))
+  `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) ()
+     (with-temp-buffer
+       (should (equal ,should-expr (overlayp ,arg-expr))))))
+
+(defmacro deftest-next-overlay-change-1 (id pos result &rest ov-tuple)
+  `(ert-deftest ,(make-overlay-test-name 'next-overlay-change 1 id) ()
+     (let ((tuple (copy-sequence ',ov-tuple)))
+       (with-temp-buffer
+         (insert (make-string (max 100 (if tuple
+                                           (apply #'max
+                                                  (mapcar
+                                                   (lambda (m) (apply #'max m)) tuple))
+                                         0))
+                              ?\n))
+         (dolist (tup tuple)
+           (make-overlay (car tup) (cadr tup)))
+         (should (equal (next-overlay-change ,pos)
+                        ,result))))))
+
+(defmacro deftest-previous-overlay-change-1 (id pos result &rest ov-tuple)
+  `(ert-deftest ,(make-overlay-test-name 'previous-overlay-change 1 id) ()
+     (let ((tuple ',ov-tuple))
+       (with-temp-buffer
+         (insert (make-string (max 100 (if tuple
+                                           (apply #'max
+                                                  (mapcar
+                                                   (lambda (m) (apply #'max m)) tuple))
+                                         0))
+                              ?\n))
+         (dolist (tup tuple)
+           (make-overlay (car tup) (cadr tup)))
+         (should (equal (previous-overlay-change ,pos)
+                        ,result))))))
+
+(defmacro deftest-overlays-at-1 (id pos result &rest ov-triple)
+  `(ert-deftest ,(make-overlay-test-name 'overlays-at 1 id) ()
+     (let ((pos* ,pos))
+       (with-temp-buffer
+         (insert (make-string 100 ?\s))
+         (should-not (memq nil ',result))
+         (dolist (v ',ov-triple)
+           (cl-destructuring-bind (tag start end)
+               v
+             (overlay-put (make-overlay start end) 'tag tag)))
+         (let ((ovl (overlays-at pos*)))
+           (should (equal (length ovl) (length ',result)))
+           (dolist (ov ovl)
+             (should (memq (overlay-get ov 'tag) ',result))))))))
+
+(defmacro deftest-overlays-in-1 (id beg end result &rest ov-triple)
+  `(ert-deftest ,(make-overlay-test-name 'overlays-in 1 id) ()
+     (let ((beg* ,beg)
+           (end* ,end))
+       (with-temp-buffer
+         (insert (make-string 100 ?\s))
+         (should-not (memq nil ',result))
+         (dolist (v ',ov-triple)
+           (cl-destructuring-bind (tag start end)
+               v
+             (overlay-put (make-overlay start end) 'tag tag)))
+         (let ((ovl (overlays-in beg* end*)))
+           (should (equal (length ovl) (length ',result)))
+           (dolist (ov ovl)
+             (should (memq (overlay-get ov 'tag) ',result))))))))
+
+(defmacro test-with-overlay-in-buffer (symbol-beg-end-fa-ra &rest body)
+  (declare (indent 1))
+  (cl-destructuring-bind (symbol beg end &optional fa ra)
+      symbol-beg-end-fa-ra
+    `(with-temp-buffer
+       (insert (make-string (max 1000 (1- ,end)) ?\s))
+       (goto-char 1)
+       (let ((,symbol (make-overlay ,beg ,end nil ,fa ,ra)))
+         ,@body))))
+
+(defmacro deftest-overlays-equal-1 (id result ov1-args ov2-args)
+  `(ert-deftest ,(make-overlay-test-name 'overlays-equal 1 id) ()
+     (cl-labels ((create-overlay (args)
+                                 (cl-destructuring-bind (start end &optional fa ra &rest properties)
+                                     args
+                                   (let ((ov (make-overlay start end nil fa ra)))
+                                     (while properties
+                                       (overlay-put ov (pop properties) (pop properties)))
+                                     ov))))
+       (with-temp-buffer
+         (insert (make-string 1024 ?\s))
+         (should (,(if result 'identity 'not)
+                  (equal (create-overlay ',ov1-args)
+                         (create-overlay ',ov2-args))))))))
+
+
+(defun find-ert-overlay-test (name)
+  (let ((test (unmake-ov-test-name name)))
+    (or (and test
+             (cl-destructuring-bind (fn x y)
+                 test
+               (let ((regexp (format "deftest-%s-%s +%s" fn x y)))
+                 (re-search-forward regexp nil t))))
+        (let ((find-function-regexp-alist
+               (cl-remove 'find-ert-overlay-test find-function-regexp-alist :key #'cdr)))
+          (find-function-do-it name 'ert-deftest 'switch-to-buffer-other-window)))))
+
+(add-to-list 'find-function-regexp-alist
+             '(ert-deftest . find-ert-overlay-test))
+
+
+;; +===================================================================================+
+;; | make-overlay
+;; +===================================================================================+
+
+;; Test if making an overlay succeeds.
+(deftest-make-overlay-1 A (1 1))
+(deftest-make-overlay-1 B (7 26))
+(deftest-make-overlay-1 C (29 7))
+(deftest-make-overlay-1 D (most-positive-fixnum 1))
+(deftest-make-overlay-1 E (most-negative-fixnum 1))
+(deftest-make-overlay-1 F (1 most-positive-fixnum))
+(deftest-make-overlay-1 G (1 most-negative-fixnum))
+(deftest-make-overlay-1 H (1 1 nil t))
+(deftest-make-overlay-1 I (1 1 nil nil))
+(deftest-make-overlay-1 J (1 1 nil nil nil))
+(deftest-make-overlay-1 K (1 1 nil nil t))
+(deftest-make-overlay-1 L (1 1 nil t t))
+(deftest-make-overlay-1 M (1 1 nil "yes" "yes"))
+
+;; Test if trying to make an overlay signals conditions.
+(deftest-make-overlay-2 A ()            wrong-number-of-arguments)
+(deftest-make-overlay-2 B (1)           wrong-number-of-arguments)
+(deftest-make-overlay-2 C (1 2 3 4 5 6) wrong-number-of-arguments)
+(deftest-make-overlay-2 D ("1")         wrong-number-of-arguments)
+(deftest-make-overlay-2 E ("1" "2")     wrong-type-argument)
+(deftest-make-overlay-2 F (1 2 "b")     wrong-type-argument)
+(deftest-make-overlay-2 G (1 2 3.14)    wrong-type-argument)
+(deftest-make-overlay-2 H (3.14 3)      wrong-type-argument)
+(deftest-make-overlay-2 I (1 [1])       wrong-type-argument)
+(deftest-make-overlay-2 J (1 1 (with-temp-buffer
+                                 (current-buffer)))
+  error)
+
+
+;; +===================================================================================+
+;; | overlay-start/end
+;; +===================================================================================+
+
+;; Test if the overlays return proper positions.  point-max of the
+;; buffer will equal 10.        ARG RESULT
+(deftest-overlay-start/end-1 A (1 1) (1 1))
+(deftest-overlay-start/end-1 B (2 7) (2 7))
+(deftest-overlay-start/end-1 C (7 2) (2 7))
+(deftest-overlay-start/end-1 D (1 10) (1 10))
+(deftest-overlay-start/end-1 E (1 11) (1 10))
+(deftest-overlay-start/end-1 F (1 most-positive-fixnum) (1 10))
+(deftest-overlay-start/end-1 G (most-positive-fixnum 1) (1 10))
+(deftest-overlay-start/end-1 H (most-positive-fixnum most-positive-fixnum) (10 10))
+(deftest-overlay-start/end-1 I (100 11) (10 10))
+(deftest-overlay-start/end-1 J (11 100) (10 10))
+(deftest-overlay-start/end-1 K (0 1) (1 1))
+(deftest-overlay-start/end-1 L (1 0) (1 1))
+(deftest-overlay-start/end-1 M (0 0) (1 1))
+
+(ert-deftest test-overlay-start/end-2 ()
+  (should-not (overlay-start (with-temp-buffer (make-overlay 1 1))))
+  (should-not (overlay-end (with-temp-buffer (make-overlay 1 1)))))
+
+
+;; +===================================================================================+
+;; | overlay-buffer
+;; +===================================================================================+
+
+;; Test if overlay-buffer returns appropriate values.
+(deftest-overlay-buffer-1 A (current-buffer) (current-buffer))
+(deftest-overlay-buffer-1 B nil (current-buffer))
+(ert-deftest test-overlay-buffer-1-C ()
+  (should-error (make-overlay
+                 1 1 (with-temp-buffer (current-buffer)))))
+
+
+;; +===================================================================================+
+;; | overlayp
+;; +===================================================================================+
+
+;; Check the overlay predicate.
+(deftest-overlayp-1 A (make-overlay 1 1) t)
+(deftest-overlayp-1 B (with-temp-buffer (make-overlay 1 1)) t)
+(deftest-overlayp-1 C nil                            nil)
+(deftest-overlayp-1 D 'symbol                        nil)
+(deftest-overlayp-1 E "string"                       nil)
+(deftest-overlayp-1 F 42                             nil)
+(deftest-overlayp-1 G [1 2]                          nil)
+(deftest-overlayp-1 H (symbol-function 'car)         nil)
+(deftest-overlayp-1 I float-pi                       nil)
+(deftest-overlayp-1 J (cons 1 2)                     nil)
+(deftest-overlayp-1 K (make-hash-table)              nil)
+(deftest-overlayp-1 L (symbol-function 'ert-deftest) nil)
+(deftest-overlayp-1 M (current-buffer)               nil)
+(deftest-overlayp-1 N (selected-window)              nil)
+(deftest-overlayp-1 O (selected-frame)               nil)
+
+
+;; +===================================================================================+
+;; | overlay equality
+;; +===================================================================================+
+
+(deftest-overlays-equal-1 A t (1 1) (1 1))
+(deftest-overlays-equal-1 B t (5 10) (5 10))
+(deftest-overlays-equal-1 C nil (5 11) (5 10))
+(deftest-overlays-equal-1 D t (10 20 t) (10 20))
+(deftest-overlays-equal-1 E t (10 20 nil t) (10 20))
+(deftest-overlays-equal-1 F t (10 20 t t) (10 20 nil t))
+(deftest-overlays-equal-1 G t (10 20 t t) (10 20 t nil))
+(deftest-overlays-equal-1 H t (10 20 nil nil foo 42) (10 20 nil nil foo 42))
+(deftest-overlays-equal-1 I nil (10 20 nil nil foo 42) (10 20 nil nil foo 43))
+
+
+;; +===================================================================================+
+;; | overlay-lists
+;; +===================================================================================+
+
+;; Check whether overlay-lists returns something sensible.
+(ert-deftest test-overlay-lists-1 ()
+  (with-temp-buffer
+    (should (equal (cons nil nil) (overlay-lists)))
+    (dotimes (i 10) (make-overlay 1 i))
+    (should (listp (car (overlay-lists))))
+    (should (listp (cdr (overlay-lists))))
+    (let ((list (append (car (overlay-lists))
+                        (cdr (overlay-lists)))))
+      (should (= 10 (length list)))
+      (should (seq-every-p #'overlayp list)))))
+
+
+;; +===================================================================================+
+;; | overlay-put/get/properties
+;; +===================================================================================+
+
+;; Test if overlay-put properties can be retrieved by overlay-get and
+;; overlay-properties.
+(ert-deftest test-overlay-props-1 ()
+  (with-temp-buffer
+    (let* ((keys '(:k1 :k2 :k3))
+           (values '(1 "v2" v3))
+           (ov (make-overlay 1 1))
+           (n (length keys)))
+      (should (equal (length keys) (length values)))
+      (should (null (overlay-properties ov)))
+      ;; Insert keys and values.
+      (dotimes (i n)
+        (should (equal (overlay-put ov (nth i keys) (nth i values))
+                       (nth i values))))
+      ;; Compare with what overlay-get says.
+      (dotimes (i n)
+        (should (equal (overlay-get ov (nth i keys))
+                       (nth i values))))
+      ;; Test if overlay-properties is a superset.
+      (dotimes (i n)
+        (should (equal (plist-get (overlay-properties ov)
+                                  (nth i keys))
+                       (nth i values))))
+      ;; Check if overlay-properties is a subset.
+      (should (= (length (overlay-properties ov)) (* n 2))))))
+
+
+;; +===================================================================================+
+;; | next-overlay-change
+;; +===================================================================================+
+
+;; Test if next-overlay-change returns RESULT if called with POS in a
+;; buffer with overlays corresponding to OVS and point-max >= 100.
+;;                               (POS RESULT &rest OVS)
+;; 0 overlays
+(deftest-next-overlay-change-1 A (point-min) (point-max))
+(deftest-next-overlay-change-1 B (point-max) (point-max))
+;; 1 non-empty overlay
+(deftest-next-overlay-change-1 C 1 10 (10 20))
+(deftest-next-overlay-change-1 D 10 20 (10 20))
+(deftest-next-overlay-change-1 E 15 20 (10 20))
+(deftest-next-overlay-change-1 F 20 (point-max) (10 20))
+(deftest-next-overlay-change-1 G 30 (point-max) (10 20))
+;; 1 empty overlay
+(deftest-next-overlay-change-1 H 1 10 (10 10))
+(deftest-next-overlay-change-1 I 10 (point-max) (10 10))
+(deftest-next-overlay-change-1 J 20 (point-max) (10 10))
+;; 2 non-empty, non-intersecting
+(deftest-next-overlay-change-1 D 10 20 (20 30) (40 50))
+(deftest-next-overlay-change-1 E 35 40 (20 30) (40 50))
+(deftest-next-overlay-change-1 F 60 (point-max) (20 30) (40 50))
+(deftest-next-overlay-change-1 G 30 40 (20 30) (40 50))
+(deftest-next-overlay-change-1 H 50 (point-max) (20 30) (40 50))
+;; 2 non-empty, intersecting
+(deftest-next-overlay-change-1 I 10 20 (20 30) (25 35))
+(deftest-next-overlay-change-1 J 20 25 (20 30) (25 35))
+(deftest-next-overlay-change-1 K 23 25 (20 30) (25 35))
+(deftest-next-overlay-change-1 L 25 30 (20 30) (25 35))
+(deftest-next-overlay-change-1 M 28 30 (20 30) (25 35))
+(deftest-next-overlay-change-1 N 30 35 (20 30) (25 35))
+(deftest-next-overlay-change-1 O 35 (point-max) (20 30) (25 35))
+(deftest-next-overlay-change-1 P 50 (point-max) (20 30) (25 35))
+;; 2 non-empty, continuous
+(deftest-next-overlay-change-1 Q 10 20 (20 30) (30 40))
+(deftest-next-overlay-change-1 R 20 30 (20 30) (30 40))
+(deftest-next-overlay-change-1 S 25 30 (20 30) (30 40))
+(deftest-next-overlay-change-1 T 30 40 (20 30) (30 40))
+(deftest-next-overlay-change-1 U 35 40 (20 30) (30 40))
+(deftest-next-overlay-change-1 V 40 (point-max) (20 30) (30 40))
+(deftest-next-overlay-change-1 W 50 (point-max) (20 30) (30 40))
+;; 1 empty, 1 non-empty, non-in
+(deftest-next-overlay-change-1 a 10 20 (20 20) (30 40))
+(deftest-next-overlay-change-1 b 20 30 (20 30) (30 40))
+(deftest-next-overlay-change-1 c 25 30 (20 30) (30 40))
+(deftest-next-overlay-change-1 d 30 40 (20 30) (30 40))
+(deftest-next-overlay-change-1 e 35 40 (20 30) (30 40))
+(deftest-next-overlay-change-1 f 40 (point-max) (20 30) (30 40))
+(deftest-next-overlay-change-1 g 50 (point-max) (20 30) (30 40))
+;; 1 empty, 1 non-empty, intersecting at begin
+(deftest-next-overlay-change-1 h 10 20 (20 20) (20 30))
+(deftest-next-overlay-change-1 i 20 30 (20 20) (20 30))
+(deftest-next-overlay-change-1 j 25 30 (20 20) (20 30))
+(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30))
+(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30))
+;; 1 empty, 1 non-empty, intersecting at end
+(deftest-next-overlay-change-1 h 10 20 (30 30) (20 30))
+(deftest-next-overlay-change-1 i 20 30 (30 30) (20 30))
+(deftest-next-overlay-change-1 j 25 30 (30 30) (20 30))
+(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30))
+(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30))
+;; 1 empty, 1 non-empty, intersecting in the middle
+(deftest-next-overlay-change-1 m 10 20 (25 25) (20 30))
+(deftest-next-overlay-change-1 n 20 25 (25 25) (20 30))
+(deftest-next-overlay-change-1 o 25 30 (25 25) (20 30))
+(deftest-next-overlay-change-1 p 30 (point-max) (25 25) (20 30))
+(deftest-next-overlay-change-1 q 40 (point-max) (25 25) (20 30))
+;; 2 empty, intersecting
+(deftest-next-overlay-change-1 r 10 20 (20 20) (20 20))
+(deftest-next-overlay-change-1 s 20 (point-max) (20 20) (20 20))
+(deftest-next-overlay-change-1 t 30 (point-max) (20 20) (20 20))
+;; 2 empty, non-intersecting
+(deftest-next-overlay-change-1 u 10 20 (20 20) (30 30))
+(deftest-next-overlay-change-1 v 20 30 (20 20) (30 30))
+(deftest-next-overlay-change-1 w 25 30 (20 20) (30 30))
+(deftest-next-overlay-change-1 x 30 (point-max) (20 20) (30 30))
+(deftest-next-overlay-change-1 y 50 (point-max) (20 20) (30 30))
+;; 10 random
+(deftest-next-overlay-change-1 aa 1 5
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+(deftest-next-overlay-change-1 ab (point-max) (point-max)
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+(deftest-next-overlay-change-1 ac 67 88
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+
+
+;; +===================================================================================+
+;; | previous-overlay-change.
+;; +===================================================================================+
+
+;; Same for previous-overlay-change.
+;; 1 non-empty overlay
+(deftest-previous-overlay-change-1 A (point-max) 1)
+(deftest-previous-overlay-change-1 B 1 1)
+(deftest-previous-overlay-change-1 C 1 1 (10 20))
+(deftest-previous-overlay-change-1 D 10 1 (10 20))
+(deftest-previous-overlay-change-1 E 15 10 (10 20))
+(deftest-previous-overlay-change-1 F 20 10 (10 20))
+(deftest-previous-overlay-change-1 G 30 20 (10 20))
+;; 1 empty overlay
+(deftest-previous-overlay-change-1 H 1 1 (10 10))
+(deftest-previous-overlay-change-1 I 10 1 (10 10))
+(deftest-previous-overlay-change-1 J 20 10 (10 10))
+;; 2 non-empty, non-intersecting
+(deftest-previous-overlay-change-1 D 10 1 (20 30) (40 50))
+(deftest-previous-overlay-change-1 E 35 30 (20 30) (40 50))
+(deftest-previous-overlay-change-1 F 60 50 (20 30) (40 50))
+(deftest-previous-overlay-change-1 G 30 20 (20 30) (40 50))
+(deftest-previous-overlay-change-1 H 50 40 (20 30) (40 50))
+;; 2 non-empty, intersecting
+(deftest-previous-overlay-change-1 I 10 1 (20 30) (25 35))
+(deftest-previous-overlay-change-1 J 20 1 (20 30) (25 35))
+(deftest-previous-overlay-change-1 K 23 20 (20 30) (25 35))
+(deftest-previous-overlay-change-1 L 25 20 (20 30) (25 35))
+(deftest-previous-overlay-change-1 M 28 25 (20 30) (25 35))
+(deftest-previous-overlay-change-1 N 30 25 (20 30) (25 35))
+(deftest-previous-overlay-change-1 O 35 30 (20 30) (25 35))
+(deftest-previous-overlay-change-1 P 50 35 (20 30) (25 35))
+;; 2 non-empty, continuous
+(deftest-previous-overlay-change-1 Q 10 1 (20 30) (30 40))
+(deftest-previous-overlay-change-1 R 20 1 (20 30) (30 40))
+(deftest-previous-overlay-change-1 S 25 20 (20 30) (30 40))
+(deftest-previous-overlay-change-1 T 30 20 (20 30) (30 40))
+(deftest-previous-overlay-change-1 U 35 30 (20 30) (30 40))
+(deftest-previous-overlay-change-1 V 40 30 (20 30) (30 40))
+(deftest-previous-overlay-change-1 W 50 40 (20 30) (30 40))
+;; 1 empty, 1 non-empty, non-intersecting
+(deftest-previous-overlay-change-1 a 10 1 (20 20) (30 40))
+(deftest-previous-overlay-change-1 b 20 1 (20 30) (30 40))
+(deftest-previous-overlay-change-1 c 25 20 (20 30) (30 40))
+(deftest-previous-overlay-change-1 d 30 20 (20 30) (30 40))
+(deftest-previous-overlay-change-1 e 35 30 (20 30) (30 40))
+(deftest-previous-overlay-change-1 f 40 30 (20 30) (30 40))
+(deftest-previous-overlay-change-1 g 50 40 (20 30) (30 40))
+;; 1 empty, 1 non-empty, intersecting at begin
+(deftest-previous-overlay-change-1 h 10 1 (20 20) (20 30))
+(deftest-previous-overlay-change-1 i 20 1 (20 20) (20 30))
+(deftest-previous-overlay-change-1 j 25 20 (20 20) (20 30))
+(deftest-previous-overlay-change-1 k 30 20 (20 20) (20 30))
+(deftest-previous-overlay-change-1 l 40 30 (20 20) (20 30))
+;; 1 empty, 1 non-empty, intersecting at end
+(deftest-previous-overlay-change-1 m 10 1 (30 30) (20 30))
+(deftest-previous-overlay-change-1 n 20 1 (30 30) (20 30))
+(deftest-previous-overlay-change-1 o 25 20 (30 30) (20 30))
+(deftest-previous-overlay-change-1 p 30 20 (20 20) (20 30))
+(deftest-previous-overlay-change-1 q 40 30 (20 20) (20 30))
+;; 1 empty, 1 non-empty, intersectig in the middle
+(deftest-previous-overlay-change-1 r 10 1 (25 25) (20 30))
+(deftest-previous-overlay-change-1 s 20 1 (25 25) (20 30))
+(deftest-previous-overlay-change-1 t 25 20 (25 25) (20 30))
+(deftest-previous-overlay-change-1 u 30 25 (25 25) (20 30))
+(deftest-previous-overlay-change-1 v 40 30 (25 25) (20 30))
+;; 2 empty, intersecting
+(deftest-previous-overlay-change-1 w 10 1 (20 20) (20 20))
+(deftest-previous-overlay-change-1 x 20 1 (20 20) (20 20))
+(deftest-previous-overlay-change-1 y 30 20 (20 20) (20 20))
+;; 2 empty, non-intersecting
+(deftest-previous-overlay-change-1 z 10 1 (20 20) (30 30))
+(deftest-previous-overlay-change-1 aa 20 1 (20 20) (30 30))
+(deftest-previous-overlay-change-1 ab 25 20 (20 20) (30 30))
+(deftest-previous-overlay-change-1 ac 30 20 (20 20) (30 30))
+(deftest-previous-overlay-change-1 ad 50 30 (20 20) (30 30))
+;; 10 random
+(deftest-previous-overlay-change-1 ae 100 90
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+(deftest-previous-overlay-change-1 af (point-min) (point-min)
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+(deftest-previous-overlay-change-1 ag 29 28
+  (58 66) (41 10) (9 67) (28 88) (27 43)
+  (24 27) (48 36) (5 90) (61 9))
+
+
+;; +===================================================================================+
+;; | overlays-at
+;; +===================================================================================+
+
+
+;; Test whether overlay-at returns RESULT at POS after overlays OVL were
+;; created in a buffer.         POS RES OVL
+(deftest-overlays-at-1 A 1 ())
+;; 1 overlay
+(deftest-overlays-at-1 B 10 (a) (a 10 20))
+(deftest-overlays-at-1 C 15 (a) (a 10 20))
+(deftest-overlays-at-1 D 19 (a) (a 10 20))
+(deftest-overlays-at-1 E 20 ()  (a 10 20))
+(deftest-overlays-at-1 F 1 () (a 10 20))
+
+;; 2 non-empty overlays non-intersecting
+(deftest-overlays-at-1 G 1 () (a 10 20) (b 30 40))
+(deftest-overlays-at-1 H 10 (a) (a 10 20) (b 30 40))
+(deftest-overlays-at-1 I 15 (a) (a 10 20) (b 30 40))
+(deftest-overlays-at-1 K 20 () (a 10 20) (b 30 40))
+(deftest-overlays-at-1 L 25 () (a 10 20) (b 30 40))
+(deftest-overlays-at-1 M 30 (b) (a 10 20) (b 30 40))
+(deftest-overlays-at-1 N 35 (b) (a 10 20) (b 30 40))
+(deftest-overlays-at-1 O 40 () (a 10 20) (b 30 40))
+(deftest-overlays-at-1 P 50 () (a 10 20) (b 30 40))
+
+;; 2 non-empty overlays intersecting
+(deftest-overlays-at-1 G 1 () (a 10 30) (b 20 40))
+(deftest-overlays-at-1 H 10 (a) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 I 15 (a) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 K 20 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 L 25 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 M 30 (b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 N 35 (b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 O 40 () (a 10 30) (b 20 40))
+(deftest-overlays-at-1 P 50 () (a 10 30) (b 20 40))
+
+;; 2 non-empty overlays continuous
+(deftest-overlays-at-1 G 1 () (a 10 20) (b 20 30))
+(deftest-overlays-at-1 H 10 (a) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 I 15 (a) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 K 20 (b) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 L 25 (b) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 M 30 () (a 10 20) (b 20 30))
+
+;; overlays-at never returns empty overlays.
+(deftest-overlays-at-1 N 1 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 O 20 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 P 30 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 Q 40 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 R 50 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 S 60 () (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+
+;; behaviour at point-min and point-max
+(ert-deftest test-overlays-at-2 ()
+  (cl-macrolet ((should-length (n list)
+                               `(should (= ,n (length ,list)))))
+    (with-temp-buffer
+      (insert (make-string 100 ?\s))
+      (make-overlay 1 (point-max))
+      (make-overlay 10 10)
+      (make-overlay 20 20)
+      (make-overlay (point-max) (point-max))
+      (should-length 1 (overlays-at 1))
+      (should-length 1 (overlays-at 10))
+      (should-length 1 (overlays-at 20))
+      (should-length 0 (overlays-at (point-max)))
+      (narrow-to-region 10 20)
+      (should-length 1 (overlays-at (point-min)))
+      (should-length 1 (overlays-at 15))
+      (should-length 1 (overlays-at (point-max))))))
+
+
+;; +===================================================================================+
+;; | overlay-in
+;; +===================================================================================+
+
+
+;; Test whether overlays-in returns RES in BEG,END after overlays OVL were
+;; created in a buffer.
+
+(deftest-overlays-in-1 A 1 (point-max) ());;POS RES OVL
+;; 1 overlay
+(deftest-overlays-in-1 B 1 10 () (a 10 20))
+(deftest-overlays-in-1 C 5 10 () (a 10 20))
+(deftest-overlays-in-1 D 5 15 (a) (a 10 20))
+(deftest-overlays-in-1 E 10 15 (a)  (a 10 20))
+(deftest-overlays-in-1 F 10 20 (a) (a 10 20))
+(deftest-overlays-in-1 G 15 20 (a) (a 10 20))
+(deftest-overlays-in-1 H 15 25 (a) (a 10 20))
+(deftest-overlays-in-1 I 20 25 () (a 10 20))
+(deftest-overlays-in-1 J 30 50 () (a 10 20))
+
+;; 2 non-empty overlays non-intersecting
+(deftest-overlays-in-1 K 1 5 () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 L 5 10 () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 M 5 15 (a) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 N 10 15 (a) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 O 15 20 (a) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 P 15 25 (a) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 Q 20 25 () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 R 20 30 () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 S 25 30 () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 T 25 35 (b) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 U 30 35 (b) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 V 40 50  () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 W 50 60  () (a 10 20) (b 30 40))
+(deftest-overlays-in-1 X 1 50  (a b) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 Y 10 40  (a b) (a 10 20) (b 30 40))
+(deftest-overlays-in-1 Z 10 41  (a b) (a 10 20) (b 30 40))
+
+;; 2 non-empty overlays intersecting
+(deftest-overlays-in-1 a 1 5 () (a 10 30) (b 20 40))
+(deftest-overlays-in-1 b 5 10 () (a 10 30) (b 20 40))
+(deftest-overlays-in-1 c 5 15 (a) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 d 10 15 (a) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 e 10 20 (a) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 f 15 20 (a) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 g 20 30 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 h 20 40 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 i 25 30 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 j 30 30 (b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 k 30 35 (b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 l 35 40 (b) (a 10 30) (b 20 40))
+(deftest-overlays-in-1 m 40 45 () (a 10 30) (b 20 40))
+(deftest-overlays-in-1 n 41 45 () (a 10 30) (b 20 40))
+(deftest-overlays-in-1 o 50 60 () (a 10 30) (b 20 40))
+
+;; 2 non-empty overlays continuous
+(deftest-overlays-in-1 p 1 5 () (a 10 20) (b 20 30))
+(deftest-overlays-in-1 q 5 10 () (a 10 20) (b 20 30))
+(deftest-overlays-in-1 r 15 20 (a) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 s 15 25 (a b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 t 20 25 (b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 u 25 30 (b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 v 29 35 (b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 w 30 35 () (a 10 20) (b 20 30))
+(deftest-overlays-in-1 x 35 50 () (a 10 20) (b 20 30))
+(deftest-overlays-in-1 y 1 50 (a b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 z 15 50 (a b) (a 10 20) (b 20 30))
+(deftest-overlays-in-1 aa 1 25 (a b) (a 10 20) (b 20 30))
+
+;; 1 empty overlay
+(deftest-overlays-in-1 ab 1 10 () (a 10 10))
+(deftest-overlays-in-1 ac 10 10 (a) (a 10 10))
+(deftest-overlays-in-1 ad 9 10 () (a 10 10))
+(deftest-overlays-in-1 ae 9 11 (a) (a 10 10))
+(deftest-overlays-in-1 af 10 11 (a) (a 10 10))
+
+
+;; behaviour at point-max
+(ert-deftest test-overlays-in-2 ()
+  (cl-macrolet ((should-length (n list)
+                               `(should (= ,n (length ,list)))))
+    (with-temp-buffer
+      (insert (make-string 100 ?\s))
+      (make-overlay (point-max) (point-max))
+      (make-overlay 50 50)
+      (should-length 1 (overlays-in 50 50))
+      (should-length 2 (overlays-in 1 (point-max)))
+      (should-length 1 (overlays-in (point-max) (point-max)))
+      (narrow-to-region 1 50)
+      (should-length 0 (overlays-in 1 (point-max)))
+      (should-length 1 (overlays-in (point-max) (point-max))))))
+
+
+;; +===================================================================================+
+;; | overlay-recenter
+;; +===================================================================================+
+
+;; This function is a noop in the overlay tree branch.
+(ert-deftest test-overlay-recenter ()
+  (with-temp-buffer
+    (should-not (overlay-recenter 1))
+    (insert (make-string 100 ?\s))
+    (dotimes (i 10)
+      (make-overlay i (1+ i))
+      (should-not (overlay-recenter i)))))
+
+
+;; +===================================================================================+
+;; | move-overlay
+;; +===================================================================================+
+
+;; buffer nil with live overlay
+(ert-deftest test-move-overlay-1 ()
+  (test-with-overlay-in-buffer (ov 1 100)
+                               (move-overlay ov 50 60)
+                               (should (= 50 (overlay-start ov)))
+                               (should (= 60 (overlay-end ov)))
+                               (should (eq (current-buffer) (overlay-buffer ov)))))
+
+;; buffer nil, dead overlay
+(ert-deftest test-move-overlay-2 ()
+  (with-temp-buffer
+    (let ((ov (test-with-overlay-in-buffer (ov 1 100) ov)))
+      (insert (make-string 100 ?\s))
+      (move-overlay ov 50 60)
+      (should (= 50 (overlay-start ov)))
+      (should (= 60 (overlay-end ov)))
+      (should (eq (current-buffer) (overlay-buffer ov))))))
+
+;; buffer non-nil, live overlay
+(ert-deftest test-move-overlay-3 ()
+  (test-with-overlay-in-buffer (ov 10 100)
+                               (with-temp-buffer
+                                 (move-overlay ov 1 1 (current-buffer))
+                                 (should (= 1 (overlay-start ov)))
+                                 (should (= 1 (overlay-end ov)))
+                                 (should (eq (current-buffer) (overlay-buffer ov))))
+                               (should-not (overlay-start ov))
+                               (should-not (overlay-end ov))
+                               (should-not (overlay-buffer ov))))
+
+;; buffer non-nil, dead overlay
+(ert-deftest test-move-overlay-4 ()
+  (let ((ov (test-with-overlay-in-buffer (ov 1 1) ov)))
+    (with-temp-buffer
+      (move-overlay ov 1 1 (current-buffer))
+      (should (= 1 (overlay-start ov)))
+      (should (= 1 (overlay-end ov)))
+      (should (eq (current-buffer) (overlay-buffer ov))))
+    (should-not (overlay-start ov))
+    (should-not (overlay-end ov))
+    (should-not (overlay-buffer ov))))
+
+;; +===================================================================================+
+;; | delete-(all-)overlay
+;; +===================================================================================+
+
+;; delete live overlay
+(ert-deftest test-delete-overlay-1 ()
+  (test-with-overlay-in-buffer (ov 10 100)
+                               (should (buffer-live-p (overlay-buffer ov)))
+                               (delete-overlay ov)
+                               (should-not (overlay-start ov))
+                               (should-not (overlay-end ov))
+                               (should-not (overlay-buffer ov))))
+
+;; delete dead overlay
+(ert-deftest test-delete-overlay-2 ()
+  (let ((ov (test-with-overlay-in-buffer (ov 10 100) ov)))
+    (should-not (overlay-start ov))
+    (should-not (overlay-end ov))
+    (should-not (overlay-buffer ov))
+    (should-not (delete-overlay ov))
+    (should-not (overlay-start ov))
+    (should-not (overlay-end ov))
+    (should-not (overlay-buffer ov))))
+
+(ert-deftest test-delete-all-overlay-1 ()
+  (with-temp-buffer
+    (should-not (delete-all-overlays))
+    (should-not (delete-all-overlays (current-buffer)))
+    (insert (make-string 100 ?\s))
+    (dotimes (i 10) (make-overlay i (1+ i)))
+    (should-not (delete-all-overlays (current-buffer)))
+    (should-not (delete-all-overlays))))
+
+
+;; +===================================================================================+
+;; | get-char-property(-and-overlay)
+;; +===================================================================================+
+
+;; FIXME: TBD
+
+
+;; +===================================================================================+
+;; | Moving by insertions
+;; +===================================================================================+
+
+(defmacro deftest-moving-insert-1 (id beg-end insert sbeg-send fa ra)
+  (cl-destructuring-bind (beg end ipos ilen sbeg send fa ra)
+      (append beg-end insert sbeg-send (list fa ra) nil)
+    `(ert-deftest ,(make-overlay-test-name 'moving-insert 1 id) ()
+       (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
+                                    (should (= ,beg (overlay-start ov)))
+                                    (should (= ,end (overlay-end ov)))
+                                    (goto-char ,ipos)
+                                    (insert (make-string ,ilen ?x))
+                                    (should (= ,sbeg (overlay-start ov)))
+                                    (should (= ,send (overlay-end ov)))))))
+
+;; non-empty, no fa, no ra
+;; --------------------  OV      INS    RESULT
+(deftest-moving-insert-1 A (10 20) (15 3) (10 23) nil nil)
+(deftest-moving-insert-1 B (10 20) (20 4) (10 20) nil nil)
+(deftest-moving-insert-1 C (10 20) (5 5) (15 25) nil nil)
+(deftest-moving-insert-1 D (10 20) (10 3) (10 23) nil nil)
+(deftest-moving-insert-1 E (10 20) (20 4) (10 20) nil nil)
+
+;; non-empty no fa, ra
+(deftest-moving-insert-1 F (10 20) (15 3) (10 23) nil t)
+(deftest-moving-insert-1 G (10 20) (20 4) (10 24) nil t)
+(deftest-moving-insert-1 H (10 20) (5 5) (15 25) nil t)
+(deftest-moving-insert-1 I (10 20) (10 3) (10 23) nil t)
+(deftest-moving-insert-1 J (10 20) (20 4) (10 24) nil t)
+
+;; non-empty, fa, no r
+(deftest-moving-insert-1 K (10 20) (15 3) (10 23) t nil)
+(deftest-moving-insert-1 L (10 20) (20 4) (10 20) t nil)
+(deftest-moving-insert-1 M (10 20) (5 5) (15 25) t nil)
+(deftest-moving-insert-1 N (10 20) (10 3) (13 23) t nil)
+(deftest-moving-insert-1 O (10 20) (20 4) (10 20) t nil)
+
+;; This used to fail.
+(ert-deftest test-moving-insert-2-a ()
+  (with-temp-buffer
+    (insert (make-string 1 ?.))
+    (let ((ov (make-overlay 1 1 nil t nil)))
+      (insert "()")
+      (should (= 1 (overlay-end ov))))))
+
+;; non-empty, fa, ra
+(deftest-moving-insert-1 P (10 20) (15 3) (10 23) t t)
+(deftest-moving-insert-1 Q (10 20) (20 4) (10 24) t t)
+(deftest-moving-insert-1 R (10 20) (5 5) (15 25) t t)
+(deftest-moving-insert-1 S (10 20) (10 3) (13 23) t t)
+(deftest-moving-insert-1 T (10 20) (20 4) (10 24) t t)
+
+;; empty, no fa, no ra
+(deftest-moving-insert-1 U (15 15) (20 4) (15 15) nil nil)
+(deftest-moving-insert-1 V (15 15) (5 5) (20 20) nil nil)
+(deftest-moving-insert-1 W (15 15) (15 3) (15 15) nil nil)
+
+;; empty no fa, ra
+(deftest-moving-insert-1 X (15 15) (20 4) (15 15) nil t)
+(deftest-moving-insert-1 Y (15 15) (5 5) (20 20) nil t)
+(deftest-moving-insert-1 Z (15 15) (15 3) (15 18) nil t)
+
+;; empty, fa, no ra
+(deftest-moving-insert-1 a (15 15) (20 4) (15 15) t nil)
+(deftest-moving-insert-1 b (15 15) (5 5) (20 20) t nil)
+(deftest-moving-insert-1 c (15 15) (15 3) (15 15) t nil)
+
+;; empty, fa, ra
+(deftest-moving-insert-1 d (15 15) (20 4) (15 15) t t)
+(deftest-moving-insert-1 e (15 15) (5 5) (20 20) t t)
+(deftest-moving-insert-1 f (15 15) (15 3) (18 18) t t)
+
+;; Try to trigger a pathological case where the tree could become
+;; unordered due to an insert operation.
+
+(ert-deftest test-moving-insert-2 ()
+  (with-temp-buffer
+    (insert (make-string 1000 ?x))
+    (let ((root (make-overlay 50 75 nil    nil             'rear-advance))
+          (left (make-overlay 25 50 nil    'front-advance  'rear-advance))
+          (right (make-overlay 75 100 nil  nil             nil)))
+      ;;     [50] <--- start
+      ;;    /    \
+      ;; (25)    (75)
+      (delete-region 25 75)
+      ;;     [25]
+      ;;    /    \
+      ;; (25)    (25)
+      (should (= 25 (overlay-start root)))
+      (should (= 25 (overlay-end root)))
+      (should (= 25 (overlay-start left)))
+      (should (= 25 (overlay-end left)))
+      (should (= 25 (overlay-start right)))
+      (should (= 50 (overlay-end right)))
+      ;; Inserting at start should make left advance while right and
+      ;; root stay, thus we would have left > right .
+      (goto-char 25)
+      (insert (make-string 25 ?x))
+      ;;     [25]
+      ;;    /    \
+      ;; (50)    (25)
+      (should (= 25 (overlay-start root)))
+      (should (= 50 (overlay-end root)))
+      (should (= 50 (overlay-start left)))
+      (should (= 50 (overlay-end left)))
+      (should (= 25 (overlay-start right)))
+      (should (= 75 (overlay-end right)))
+      ;; Try to detect the error, by removing left.  The should fail
+      ;; an eassert, since it won't be found by a reular tree
+      ;; traversal - in theory.
+      (delete-overlay left)
+      (should (= 2 (length (overlays-in 1 (point-max))))))))
+
+
+
+;; +===================================================================================+
+;; | Moving by deletions
+;; +===================================================================================+
+
+(defmacro deftest-moving-delete-1 (id beg-end delete sbeg-send fa ra)
+  (cl-destructuring-bind (beg end dpos dlen sbeg send fa ra)
+      (append beg-end delete sbeg-send (list fa ra) nil)
+    `(ert-deftest ,(make-overlay-test-name 'moving-delete 1 id) ()
+       (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
+                                    (should (= ,beg (overlay-start ov)))
+                                    (should (= ,end (overlay-end ov)))
+                                    (delete-region ,dpos (+ ,dpos ,dlen))
+                                    (should (= ,sbeg (overlay-start ov)))
+                                    (should (= ,send (overlay-end ov)))))))
+
+;; non-empty, no fa, no ra
+;; --------------------  OV      DEL    RESULT
+(deftest-moving-delete-1 A (10 20) (15 3) (10 17) nil nil)
+(deftest-moving-delete-1 B (10 20) (20 4) (10 20) nil nil)
+(deftest-moving-delete-1 C (10 20) (5 5) (5 15) nil nil)
+(deftest-moving-delete-1 D (10 20) (10 3) (10 17) nil nil)
+(deftest-moving-delete-1 E (10 20) (20 4) (10 20) nil nil)
+
+;; non-empty no fa, ra
+(deftest-moving-delete-1 F (10 20) (15 3) (10 17) nil t)
+(deftest-moving-delete-1 G (10 20) (20 4) (10 20) nil t)
+(deftest-moving-delete-1 H (10 20) (5 5) (5 15) nil t)
+(deftest-moving-delete-1 I (10 20) (10 3) (10 17) nil t)
+(deftest-moving-delete-1 J (10 20) (20 4) (10 20) nil t)
+
+;; non-empty, fa, no ra
+(deftest-moving-delete-1 K (10 20) (15 3) (10 17) t nil)
+(deftest-moving-delete-1 L (10 20) (20 4) (10 20) t nil)
+(deftest-moving-delete-1 M (10 20) (5 5) (5 15) t nil)
+(deftest-moving-delete-1 N (10 20) (10 3) (10 17) t nil)
+(deftest-moving-delete-1 O (10 20) (20 4) (10 20) t nil)
+
+;; non-empty, fa, ra
+(deftest-moving-delete-1 P (10 20) (15 3) (10 17) t t)
+(deftest-moving-delete-1 Q (10 20) (20 4) (10 20) t t)
+(deftest-moving-delete-1 R (10 20) (5 5) (5 15) t t)
+(deftest-moving-delete-1 S (10 20) (10 3) (10 17) t t)
+(deftest-moving-delete-1 T (10 20) (20 4) (10 20) t t)
+
+;; empty, no fa, no ra
+(deftest-moving-delete-1 U (15 15) (20 4) (15 15) nil nil)
+(deftest-moving-delete-1 V (15 15) (5 5) (10 10) nil nil)
+(deftest-moving-delete-1 W (15 15) (15 3) (15 15) nil nil)
+
+;; empty no fa, ra
+(deftest-moving-delete-1 X (15 15) (20 4) (15 15) nil t)
+(deftest-moving-delete-1 Y (15 15) (5 5) (10 10) nil t)
+(deftest-moving-delete-1 Z (15 15) (15 3) (15 15) nil t)
+
+;; empty, fa, no ra
+(deftest-moving-delete-1 a (15 15) (20 4) (15 15) t nil)
+(deftest-moving-delete-1 b (15 15) (5 5) (10 10) t nil)
+(deftest-moving-delete-1 c (15 15) (15 3) (15 15) t nil)
+
+;; empty, fa, ra
+(deftest-moving-delete-1 d (15 15) (20 4) (15 15) t t)
+(deftest-moving-delete-1 e (15 15) (5 5) (10 10) t t)
+(deftest-moving-delete-1 f (15 15) (15 3) (15 15) t t)
+
+
+;; +===================================================================================+
+;; | make-indirect-buffer
+;; +===================================================================================+
+
+;; Check if overlays are cloned/seperate from indirect buffer.
+(ert-deftest test-make-indirect-buffer-1 ()
+  (with-temp-buffer
+    (dotimes (_ 10) (make-overlay 1 1))
+    (let (indirect clone)
+      (unwind-protect
+          (progn
+            (setq indirect (make-indirect-buffer
+                            (current-buffer) "indirect"))
+            (with-current-buffer indirect
+              (should-not (overlays-in (point-min) (point-max)))
+              (dotimes (_ 20) (make-overlay 1 1))
+              (should (= 20 (length (overlays-in (point-min) (point-max)))))
+              (delete-all-overlays)
+              (should-not (overlays-in (point-min) (point-max))))
+            (should (= 10 (length (overlays-in (point-min) (point-max)))))
+            (setq clone (make-indirect-buffer
+                         (current-buffer) "clone" 'clone))
+            (with-current-buffer clone
+              (should (= 10 (length (overlays-in (point-min) (point-max)))))
+              (dotimes (_ 30) (make-overlay 1 1))
+              (should (= 40 (length (overlays-in (point-min) (point-max))))))
+            ;; back in temp buffer
+            (should (= 10 (length (overlays-in (point-min) (point-max)))))
+            (with-current-buffer clone
+              (mapc #'delete-overlay
+                    (seq-take (overlays-in (point-min) (point-max)) 10))
+              (should (= 30 (length (overlays-in (point-min) (point-max))))))
+            (should (= 10 (length (overlays-in (point-min) (point-max)))))
+            (delete-all-overlays)
+            (with-current-buffer clone
+              (should (= 30 (length (overlays-in (point-min) (point-max)))))))
+        (when (buffer-live-p clone)
+          (kill-buffer clone))
+        (when (buffer-live-p indirect)
+          (kill-buffer indirect))))))
+
+
+
+;; +===================================================================================+
+;; | buffer-swap-text
+;; +===================================================================================+
+
+(defmacro test-with-temp-buffers (vars &rest body)
+  (declare (indent 1) (debug (sexp &rest form)))
+  (if (null vars)
+      `(progn ,@body)
+    `(with-temp-buffer
+       (let ((,(car vars) (current-buffer)))
+         (test-with-temp-buffers ,(cdr vars) ,@body)))))
+
+;; basic
+(ert-deftest test-buffer-swap-text-1 ()
+  (test-with-temp-buffers (buffer other)
+                          (with-current-buffer buffer
+                            (let ((ov (make-overlay 1 1)))
+                              (buffer-swap-text other)
+                              (should-not (overlays-in 1 1))
+                              (with-current-buffer other
+                                (should (overlays-in 1 1))
+                                (should (eq ov (car (overlays-in 1 1)))))))))
+
+;; properties
+(ert-deftest test-buffer-swap-text-1 ()
+  (test-with-temp-buffers (buffer other)
+                          (with-current-buffer other
+                            (overlay-put (make-overlay 1 1) 'buffer 'other))
+                          (with-current-buffer buffer
+                            (overlay-put (make-overlay 1 1) 'buffer 'buffer)
+                            (buffer-swap-text other)
+                            (should (= 1 (length (overlays-in 1 1))))
+                            (should (eq (overlay-get (car (overlays-in 1 1)) 'buffer) 'other)))
+                          (with-current-buffer other
+                            (should (= 1 (length (overlays-in 1 1))))
+                            (should (eq (overlay-get (car (overlays-in 1 1)) 'buffer) 'buffer)))))
+
+
+;; +===================================================================================+
+;; | priorities
+;; +===================================================================================+
+
+(ert-deftest test-overlay-priorities-1 ()
+  (with-temp-buffer
+    (insert " ")
+    (dotimes (i 10)
+      (let ((ov (make-overlay 1 2)))
+        (overlay-put ov 'priority i)
+        (overlay-put ov 'value i)))
+    (should (eq 9 (get-char-property 1 'value)))))
+
+(ert-deftest test-overlay-priorities-2 ()
+  (with-temp-buffer
+    (insert " ")
+    (dotimes (j 10)
+      (let* ((i (- 9 j))
+             (ov (make-overlay 1 2)))
+        (overlay-put ov 'priority i)
+        (overlay-put ov 'value i)))
+    (should (eq 9 (get-char-property 1 'value)))))
+
+
+;; +===================================================================================+
+;; | Other
+;; +===================================================================================+
+
+(defun test-overlay-regions ()
+  (sort (mapcar (lambda (ov)
+                  (cons (overlay-start ov)
+                        (overlay-end ov)))
+                (overlays-in (point-min)
+                             (point-max)))
+        (lambda (o1 o2)
+          (or (< (car o1) (car o2))
+              (and (= (car o1) (car o2))
+                   (< (cdr o1) (cdr o2)))))))
+
+;; This test used to fail.
+(ert-deftest overlay-complex-delete-with-offset ()
+  (with-temp-buffer
+    (let (todelete)
+      (insert (make-string 1000 ?\s))
+      (make-overlay 1 2 nil t nil)
+      (make-overlay 2 3 nil t nil)
+      (make-overlay 3 4 nil t nil)
+      (make-overlay 4 5 nil t nil)
+      (setq todelete (make-overlay 280 287 nil t nil))
+      (make-overlay 265 275 nil t nil)
+      (make-overlay 329 386 nil t nil)
+      (make-overlay 386 390 nil t nil)
+      (goto-char 50)
+      (delete-char 50)
+      (goto-char 1)
+      (delete-char 2)
+      (delete-overlay todelete)
+      (should (equal (test-overlay-regions)
+                     '((1 . 1) (1 . 1) (1 . 2) (2 . 3) (213 . 223) (277 . 334) (334 . 338)))))))
+
+;; This test used to fail.
+(ert-deftest overlay-complex-insert-1 ()
+  (with-temp-buffer
+    (insert "          ")
+    (make-overlay 8 11 nil nil t)
+    (make-overlay 2 7 nil nil nil)
+    (make-overlay 2 4 nil t nil)
+    (goto-char 1)
+    (insert "     ")
+    (should (equal (test-overlay-regions)
+                   '((7 . 9)
+                     (7 . 12)
+                     (13 . 16))))))
+
+;; This test used to fail.
+(ert-deftest overlay-complex-insert-2 ()
+  (with-temp-buffer
+    (insert (make-string 100 ?\s))
+    (make-overlay 77 7 nil nil t)
+    (make-overlay 21 53 nil t t)
+    (make-overlay 84 14 nil nil nil)
+    (make-overlay 38 69 nil t nil)
+    (make-overlay 93 15 nil nil t)
+    (make-overlay 73 48 nil t t)
+    (make-overlay 96 51 nil t t)
+    (make-overlay 6 43 nil t t)
+    (make-overlay 15 100 nil t t)
+    (make-overlay 22 17 nil nil nil)
+    (make-overlay 72 45 nil t nil)
+    (make-overlay 2 74 nil nil t)
+    (make-overlay 15 29 nil t t)
+    (make-overlay 17 34 nil t t)
+    (make-overlay 101 66 nil t nil)
+    (make-overlay 94 24 nil nil nil)
+    (goto-char 78)
+    (insert "           ")
+    (narrow-to-region 47 19)
+    (goto-char 46)
+    (widen)
+    (narrow-to-region 13 3)
+    (goto-char 9)
+    (delete-char 0)
+    (goto-char 11)
+    (insert "           ")
+    (goto-char 3)
+    (insert "          ")
+    (goto-char 8)
+    (insert "       ")
+    (goto-char 26)
+    (insert "  ")
+    (goto-char 14)
+    (widen)
+    (narrow-to-region 71 35)
+    (should
+     (equal (test-overlay-regions)
+            '((2 . 104)
+              (23 . 73)
+              (24 . 107)
+              (44 . 125)
+              (45 . 59)
+              (45 . 134)
+              (45 . 141)
+              (47 . 52)
+              (47 . 64)
+              (51 . 83)
+              (54 . 135)
+              (68 . 99))))))
+
+(ert-deftest test-overlay-multibyte-transition-1 ()
+  (with-temp-buffer
+    (set-buffer-multibyte t)
+    (insert "ääää")
+    ;; aeaeaeae
+    ;; 1 2 3 4 5
+    ;; 123456789
+    (let ((nonempty-bob (make-overlay 1 2))
+          (empty-bob    (make-overlay 1 1))
+          (empty        (make-overlay 2 2))
+          (nonempty     (make-overlay 2 4))
+          (nonempty-eob (make-overlay 4 5))
+          (empty-eob    (make-overlay 5 5)))
+      (set-buffer-multibyte nil)
+      (cl-macrolet ((ovshould (ov begin end)
+                              `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
+                                              (list ,begin ,end)))))
+        (ovshould nonempty-bob 1 3)
+        (ovshould empty-bob    1 1)
+        (ovshould empty        3 3)
+        (ovshould nonempty     3 7)
+        (ovshould nonempty-eob 7 9)
+        (ovshould empty-eob    9 9)))))
+
+(ert-deftest test-overlay-multibyte-transition-2 ()
+  (with-temp-buffer
+    (set-buffer-multibyte t)
+    (insert "ääää")
+    (set-buffer-multibyte nil)
+    ;; aeaeaeae
+    ;; 1 2 3 4 5
+    ;; 123456789
+    (let ((nonempty-bob-end (make-overlay 1 2))
+          (nonempty-bob-beg (make-overlay 1 3))
+          (empty-bob        (make-overlay 1 1))
+          (empty-beg        (make-overlay 3 3))
+          (empty-end        (make-overlay 2 2))
+          (nonempty-beg-beg (make-overlay 3 7))
+          (nonempty-beg-end (make-overlay 3 8))
+          (nonempty-end-beg (make-overlay 4 7))
+          (nonempty-end-end (make-overlay 4 8))
+          (nonempty-eob-beg (make-overlay 5 9))
+          (nonempty-eob-end (make-overlay 6 9))
+          (empty-eob        (make-overlay 9 9)))
+      (set-buffer-multibyte t)
+      (cl-macrolet ((ovshould (ov begin end)
+                              `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
+                                              (list ,begin ,end)))))
+        (ovshould nonempty-bob-end 1 2)
+        (ovshould nonempty-bob-beg 1 2)
+        (ovshould empty-bob        1 1)
+        (ovshould empty-beg        2 2)
+        (ovshould empty-end        2 2)
+        (ovshould nonempty-beg-beg 2 4)
+        (ovshould nonempty-beg-end 2 5)
+        (ovshould nonempty-end-beg 3 4)
+        (ovshould nonempty-end-end 3 5)
+        (ovshould nonempty-eob-beg 3 5)
+        (ovshould nonempty-eob-end 4 5)
+        (ovshould empty-eob        5 5)))))
+
 ;;; buffer-tests.el ends here

  reply	other threads:[~2019-12-04 11:41 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-26 14:44 The overlay branch (yet again) Vladimir Kazanov
2019-12-03 15:35 ` Vladimir Kazanov
2019-12-03 15:58   ` Eli Zaretskii
2019-12-03 16:06   ` martin rudalics
2019-12-03 16:21     ` Vladimir Kazanov
2019-12-03 17:58       ` Stefan Monnier
2019-12-03 20:46         ` Vladimir Kazanov
2019-12-03 22:43           ` Stefan Monnier
2019-12-04 11:41             ` Vladimir Kazanov [this message]
2019-12-05 14:13               ` Vladimir Kazanov
2019-12-05 15:14                 ` Eli Zaretskii
2019-12-05 15:31                   ` Vladimir Kazanov
2019-12-05 16:38                     ` Eli Zaretskii
2019-12-06  6:48                       ` Vladimir Kazanov
2019-12-09  8:10                         ` Vladimir Kazanov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAAs=0-0daXrvurzNt9xJAR6nUbPtT1TDZQuiqVrsFM4VtfaqLQ@mail.gmail.com' \
    --to=vekazanov@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=rudalics@gmx.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).