562 lines
15 KiB
EmacsLisp
562 lines
15 KiB
EmacsLisp
;;; diff-mode-tests.el --- Tests for diff-mode.el -*- lexical-binding:t -*-
|
|
|
|
;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
|
|
|
;; Author: Dima Kogan <dima@secretsauce.net>
|
|
;; Maintainer: emacs-devel@gnu.org
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Code:
|
|
|
|
(require 'ert)
|
|
(require 'ert-x)
|
|
(require 'diff-mode)
|
|
(require 'diff)
|
|
|
|
(ert-deftest diff-mode-test-ignore-trailing-dashes ()
|
|
"Check to make sure we successfully ignore trailing -- made by
|
|
'git format-patch'. This is bug #9597"
|
|
|
|
;; I made a test repo, put some files in it, made arbitrary changes
|
|
;; and invoked 'git format-patch' to get a patch out of it. The
|
|
;; patch and the before and after versions of the files appear here.
|
|
;; The test simply tries to apply the patch. The patch contains
|
|
;; trailing --, which confused diff-mode previously
|
|
(let ((patch "From 18ed35640be496647e0a02fc155b4ee4a0490eca Mon Sep 17 00:00:00 2001
|
|
From: Dima Kogan <dima@secretsauce.net>
|
|
Date: Mon, 30 Jan 2017 22:24:13 -0800
|
|
Subject: [PATCH] test commit
|
|
|
|
---
|
|
fil | 3 ---
|
|
fil2 | 4 ----
|
|
2 files changed, 7 deletions(-)
|
|
|
|
diff --git a/fil b/fil
|
|
index 10344f1..2a56245 100644
|
|
--- a/fil
|
|
+++ b/fil
|
|
@@ -2,10 +2,8 @@ Afrocentrism
|
|
Americanisms
|
|
Americanization
|
|
Americanizations
|
|
-Americanized
|
|
Americanizes
|
|
Americanizing
|
|
-Andrianampoinimerina
|
|
Anglicanisms
|
|
Antananarivo
|
|
Apalachicola
|
|
@@ -15,6 +13,5 @@ Aristophanes
|
|
Aristotelian
|
|
Ashurbanipal
|
|
Australopithecus
|
|
-Austronesian
|
|
Bangladeshis
|
|
Barquisimeto
|
|
diff --git a/fil2 b/fil2
|
|
index 8858f0d..86e8ea5 100644
|
|
--- a/fil2
|
|
+++ b/fil2
|
|
@@ -1,20 +1,16 @@
|
|
whippoorwills
|
|
whitewashing
|
|
wholehearted
|
|
-wholeheartedly
|
|
wholesomeness
|
|
wildernesses
|
|
windbreakers
|
|
wisecracking
|
|
withstanding
|
|
-woodcarvings
|
|
woolgathering
|
|
workstations
|
|
worthlessness
|
|
wretchedness
|
|
wristwatches
|
|
-wrongfulness
|
|
wrongheadedly
|
|
wrongheadedness
|
|
-xylophonists
|
|
youthfulness
|
|
--
|
|
2.11.0
|
|
|
|
")
|
|
(fil_before "Afrocentrism
|
|
Americanisms
|
|
Americanization
|
|
Americanizations
|
|
Americanized
|
|
Americanizes
|
|
Americanizing
|
|
Andrianampoinimerina
|
|
Anglicanisms
|
|
Antananarivo
|
|
Apalachicola
|
|
Appalachians
|
|
Argentinians
|
|
Aristophanes
|
|
Aristotelian
|
|
Ashurbanipal
|
|
Australopithecus
|
|
Austronesian
|
|
Bangladeshis
|
|
Barquisimeto
|
|
")
|
|
(fil_after "Afrocentrism
|
|
Americanisms
|
|
Americanization
|
|
Americanizations
|
|
Americanizes
|
|
Americanizing
|
|
Anglicanisms
|
|
Antananarivo
|
|
Apalachicola
|
|
Appalachians
|
|
Argentinians
|
|
Aristophanes
|
|
Aristotelian
|
|
Ashurbanipal
|
|
Australopithecus
|
|
Bangladeshis
|
|
Barquisimeto
|
|
")
|
|
(fil2_before "whippoorwills
|
|
whitewashing
|
|
wholehearted
|
|
wholeheartedly
|
|
wholesomeness
|
|
wildernesses
|
|
windbreakers
|
|
wisecracking
|
|
withstanding
|
|
woodcarvings
|
|
woolgathering
|
|
workstations
|
|
worthlessness
|
|
wretchedness
|
|
wristwatches
|
|
wrongfulness
|
|
wrongheadedly
|
|
wrongheadedness
|
|
xylophonists
|
|
youthfulness
|
|
")
|
|
(fil2_after "whippoorwills
|
|
whitewashing
|
|
wholehearted
|
|
wholesomeness
|
|
wildernesses
|
|
windbreakers
|
|
wisecracking
|
|
withstanding
|
|
woolgathering
|
|
workstations
|
|
worthlessness
|
|
wretchedness
|
|
wristwatches
|
|
wrongheadedly
|
|
wrongheadedness
|
|
youthfulness
|
|
"))
|
|
(ert-with-temp-directory temp-dir
|
|
(let ((buf (find-file-noselect (format "%s/%s" temp-dir "fil" )))
|
|
(buf2 (find-file-noselect (format "%s/%s" temp-dir "fil2"))))
|
|
(unwind-protect
|
|
(progn
|
|
(with-current-buffer buf (insert fil_before) (save-buffer))
|
|
(with-current-buffer buf2 (insert fil2_before) (save-buffer))
|
|
|
|
(with-temp-buffer
|
|
(cd temp-dir)
|
|
(insert patch)
|
|
(goto-char (point-min))
|
|
(diff-apply-hunk)
|
|
(diff-apply-hunk)
|
|
(diff-apply-hunk))
|
|
|
|
(should (equal (with-current-buffer buf (buffer-string))
|
|
fil_after))
|
|
(should (equal (with-current-buffer buf2 (buffer-string))
|
|
fil2_after)))
|
|
|
|
(ignore-errors
|
|
(with-current-buffer buf (set-buffer-modified-p nil))
|
|
(kill-buffer buf)
|
|
(with-current-buffer buf2 (set-buffer-modified-p nil))
|
|
(kill-buffer buf2)))))))
|
|
|
|
(ert-deftest diff-mode-test-hunk-text-no-newline ()
|
|
"Check output of `diff-hunk-text' with no newline at end of file."
|
|
|
|
;; First check unified change/remove/add cases with newline
|
|
(let ((hunk "\
|
|
@@ -1 +1 @@
|
|
-foo
|
|
+bar
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
")))
|
|
|
|
(let ((hunk "\
|
|
@@ -1 +0,0 @@
|
|
-foo
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
")))
|
|
|
|
(let ((hunk "\
|
|
@@ -0,0 +1 @@
|
|
+bar
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
")))
|
|
|
|
;; Check unified change/remove cases with no newline in old file
|
|
(let ((hunk "\
|
|
@@ -1 +1 @@
|
|
-foo
|
|
\\ No newline at end of file
|
|
+bar
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
")))
|
|
|
|
(let ((hunk "\
|
|
@@ -1 +0,0 @@
|
|
-foo
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
")))
|
|
|
|
;; Check unified change/add cases with no newline in new file
|
|
(let ((hunk "\
|
|
@@ -1 +1 @@
|
|
-foo
|
|
+bar
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar")))
|
|
|
|
(let ((hunk "\
|
|
@@ -0,0 +1 @@
|
|
+bar
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar")))
|
|
|
|
;; Check unified change case with no newline in both old/new file
|
|
(let ((hunk "\
|
|
@@ -1 +1 @@
|
|
-foo
|
|
\\ No newline at end of file
|
|
+bar
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar")))
|
|
|
|
;; Check context-after unified change case with no newline in both old/new file
|
|
(let ((hunk "\
|
|
@@ -1,2 +1,2 @@
|
|
-foo
|
|
+bar
|
|
baz
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
baz"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
baz")))
|
|
|
|
(let ((hunk "\
|
|
@@ -1,2 +1,2 @@
|
|
-foo
|
|
-baz
|
|
\\ No newline at end of file
|
|
+bar
|
|
+baz
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
baz"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
baz
|
|
")))
|
|
|
|
(let ((hunk "\
|
|
@@ -1,2 +1,2 @@
|
|
-foo
|
|
-baz
|
|
+bar
|
|
+baz
|
|
\\ No newline at end of file
|
|
"))
|
|
(should (equal (diff-hunk-text hunk nil nil) "\
|
|
foo
|
|
baz
|
|
"))
|
|
(should (equal (diff-hunk-text hunk t nil) "\
|
|
bar
|
|
baz"))))
|
|
|
|
(ert-deftest diff-mode-test-font-lock ()
|
|
"Check font-locking of diff hunks."
|
|
;; See comments in diff-hunk-file-names about nonascii.
|
|
;; In such cases, the diff-font-lock-syntax portion of this fails.
|
|
:expected-result (if (string-match-p "[[:nonascii:]]"
|
|
(ert-resource-directory))
|
|
:failed :passed)
|
|
(skip-unless (executable-find shell-file-name))
|
|
(skip-unless (executable-find diff-command))
|
|
(let ((default-directory (ert-resource-directory))
|
|
(old "hello_world.c")
|
|
(new "hello_emacs.c")
|
|
(diff-buffer (get-buffer-create "*Diff*"))
|
|
(diff-refine 'font-lock)
|
|
(diff-font-lock-syntax t)
|
|
diff-beg)
|
|
(diff-no-select old new '("-u") 'no-async diff-buffer)
|
|
(with-current-buffer diff-buffer
|
|
(font-lock-ensure)
|
|
(narrow-to-region (progn (diff-hunk-next)
|
|
(setq diff-beg (diff-beginning-of-hunk)))
|
|
(diff-end-of-hunk))
|
|
|
|
(should (equal-including-properties
|
|
(buffer-string)
|
|
#("@@ -1,6 +1,6 @@
|
|
#include <stdio.h>
|
|
int main()
|
|
{
|
|
- printf(\"Hello, World!\\n\");
|
|
+ printf(\"Hello, Emacs!\\n\");
|
|
return 0;
|
|
}
|
|
"
|
|
0 15 (face diff-hunk-header)
|
|
16 36 (face diff-context)
|
|
36 48 (face diff-context)
|
|
48 51 (face diff-context)
|
|
51 52 (face diff-indicator-removed)
|
|
52 81 (face diff-removed)
|
|
81 82 (face diff-indicator-added)
|
|
82 111 (face diff-added)
|
|
111 124 (face diff-context)
|
|
124 127 (face diff-context))))
|
|
|
|
;; Test diff-font-lock-syntax.
|
|
(should (equal (mapcar (lambda (o)
|
|
(list (- (overlay-start o) diff-beg)
|
|
(- (overlay-end o) diff-beg)
|
|
(append (and (overlay-get o 'diff-mode)
|
|
`(diff-mode ,(overlay-get o 'diff-mode)))
|
|
(and (overlay-get o 'face)
|
|
`(face ,(overlay-get o 'face))))))
|
|
(sort (overlays-in (point-min) (point-max))
|
|
(lambda (a b) (< (overlay-start a) (overlay-start b)))))
|
|
'((0 127 (diff-mode fine))
|
|
(0 127 (diff-mode syntax))
|
|
(17 25 (diff-mode syntax face font-lock-preprocessor-face))
|
|
(26 35 (diff-mode syntax face font-lock-string-face))
|
|
(37 40 (diff-mode syntax face font-lock-type-face))
|
|
(41 45 (diff-mode syntax face font-lock-function-name-face))
|
|
(61 78 (diff-mode syntax face font-lock-string-face))
|
|
(69 74 (diff-mode fine face diff-refine-removed))
|
|
(91 108 (diff-mode syntax face font-lock-string-face))
|
|
(99 104 (diff-mode fine face diff-refine-added))
|
|
(114 120 (diff-mode syntax face font-lock-keyword-face))))))))
|
|
|
|
(ert-deftest diff-mode-test-font-lock-syntax-one-line ()
|
|
"Check diff syntax highlighting for one line with no newline at end."
|
|
:expected-result (if (string-match-p "[[:nonascii:]]"
|
|
(ert-resource-directory))
|
|
:failed :passed)
|
|
(skip-unless (executable-find shell-file-name))
|
|
(skip-unless (executable-find diff-command))
|
|
(let ((default-directory (ert-resource-directory))
|
|
(old "hello_world_1.c")
|
|
(new "hello_emacs_1.c")
|
|
(diff-buffer (get-buffer-create "*Diff*"))
|
|
(diff-refine nil)
|
|
(diff-font-lock-syntax t)
|
|
diff-beg)
|
|
(diff-no-select old new '("-u") 'no-async diff-buffer)
|
|
(with-current-buffer diff-buffer
|
|
(font-lock-ensure)
|
|
(narrow-to-region (progn (diff-hunk-next)
|
|
(setq diff-beg (diff-beginning-of-hunk)))
|
|
(diff-end-of-hunk))
|
|
|
|
(should (equal-including-properties
|
|
(buffer-string)
|
|
#("@@ -1 +1 @@
|
|
-int main() { printf(\"Hello, World!\\n\"); return 0; }
|
|
\\ No newline at end of file
|
|
+int main() { printf(\"Hello, Emacs!\\n\"); return 0; }
|
|
\\ No newline at end of file
|
|
"
|
|
0 11 (face diff-hunk-header)
|
|
12 13 (face diff-indicator-removed)
|
|
13 65 (face diff-removed)
|
|
65 93 (face diff-context)
|
|
93 94 (face diff-indicator-added)
|
|
94 146 (face diff-added)
|
|
146 174 (face diff-context))))
|
|
|
|
(should (equal (mapcar (lambda (o)
|
|
(list (- (overlay-start o) diff-beg)
|
|
(- (overlay-end o) diff-beg)
|
|
(append (and (overlay-get o 'diff-mode)
|
|
`(diff-mode ,(overlay-get o 'diff-mode)))
|
|
(and (overlay-get o 'face)
|
|
`(face ,(overlay-get o 'face))))))
|
|
(sort (overlays-in (point-min) (point-max))
|
|
(lambda (a b) (< (overlay-start a) (overlay-start b)))))
|
|
'((0 174 (diff-mode syntax))
|
|
(13 16 (diff-mode syntax face font-lock-type-face))
|
|
(17 21 (diff-mode syntax face font-lock-function-name-face))
|
|
(33 50 (diff-mode syntax face font-lock-string-face))
|
|
(53 59 (diff-mode syntax face font-lock-keyword-face))
|
|
(94 97 (diff-mode syntax face font-lock-type-face))
|
|
(98 102 (diff-mode syntax face font-lock-function-name-face))
|
|
(114 131 (diff-mode syntax face font-lock-string-face))
|
|
(134 140 (diff-mode syntax face font-lock-keyword-face))))))))
|
|
|
|
(ert-deftest test-hunk-file-names ()
|
|
(with-temp-buffer
|
|
(insert "diff -c /tmp/ange-ftp13518wvE.el /tmp/ange-ftp1351895K.el\n")
|
|
(goto-char (point-min))
|
|
(should (equal (diff-hunk-file-names)
|
|
'("/tmp/ange-ftp1351895K.el" "/tmp/ange-ftp13518wvE.el"))))
|
|
(with-temp-buffer
|
|
(insert "diff -c -L /ftp:slbhao:/home/albinus/src/tramp/lisp/tramp.el -L /ftp:slbhao:/home/albinus/src/emacs/lisp/net/tramp.el /tmp/ange-ftp13518wvE.el /tmp/ange-ftp1351895K.el\n")
|
|
(goto-char (point-min))
|
|
(should (equal (diff-hunk-file-names)
|
|
'("/tmp/ange-ftp1351895K.el" "/tmp/ange-ftp13518wvE.el")))))
|
|
|
|
(ert-deftest diff-mode-test-fixups-added-lines ()
|
|
"Check that `diff-fixup-modifs' works well with hunks with added lines."
|
|
(let ((patch "--- file
|
|
+++ file
|
|
@@ -0,0 +1,15 @@
|
|
+1
|
|
+2
|
|
+3
|
|
+4
|
|
"))
|
|
(with-temp-buffer
|
|
(insert patch)
|
|
(diff-fixup-modifs (point-min) (point-max))
|
|
(should (equal (buffer-string) "--- file
|
|
+++ file
|
|
@@ -0,0 +1,4 @@
|
|
+1
|
|
+2
|
|
+3
|
|
+4
|
|
"))))
|
|
(let ((patch "--- file
|
|
+++ file
|
|
@@ -389,5 +398,6 @@
|
|
while (1)
|
|
;
|
|
+ # not needed
|
|
# at all
|
|
# stop
|
|
"))
|
|
(with-temp-buffer
|
|
(insert patch)
|
|
(diff-fixup-modifs (point-min) (point-max))
|
|
(should (equal (buffer-string) "--- file
|
|
+++ file
|
|
@@ -389,4 +398,5 @@
|
|
while (1)
|
|
;
|
|
+ # not needed
|
|
# at all
|
|
# stop
|
|
")))))
|
|
|
|
(ert-deftest diff-mode-test-fixups-empty-hunks ()
|
|
"Check that `diff-fixup-modifs' works well with empty hunks."
|
|
(let ((patch "--- file
|
|
+++ file
|
|
@@ -1 +1 @@
|
|
-1
|
|
@@ -10 +10 @@
|
|
-1
|
|
+1
|
|
--- otherfile
|
|
+++ otherfile
|
|
@@ -1 +1 @@
|
|
+2
|
|
@@ -10 +10 @@
|
|
-1
|
|
+1
|
|
"))
|
|
(with-temp-buffer
|
|
(insert patch)
|
|
(diff-fixup-modifs (point-min) (point-max))
|
|
(should (equal (buffer-string) "--- file
|
|
+++ file
|
|
@@ -1,1 +1,0 @@
|
|
-1
|
|
@@ -10,1 +10,1 @@
|
|
-1
|
|
+1
|
|
--- otherfile
|
|
+++ otherfile
|
|
@@ -1,0 +1,1 @@
|
|
+2
|
|
@@ -10,1 +10,1 @@
|
|
-1
|
|
+1
|
|
")))))
|
|
|
|
(provide 'diff-mode-tests)
|
|
;;; diff-mode-tests.el ends here
|