aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lisp/emacs-lisp/track-changes-tests.el156
1 files changed, 156 insertions, 0 deletions
diff --git a/test/lisp/emacs-lisp/track-changes-tests.el b/test/lisp/emacs-lisp/track-changes-tests.el
new file mode 100644
index 00000000000..ed35477cafd
--- /dev/null
+++ b/test/lisp/emacs-lisp/track-changes-tests.el
@@ -0,0 +1,156 @@
1;;; track-changes-tests.el --- tests for emacs-lisp/track-changes.el -*- lexical-binding:t -*-
2
3;; Copyright (C) 2024 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;; Code:
23
24(require 'track-changes)
25(require 'cl-lib)
26(require 'ert)
27
28(defun track-changes-tests--random-word ()
29 (let ((chars ()))
30 (dotimes (_ (1+ (random 12)))
31 (push (+ ?A (random (1+ (- ?z ?A)))) chars))
32 (apply #'string chars)))
33
34(defvar track-changes-tests--random-verbose nil)
35
36(defun track-changes-tests--message (&rest args)
37 (when track-changes-tests--random-verbose (apply #'message args)))
38
39(defvar track-changes-tests--random-seed
40 (let ((seed (number-to-string (random (expt 2 24)))))
41 (message "Random seed = %S" seed)
42 seed))
43
44(ert-deftest track-changes-tests--random ()
45 ;; Keep 2 buffers in sync with a third one as we make random
46 ;; changes to that 3rd one.
47 ;; We have 3 trackers: a "normal" one which we sync
48 ;; at random intervals, one which syncs via the "disjoint" signal,
49 ;; plus a third one which verifies that "nobefore" gets
50 ;; information consistent with the "normal" tracker.
51 (with-temp-buffer
52 (random track-changes-tests--random-seed)
53 (dotimes (_ 100)
54 (insert (track-changes-tests--random-word) "\n"))
55 (let* ((buf1 (generate-new-buffer " *tc1*"))
56 (buf2 (generate-new-buffer " *tc2*"))
57 (char-counts (make-vector 2 0))
58 (sync-counts (make-vector 2 0))
59 (print-escape-newlines t)
60 (file (make-temp-file "tc"))
61 (id1 (track-changes-register #'ignore))
62 (id3 (track-changes-register #'ignore :nobefore t))
63 (sync
64 (lambda (id buf n)
65 (track-changes-tests--message "!! SYNC %d !!" n)
66 (track-changes-fetch
67 id (lambda (beg end before)
68 (when (eq n 1)
69 (track-changes-fetch
70 id3 (lambda (beg3 end3 before3)
71 (should (eq beg3 beg))
72 (should (eq end3 end))
73 (should (eq before3
74 (if (symbolp before)
75 before (length before)))))))
76 (cl-incf (aref sync-counts (1- n)))
77 (cl-incf (aref char-counts (1- n)) (- end beg))
78 (let ((after (buffer-substring beg end)))
79 (track-changes-tests--message
80 "Sync:\n %S\n=> %S\nat %d .. %d"
81 before after beg end)
82 (with-current-buffer buf
83 (if (eq before 'error)
84 (erase-buffer)
85 (should (equal before
86 (buffer-substring
87 beg (+ beg (length before)))))
88 (delete-region beg (+ beg (length before))))
89 (goto-char beg)
90 (insert after)))
91 (should (equal (buffer-string)
92 (with-current-buffer buf
93 (buffer-string))))))))
94 (id2 (track-changes-register
95 (lambda (id2 &optional distance)
96 (when distance
97 (track-changes-tests--message "Disjoint distance: %d"
98 distance)
99 (funcall sync id2 buf2 2)))
100 :disjoint t)))
101 (write-region (point-min) (point-max) file)
102 (insert-into-buffer buf1)
103 (insert-into-buffer buf2)
104 (should (equal (buffer-hash) (buffer-hash buf1)))
105 (should (equal (buffer-hash) (buffer-hash buf2)))
106 (message "seeding with: %S" track-changes-tests--random-seed)
107 (dotimes (_ 1000)
108 (pcase (random 15)
109 (0
110 (track-changes-tests--message "Manual sync1")
111 (funcall sync id1 buf1 1))
112 (1
113 (track-changes-tests--message "Manual sync2")
114 (funcall sync id2 buf2 2))
115 ((pred (< _ 5))
116 (let* ((beg (+ (point-min) (random (1+ (buffer-size)))))
117 (end (min (+ beg (1+ (random 100))) (point-max))))
118 (track-changes-tests--message "Fill %d .. %d" beg end)
119 (fill-region-as-paragraph beg end)))
120 ((pred (< _ 8))
121 (let* ((beg (+ (point-min) (random (1+ (buffer-size)))))
122 (end (min (+ beg (1+ (random 12))) (point-max))))
123 (track-changes-tests--message "Delete %S at %d .. %d"
124 (buffer-substring beg end) beg end)
125 (delete-region beg end)))
126 ((and 8 (guard (= (random 50) 0)))
127 (track-changes-tests--message "Silent insertion")
128 (let ((inhibit-modification-hooks t))
129 (insert "a")))
130 ((and 8 (guard (= (random 10) 0)))
131 (track-changes-tests--message "Revert")
132 (insert-file-contents file nil nil nil 'replace))
133 ((and 8 (guard (= (random 3) 0)))
134 (let* ((beg (+ (point-min) (random (1+ (buffer-size)))))
135 (end (min (+ beg (1+ (random 12))) (point-max)))
136 (after (eq (random 2) 0)))
137 (track-changes-tests--message "Bogus %S %d .. %d"
138 (if after 'after 'before) beg end)
139 (if after
140 (run-hook-with-args 'after-change-functions
141 beg end (- end beg))
142 (run-hook-with-args 'before-change-functions beg end))))
143 (_
144 (goto-char (+ (point-min) (random (1+ (buffer-size)))))
145 (let ((word (track-changes-tests--random-word)))
146 (track-changes-tests--message "insert %S at %d" word (point))
147 (insert word "\n")))))
148 (message "SCOREs: default: %d/%d=%d disjoint: %d/%d=%d"
149 (aref char-counts 0) (aref sync-counts 0)
150 (/ (aref char-counts 0) (aref sync-counts 0))
151 (aref char-counts 1) (aref sync-counts 1)
152 (/ (aref char-counts 1) (aref sync-counts 1))))))
153
154
155
156;;; track-changes-tests.el ends here