summaryrefslogtreecommitdiff
path: root/test/lisp/legacy
diff options
context:
space:
mode:
Diffstat (limited to 'test/lisp/legacy')
-rw-r--r--test/lisp/legacy/bytecomp-tests.el429
-rw-r--r--test/lisp/legacy/coding-tests.el50
-rw-r--r--test/lisp/legacy/core-elisp-tests.el52
-rw-r--r--test/lisp/legacy/decoder-tests.el349
-rw-r--r--test/lisp/legacy/files-tests.el172
-rw-r--r--test/lisp/legacy/font-parse-tests.el165
-rw-r--r--test/lisp/legacy/lexbind-tests.el75
-rw-r--r--test/lisp/legacy/occur-tests.el352
-rw-r--r--test/lisp/legacy/process-tests.el165
-rw-r--r--test/lisp/legacy/syntax-tests.el97
-rw-r--r--test/lisp/legacy/textprop-tests.el69
-rw-r--r--test/lisp/legacy/undo-tests.el448
12 files changed, 2423 insertions, 0 deletions
diff --git a/test/lisp/legacy/bytecomp-tests.el b/test/lisp/legacy/bytecomp-tests.el
new file mode 100644
index 00000000000..c65009cb1b0
--- /dev/null
+++ b/test/lisp/legacy/bytecomp-tests.el
@@ -0,0 +1,429 @@
+;;; bytecomp-testsuite.el
+
+;; Copyright (C) 2008-2015 Free Software Foundation, Inc.
+
+;; Author: Shigeru Fukaya <shigeru.fukaya@gmail.com>
+;; Created: November 2008
+;; Keywords: internal
+;; Human-Keywords: internal
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+(require 'ert)
+
+;;; Code:
+(defconst byte-opt-testsuite-arith-data
+ '(
+ ;; some functional tests
+ (let ((a most-positive-fixnum) (b 1) (c 1.0)) (+ a b c))
+ (let ((a most-positive-fixnum) (b -2) (c 1.0)) (- a b c))
+ (let ((a most-positive-fixnum) (b 2) (c 1.0)) (* a b c))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b c))
+ (let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (+ a -1 b))
+ (let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (- a 1 (- b)))
+ ;; This fails. Should it be a bug?
+ ;; (let ((a (expt 2 -1074)) (b 0.125)) (* a 8 b))
+ (let ((a 1.0)) (* a 0))
+ (let ((a 1.0)) (* a 2.0 0))
+ (let ((a 1.0)) (/ 0 a))
+ (let ((a 1.0)) (/ 3 a 2))
+ (let ((a most-positive-fixnum) (b 2.0)) (* a 2 b))
+ (let ((a 3) (b 2)) (/ a b 1.0))
+ (/ 3 -1)
+ (+ 4 3 2 1)
+ (+ 4 3 2.0 1)
+ (- 4 3 2 1) ; not new, for reference
+ (- 4 3 2.0 1) ; not new, for reference
+ (* 4 3 2 1)
+ (* 4 3 2.0 1)
+ (/ 4 3 2 1)
+ (/ 4 3 2.0 1)
+ (let ((a 3) (b 2)) (+ a b 1))
+ (let ((a 3) (b 2)) (+ a b -1))
+ (let ((a 3) (b 2)) (- a b 1))
+ (let ((a 3) (b 2)) (- a b -1))
+ (let ((a 3) (b 2)) (+ a b a 1))
+ (let ((a 3) (b 2)) (+ a b a -1))
+ (let ((a 3) (b 2)) (- a b a 1))
+ (let ((a 3) (b 2)) (- a b a -1))
+ (let ((a 3) (b 2)) (* a b -1))
+ (let ((a 3) (b 2)) (* a -1))
+ (let ((a 3) (b 2)) (/ a b 1))
+ (let ((a 3) (b 2)) (/ (+ a b) 1))
+
+ ;; coverage test
+ (let ((a 3) (b 2) (c 1.0)) (+))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2.0 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 2.0 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 2))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0.0 2))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0.0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ a))
+ (let ((a 3) (b 2) (c 1.0)) (+ a 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ a 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0.0 a))
+ (let ((a 3) (b 2) (c 1.0)) (+ c 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ c 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 c))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0.0 c))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b 0 c 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 a b))
+ (let ((a 3) (b 2) (c 1.0)) (+ 0 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (+ 1 2 3))
+ (let ((a 3) (b 2) (c 1.0)) (+ 3.0 2.0 1))
+ (let ((a 3) (b 2) (c 1.0)) (+ 3.0 2.0 1 4))
+ (let ((a 3) (b 2) (c 1.0)) (+ a 1))
+ (let ((a 3) (b 2) (c 1.0)) (+ a -1))
+ (let ((a 3) (b 2) (c 1.0)) (+ 1 a))
+ (let ((a 3) (b 2) (c 1.0)) (+ -1 a))
+ (let ((a 3) (b 2) (c 1.0)) (+ c 1))
+ (let ((a 3) (b 2) (c 1.0)) (+ c -1))
+ (let ((a 3) (b 2) (c 1.0)) (+ 1 c))
+ (let ((a 3) (b 2) (c 1.0)) (+ -1 c))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b 1))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b -1))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b 2))
+ (let ((a 3) (b 2) (c 1.0)) (+ 1 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b c 0))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b c 1))
+ (let ((a 3) (b 2) (c 1.0)) (+ a b c -1))
+
+ (let ((a 3) (b 2) (c 1.0)) (-))
+ (let ((a 3) (b 2) (c 1.0)) (- 2))
+ (let ((a 3) (b 2) (c 1.0)) (- 2 0))
+ (let ((a 3) (b 2) (c 1.0)) (- 2 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 2.0 0))
+ (let ((a 3) (b 2) (c 1.0)) (- 2.0 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 2))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 0.0 2))
+ (let ((a 3) (b 2) (c 1.0)) (- 0.0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (- a))
+ (let ((a 3) (b 2) (c 1.0)) (- a 0))
+ (let ((a 3) (b 2) (c 1.0)) (- a 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (- 0.0 a))
+ (let ((a 3) (b 2) (c 1.0)) (- c 0))
+ (let ((a 3) (b 2) (c 1.0)) (- c 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 c))
+ (let ((a 3) (b 2) (c 1.0)) (- 0.0 c))
+ (let ((a 3) (b 2) (c 1.0)) (- a b 0 c 0))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 a b))
+ (let ((a 3) (b 2) (c 1.0)) (- 0 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (- 1 2 3))
+ (let ((a 3) (b 2) (c 1.0)) (- 3.0 2.0 1))
+ (let ((a 3) (b 2) (c 1.0)) (- 3.0 2.0 1 4))
+ (let ((a 3) (b 2) (c 1.0)) (- a 1))
+ (let ((a 3) (b 2) (c 1.0)) (- a -1))
+ (let ((a 3) (b 2) (c 1.0)) (- 1 a))
+ (let ((a 3) (b 2) (c 1.0)) (- -1 a))
+ (let ((a 3) (b 2) (c 1.0)) (- c 1))
+ (let ((a 3) (b 2) (c 1.0)) (- c -1))
+ (let ((a 3) (b 2) (c 1.0)) (- 1 c))
+ (let ((a 3) (b 2) (c 1.0)) (- -1 c))
+ (let ((a 3) (b 2) (c 1.0)) (- a b 0))
+ (let ((a 3) (b 2) (c 1.0)) (- a b 1))
+ (let ((a 3) (b 2) (c 1.0)) (- a b -1))
+ (let ((a 3) (b 2) (c 1.0)) (- a b 2))
+ (let ((a 3) (b 2) (c 1.0)) (- 1 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (- a b c 0))
+ (let ((a 3) (b 2) (c 1.0)) (- a b c 1))
+ (let ((a 3) (b 2) (c 1.0)) (- a b c -1))
+
+ (let ((a 3) (b 2) (c 1.0)) (*))
+ (let ((a 3) (b 2) (c 1.0)) (* 2))
+ (let ((a 3) (b 2) (c 1.0)) (* 2 0))
+ (let ((a 3) (b 2) (c 1.0)) (* 2 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 2.0 0))
+ (let ((a 3) (b 2) (c 1.0)) (* 2.0 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 2))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 0.0 2))
+ (let ((a 3) (b 2) (c 1.0)) (* 0.0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (* a))
+ (let ((a 3) (b 2) (c 1.0)) (* a 0))
+ (let ((a 3) (b 2) (c 1.0)) (* a 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (* 0.0 a))
+ (let ((a 3) (b 2) (c 1.0)) (* c 0))
+ (let ((a 3) (b 2) (c 1.0)) (* c 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 c))
+ (let ((a 3) (b 2) (c 1.0)) (* 0.0 c))
+ (let ((a 3) (b 2) (c 1.0)) (* a b 0 c 0))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 a b))
+ (let ((a 3) (b 2) (c 1.0)) (* 0 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (* 1 2 3))
+ (let ((a 3) (b 2) (c 1.0)) (* 3.0 2.0 1))
+ (let ((a 3) (b 2) (c 1.0)) (* 3.0 2.0 1 4))
+ (let ((a 3) (b 2) (c 1.0)) (* a 1))
+ (let ((a 3) (b 2) (c 1.0)) (* a -1))
+ (let ((a 3) (b 2) (c 1.0)) (* 1 a))
+ (let ((a 3) (b 2) (c 1.0)) (* -1 a))
+ (let ((a 3) (b 2) (c 1.0)) (* c 1))
+ (let ((a 3) (b 2) (c 1.0)) (* c -1))
+ (let ((a 3) (b 2) (c 1.0)) (* 1 c))
+ (let ((a 3) (b 2) (c 1.0)) (* -1 c))
+ (let ((a 3) (b 2) (c 1.0)) (* a b 0))
+ (let ((a 3) (b 2) (c 1.0)) (* a b 1))
+ (let ((a 3) (b 2) (c 1.0)) (* a b -1))
+ (let ((a 3) (b 2) (c 1.0)) (* a b 2))
+ (let ((a 3) (b 2) (c 1.0)) (* 1 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (* a b c 0))
+ (let ((a 3) (b 2) (c 1.0)) (* a b c 1))
+ (let ((a 3) (b 2) (c 1.0)) (* a b c -1))
+
+ (let ((a 3) (b 2) (c 1.0)) (/))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2.0 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 2.0 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 2))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0.0 2))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0.0 2.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ a))
+ (let ((a 3) (b 2) (c 1.0)) (/ a 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ a 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0.0 a))
+ (let ((a 3) (b 2) (c 1.0)) (/ c 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ c 0.0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 c))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0.0 c))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b 0 c 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 a))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 a b))
+ (let ((a 3) (b 2) (c 1.0)) (/ 0 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (/ 1 2 3))
+ (let ((a 3) (b 2) (c 1.0)) (/ 3.0 2.0 1))
+ (let ((a 3) (b 2) (c 1.0)) (/ 3.0 2.0 1 4))
+ (let ((a 3) (b 2) (c 1.0)) (/ a 1))
+ (let ((a 3) (b 2) (c 1.0)) (/ a -1))
+ (let ((a 3) (b 2) (c 1.0)) (/ 1 a))
+ (let ((a 3) (b 2) (c 1.0)) (/ -1 a))
+ (let ((a 3) (b 2) (c 1.0)) (/ c 1))
+ (let ((a 3) (b 2) (c 1.0)) (/ c -1))
+ (let ((a 3) (b 2) (c 1.0)) (/ 1 c))
+ (let ((a 3) (b 2) (c 1.0)) (/ -1 c))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b 1))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b -1))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b 2))
+ (let ((a 3) (b 2) (c 1.0)) (/ 1 a b c))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b c 0))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b c 1))
+ (let ((a 3) (b 2) (c 1.0)) (/ a b c -1)))
+ "List of expression for test.
+Each element will be executed by interpreter and with
+bytecompiled code, and their results compared.")
+
+(defun bytecomp-check-1 (pat)
+ "Return non-nil if PAT is the same whether directly evalled or compiled."
+ (let ((warning-minimum-log-level :emergency)
+ (byte-compile-warnings nil)
+ (v0 (condition-case nil
+ (eval pat)
+ (error nil)))
+ (v1 (condition-case nil
+ (funcall (byte-compile (list 'lambda nil pat)))
+ (error nil))))
+ (equal v0 v1)))
+
+(put 'bytecomp-check-1 'ert-explainer 'bytecomp-explain-1)
+
+(defun bytecomp-explain-1 (pat)
+ (let ((v0 (condition-case nil
+ (eval pat)
+ (error nil)))
+ (v1 (condition-case nil
+ (funcall (byte-compile (list 'lambda nil pat)))
+ (error nil))))
+ (format "Expression `%s' gives `%s' if directly evalled, `%s' if compiled."
+ pat v0 v1)))
+
+(ert-deftest bytecomp-tests ()
+ "Test the Emacs byte compiler."
+ (dolist (pat byte-opt-testsuite-arith-data)
+ (should (bytecomp-check-1 pat))))
+
+(defun test-byte-opt-arithmetic (&optional arg)
+ "Unit test for byte-opt arithmetic operations.
+Subtests signal errors if something goes wrong."
+ (interactive "P")
+ (switch-to-buffer (generate-new-buffer "*Font Pase Test*"))
+ (let ((warning-minimum-log-level :emergency)
+ (byte-compile-warnings nil)
+ (pass-face '((t :foreground "green")))
+ (fail-face '((t :foreground "red")))
+ (print-escape-nonascii t)
+ (print-escape-newlines t)
+ (print-quoted t)
+ v0 v1)
+ (dolist (pat byte-opt-testsuite-arith-data)
+ (condition-case nil
+ (setq v0 (eval pat))
+ (error (setq v0 nil)))
+ (condition-case nil
+ (setq v1 (funcall (byte-compile (list 'lambda nil pat))))
+ (error (setq v1 nil)))
+ (insert (format "%s" pat))
+ (indent-to-column 65)
+ (if (equal v0 v1)
+ (insert (propertize "OK" 'face pass-face))
+ (insert (propertize "FAIL\n" 'face fail-face))
+ (indent-to-column 55)
+ (insert (propertize (format "[%s] vs [%s]" v0 v1)
+ 'face fail-face)))
+ (insert "\n"))))
+
+(defun test-byte-comp-compile-and-load (compile &rest forms)
+ (let ((elfile nil)
+ (elcfile nil))
+ (unwind-protect
+ (progn
+ (setf elfile (make-temp-file "test-bytecomp" nil ".el"))
+ (when compile
+ (setf elcfile (make-temp-file "test-bytecomp" nil ".elc")))
+ (with-temp-buffer
+ (dolist (form forms)
+ (print form (current-buffer)))
+ (write-region (point-min) (point-max) elfile nil 'silent))
+ (if compile
+ (let ((byte-compile-dest-file-function
+ (lambda (e) elcfile)))
+ (byte-compile-file elfile t))
+ (load elfile nil 'nomessage)))
+ (when elfile (delete-file elfile))
+ (when elcfile (delete-file elcfile)))))
+(put 'test-byte-comp-compile-and-load 'lisp-indent-function 1)
+
+(ert-deftest test-byte-comp-macro-expansion ()
+ (test-byte-comp-compile-and-load t
+ '(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
+ (should (equal (funcall 'def) 1)))
+
+(ert-deftest test-byte-comp-macro-expansion-eval-and-compile ()
+ (test-byte-comp-compile-and-load t
+ '(eval-and-compile (defmacro abc (arg) -1) (defun def () (abc 2))))
+ (should (equal (funcall 'def) -1)))
+
+(ert-deftest test-byte-comp-macro-expansion-eval-when-compile ()
+ ;; Make sure we interpret eval-when-compile forms properly. CLISP
+ ;; and SBCL interpreter eval-when-compile (well, the CL equivalent)
+ ;; in the same way.
+ (test-byte-comp-compile-and-load t
+ '(eval-when-compile
+ (defmacro abc (arg) -10)
+ (defun abc-1 () (abc 2)))
+ '(defmacro abc-2 () (abc-1))
+ '(defun def () (abc-2)))
+ (should (equal (funcall 'def) -10)))
+
+(ert-deftest test-byte-comp-macro-expand-lexical-override ()
+ ;; Intuitively, one might expect the defmacro to override the
+ ;; macrolet since macrolet's is explicitly called out as being
+ ;; equivalent to toplevel, but CLISP and SBCL both evaluate the form
+ ;; this way, so we should too.
+ (test-byte-comp-compile-and-load t
+ '(require 'cl-lib)
+ '(cl-macrolet ((m () 4))
+ (defmacro m () 5)
+ (defun def () (m))))
+ (should (equal (funcall 'def) 4)))
+
+(ert-deftest bytecomp-tests--warnings ()
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t)) (erase-buffer)))
+ (test-byte-comp-compile-and-load t
+ '(progn
+ (defun my-test0 ()
+ (my--test11 3)
+ (my--test12 3)
+ (my--test2 5))
+ (defmacro my--test11 (arg) (+ arg 1))
+ (eval-and-compile
+ (defmacro my--test12 (arg) (+ arg 1))
+ (defun my--test2 (arg) (+ arg 1)))))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (goto-char (point-min))
+ ;; Should warn that mt--test1[12] are first used as functions.
+ ;; The second alternative is for when the file name is so long
+ ;; that pretty-printing starts the message on the next line.
+ (should (or (re-search-forward "my--test11:\n.*macro" nil t)
+ (re-search-forward "my--test11:\n.*:\n.*macro" nil t)))
+ (should (or (re-search-forward "my--test12:\n.*macro" nil t)
+ (re-search-forward "my--test12:\n.*:\n.*macro" nil t)))
+ (goto-char (point-min))
+ ;; Should not warn that mt--test2 is not known to be defined.
+ (should-not (re-search-forward "my--test2" nil t))))
+
+(ert-deftest test-eager-load-macro-expansion ()
+ (test-byte-comp-compile-and-load nil
+ '(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
+ (should (equal (funcall 'def) 1)))
+
+(ert-deftest test-eager-load-macro-expansion-eval-and-compile ()
+ (test-byte-comp-compile-and-load nil
+ '(eval-and-compile (defmacro abc (arg) -1) (defun def () (abc 2))))
+ (should (equal (funcall 'def) -1)))
+
+(ert-deftest test-eager-load-macro-expansion-eval-when-compile ()
+ ;; Make sure we interpret eval-when-compile forms properly. CLISP
+ ;; and SBCL interpreter eval-when-compile (well, the CL equivalent)
+ ;; in the same way.
+ (test-byte-comp-compile-and-load nil
+ '(eval-when-compile
+ (defmacro abc (arg) -10)
+ (defun abc-1 () (abc 2)))
+ '(defmacro abc-2 () (abc-1))
+ '(defun def () (abc-2)))
+ (should (equal (funcall 'def) -10)))
+
+(ert-deftest test-eager-load-macro-expand-lexical-override ()
+ ;; Intuitively, one might expect the defmacro to override the
+ ;; macrolet since macrolet's is explicitly called out as being
+ ;; equivalent to toplevel, but CLISP and SBCL both evaluate the form
+ ;; this way, so we should too.
+ (test-byte-comp-compile-and-load nil
+ '(require 'cl-lib)
+ '(cl-macrolet ((m () 4))
+ (defmacro m () 5)
+ (defun def () (m))))
+ (should (equal (funcall 'def) 4)))
+
+
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
+
+(provide 'byte-opt-testsuite)
+
diff --git a/test/lisp/legacy/coding-tests.el b/test/lisp/legacy/coding-tests.el
new file mode 100644
index 00000000000..cda382fff97
--- /dev/null
+++ b/test/lisp/legacy/coding-tests.el
@@ -0,0 +1,50 @@
+;;; coding-tests.el --- tests for text encoding and decoding
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Eli Zaretskii <eliz@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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+;; Directory to hold test data files.
+(defvar coding-tests-workdir
+ (expand-file-name "coding-tests" temporary-file-directory))
+
+;; Remove all generated test files.
+(defun coding-tests-remove-files ()
+ (delete-directory coding-tests-workdir t))
+
+(ert-deftest ert-test-coding-bogus-coding-systems ()
+ (unwind-protect
+ (let (test-file)
+ (or (file-directory-p coding-tests-workdir)
+ (mkdir coding-tests-workdir t))
+ (setq test-file (expand-file-name "nonexistent" coding-tests-workdir))
+ (if (file-exists-p test-file)
+ (delete-file test-file))
+ (should-error
+ (let ((coding-system-for-read 'bogus))
+ (insert-file-contents test-file)))
+ ;; See bug #21602.
+ (setq test-file (expand-file-name "writing" coding-tests-workdir))
+ (should-error
+ (let ((coding-system-for-write (intern "\"us-ascii\"")))
+ (write-region "some text" nil test-file))))
+ (coding-tests-remove-files)))
diff --git a/test/lisp/legacy/core-elisp-tests.el b/test/lisp/legacy/core-elisp-tests.el
new file mode 100644
index 00000000000..c31ecef4a32
--- /dev/null
+++ b/test/lisp/legacy/core-elisp-tests.el
@@ -0,0 +1,52 @@
+;;; core-elisp-tests.el --- Testing some core Elisp rules
+
+;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(ert-deftest core-elisp-tests-1-defvar-in-let ()
+ "Test some core Elisp rules."
+ (with-temp-buffer
+ ;; Check that when defvar is run within a let-binding, the toplevel default
+ ;; is properly initialized.
+ (should (equal (list (let ((c-e-x 1)) (defvar c-e-x 2) c-e-x) c-e-x)
+ '(1 2)))
+ (should (equal (list (let ((c-e-x 1))
+ (defcustom c-e-x 2 "doc" :group 'blah) c-e-x)
+ c-e-x)
+ '(1 2)))))
+
+(ert-deftest core-elisp-tests-2-window-configurations ()
+ "Test properties of window-configurations."
+ (let ((wc (current-window-configuration)))
+ (with-current-buffer (window-buffer (frame-selected-window))
+ (push-mark)
+ (activate-mark))
+ (set-window-configuration wc)
+ (should (or (not mark-active) (mark)))))
+
+(ert-deftest core-elisp-tests-3-backquote ()
+ (should (eq 3 (eval ``,,'(+ 1 2)))))
+
+(provide 'core-elisp-tests)
+;;; core-elisp-tests.el ends here
diff --git a/test/lisp/legacy/decoder-tests.el b/test/lisp/legacy/decoder-tests.el
new file mode 100644
index 00000000000..80ff5205ac5
--- /dev/null
+++ b/test/lisp/legacy/decoder-tests.el
@@ -0,0 +1,349 @@
+;;; decoder-tests.el --- test for text decoder
+
+;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+;; Author: Kenichi Handa <handa@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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+;; Directory to hold test data files.
+(defvar decoder-tests-workdir
+ (expand-file-name "decoder-tests" temporary-file-directory))
+
+;; Remove all generated test files.
+(defun decoder-tests-remove-files ()
+ (delete-directory decoder-tests-workdir t))
+
+;; Return the contents (specified by CONTENT-TYPE; ascii, latin, or
+;; binary) of a test file.
+(defun decoder-tests-file-contents (content-type)
+ (let* ((ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")
+ (latin (concat ascii "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ\n"))
+ (binary (string-to-multibyte
+ (concat (string-as-unibyte latin)
+ (unibyte-string #xC0 #xC1 ?\n)))))
+ (cond ((eq content-type 'ascii) ascii)
+ ((eq content-type 'latin) latin)
+ ((eq content-type 'binary) binary)
+ (t
+ (error "Invalid file content type: %s" content-type)))))
+
+;; Generate FILE with CONTENTS encoded by CODING-SYSTEM.
+;; whose encoding specified by CODING-SYSTEM.
+(defun decoder-tests-gen-file (file contents coding-system)
+ (or (file-directory-p decoder-tests-workdir)
+ (mkdir decoder-tests-workdir t))
+ (setq file (expand-file-name file decoder-tests-workdir))
+ (with-temp-file file
+ (set-buffer-file-coding-system coding-system)
+ (insert contents))
+ file)
+
+;;; The following three functions are filters for contents of a test
+;;; file.
+
+;; Convert all LFs to CR LF sequences in the string STR.
+(defun decoder-tests-lf-to-crlf (str)
+ (with-temp-buffer
+ (insert str)
+ (goto-char (point-min))
+ (while (search-forward "\n" nil t)
+ (delete-char -1)
+ (insert "\r\n"))
+ (buffer-string)))
+
+;; Convert all LFs to CRs in the string STR.
+(defun decoder-tests-lf-to-cr (str)
+ (with-temp-buffer
+ (insert str)
+ (subst-char-in-region (point-min) (point-max) ?\n ?\r)
+ (buffer-string)))
+
+;; Convert all LFs to LF LF sequences in the string STR.
+(defun decoder-tests-lf-to-lflf (str)
+ (with-temp-buffer
+ (insert str)
+ (goto-char (point-min))
+ (while (search-forward "\n" nil t)
+ (insert "\n"))
+ (buffer-string)))
+
+;; Prepend the UTF-8 BOM to STR.
+(defun decoder-tests-add-bom (str)
+ (concat "\xfeff" str))
+
+;; Return the name of test file whose contents specified by
+;; CONTENT-TYPE and whose encoding specified by CODING-SYSTEM.
+(defun decoder-tests-filename (content-type coding-system &optional ext)
+ (if ext
+ (expand-file-name (format "%s-%s.%s" content-type coding-system ext)
+ decoder-tests-workdir)
+ (expand-file-name (format "%s-%s" content-type coding-system)
+ decoder-tests-workdir)))
+
+
+;;; Check ASCII optimizing decoder
+
+;; Generate a test file whose contents specified by CONTENT-TYPE and
+;; whose encoding specified by CODING-SYSTEM.
+(defun decoder-tests-ao-gen-file (content-type coding-system)
+ (let ((file (decoder-tests-filename content-type coding-system)))
+ (decoder-tests-gen-file file
+ (decoder-tests-file-contents content-type)
+ coding-system)))
+
+;; Test the decoding of a file whose contents and encoding are
+;; specified by CONTENT-TYPE and WRITE-CODING. The test passes if the
+;; file is read by READ-CODING and detected as DETECTED-CODING and the
+;; contents is correctly decoded.
+;; Optional 5th arg TRANSLATOR is a function to translate the original
+;; file contents to match with the expected result of decoding. For
+;; instance, when a file of dos eol-type is read by unix eol-type,
+;; `decode-test-lf-to-crlf' must be specified.
+
+(defun decoder-tests (content-type write-coding read-coding detected-coding
+ &optional translator)
+ (prefer-coding-system 'utf-8-auto)
+ (let ((filename (decoder-tests-filename content-type write-coding)))
+ (with-temp-buffer
+ (let ((coding-system-for-read read-coding)
+ (contents (decoder-tests-file-contents content-type))
+ (disable-ascii-optimization nil))
+ (if translator
+ (setq contents (funcall translator contents)))
+ (insert-file-contents filename)
+ (if (and (coding-system-equal buffer-file-coding-system detected-coding)
+ (string= (buffer-string) contents))
+ nil
+ (list buffer-file-coding-system
+ (string-to-list (buffer-string))
+ (string-to-list contents)))))))
+
+(ert-deftest ert-test-decoder-ascii ()
+ (unwind-protect
+ (progn
+ (dolist (eol-type '(unix dos mac))
+ (decoder-tests-ao-gen-file 'ascii eol-type))
+ (should-not (decoder-tests 'ascii 'unix 'undecided 'unix))
+ (should-not (decoder-tests 'ascii 'dos 'undecided 'dos))
+ (should-not (decoder-tests 'ascii 'dos 'dos 'dos))
+ (should-not (decoder-tests 'ascii 'mac 'undecided 'mac))
+ (should-not (decoder-tests 'ascii 'mac 'mac 'mac))
+ (should-not (decoder-tests 'ascii 'dos 'utf-8 'utf-8-dos))
+ (should-not (decoder-tests 'ascii 'dos 'unix 'unix
+ 'decoder-tests-lf-to-crlf))
+ (should-not (decoder-tests 'ascii 'mac 'dos 'dos
+ 'decoder-tests-lf-to-cr))
+ (should-not (decoder-tests 'ascii 'dos 'mac 'mac
+ 'decoder-tests-lf-to-lflf)))
+ (decoder-tests-remove-files)))
+
+(ert-deftest ert-test-decoder-latin ()
+ (unwind-protect
+ (progn
+ (dolist (coding '("utf-8" "utf-8-with-signature"))
+ (dolist (eol-type '("unix" "dos" "mac"))
+ (decoder-tests-ao-gen-file 'latin
+ (intern (concat coding "-" eol-type)))))
+ (should-not (decoder-tests 'latin 'utf-8-unix 'undecided 'utf-8-unix))
+ (should-not (decoder-tests 'latin 'utf-8-unix 'utf-8-unix 'utf-8-unix))
+ (should-not (decoder-tests 'latin 'utf-8-dos 'undecided 'utf-8-dos))
+ (should-not (decoder-tests 'latin 'utf-8-dos 'utf-8-dos 'utf-8-dos))
+ (should-not (decoder-tests 'latin 'utf-8-mac 'undecided 'utf-8-mac))
+ (should-not (decoder-tests 'latin 'utf-8-mac 'utf-8-mac 'utf-8-mac))
+ (should-not (decoder-tests 'latin 'utf-8-dos 'unix 'utf-8-unix
+ 'decoder-tests-lf-to-crlf))
+ (should-not (decoder-tests 'latin 'utf-8-mac 'dos 'utf-8-dos
+ 'decoder-tests-lf-to-cr))
+ (should-not (decoder-tests 'latin 'utf-8-dos 'mac 'utf-8-mac
+ 'decoder-tests-lf-to-lflf))
+ (should-not (decoder-tests 'latin 'utf-8-with-signature-unix 'undecided
+ 'utf-8-with-signature-unix))
+ (should-not (decoder-tests 'latin 'utf-8-with-signature-unix 'utf-8-auto
+ 'utf-8-with-signature-unix))
+ (should-not (decoder-tests 'latin 'utf-8-with-signature-dos 'undecided
+ 'utf-8-with-signature-dos))
+ (should-not (decoder-tests 'latin 'utf-8-with-signature-unix 'utf-8
+ 'utf-8-unix 'decoder-tests-add-bom))
+ (should-not (decoder-tests 'latin 'utf-8-with-signature-unix 'utf-8
+ 'utf-8-unix 'decoder-tests-add-bom)))
+ (decoder-tests-remove-files)))
+
+(ert-deftest ert-test-decoder-binary ()
+ (unwind-protect
+ (progn
+ (dolist (eol-type '("unix" "dos" "mac"))
+ (decoder-tests-ao-gen-file 'binary
+ (intern (concat "raw-text" "-" eol-type))))
+ (should-not (decoder-tests 'binary 'raw-text-unix 'undecided
+ 'raw-text-unix))
+ (should-not (decoder-tests 'binary 'raw-text-dos 'undecided
+ 'raw-text-dos))
+ (should-not (decoder-tests 'binary 'raw-text-mac 'undecided
+ 'raw-text-mac))
+ (should-not (decoder-tests 'binary 'raw-text-dos 'unix
+ 'raw-text-unix 'decoder-tests-lf-to-crlf))
+ (should-not (decoder-tests 'binary 'raw-text-mac 'dos
+ 'raw-text-dos 'decoder-tests-lf-to-cr))
+ (should-not (decoder-tests 'binary 'raw-text-dos 'mac
+ 'raw-text-mac 'decoder-tests-lf-to-lflf)))
+ (decoder-tests-remove-files)))
+
+
+;;; Check the coding system `prefer-utf-8'.
+
+;; Read FILE. Check if the encoding was detected as DETECT. If
+;; PREFER is non-nil, prefer that coding system before reading.
+
+(defun decoder-tests-prefer-utf-8-read (file detect prefer)
+ (with-temp-buffer
+ (with-coding-priority (if prefer (list prefer))
+ (insert-file-contents file))
+ (if (eq buffer-file-coding-system detect)
+ nil
+ (format "Invalid detection: %s" buffer-file-coding-system))))
+
+;; Read FILE, modify it, and write it. Check if the coding system
+;; used for writing was CODING. If CODING-TAG is non-nil, insert
+;; coding tag with it before writing. If STR is non-nil, insert it
+;; before writing.
+
+(defun decoder-tests-prefer-utf-8-write (file coding-tag coding
+ &optional str)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (if coding-tag
+ (insert (format ";; -*- coding: %s; -*-\n" coding-tag))
+ (insert ";;\n"))
+ (if str
+ (insert str))
+ (write-file (decoder-tests-filename 'test 'test "el"))
+ (if (coding-system-equal buffer-file-coding-system coding)
+ nil
+ (format "Incorrect encoding: %s" last-coding-system-used))))
+
+(ert-deftest ert-test-decoder-prefer-utf-8 ()
+ (unwind-protect
+ (let ((ascii (decoder-tests-gen-file "ascii.el"
+ (decoder-tests-file-contents 'ascii)
+ 'unix))
+ (latin (decoder-tests-gen-file "utf-8.el"
+ (decoder-tests-file-contents 'latin)
+ 'utf-8-unix)))
+ (should-not (decoder-tests-prefer-utf-8-read
+ ascii 'prefer-utf-8-unix nil))
+ (should-not (decoder-tests-prefer-utf-8-read
+ latin 'utf-8-unix nil))
+ (should-not (decoder-tests-prefer-utf-8-read
+ latin 'utf-8-unix 'iso-8859-1))
+ (should-not (decoder-tests-prefer-utf-8-read
+ latin 'utf-8-unix 'sjis))
+ (should-not (decoder-tests-prefer-utf-8-write
+ ascii nil 'prefer-utf-8-unix))
+ (should-not (decoder-tests-prefer-utf-8-write
+ ascii 'iso-8859-1 'iso-8859-1-unix))
+ (should-not (decoder-tests-prefer-utf-8-write
+ ascii nil 'utf-8-unix "À")))
+ (decoder-tests-remove-files)))
+
+
+;;; The following is for benchmark testing of the new optimized
+;;; decoder, not for regression testing.
+
+(defun generate-ascii-file ()
+ (dotimes (i 100000)
+ (insert-char ?a 80)
+ (insert "\n")))
+
+(defun generate-rarely-nonascii-file ()
+ (dotimes (i 100000)
+ (if (/= i 50000)
+ (insert-char ?a 80)
+ (insert ?À)
+ (insert-char ?a 79))
+ (insert "\n")))
+
+(defun generate-mostly-nonascii-file ()
+ (dotimes (i 30000)
+ (insert-char ?a 80)
+ (insert "\n"))
+ (dotimes (i 20000)
+ (insert-char ?À 80)
+ (insert "\n"))
+ (dotimes (i 10000)
+ (insert-char ?あ 80)
+ (insert "\n")))
+
+
+(defvar test-file-list
+ '((generate-ascii-file
+ ("~/ascii-tag-utf-8-unix.unix" ";; -*- coding: utf-8-unix; -*-" unix)
+ ("~/ascii-tag-utf-8.unix" ";; -*- coding: utf-8; -*-" unix)
+ ("~/ascii-tag-none.unix" "" unix)
+ ("~/ascii-tag-utf-8-dos.dos" ";; -*- coding: utf-8-dos; -*-" dos)
+ ("~/ascii-tag-utf-8.dos" ";; -*- coding: utf-8; -*-" dos)
+ ("~/ascii-tag-none.dos" "" dos))
+ (generate-rarely-nonascii-file
+ ("~/utf-8-r-tag-utf-8-unix.unix" ";; -*- coding: utf-8-unix; -*-" utf-8-unix)
+ ("~/utf-8-r-tag-utf-8.unix" ";; -*- coding: utf-8; -*-" utf-8-unix)
+ ("~/utf-8-r-tag-none.unix" "" utf-8-unix)
+ ("~/utf-8-r-tag-utf-8-dos.dos" ";; -*- coding: utf-8-dos; -*-" utf-8-dos)
+ ("~/utf-8-r-tag-utf-8.dos" ";; -*- coding: utf-8; -*-" utf-8-dos)
+ ("~/utf-8-r-tag-none.dos" "" utf-8-dos))
+ (generate-mostly-nonascii-file
+ ("~/utf-8-m-tag-utf-8-unix.unix" ";; -*- coding: utf-8-unix; -*-" utf-8-unix)
+ ("~/utf-8-m-tag-utf-8.unix" ";; -*- coding: utf-8; -*-" utf-8-unix)
+ ("~/utf-8-m-tag-none.unix" "" utf-8-unix)
+ ("~/utf-8-m-tag-utf-8-dos.dos" ";; -*- coding: utf-8-dos; -*-" utf-8-dos)
+ ("~/utf-8-m-tag-utf-8.dos" ";; -*- coding: utf-8; -*-" utf-8-dos)
+ ("~/utf-8-m-tag-none.dos" "" utf-8-dos))))
+
+(defun generate-benchmark-test-file ()
+ (interactive)
+ (with-temp-buffer
+ (message "Generating data...")
+ (dolist (files test-file-list)
+ (delete-region (point-min) (point-max))
+ (funcall (car files))
+ (dolist (file (cdr files))
+ (message "Writing %s..." (car file))
+ (goto-char (point-min))
+ (insert (nth 1 file) "\n")
+ (let ((coding-system-for-write (nth 2 file)))
+ (write-region (point-min) (point-max) (car file)))
+ (delete-region (point-min) (point))))))
+
+(defun benchmark-decoder ()
+ (let ((gc-cons-threshold 4000000))
+ (insert "Without optimization:\n")
+ (dolist (files test-file-list)
+ (dolist (file (cdr files))
+ (let* ((disable-ascii-optimization t)
+ (result (benchmark-run 10
+ (with-temp-buffer (insert-file-contents (car file))))))
+ (insert (format "%s: %s\n" (car file) result)))))
+ (insert "With optimization:\n")
+ (dolist (files test-file-list)
+ (dolist (file (cdr files))
+ (let* ((disable-ascii-optimization nil)
+ (result (benchmark-run 10
+ (with-temp-buffer (insert-file-contents (car file))))))
+ (insert (format "%s: %s\n" (car file) result)))))))
diff --git a/test/lisp/legacy/files-tests.el b/test/lisp/legacy/files-tests.el
new file mode 100644
index 00000000000..0522e0c5c79
--- /dev/null
+++ b/test/lisp/legacy/files-tests.el
@@ -0,0 +1,172 @@
+;;; files.el --- tests for file handling.
+
+;; Copyright (C) 2012-2015 Free Software Foundation, Inc.
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+;; Set to t if the local variable was set, `query' if the query was
+;; triggered.
+(defvar files-test-result nil)
+
+(defvar files-test-safe-result nil)
+(put 'files-test-safe-result 'safe-local-variable 'booleanp)
+
+(defun files-test-fun1 ()
+ (setq files-test-result t))
+
+;; Test combinations:
+;; `enable-local-variables' t, nil, :safe, :all, or something else.
+;; `enable-local-eval' t, nil, or something else.
+
+(defvar files-test-local-variable-data
+ ;; Unsafe eval form
+ '((("eval: (files-test-fun1)")
+ (t t (eq files-test-result t))
+ (t nil (eq files-test-result nil))
+ (t maybe (eq files-test-result 'query))
+ (nil t (eq files-test-result nil))
+ (nil nil (eq files-test-result nil))
+ (nil maybe (eq files-test-result nil))
+ (:safe t (eq files-test-result nil))
+ (:safe nil (eq files-test-result nil))
+ (:safe maybe (eq files-test-result nil))
+ (:all t (eq files-test-result t))
+ (:all nil (eq files-test-result nil))
+ (:all maybe (eq files-test-result t)) ; This combination is ambiguous.
+ (maybe t (eq files-test-result 'query))
+ (maybe nil (eq files-test-result nil))
+ (maybe maybe (eq files-test-result 'query)))
+ ;; Unsafe local variable value
+ (("files-test-result: t")
+ (t t (eq files-test-result 'query))
+ (t nil (eq files-test-result 'query))
+ (t maybe (eq files-test-result 'query))
+ (nil t (eq files-test-result nil))
+ (nil nil (eq files-test-result nil))
+ (nil maybe (eq files-test-result nil))
+ (:safe t (eq files-test-result nil))
+ (:safe nil (eq files-test-result nil))
+ (:safe maybe (eq files-test-result nil))
+ (:all t (eq files-test-result t))
+ (:all nil (eq files-test-result t))
+ (:all maybe (eq files-test-result t))
+ (maybe t (eq files-test-result 'query))
+ (maybe nil (eq files-test-result 'query))
+ (maybe maybe (eq files-test-result 'query)))
+ ;; Safe local variable
+ (("files-test-safe-result: t")
+ (t t (eq files-test-safe-result t))
+ (t nil (eq files-test-safe-result t))
+ (t maybe (eq files-test-safe-result t))
+ (nil t (eq files-test-safe-result nil))
+ (nil nil (eq files-test-safe-result nil))
+ (nil maybe (eq files-test-safe-result nil))
+ (:safe t (eq files-test-safe-result t))
+ (:safe nil (eq files-test-safe-result t))
+ (:safe maybe (eq files-test-safe-result t))
+ (:all t (eq files-test-safe-result t))
+ (:all nil (eq files-test-safe-result t))
+ (:all maybe (eq files-test-safe-result t))
+ (maybe t (eq files-test-result 'query))
+ (maybe nil (eq files-test-result 'query))
+ (maybe maybe (eq files-test-result 'query)))
+ ;; Safe local variable with unsafe value
+ (("files-test-safe-result: 1")
+ (t t (eq files-test-result 'query))
+ (t nil (eq files-test-result 'query))
+ (t maybe (eq files-test-result 'query))
+ (nil t (eq files-test-safe-result nil))
+ (nil nil (eq files-test-safe-result nil))
+ (nil maybe (eq files-test-safe-result nil))
+ (:safe t (eq files-test-safe-result nil))
+ (:safe nil (eq files-test-safe-result nil))
+ (:safe maybe (eq files-test-safe-result nil))
+ (:all t (eq files-test-safe-result 1))
+ (:all nil (eq files-test-safe-result 1))
+ (:all maybe (eq files-test-safe-result 1))
+ (maybe t (eq files-test-result 'query))
+ (maybe nil (eq files-test-result 'query))
+ (maybe maybe (eq files-test-result 'query))))
+ "List of file-local variable tests.
+Each list element should have the form
+
+ (LOCAL-VARS-LIST . TEST-LIST)
+
+where LOCAL-VARS-LISTS should be a list of local variable
+definitions (strings) and TEST-LIST is a list of tests to
+perform. Each entry of TEST-LIST should have the form
+
+ (ENABLE-LOCAL-VARIABLES ENABLE-LOCAL-EVAL FORM)
+
+where ENABLE-LOCAL-VARIABLES is the value to assign to
+`enable-local-variables', ENABLE-LOCAL-EVAL is the value to
+assign to `enable-local-eval', and FORM is a desired `should'
+form.")
+
+(defun file-test--do-local-variables-test (str test-settings)
+ (with-temp-buffer
+ (insert str)
+ (setq files-test-result nil
+ files-test-safe-result nil)
+ (let ((enable-local-variables (nth 0 test-settings))
+ (enable-local-eval (nth 1 test-settings))
+ ;; Prevent any dir-locals file interfering with the tests.
+ (enable-dir-local-variables nil)
+ (files-test-queried nil))
+ (hack-local-variables)
+ (eval (nth 2 test-settings)))))
+
+(ert-deftest files-test-local-variables ()
+ "Test the file-local variables implementation."
+ (unwind-protect
+ (progn
+ (defadvice hack-local-variables-confirm (around files-test activate)
+ (setq files-test-result 'query)
+ nil)
+ (dolist (test files-test-local-variable-data)
+ (let ((str (concat "text\n\n;; Local Variables:\n;; "
+ (mapconcat 'identity (car test) "\n;; ")
+ "\n;; End:\n")))
+ (dolist (subtest (cdr test))
+ (should (file-test--do-local-variables-test str subtest))))))
+ (ad-disable-advice 'hack-local-variables-confirm 'around 'files-test)))
+
+(defvar files-test-bug-18141-file
+ (expand-file-name "data/files-bug18141.el.gz" (getenv "EMACS_TEST_DIRECTORY"))
+ "Test file for bug#18141.")
+
+(ert-deftest files-test-bug-18141 ()
+ "Test for http://debbugs.gnu.org/18141 ."
+ (skip-unless (executable-find "gzip"))
+ (let ((tempfile (make-temp-file "files-test-bug-18141" nil ".gz")))
+ (unwind-protect
+ (progn
+ (copy-file files-test-bug-18141-file tempfile t)
+ (with-current-buffer (find-file-noselect tempfile)
+ (set-buffer-modified-p t)
+ (save-buffer)
+ (should (eq buffer-file-coding-system 'iso-2022-7bit-unix))))
+ (delete-file tempfile))))
+
+
+;; Stop the above "Local Var..." confusing Emacs.
+
+
+;;; files.el ends here
diff --git a/test/lisp/legacy/font-parse-tests.el b/test/lisp/legacy/font-parse-tests.el
new file mode 100644
index 00000000000..e2c51e6bfde
--- /dev/null
+++ b/test/lisp/legacy/font-parse-tests.el
@@ -0,0 +1,165 @@
+;;; font-parse-tests.el --- Test suite for font parsing.
+
+;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
+
+;; Author: Chong Yidong <cyd@stupidchicken.com>
+;; Keywords: internal
+;; Human-Keywords: internal
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Type M-x test-font-parse RET to generate the test buffer.
+
+;;; Code:
+
+(require 'ert)
+
+(defvar font-parse-tests--data
+ `((" " ,(intern " ") nil nil nil nil)
+ ("Monospace" Monospace nil nil nil nil)
+ ("Foo1" Foo1 nil nil nil nil)
+ ("12" nil 12.0 nil nil nil)
+ ("12 " ,(intern "12 ") nil nil nil nil)
+ ;; Fontconfig format
+ ("Foo:" Foo nil nil nil nil)
+ ("Foo-8" Foo 8.0 nil nil nil)
+ ("Foo-18:" Foo 18.0 nil nil nil)
+ ("Foo-18:light" Foo 18.0 light nil nil)
+ ("Foo 10:weight=bold" ,(intern "Foo 10") nil bold nil nil)
+ ("Foo-12:weight=bold" Foo 12.0 bold nil nil)
+ ("Foo 8-20:slant=oblique" ,(intern "Foo 8") 20.0 nil oblique nil)
+ ("Foo:light:roman" Foo nil light roman nil)
+ ("Foo:italic:roman" Foo nil nil roman nil)
+ ("Foo 12:light:oblique" ,(intern "Foo 12") nil light oblique nil)
+ ("Foo-12:demibold:oblique" Foo 12.0 demibold oblique nil)
+ ("Foo:black:proportional" Foo nil black nil 0)
+ ("Foo-10:black:proportional" Foo 10.0 black nil 0)
+ ("Foo:weight=normal" Foo nil normal nil nil)
+ ("Foo:weight=bold" Foo nil bold nil nil)
+ ("Foo:weight=bold:slant=italic" Foo nil bold italic)
+ ("Foo:weight=bold:slant=italic:mono" Foo nil bold italic 100)
+ ("Foo-10:demibold:slant=normal" Foo 10.0 demibold normal nil)
+ ("Foo 11-16:oblique:weight=bold" ,(intern "Foo 11") 16.0 bold oblique nil)
+ ("Foo:oblique:randomprop=randomtag:weight=bold" Foo nil bold oblique nil)
+ ("Foo:randomprop=randomtag:bar=baz" Foo nil nil nil nil)
+ ("Foo Book Light:bar=baz" ,(intern "Foo Book Light") nil nil nil nil)
+ ("Foo Book Light 10:bar=baz" ,(intern "Foo Book Light 10") nil nil nil nil)
+ ("Foo Book Light-10:bar=baz" ,(intern "Foo Book Light") 10.0 nil nil nil)
+ ;; GTK format
+ ("Oblique" nil nil nil oblique nil)
+ ("Bold 17" nil 17.0 bold nil nil)
+ ("17 Bold" ,(intern "17") nil bold nil nil)
+ ("Book Oblique 2" nil 2.0 book oblique nil)
+ ("Bar 7" Bar 7.0 nil nil nil)
+ ("Bar Ultra-Light" Bar nil ultra-light nil nil)
+ ("Bar Light 8" Bar 8.0 light nil nil)
+ ("Bar Book Medium 9" Bar 9.0 medium nil nil)
+ ("Bar Semi-Bold Italic 10" Bar 10.0 semi-bold italic nil)
+ ("Bar Semi-Condensed Bold Italic 11" Bar 11.0 bold italic nil)
+ ("Foo 10 11" ,(intern "Foo 10") 11.0 nil nil nil)
+ ("Foo 1985 Book" ,(intern "Foo 1985") nil book nil nil)
+ ("Foo 1985 A Book" ,(intern "Foo 1985 A") nil book nil nil)
+ ("Foo 1 Book 12" ,(intern "Foo 1") 12.0 book nil nil)
+ ("Foo A Book 12 A" ,(intern "Foo A Book 12 A") nil nil nil nil)
+ ("Foo 1985 Book 12 Oblique" ,(intern "Foo 1985 Book 12") nil nil oblique nil)
+ ("Foo 1985 Book 12 Italic 10" ,(intern "Foo 1985 Book 12") 10.0 nil italic nil)
+ ("Foo Book Bar 6 Italic" ,(intern "Foo Book Bar 6") nil nil italic nil)
+ ("Foo Book Bar Bold" ,(intern "Foo Book Bar") nil bold nil nil))
+ "List of font names parse data.
+Each element should have the form
+ (NAME FAMILY SIZE WEIGHT SLANT SPACING)
+where NAME is the name to parse, and the remainder are the
+expected font properties from parsing NAME.")
+
+(defun font-parse-check (name prop expected)
+ (let ((result (font-get (font-spec :name name) prop)))
+ (if (and (symbolp result) (symbolp expected))
+ (eq result expected)
+ (equal result expected))))
+
+(put 'font-parse-check 'ert-explainer 'font-parse-explain)
+
+(defun font-parse-explain (name prop expected)
+ (let ((result (font-get (font-spec :name name) prop))
+ (propname (symbol-name prop)))
+ (format "Parsing `%s': expected %s `%s', got `%s'."
+ name (substring propname 1) expected
+ (font-get (font-spec :name name) prop))))
+
+(ert-deftest font-parse-tests ()
+ "Test parsing of Fontconfig-style and GTK-style font names."
+ (dolist (test font-parse-tests--data)
+ (let* ((name (nth 0 test)))
+ (should (font-parse-check name :family (nth 1 test)))
+ (should (font-parse-check name :size (nth 2 test)))
+ (should (font-parse-check name :weight (nth 3 test)))
+ (should (font-parse-check name :slant (nth 4 test)))
+ (should (font-parse-check name :spacing (nth 5 test))))))
+
+
+(defun test-font-parse ()
+ "Test font name parsing."
+ (interactive)
+ (switch-to-buffer (generate-new-buffer "*Font Pase Test*"))
+ (setq show-trailing-whitespace nil)
+ (let ((pass-face '((t :foreground "green")))
+ (fail-face '((t :foreground "red"))))
+ (dolist (test font-parse-tests--data)
+ (let* ((name (nth 0 test))
+ (fs (font-spec :name name))
+ (family (font-get fs :family))
+ (size (font-get fs :size))
+ (weight (font-get fs :weight))
+ (slant (font-get fs :slant))
+ (spacing (font-get fs :spacing)))
+ (insert name)
+ (if (> (current-column) 20)
+ (insert "\n"))
+ (indent-to-column 21)
+ (insert (propertize (symbol-name family)
+ 'face (if (eq family (nth 1 test))
+ pass-face
+ fail-face)))
+ (indent-to-column 40)
+ (insert (propertize (format "%s" size)
+ 'face (if (equal size (nth 2 test))
+ pass-face
+ fail-face)))
+ (indent-to-column 48)
+ (insert (propertize (format "%s" weight)
+ 'face (if (eq weight (nth 3 test))
+ pass-face
+ fail-face)))
+ (indent-to-column 60)
+ (insert (propertize (format "%s" slant)
+ 'face (if (eq slant (nth 4 test))
+ pass-face
+ fail-face)))
+ (indent-to-column 69)
+ (insert (propertize (format "%s" spacing)
+ 'face (if (eq spacing (nth 5 test))
+ pass-face
+ fail-face)))
+ (insert "\n"))))
+ (goto-char (point-min)))
+
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
+
+;;; font-parse-tests.el ends here.
diff --git a/test/lisp/legacy/lexbind-tests.el b/test/lisp/legacy/lexbind-tests.el
new file mode 100644
index 00000000000..dd60cd6db41
--- /dev/null
+++ b/test/lisp/legacy/lexbind-tests.el
@@ -0,0 +1,75 @@
+;;; lexbind-tests.el --- Testing the lexbind byte-compiler
+
+;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+
+(defconst lexbind-tests
+ `(
+ (let ((f #'car))
+ (let ((f (lambda (x) (cons (funcall f x) (cdr x)))))
+ (funcall f '(1 . 2))))
+ )
+ "List of expression for test.
+Each element will be executed by interpreter and with
+bytecompiled code, and their results compared.")
+
+
+
+(defun lexbind-check-1 (pat)
+ "Return non-nil if PAT is the same whether directly evalled or compiled."
+ (let ((warning-minimum-log-level :emergency)
+ (byte-compile-warnings nil)
+ (v0 (condition-case nil
+ (eval pat t)
+ (error nil)))
+ (v1 (condition-case nil
+ (funcall (let ((lexical-binding t))
+ (byte-compile `(lambda nil ,pat))))
+ (error nil))))
+ (equal v0 v1)))
+
+(put 'lexbind-check-1 'ert-explainer 'lexbind-explain-1)
+
+(defun lexbind-explain-1 (pat)
+ (let ((v0 (condition-case nil
+ (eval pat t)
+ (error nil)))
+ (v1 (condition-case nil
+ (funcall (let ((lexical-binding t))
+ (byte-compile (list 'lambda nil pat))))
+ (error nil))))
+ (format "Expression `%s' gives `%s' if directly evalled, `%s' if compiled."
+ pat v0 v1)))
+
+(ert-deftest lexbind-tests ()
+ "Test the Emacs byte compiler lexbind handling."
+ (dolist (pat lexbind-tests)
+ (should (lexbind-check-1 pat))))
+
+
+
+(provide 'lexbind-tests)
+;;; lexbind-tests.el ends here
diff --git a/test/lisp/legacy/occur-tests.el b/test/lisp/legacy/occur-tests.el
new file mode 100644
index 00000000000..1699cd007e5
--- /dev/null
+++ b/test/lisp/legacy/occur-tests.el
@@ -0,0 +1,352 @@
+;;; occur-tests.el --- Test suite for occur.
+
+;; Copyright (C) 2010-2015 Free Software Foundation, Inc.
+
+;; Author: Juri Linkov <juri@jurta.org>
+;; Keywords: matching, internal
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst occur-tests
+ '(
+ ;; * Test one-line matches (at bob, eob, bol, eol).
+ ("x" 0 "\
+xa
+b
+cx
+xd
+xex
+fx
+" "\
+6 matches in 5 lines for \"x\" in buffer: *test-occur*
+ 1:xa
+ 3:cx
+ 4:xd
+ 5:xex
+ 6:fx
+")
+ ;; * Test multi-line matches, this is the first test from
+ ;; http://lists.gnu.org/archive/html/emacs-devel/2005-06/msg01008.html
+ ;; where numbers are replaced with letters.
+ ("a\na" 0 "\
+a
+a
+a
+a
+a
+" "\
+2 matches for \"a\na\" in buffer: *test-occur*
+ 1:a
+ :a
+ 3:a
+ :a
+")
+ ;; * Test multi-line matches, this is the second test from
+ ;; http://lists.gnu.org/archive/html/emacs-devel/2005-06/msg01008.html
+ ;; where numbers are replaced with letters.
+ ("a\nb" 0 "\
+a
+b
+c
+a
+b
+" "\
+2 matches for \"a\nb\" in buffer: *test-occur*
+ 1:a
+ :b
+ 4:a
+ :b
+")
+ ;; * Test line numbers for multi-line matches with empty last match line.
+ ("a\n" 0 "\
+a
+
+c
+a
+
+" "\
+2 matches for \"a\n\" in buffer: *test-occur*
+ 1:a
+ :
+ 4:a
+ :
+")
+ ;; * Test multi-line matches with 3 match lines.
+ ("x\n.x\n" 0 "\
+ax
+bx
+c
+d
+ex
+fx
+" "\
+2 matches for \"x\n.x\n\" in buffer: *test-occur*
+ 1:ax
+ :bx
+ :c
+ 5:ex
+ :fx
+ :
+")
+ ;; * Test non-overlapping context lines with matches at bob/eob.
+ ("x" 1 "\
+ax
+b
+c
+d
+ex
+f
+g
+hx
+" "\
+3 matches for \"x\" in buffer: *test-occur*
+ 1:ax
+ :b
+-------
+ :d
+ 5:ex
+ :f
+-------
+ :g
+ 8:hx
+")
+ ;; * Test non-overlapping context lines with matches not at bob/eob.
+ ("x" 1 "\
+a
+bx
+c
+d
+ex
+f
+" "\
+2 matches for \"x\" in buffer: *test-occur*
+ :a
+ 2:bx
+ :c
+-------
+ :d
+ 5:ex
+ :f
+")
+ ;; * Test overlapping context lines with matches at bob/eob.
+ ("x" 2 "\
+ax
+bx
+c
+dx
+e
+f
+gx
+h
+i
+j
+kx
+" "\
+5 matches for \"x\" in buffer: *test-occur*
+ 1:ax
+ 2:bx
+ :c
+ 4:dx
+ :e
+ :f
+ 7:gx
+ :h
+ :i
+ :j
+ 11:kx
+")
+ ;; * Test overlapping context lines with matches not at bob/eob.
+ ("x" 2 "\
+a
+b
+cx
+d
+e
+f
+gx
+h
+i
+" "\
+2 matches for \"x\" in buffer: *test-occur*
+ :a
+ :b
+ 3:cx
+ :d
+ :e
+ :f
+ 7:gx
+ :h
+ :i
+")
+ ;; * Test overlapping context lines with empty first and last line..
+ ("x" 2 "\
+
+b
+cx
+d
+e
+f
+gx
+h
+
+" "\
+2 matches for \"x\" in buffer: *test-occur*
+ :
+ :b
+ 3:cx
+ :d
+ :e
+ :f
+ 7:gx
+ :h
+ :
+")
+ ;; * Test multi-line overlapping context lines.
+ ("x\n.x" 2 "\
+ax
+bx
+c
+d
+ex
+fx
+g
+h
+i
+jx
+kx
+" "\
+3 matches for \"x\n.x\" in buffer: *test-occur*
+ 1:ax
+ :bx
+ :c
+ :d
+ 5:ex
+ :fx
+ :g
+ :h
+ :i
+ 10:jx
+ :kx
+")
+ ;; * Test multi-line non-overlapping context lines.
+ ("x\n.x" 2 "\
+ax
+bx
+c
+d
+e
+f
+gx
+hx
+" "\
+2 matches for \"x\n.x\" in buffer: *test-occur*
+ 1:ax
+ :bx
+ :c
+ :d
+-------
+ :e
+ :f
+ 7:gx
+ :hx
+")
+ ;; * Test non-overlapping negative (before-context) lines.
+ ("x" -2 "\
+a
+bx
+c
+d
+e
+fx
+g
+h
+ix
+" "\
+3 matches for \"x\" in buffer: *test-occur*
+ :a
+ 2:bx
+-------
+ :d
+ :e
+ 6:fx
+-------
+ :g
+ :h
+ 9:ix
+")
+ ;; * Test overlapping negative (before-context) lines.
+ ("x" -3 "\
+a
+bx
+c
+dx
+e
+f
+gx
+h
+" "\
+3 matches for \"x\" in buffer: *test-occur*
+ :a
+ 2:bx
+ :c
+ 4:dx
+ :e
+ :f
+ 7:gx
+")
+
+)
+ "List of tests for `occur'.
+Each element has the format:
+\(REGEXP NLINES INPUT-BUFFER-STRING OUTPUT-BUFFER-STRING).")
+
+(defun occur-test-case (test)
+ (let ((regexp (nth 0 test))
+ (nlines (nth 1 test))
+ (input-buffer-string (nth 2 test))
+ (temp-buffer (get-buffer-create " *test-occur*")))
+ (unwind-protect
+ (save-window-excursion
+ (with-current-buffer temp-buffer
+ (erase-buffer)
+ (insert input-buffer-string)
+ (occur regexp nlines)
+ (with-current-buffer "*Occur*"
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ (and (buffer-name temp-buffer)
+ (kill-buffer temp-buffer)))))
+
+(defun occur-test-create (n)
+ "Create a test for element N of the `occur-tests' constant."
+ (let ((testname (intern (format "occur-test-%.2d" n)))
+ (testdoc (format "Test element %d of `occur-tests'." n)))
+ (eval
+ `(ert-deftest ,testname ()
+ ,testdoc
+ (let (occur-hook)
+ (should (equal (occur-test-case (nth ,n occur-tests))
+ (nth 3 (nth ,n occur-tests)))))))))
+
+(dotimes (i (length occur-tests))
+ (occur-test-create i))
+
+(provide 'occur-tests)
+
+;;; occur-tests.el ends here
diff --git a/test/lisp/legacy/process-tests.el b/test/lisp/legacy/process-tests.el
new file mode 100644
index 00000000000..ee9e4f35891
--- /dev/null
+++ b/test/lisp/legacy/process-tests.el
@@ -0,0 +1,165 @@
+;;; process-tests.el --- Testing the process facilities
+
+;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+
+;; Timeout in seconds; the test fails if the timeout is reached.
+(defvar process-test-sentinel-wait-timeout 2.0)
+
+;; Start a process that exits immediately. Call WAIT-FUNCTION,
+;; possibly multiple times, to wait for the process to complete.
+(defun process-test-sentinel-wait-function-working-p (wait-function)
+ (let ((proc (start-process "test" nil "bash" "-c" "exit 20"))
+ (sentinel-called nil)
+ (start-time (float-time)))
+ (set-process-sentinel proc (lambda (proc msg)
+ (setq sentinel-called t)))
+ (while (not (or sentinel-called
+ (> (- (float-time) start-time)
+ process-test-sentinel-wait-timeout)))
+ (funcall wait-function))
+ (cl-assert (eq (process-status proc) 'exit))
+ (cl-assert (= (process-exit-status proc) 20))
+ sentinel-called))
+
+(ert-deftest process-test-sentinel-accept-process-output ()
+ (skip-unless (executable-find "bash"))
+ (should (process-test-sentinel-wait-function-working-p
+ #'accept-process-output)))
+
+(ert-deftest process-test-sentinel-sit-for ()
+ (skip-unless (executable-find "bash"))
+ (should
+ (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t)))))
+
+(when (eq system-type 'windows-nt)
+ (ert-deftest process-test-quoted-batfile ()
+ "Check that Emacs hides CreateProcess deficiency (bug#18745)."
+ (let (batfile)
+ (unwind-protect
+ (progn
+ ;; CreateProcess will fail when both the bat file and 1st
+ ;; argument are quoted, so include spaces in both of those
+ ;; to force quoting.
+ (setq batfile (make-temp-file "echo args" nil ".bat"))
+ (with-temp-file batfile
+ (insert "@echo arg1=%1, arg2=%2\n"))
+ (with-temp-buffer
+ (call-process batfile nil '(t t) t "x &y")
+ (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n")))
+ (with-temp-buffer
+ (call-process-shell-command
+ (mapconcat #'shell-quote-argument (list batfile "x &y") " ")
+ nil '(t t) t)
+ (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))))
+ (when batfile (delete-file batfile))))))
+
+(ert-deftest process-test-stderr-buffer ()
+ (skip-unless (executable-find "bash"))
+ (let* ((stdout-buffer (generate-new-buffer "*stdout*"))
+ (stderr-buffer (generate-new-buffer "*stderr*"))
+ (proc (make-process :name "test"
+ :command (list "bash" "-c"
+ (concat "echo hello stdout!; "
+ "echo hello stderr! >&2; "
+ "exit 20"))
+ :buffer stdout-buffer
+ :stderr stderr-buffer))
+ (sentinel-called nil)
+ (start-time (float-time)))
+ (set-process-sentinel proc (lambda (proc msg)
+ (setq sentinel-called t)))
+ (while (not (or sentinel-called
+ (> (- (float-time) start-time)
+ process-test-sentinel-wait-timeout)))
+ (accept-process-output))
+ (cl-assert (eq (process-status proc) 'exit))
+ (cl-assert (= (process-exit-status proc) 20))
+ (should (with-current-buffer stdout-buffer
+ (goto-char (point-min))
+ (looking-at "hello stdout!")))
+ (should (with-current-buffer stderr-buffer
+ (goto-char (point-min))
+ (looking-at "hello stderr!")))))
+
+(ert-deftest process-test-stderr-filter ()
+ (skip-unless (executable-find "bash"))
+ (let* ((sentinel-called nil)
+ (stderr-sentinel-called nil)
+ (stdout-output nil)
+ (stderr-output nil)
+ (stdout-buffer (generate-new-buffer "*stdout*"))
+ (stderr-buffer (generate-new-buffer "*stderr*"))
+ (stderr-proc (make-pipe-process :name "stderr"
+ :buffer stderr-buffer))
+ (proc (make-process :name "test" :buffer stdout-buffer
+ :command (list "bash" "-c"
+ (concat "echo hello stdout!; "
+ "echo hello stderr! >&2; "
+ "exit 20"))
+ :stderr stderr-proc))
+ (start-time (float-time)))
+ (set-process-filter proc (lambda (proc input)
+ (push input stdout-output)))
+ (set-process-sentinel proc (lambda (proc msg)
+ (setq sentinel-called t)))
+ (set-process-filter stderr-proc (lambda (proc input)
+ (push input stderr-output)))
+ (set-process-sentinel stderr-proc (lambda (proc input)
+ (setq stderr-sentinel-called t)))
+ (while (not (or sentinel-called
+ (> (- (float-time) start-time)
+ process-test-sentinel-wait-timeout)))
+ (accept-process-output))
+ (cl-assert (eq (process-status proc) 'exit))
+ (cl-assert (= (process-exit-status proc) 20))
+ (should sentinel-called)
+ (should (equal 1 (with-current-buffer stdout-buffer
+ (point-max))))
+ (should (equal "hello stdout!\n"
+ (mapconcat #'identity (nreverse stdout-output) "")))
+ (should stderr-sentinel-called)
+ (should (equal 1 (with-current-buffer stderr-buffer
+ (point-max))))
+ (should (equal "hello stderr!\n"
+ (mapconcat #'identity (nreverse stderr-output) "")))))
+
+(ert-deftest start-process-should-not-modify-arguments ()
+ "`start-process' must not modify its arguments in-place."
+ ;; See bug#21831.
+ (let* ((path (pcase system-type
+ ((or 'windows-nt 'ms-dos)
+ ;; Make sure the file name uses forward slashes.
+ ;; The original bug was that 'start-process' would
+ ;; convert forward slashes to backslashes.
+ (expand-file-name (executable-find "attrib.exe")))
+ (_ "/bin//sh")))
+ (samepath (copy-sequence path)))
+ ;; Make sure 'start-process' actually goes all the way and invokes
+ ;; the program.
+ (should (process-live-p (condition-case nil
+ (start-process "" nil path)
+ (error nil))))
+ (should (equal path samepath))))
+
+(provide 'process-tests)
diff --git a/test/lisp/legacy/syntax-tests.el b/test/lisp/legacy/syntax-tests.el
new file mode 100644
index 00000000000..b884c3ef5b8
--- /dev/null
+++ b/test/lisp/legacy/syntax-tests.el
@@ -0,0 +1,97 @@
+;;; syntax-tests.el --- Testing syntax rules and basic movement -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
+
+;; Author: Daniel Colascione <dancol@dancol.org>
+;; Keywords:
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+(require 'ert)
+(require 'cl-lib)
+
+(defun run-up-list-test (fn data start instructions)
+ (cl-labels ((posof (thing)
+ (and (symbolp thing)
+ (= (length (symbol-name thing)) 1)
+ (- (aref (symbol-name thing) 0) ?a -1))))
+ (with-temp-buffer
+ (set-syntax-table (make-syntax-table))
+ ;; Use a syntax table in which single quote is a string
+ ;; character so that we can embed the test data in a lisp string
+ ;; literal.
+ (modify-syntax-entry ?\' "\"")
+ (insert data)
+ (goto-char (posof start))
+ (dolist (instruction instructions)
+ (cond ((posof instruction)
+ (funcall fn)
+ (should (eql (point) (posof instruction))))
+ ((symbolp instruction)
+ (should-error (funcall fn)
+ :type instruction))
+ (t (cl-assert nil nil "unknown ins")))))))
+
+(defmacro define-up-list-test (name fn data start &rest expected)
+ `(ert-deftest ,name ()
+ (run-up-list-test ,fn ,data ',start ',expected)))
+
+(define-up-list-test up-list-basic
+ (lambda () (up-list))
+ (or "(1 1 (1 1) 1 (1 1) 1)")
+ ;; abcdefghijklmnopqrstuv
+ i k v scan-error)
+
+(define-up-list-test up-list-with-forward-sexp-function
+ (lambda ()
+ (let ((forward-sexp-function
+ (lambda (&optional arg)
+ (let ((forward-sexp-function nil))
+ (forward-sexp arg)))))
+ (up-list)))
+ (or "(1 1 (1 1) 1 (1 1) 1)")
+ ;; abcdefghijklmnopqrstuv
+ i k v scan-error)
+
+(define-up-list-test up-list-out-of-string
+ (lambda () (up-list 1 t))
+ (or "1 (1 '2 2 (2 2 2' 1) 1")
+ ;; abcdefghijklmnopqrstuvwxy
+ o r u scan-error)
+
+(define-up-list-test up-list-cross-string
+ (lambda () (up-list 1 t))
+ (or "(1 '2 ( 2' 1 '2 ) 2' 1)")
+ ;; abcdefghijklmnopqrstuvwxy
+ i r u x scan-error)
+
+(define-up-list-test up-list-no-cross-string
+ (lambda () (up-list 1 t t))
+ (or "(1 '2 ( 2' 1 '2 ) 2' 1)")
+ ;; abcdefghijklmnopqrstuvwxy
+ i k x scan-error)
+
+(define-up-list-test backward-up-list-basic
+ (lambda () (backward-up-list))
+ (or "(1 1 (1 1) 1 (1 1) 1)")
+ ;; abcdefghijklmnopqrstuv
+ i f a scan-error)
+
+(provide 'syntax-tests)
+;;; syntax-tests.el ends here
diff --git a/test/lisp/legacy/textprop-tests.el b/test/lisp/legacy/textprop-tests.el
new file mode 100644
index 00000000000..0baa911421b
--- /dev/null
+++ b/test/lisp/legacy/textprop-tests.el
@@ -0,0 +1,69 @@
+;;; textprop-tests.el --- Test suite for text properties.
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Wolfgang Jenkner <wjenkner@inode.at>
+;; Keywords: internal
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest textprop-tests-format ()
+ "Test `format' with text properties."
+ ;; See Bug#21351.
+ (should (equal-including-properties
+ (format #("mouse-1, RET: %s -- w: copy %s"
+ 12 20 (face minibuffer-prompt)
+ 21 30 (face minibuffer-prompt))
+ "visit" "link")
+ #("mouse-1, RET: visit -- w: copy link"
+ 12 23 (face minibuffer-prompt)
+ 24 35 (face minibuffer-prompt)))))
+
+(ert-deftest textprop-tests-font-lock--remove-face-from-text-property ()
+ "Test `font-lock--remove-face-from-text-property'."
+ (let* ((string "foobar")
+ (stack (list string))
+ (faces '(bold (:foreground "red") underline)))
+ ;; Build each string in `stack' by adding a face to the previous
+ ;; string.
+ (let ((faces (reverse faces)))
+ (push (copy-sequence (car stack)) stack)
+ (put-text-property 0 3 'font-lock-face (pop faces) (car stack))
+ (push (copy-sequence (car stack)) stack)
+ (put-text-property 3 6 'font-lock-face (pop faces) (car stack))
+ (push (copy-sequence (car stack)) stack)
+ (font-lock-prepend-text-property 2 5
+ 'font-lock-face (pop faces) (car stack)))
+ ;; Check that removing the corresponding face from each string
+ ;; yields the previous string in `stack'.
+ (while faces
+ ;; (message "%S" (car stack))
+ (should (equal-including-properties
+ (progn
+ (font-lock--remove-face-from-text-property 0 6
+ 'font-lock-face
+ (pop faces)
+ (car stack))
+ (pop stack))
+ (car stack))))
+ ;; Sanity check.
+ ;; (message "%S" (car stack))
+ (should (and (equal-including-properties (pop stack) string)
+ (null stack)))))
diff --git a/test/lisp/legacy/undo-tests.el b/test/lisp/legacy/undo-tests.el
new file mode 100644
index 00000000000..f462b269337
--- /dev/null
+++ b/test/lisp/legacy/undo-tests.el
@@ -0,0 +1,448 @@
+;;; undo-tests.el --- Tests of primitive-undo
+
+;; Copyright (C) 2012-2015 Free Software Foundation, Inc.
+
+;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
+
+;; This program 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.
+;;
+;; This program 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 this program. If not, see `http://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;; Profiling when the code was translate from C to Lisp on 2012-12-24.
+
+;;; C
+
+;; (elp-instrument-function 'primitive-undo)
+;; (load-file "undo-test.elc")
+;; (benchmark 100 '(let ((undo-test5-error nil)) (undo-test-all)))
+;; Elapsed time: 305.218000s (104.841000s in 14804 GCs)
+;; M-x elp-results
+;; Function Name Call Count Elapsed Time Average Time
+;; primitive-undo 2600 3.4889999999 0.0013419230
+
+;;; Lisp
+
+;; (load-file "primundo.elc")
+;; (elp-instrument-function 'primitive-undo)
+;; (benchmark 100 '(undo-test-all))
+;; Elapsed time: 295.974000s (104.582000s in 14704 GCs)
+;; M-x elp-results
+;; Function Name Call Count Elapsed Time Average Time
+;; primitive-undo 2700 3.6869999999 0.0013655555
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest undo-test0 ()
+ "Test basics of \\[undo]."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (condition-case err
+ (undo)
+ (error
+ (unless (string= "No further undo information"
+ (cadr err))
+ (error err))))
+ (undo-boundary)
+ (insert "This")
+ (undo-boundary)
+ (erase-buffer)
+ (undo-boundary)
+ (insert "That")
+ (undo-boundary)
+ (forward-word -1)
+ (undo-boundary)
+ (insert "With ")
+ (undo-boundary)
+ (forward-word -1)
+ (undo-boundary)
+ (kill-word 1)
+ (undo-boundary)
+ (put-text-property (point-min) (point-max) 'face 'bold)
+ (undo-boundary)
+ (remove-text-properties (point-min) (point-max) '(face default))
+ (undo-boundary)
+ (set-buffer-multibyte (not enable-multibyte-characters))
+ (undo-boundary)
+ (undo)
+ (should
+ (equal (should-error (undo-more nil))
+ '(wrong-type-argument number-or-marker-p nil)))
+ (undo-more 7)
+ (should (string-equal "" (buffer-string)))))
+
+(ert-deftest undo-test1 ()
+ "Test undo of \\[undo] command (redo)."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (undo-boundary)
+ (insert "This")
+ (undo-boundary)
+ (erase-buffer)
+ (undo-boundary)
+ (insert "That")
+ (undo-boundary)
+ (forward-word -1)
+ (undo-boundary)
+ (insert "With ")
+ (undo-boundary)
+ (forward-word -1)
+ (undo-boundary)
+ (kill-word 1)
+ (undo-boundary)
+ (facemenu-add-face 'bold (point-min) (point-max))
+ (undo-boundary)
+ (set-buffer-multibyte (not enable-multibyte-characters))
+ (undo-boundary)
+ (should
+ (string-equal (buffer-string)
+ (progn
+ (undo)
+ (undo-more 4)
+ (undo)
+ ;(undo-more -4)
+ (buffer-string))))))
+
+(ert-deftest undo-test2 ()
+ "Test basic redoing with \\[undo] command."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (undo-boundary)
+ (insert "One")
+ (undo-boundary)
+ (insert " Zero")
+ (undo-boundary)
+ (push-mark nil t)
+ (delete-region (save-excursion
+ (forward-word -1)
+ (point)) (point))
+ (undo-boundary)
+ (beginning-of-line)
+ (insert "Zero")
+ (undo-boundary)
+ (undo)
+ (should
+ (string-equal (buffer-string)
+ (progn
+ (undo-more 2)
+ (undo)
+ (buffer-string))))))
+
+(ert-deftest undo-test4 ()
+ "Test \\[undo] of \\[flush-lines]."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (dotimes (i 1048576)
+ (if (zerop (% i 2))
+ (insert "Evenses")
+ (insert "Oddses")))
+ (undo-boundary)
+ (should
+ ;; Avoid string-equal because ERT will save the `buffer-string'
+ ;; to the explanation. Using `not' will record nil or non-nil.
+ (not
+ (null
+ (string-equal (buffer-string)
+ (progn
+ (flush-lines "oddses" (point-min) (point-max))
+ (undo-boundary)
+ (undo)
+ (undo)
+ (buffer-string))))))))
+
+(ert-deftest undo-test5 ()
+ "Test basic redoing with \\[undo] command."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (undo-boundary)
+ (insert "AYE")
+ (undo-boundary)
+ (insert " BEE")
+ (undo-boundary)
+ (setq buffer-undo-list (cons '(0.0 bogus) buffer-undo-list))
+ (push-mark nil t)
+ (delete-region (save-excursion
+ (forward-word -1)
+ (point)) (point))
+ (undo-boundary)
+ (beginning-of-line)
+ (insert "CEE")
+ (undo-boundary)
+ (undo)
+ (setq buffer-undo-list (cons "bogus" buffer-undo-list))
+ (should
+ (string-equal
+ (buffer-string)
+ (progn
+ (if (and (boundp 'undo-test5-error) (not undo-test5-error))
+ (progn
+ (should (null (undo-more 2)))
+ (should (undo)))
+ ;; Errors are generated by new Lisp version of
+ ;; `primitive-undo' not by built-in C version.
+ (should
+ (equal (should-error (undo-more 2))
+ '(error "Unrecognized entry in undo list (0.0 bogus)")))
+ (should
+ (equal (should-error (undo))
+ '(error "Unrecognized entry in undo list \"bogus\""))))
+ (buffer-string))))))
+
+;; http://debbugs.gnu.org/14824
+(ert-deftest undo-test-buffer-modified ()
+ "Test undoing marks buffer unmodified."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (insert "1")
+ (undo-boundary)
+ (set-buffer-modified-p nil)
+ (insert "2")
+ (undo)
+ (should-not (buffer-modified-p))))
+
+(ert-deftest undo-test-file-modified ()
+ "Test undoing marks buffer visiting file unmodified."
+ (let ((tempfile (make-temp-file "undo-test")))
+ (unwind-protect
+ (progn
+ (with-current-buffer (find-file-noselect tempfile)
+ (insert "1")
+ (undo-boundary)
+ (set-buffer-modified-p nil)
+ (insert "2")
+ (undo)
+ (should-not (buffer-modified-p))))
+ (delete-file tempfile))))
+
+(ert-deftest undo-test-region-not-most-recent ()
+ "Test undo in region of an edit not the most recent."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "1111")
+ (undo-boundary)
+ (goto-char 2)
+ (insert "2")
+ (forward-char 2)
+ (undo-boundary)
+ (insert "3")
+ (undo-boundary)
+ ;; Highlight around "2", not "3"
+ (push-mark (+ 3 (point-min)) t t)
+ (setq mark-active t)
+ (goto-char (point-min))
+ (undo)
+ (should (string= (buffer-string)
+ "11131"))))
+
+(ert-deftest undo-test-region-deletion ()
+ "Test undoing a deletion to demonstrate bug 17235."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "12345")
+ (search-backward "4")
+ (undo-boundary)
+ (delete-forward-char 1)
+ (search-backward "1")
+ (undo-boundary)
+ (insert "xxxx")
+ (undo-boundary)
+ (insert "yy")
+ (search-forward "35")
+ (undo-boundary)
+ ;; Select "35"
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (forward-char -2)
+ (undo) ; Expect "4" to come back
+ (should (string= (buffer-string)
+ "xxxxyy12345"))))
+
+(ert-deftest undo-test-region-example ()
+ "The same example test case described in comments for
+undo-make-selective-list."
+ ;; buf pos:
+ ;; 123456789 buffer-undo-list undo-deltas
+ ;; --------- ---------------- -----------
+ ;; aaa (1 . 4) (1 . -3)
+ ;; aaba (3 . 4) N/A (in region)
+ ;; ccaaba (1 . 3) (1 . -2)
+ ;; ccaabaddd (7 . 10) (7 . -3)
+ ;; ccaabdd ("ad" . 6) (6 . 2)
+ ;; ccaabaddd (6 . 8) (6 . -2)
+ ;; | |<-- region: "caab", from 2 to 6
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "aaa")
+ (goto-char 3)
+ (undo-boundary)
+ (insert "b")
+ (goto-char 1)
+ (undo-boundary)
+ (insert "cc")
+ (goto-char 7)
+ (undo-boundary)
+ (insert "ddd")
+ (search-backward "ad")
+ (undo-boundary)
+ (delete-forward-char 2)
+ (undo-boundary)
+ ;; Select "dd"
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (goto-char (point-max))
+ (undo)
+ (undo-boundary)
+ (should (string= (buffer-string)
+ "ccaabaddd"))
+ ;; Select "caab"
+ (push-mark 2 t t)
+ (setq mark-active t)
+ (goto-char 6)
+ (undo)
+ (undo-boundary)
+ (should (string= (buffer-string)
+ "ccaaaddd"))))
+
+(ert-deftest undo-test-region-eob ()
+ "Test undo in region of a deletion at EOB, demonstrating bug 16411."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "This sentence corrupted?")
+ (undo-boundary)
+ ;; Same as recipe at
+ ;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16411
+ (insert "aaa")
+ (undo-boundary)
+ (undo)
+ ;; Select entire buffer
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (goto-char (point-min))
+ ;; Should undo the undo of "aaa", ie restore it.
+ (undo)
+ (should (string= (buffer-string)
+ "This sentence corrupted?aaa"))))
+
+(ert-deftest undo-test-marker-adjustment-nominal ()
+ "Test nominal behavior of marker adjustments."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (insert "abcdefg")
+ (undo-boundary)
+ (let ((m (make-marker)))
+ (set-marker m 2 (current-buffer))
+ (goto-char (point-min))
+ (delete-forward-char 3)
+ (undo-boundary)
+ (should (= (point-min) (marker-position m)))
+ (undo)
+ (undo-boundary)
+ (should (= 2 (marker-position m))))))
+
+(ert-deftest undo-test-region-t-marker ()
+ "Test undo in region containing marker with t insertion-type."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "abcdefg")
+ (undo-boundary)
+ (let ((m (make-marker)))
+ (set-marker-insertion-type m t)
+ (set-marker m (point-min) (current-buffer)) ; m at a
+ (goto-char (+ 2 (point-min)))
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (goto-char (point-min))
+ (delete-forward-char 1) ;; delete region covering "ab"
+ (undo-boundary)
+ (should (= (point-min) (marker-position m)))
+ ;; Resurrect "ab". m's insertion type means the reinsertion
+ ;; moves it forward 2, and then the marker adjustment returns it
+ ;; to its rightful place.
+ (undo)
+ (undo-boundary)
+ (should (= (point-min) (marker-position m))))))
+
+(ert-deftest undo-test-marker-adjustment-moved ()
+ "Test marker adjustment behavior when the marker moves.
+Demonstrates bug 16818."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (insert "abcdefghijk")
+ (undo-boundary)
+ (let ((m (make-marker)))
+ (set-marker m 2 (current-buffer)) ; m at b
+ (goto-char (point-min))
+ (delete-forward-char 3) ; m at d
+ (undo-boundary)
+ (set-marker m 4) ; m at g
+ (undo)
+ (undo-boundary)
+ ;; m still at g, but shifted 3 because deletion undone
+ (should (= 7 (marker-position m))))))
+
+(ert-deftest undo-test-region-mark-adjustment ()
+ "Test that the mark's marker adjustment in undo history doesn't
+obstruct undo in region from finding the correct change group.
+Demonstrates bug 16818."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode 1)
+ (insert "First line\n")
+ (insert "Second line\n")
+ (undo-boundary)
+
+ (goto-char (point-min))
+ (insert "aaa")
+ (undo-boundary)
+
+ (undo)
+ (undo-boundary)
+
+ (goto-char (point-max))
+ (insert "bbb")
+ (undo-boundary)
+
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (goto-char (- (point) 3))
+ (delete-forward-char 1)
+ (undo-boundary)
+
+ (insert "bbb")
+ (undo-boundary)
+
+ (goto-char (point-min))
+ (push-mark (point) t t)
+ (setq mark-active t)
+ (goto-char (+ (point) 3))
+ (undo)
+ (undo-boundary)
+
+ (should (string= (buffer-string) "aaaFirst line\nSecond line\nbbb"))))
+
+(defun undo-test-all (&optional interactive)
+ "Run all tests for \\[undo]."
+ (interactive "p")
+ (if interactive
+ (ert-run-tests-interactively "^undo-")
+ (ert-run-tests-batch "^undo-")))
+
+(provide 'undo-tests)
+;;; undo-tests.el ends here