1 ;;; undo-tests.el --- Tests of primitive-undo
3 ;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
5 ;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
7 ;; This program is free software: you can redistribute it and/or
8 ;; modify it under the terms of the GNU General Public License as
9 ;; published by the Free Software Foundation, either version 3 of the
10 ;; License, or (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see `http://www.gnu.org/licenses/'.
22 ;; Profiling when the code was translate from C to Lisp on 2012-12-24.
26 ;; (elp-instrument-function 'primitive-undo)
27 ;; (load-file "undo-test.elc")
28 ;; (benchmark 100 '(let ((undo-test5-error nil)) (undo-test-all)))
29 ;; Elapsed time: 305.218000s (104.841000s in 14804 GCs)
31 ;; Function Name Call Count Elapsed Time Average Time
32 ;; primitive-undo 2600 3.4889999999 0.0013419230
36 ;; (load-file "primundo.elc")
37 ;; (elp-instrument-function 'primitive-undo)
38 ;; (benchmark 100 '(undo-test-all))
39 ;; Elapsed time: 295.974000s (104.582000s in 14704 GCs)
41 ;; Function Name Call Count Elapsed Time Average Time
42 ;; primitive-undo 2700 3.6869999999 0.0013655555
48 (ert-deftest undo-test0
()
49 "Test basics of \\[undo]."
55 (unless (string= "No further undo information"
73 (put-text-property (point-min) (point-max) 'face
'bold
)
75 (remove-text-properties (point-min) (point-max) '(face default
))
77 (set-buffer-multibyte (not enable-multibyte-characters
))
81 (equal (should-error (undo-more nil
))
82 '(wrong-type-argument number-or-marker-p nil
)))
84 (should (string-equal "" (buffer-string)))))
86 (ert-deftest undo-test1
()
87 "Test undo of \\[undo] command (redo)."
105 (facemenu-add-face 'bold
(point-min) (point-max))
107 (set-buffer-multibyte (not enable-multibyte-characters
))
110 (string-equal (buffer-string)
118 (ert-deftest undo-test2
()
119 "Test basic redoing with \\[undo] command."
128 (delete-region (save-excursion
137 (string-equal (buffer-string)
143 (ert-deftest undo-test4
()
144 "Test \\[undo] of \\[flush-lines]."
153 ;; Avoid string-equal because ERT will save the `buffer-string'
154 ;; to the explanation. Using `not' will record nil or non-nil.
157 (string-equal (buffer-string)
159 (flush-lines "oddses" (point-min) (point-max))
163 (buffer-string))))))))
165 (ert-deftest undo-test5
()
166 "Test basic redoing with \\[undo] command."
174 (setq buffer-undo-list
(cons '(0.0 bogus
) buffer-undo-list
))
176 (delete-region (save-excursion
184 (setq buffer-undo-list
(cons "bogus" buffer-undo-list
))
189 (if (and (boundp 'undo-test5-error
) (not undo-test5-error
))
191 (should (null (undo-more 2)))
193 ;; Errors are generated by new Lisp version of
194 ;; `primitive-undo' not by built-in C version.
196 (equal (should-error (undo-more 2))
197 '(error "Unrecognized entry in undo list (0.0 bogus)")))
199 (equal (should-error (undo))
200 '(error "Unrecognized entry in undo list \"bogus\""))))
203 ;; http://debbugs.gnu.org/14824
204 (ert-deftest undo-test-buffer-modified
()
205 "Test undoing marks buffer unmodified."
210 (set-buffer-modified-p nil
)
213 (should-not (buffer-modified-p))))
215 (ert-deftest undo-test-file-modified
()
216 "Test undoing marks buffer visiting file unmodified."
217 (let ((tempfile (make-temp-file "undo-test")))
220 (with-current-buffer (find-file-noselect tempfile
)
223 (set-buffer-modified-p nil
)
226 (should-not (buffer-modified-p))))
227 (delete-file tempfile
))))
229 (ert-deftest undo-test-region-not-most-recent
()
230 "Test undo in region of an edit not the most recent."
233 (transient-mark-mode 1)
242 ;; Highlight around "2", not "3"
243 (push-mark (+ 3 (point-min)) t t
)
245 (goto-char (point-min))
247 (should (string= (buffer-string)
250 (ert-deftest undo-test-region-deletion
()
251 "Test undoing a deletion to demonstrate bug 17235."
254 (transient-mark-mode 1)
256 (search-backward "4")
258 (delete-forward-char 1)
259 (search-backward "1")
264 (search-forward "35")
267 (push-mark (point) t t
)
270 (undo) ; Expect "4" to come back
271 (should (string= (buffer-string)
274 (ert-deftest undo-test-region-example
()
275 "The same example test case described in comments for
276 undo-make-selective-list."
278 ;; 123456789 buffer-undo-list undo-deltas
279 ;; --------- ---------------- -----------
280 ;; aaa (1 . 4) (1 . -3)
281 ;; aaba (3 . 4) N/A (in region)
282 ;; ccaaba (1 . 3) (1 . -2)
283 ;; ccaabaddd (7 . 10) (7 . -3)
284 ;; ccaabdd ("ad" . 6) (6 . 2)
285 ;; ccaabaddd (6 . 8) (6 . -2)
286 ;; | |<-- region: "caab", from 2 to 6
289 (transient-mark-mode 1)
300 (search-backward "ad")
302 (delete-forward-char 2)
305 (push-mark (point) t t
)
307 (goto-char (point-max))
310 (should (string= (buffer-string)
318 (should (string= (buffer-string)
321 (ert-deftest undo-test-region-eob
()
322 "Test undo in region of a deletion at EOB, demonstrating bug 16411."
325 (transient-mark-mode 1)
326 (insert "This sentence corrupted?")
329 ;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16411
333 ;; Select entire buffer
334 (push-mark (point) t t
)
336 (goto-char (point-min))
337 ;; Should undo the undo of "aaa", ie restore it.
339 (should (string= (buffer-string)
340 "This sentence corrupted?aaa"))))
342 (ert-deftest undo-test-marker-adjustment-nominal
()
343 "Test nominal behavior of marker adjustments."
348 (let ((m (make-marker)))
349 (set-marker m
2 (current-buffer))
350 (goto-char (point-min))
351 (delete-forward-char 3)
353 (should (= (point-min) (marker-position m
)))
356 (should (= 2 (marker-position m
))))))
358 (ert-deftest undo-test-region-t-marker
()
359 "Test undo in region containing marker with t insertion-type."
362 (transient-mark-mode 1)
365 (let ((m (make-marker)))
366 (set-marker-insertion-type m t
)
367 (set-marker m
(point-min) (current-buffer)) ; m at a
368 (goto-char (+ 2 (point-min)))
369 (push-mark (point) t t
)
371 (goto-char (point-min))
372 (delete-forward-char 1) ;; delete region covering "ab"
374 (should (= (point-min) (marker-position m
)))
375 ;; Resurrect "ab". m's insertion type means the reinsertion
376 ;; moves it forward 2, and then the marker adjustment returns it
377 ;; to its rightful place.
380 (should (= (point-min) (marker-position m
))))))
382 (ert-deftest undo-test-marker-adjustment-moved
()
383 "Test marker adjustment behavior when the marker moves.
384 Demonstrates bug 16818."
387 (insert "abcdefghijk")
389 (let ((m (make-marker)))
390 (set-marker m
2 (current-buffer)) ; m at b
391 (goto-char (point-min))
392 (delete-forward-char 3) ; m at d
394 (set-marker m
4) ; m at g
397 ;; m still at g, but shifted 3 because deletion undone
398 (should (= 7 (marker-position m
))))))
400 (ert-deftest undo-test-region-mark-adjustment
()
401 "Test that the mark's marker adjustment in undo history doesn't
402 obstruct undo in region from finding the correct change group.
403 Demonstrates bug 16818."
406 (transient-mark-mode 1)
407 (insert "First line\n")
408 (insert "Second line\n")
411 (goto-char (point-min))
418 (goto-char (point-max))
422 (push-mark (point) t t
)
424 (goto-char (- (point) 3))
425 (delete-forward-char 1)
431 (goto-char (point-min))
432 (push-mark (point) t t
)
434 (goto-char (+ (point) 3))
438 (should (string= (buffer-string) "aaaFirst line\nSecond line\nbbb"))))
440 (defun undo-test-all (&optional interactive
)
441 "Run all tests for \\[undo]."
444 (ert-run-tests-interactively "^undo-")
445 (ert-run-tests-batch "^undo-")))
447 (ert-deftest undo-test-skip-invalidated-markers
()
448 "Test marker adjustment when the marker points nowhere.
449 Demonstrates bug 25599."
452 (insert ";; aaaaaaaaa
454 (let ((overlay-modified
455 (lambda (ov after-p _beg _end
&optional length
)
457 (when (overlay-buffer ov
)
458 (delete-overlay ov
))))))
460 (goto-char (point-min))
461 (let ((ov (make-overlay (line-beginning-position 2)
462 (line-end-position 2))))
463 (overlay-put ov
'insert-in-front-hooks
464 (list overlay-modified
)))))
465 (kill-region (point-min) (line-beginning-position 2))
469 (provide 'undo-tests
)
470 ;;; undo-tests.el ends here