summaryrefslogtreecommitdiff
path: root/test/src
diff options
context:
space:
mode:
Diffstat (limited to 'test/src')
-rw-r--r--test/src/alloc-tests.el33
-rw-r--r--test/src/buffer-tests.el48
-rw-r--r--test/src/callproc-tests.el39
-rw-r--r--test/src/chartab-tests.el51
-rw-r--r--test/src/cmds-tests.el34
-rw-r--r--test/src/coding-tests.el383
-rw-r--r--test/src/data-tests.el452
-rw-r--r--test/src/decompress-tests.el45
-rw-r--r--test/src/doc-tests.el92
-rw-r--r--test/src/editfns-tests.el136
-rw-r--r--test/src/eval-tests.el50
-rw-r--r--test/src/fns-tests.el247
-rw-r--r--test/src/font-tests.el167
-rw-r--r--test/src/inotify-tests.el64
-rw-r--r--test/src/keymap-tests.el50
-rw-r--r--test/src/lread-tests.el115
-rw-r--r--test/src/marker-tests.el60
-rw-r--r--test/src/minibuf-tests.el403
-rw-r--r--test/src/print-tests.el62
-rw-r--r--test/src/process-tests.el166
-rw-r--r--test/src/regex-resources/BOOST.tests829
-rw-r--r--test/src/regex-resources/PCRE.tests2386
-rw-r--r--test/src/regex-resources/PTESTS341
-rw-r--r--test/src/regex-resources/TESTS167
-rw-r--r--test/src/regex-tests.el680
-rw-r--r--test/src/textprop-tests.el72
-rw-r--r--test/src/thread-tests.el247
-rw-r--r--test/src/undo-tests.el448
-rw-r--r--test/src/xml-tests.el74
29 files changed, 7941 insertions, 0 deletions
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
new file mode 100644
index 00000000000..97c6b4f8070
--- /dev/null
+++ b/test/src/alloc-tests.el
@@ -0,0 +1,33 @@
+;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+;; Author: Daniel Colascione <dancol@dancol.org>
+;; Keywords:
+
+;; 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:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(ert-deftest finalizer-object-type ()
+ (should (equal (type-of (make-finalizer nil)) 'finalizer)))
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
new file mode 100644
index 00000000000..62875216a31
--- /dev/null
+++ b/test/src/buffer-tests.el
@@ -0,0 +1,48 @@
+;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015-2016 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)
+
+(ert-deftest overlay-modification-hooks-message-other-buf ()
+ "Test for bug#21824.
+After a modification-hook has been run and there is an overlay in
+the *Messages* buffer, the message coalescing [2 times] wrongly
+runs the modification-hook of the overlay in the 1st buffer, but
+with parameters from the *Messages* buffer modification."
+ (let ((buf nil)
+ (msg-ov nil))
+ (with-temp-buffer
+ (insert "123")
+ (overlay-put (make-overlay 1 3)
+ 'modification-hooks
+ (list (lambda (&rest _)
+ (setq buf (current-buffer)))))
+ (goto-char 2)
+ (insert "x")
+ (unwind-protect
+ (progn
+ (setq msg-ov (make-overlay 1 1 (get-buffer-create "*Messages*")))
+ (message "a message")
+ (message "a message")
+ (should (eq buf (current-buffer))))
+ (when msg-ov (delete-overlay msg-ov))))))
+
+;;; buffer-tests.el ends here
diff --git a/test/src/callproc-tests.el b/test/src/callproc-tests.el
new file mode 100644
index 00000000000..46541aba78c
--- /dev/null
+++ b/test/src/callproc-tests.el
@@ -0,0 +1,39 @@
+;;; callproc-tests.el --- callproc.c tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016 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)
+(eval-when-compile (require 'cl-lib))
+
+(ert-deftest initial-environment-preserved ()
+ "Check that `initial-environment' is not modified by Emacs (Bug #10980)."
+ (skip-unless (eq system-type 'windows-nt))
+ (cl-destructuring-bind (initial-shell shell)
+ (with-temp-buffer
+ (let ((process-environment (cons "SHELL" process-environment)))
+ (call-process (expand-file-name invocation-name invocation-directory)
+ nil t nil
+ "--batch" "-Q" "--eval"
+ (prin1-to-string
+ '(progn (prin1 (getenv-internal "SHELL" initial-environment))
+ (prin1 (getenv-internal "SHELL"))))))
+ (split-string-and-unquote (buffer-string)))
+ (should (equal initial-shell "nil"))
+ (should-not (equal initial-shell shell))))
diff --git a/test/src/chartab-tests.el b/test/src/chartab-tests.el
new file mode 100644
index 00000000000..016ddcdde61
--- /dev/null
+++ b/test/src/chartab-tests.el
@@ -0,0 +1,51 @@
+;;; chartab-tests.el --- Tests for char-tab.c
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Eli Zaretskii <eliz@gnu.org>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defun chartab-set-and-test (rng)
+ (let ((tbl (make-char-table nil nil))
+ (from (car rng))
+ (to (cdr rng)))
+ (set-char-table-range tbl rng t)
+ (should (eq (aref tbl from) t))
+ (should (eq (aref tbl to) t))
+ (should (eq (aref tbl (/ (+ from to) 2)) t))
+ (when (< to (max-char))
+ (should-not (eq (aref tbl (1+ to)) t)))
+ (when (> from 0)
+ (should-not (eq (aref tbl (1- from)) t)))))
+
+(ert-deftest chartab-test-range-setting ()
+ (mapc (lambda (elt)
+ (chartab-set-and-test elt))
+ '((0 . 127)
+ (128 . 256)
+ (#x1000 . #x1fff)
+ (#x1001 . #x2000)
+ (#x10000 . #x20000)
+ (#x10001 . #x1ffff)
+ (#x20000 . #x30000)
+ (#xe0e00 . #xe0ef6)
+ )))
+
+(provide 'chartab-tests)
+;;; chartab-tests.el ends here
diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el
new file mode 100644
index 00000000000..4a30d9872a1
--- /dev/null
+++ b/test/src/cmds-tests.el
@@ -0,0 +1,34 @@
+;;; cmds-tests.el --- Testing some Emacs commands
+
+;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+;; Author: Nicolas Richard <youngfrog@members.fsf.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:
+
+
+(ert-deftest self-insert-command-with-negative-argument ()
+ "Test `self-insert-command' with a negative argument."
+ (let ((last-command-event ?a))
+ (should-error (self-insert-command -1))))
+
+(provide 'cmds-tests)
+;;; cmds-tests.el ends here
diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el
new file mode 100644
index 00000000000..bd494bc26f8
--- /dev/null
+++ b/test/src/coding-tests.el
@@ -0,0 +1,383 @@
+;;; coding-tests.el --- tests for text encoding and decoding
+
+;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+;; Author: Eli Zaretskii <eliz@gnu.org>
+;; 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 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)))
+
+;; See issue #5251.
+(ert-deftest ert-test-unibyte-buffer-dos-eol-decode ()
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert (encode-coding-string "あ" 'euc-jp) "\xd" "\n")
+ (decode-coding-region (point-min) (point-max) 'euc-jp-dos)
+ (should-not (string-match-p "\^M" (buffer-string)))))
+
+;; Return the contents (specified by CONTENT-TYPE; ascii, latin, or
+;; binary) of a test file.
+(defun coding-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 coding-tests-gen-file (file contents coding-system)
+ (or (file-directory-p coding-tests-workdir)
+ (mkdir coding-tests-workdir t))
+ (setq file (expand-file-name file coding-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 coding-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 coding-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 coding-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 coding-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 coding-tests-filename (content-type coding-system &optional ext)
+ (if ext
+ (expand-file-name (format "%s-%s.%s" content-type coding-system ext)
+ coding-tests-workdir)
+ (expand-file-name (format "%s-%s" content-type coding-system)
+ coding-tests-workdir)))
+
+
+;;; Check ASCII optimizing decoder
+
+;; Generate a test file whose contents specified by CONTENT-TYPE and
+;; whose encoding specified by CODING-SYSTEM.
+(defun coding-tests-ao-gen-file (content-type coding-system)
+ (let ((file (coding-tests-filename content-type coding-system)))
+ (coding-tests-gen-file file
+ (coding-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 coding-tests (content-type write-coding read-coding detected-coding
+ &optional translator)
+ (prefer-coding-system 'utf-8-auto)
+ (let ((filename (coding-tests-filename content-type write-coding)))
+ (with-temp-buffer
+ (let ((coding-system-for-read read-coding)
+ (contents (coding-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-coding-ascii ()
+ (unwind-protect
+ (progn
+ (dolist (eol-type '(unix dos mac))
+ (coding-tests-ao-gen-file 'ascii eol-type))
+ (should-not (coding-tests 'ascii 'unix 'undecided 'unix))
+ (should-not (coding-tests 'ascii 'dos 'undecided 'dos))
+ (should-not (coding-tests 'ascii 'dos 'dos 'dos))
+ (should-not (coding-tests 'ascii 'mac 'undecided 'mac))
+ (should-not (coding-tests 'ascii 'mac 'mac 'mac))
+ (should-not (coding-tests 'ascii 'dos 'utf-8 'utf-8-dos))
+ (should-not (coding-tests 'ascii 'dos 'unix 'unix
+ 'coding-tests-lf-to-crlf))
+ (should-not (coding-tests 'ascii 'mac 'dos 'dos
+ 'coding-tests-lf-to-cr))
+ (should-not (coding-tests 'ascii 'dos 'mac 'mac
+ 'coding-tests-lf-to-lflf)))
+ (coding-tests-remove-files)))
+
+(ert-deftest ert-test-coding-latin ()
+ (unwind-protect
+ (progn
+ (dolist (coding '("utf-8" "utf-8-with-signature"))
+ (dolist (eol-type '("unix" "dos" "mac"))
+ (coding-tests-ao-gen-file 'latin
+ (intern (concat coding "-" eol-type)))))
+ (should-not (coding-tests 'latin 'utf-8-unix 'undecided 'utf-8-unix))
+ (should-not (coding-tests 'latin 'utf-8-unix 'utf-8-unix 'utf-8-unix))
+ (should-not (coding-tests 'latin 'utf-8-dos 'undecided 'utf-8-dos))
+ (should-not (coding-tests 'latin 'utf-8-dos 'utf-8-dos 'utf-8-dos))
+ (should-not (coding-tests 'latin 'utf-8-mac 'undecided 'utf-8-mac))
+ (should-not (coding-tests 'latin 'utf-8-mac 'utf-8-mac 'utf-8-mac))
+ (should-not (coding-tests 'latin 'utf-8-dos 'unix 'utf-8-unix
+ 'coding-tests-lf-to-crlf))
+ (should-not (coding-tests 'latin 'utf-8-mac 'dos 'utf-8-dos
+ 'coding-tests-lf-to-cr))
+ (should-not (coding-tests 'latin 'utf-8-dos 'mac 'utf-8-mac
+ 'coding-tests-lf-to-lflf))
+ (should-not (coding-tests 'latin 'utf-8-with-signature-unix 'undecided
+ 'utf-8-with-signature-unix))
+ (should-not (coding-tests 'latin 'utf-8-with-signature-unix 'utf-8-auto
+ 'utf-8-with-signature-unix))
+ (should-not (coding-tests 'latin 'utf-8-with-signature-dos 'undecided
+ 'utf-8-with-signature-dos))
+ (should-not (coding-tests 'latin 'utf-8-with-signature-unix 'utf-8
+ 'utf-8-unix 'coding-tests-add-bom))
+ (should-not (coding-tests 'latin 'utf-8-with-signature-unix 'utf-8
+ 'utf-8-unix 'coding-tests-add-bom)))
+ (coding-tests-remove-files)))
+
+(ert-deftest ert-test-coding-binary ()
+ (unwind-protect
+ (progn
+ (dolist (eol-type '("unix" "dos" "mac"))
+ (coding-tests-ao-gen-file 'binary
+ (intern (concat "raw-text" "-" eol-type))))
+ (should-not (coding-tests 'binary 'raw-text-unix 'undecided
+ 'raw-text-unix))
+ (should-not (coding-tests 'binary 'raw-text-dos 'undecided
+ 'raw-text-dos))
+ (should-not (coding-tests 'binary 'raw-text-mac 'undecided
+ 'raw-text-mac))
+ (should-not (coding-tests 'binary 'raw-text-dos 'unix
+ 'raw-text-unix 'coding-tests-lf-to-crlf))
+ (should-not (coding-tests 'binary 'raw-text-mac 'dos
+ 'raw-text-dos 'coding-tests-lf-to-cr))
+ (should-not (coding-tests 'binary 'raw-text-dos 'mac
+ 'raw-text-mac 'coding-tests-lf-to-lflf)))
+ (coding-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 coding-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 coding-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 (coding-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-coding-prefer-utf-8 ()
+ (unwind-protect
+ (let ((ascii (coding-tests-gen-file "ascii.el"
+ (coding-tests-file-contents 'ascii)
+ 'unix))
+ (latin (coding-tests-gen-file "utf-8.el"
+ (coding-tests-file-contents 'latin)
+ 'utf-8-unix)))
+ (should-not (coding-tests-prefer-utf-8-read
+ ascii 'prefer-utf-8-unix nil))
+ (should-not (coding-tests-prefer-utf-8-read
+ latin 'utf-8-unix nil))
+ (should-not (coding-tests-prefer-utf-8-read
+ latin 'utf-8-unix 'iso-8859-1))
+ (should-not (coding-tests-prefer-utf-8-read
+ latin 'utf-8-unix 'sjis))
+ (should-not (coding-tests-prefer-utf-8-write
+ ascii nil 'prefer-utf-8-unix))
+ (should-not (coding-tests-prefer-utf-8-write
+ ascii 'iso-8859-1 'iso-8859-1-unix))
+ (should-not (coding-tests-prefer-utf-8-write
+ ascii nil 'utf-8-unix "À")))
+ (coding-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)))))))
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; End:
+
+(provide 'coding-tests)
+;; coding-tests.el ends here
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
new file mode 100644
index 00000000000..757522e399b
--- /dev/null
+++ b/test/src/data-tests.el
@@ -0,0 +1,452 @@
+;;; data-tests.el --- tests for src/data.c
+
+;; Copyright (C) 2013-2016 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/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(eval-when-compile (require 'cl))
+
+(ert-deftest data-tests-= ()
+ (should-error (=))
+ (should (= 1))
+ (should (= 2 2))
+ (should (= 9 9 9 9 9 9 9 9 9))
+ (should-not (apply #'= '(3 8 3)))
+ (should-error (= 9 9 'foo))
+ ;; Short circuits before getting to bad arg
+ (should-not (= 9 8 'foo)))
+
+(ert-deftest data-tests-< ()
+ (should-error (<))
+ (should (< 1))
+ (should (< 2 3))
+ (should (< -6 -1 0 2 3 4 8 9 999))
+ (should-not (apply #'< '(3 8 3)))
+ (should-error (< 9 10 'foo))
+ ;; Short circuits before getting to bad arg
+ (should-not (< 9 8 'foo)))
+
+(ert-deftest data-tests-> ()
+ (should-error (>))
+ (should (> 1))
+ (should (> 3 2))
+ (should (> 6 1 0 -2 -3 -4 -8 -9 -999))
+ (should-not (apply #'> '(3 8 3)))
+ (should-error (> 9 8 'foo))
+ ;; Short circuits before getting to bad arg
+ (should-not (> 8 9 'foo)))
+
+(ert-deftest data-tests-<= ()
+ (should-error (<=))
+ (should (<= 1))
+ (should (<= 2 3))
+ (should (<= -6 -1 -1 0 0 0 2 3 4 8 999))
+ (should-not (apply #'<= '(3 8 3 3)))
+ (should-error (<= 9 10 'foo))
+ ;; Short circuits before getting to bad arg
+ (should-not (<= 9 8 'foo)))
+
+(ert-deftest data-tests->= ()
+ (should-error (>=))
+ (should (>= 1))
+ (should (>= 3 2))
+ (should (>= 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999))
+ (should-not (apply #'>= '(3 8 3)))
+ (should-error (>= 9 8 'foo))
+ ;; Short circuits before getting to bad arg
+ (should-not (>= 8 9 'foo)))
+
+;; Bool vector tests. Compactly represent bool vectors as hex
+;; strings.
+
+(ert-deftest bool-vector-count-population-all-0-nil ()
+ (cl-loop for sz in '(0 45 1 64 9 344)
+ do (let* ((bv (make-bool-vector sz nil)))
+ (should
+ (zerop
+ (bool-vector-count-population bv))))))
+
+(ert-deftest bool-vector-count-population-all-1-t ()
+ (cl-loop for sz in '(0 45 1 64 9 344)
+ do (let* ((bv (make-bool-vector sz t)))
+ (should
+ (eql
+ (bool-vector-count-population bv)
+ sz)))))
+
+(ert-deftest bool-vector-count-population-1-nil ()
+ (let* ((bv (make-bool-vector 45 nil)))
+ (aset bv 40 t)
+ (aset bv 0 t)
+ (should
+ (eql
+ (bool-vector-count-population bv)
+ 2))))
+
+(ert-deftest bool-vector-count-population-1-t ()
+ (let* ((bv (make-bool-vector 45 t)))
+ (aset bv 40 nil)
+ (aset bv 0 nil)
+ (should
+ (eql
+ (bool-vector-count-population bv)
+ 43))))
+
+(defun mock-bool-vector-count-consecutive (a b i)
+ (loop for i from i below (length a)
+ while (eq (aref a i) b)
+ sum 1))
+
+(defun test-bool-vector-bv-from-hex-string (desc)
+ (let (bv nchars nibbles)
+ (dolist (c (string-to-list desc))
+ (push (string-to-number
+ (char-to-string c)
+ 16)
+ nibbles))
+ (setf bv (make-bool-vector (* 4 (length nibbles)) nil))
+ (let ((i 0))
+ (dolist (n (nreverse nibbles))
+ (dotimes (_ 4)
+ (aset bv i (> (logand 1 n) 0))
+ (incf i)
+ (setf n (lsh n -1)))))
+ bv))
+
+(defun test-bool-vector-to-hex-string (bv)
+ (let (nibbles (v (cl-coerce bv 'list)))
+ (while v
+ (push (logior
+ (lsh (if (nth 0 v) 1 0) 0)
+ (lsh (if (nth 1 v) 1 0) 1)
+ (lsh (if (nth 2 v) 1 0) 2)
+ (lsh (if (nth 3 v) 1 0) 3))
+ nibbles)
+ (setf v (nthcdr 4 v)))
+ (mapconcat (lambda (n) (format "%X" n))
+ (nreverse nibbles)
+ "")))
+
+(defun test-bool-vector-count-consecutive-tc (desc)
+ "Run a test case for bool-vector-count-consecutive.
+DESC is a string describing the test. It is a sequence of
+hexadecimal digits describing the bool vector. We exhaustively
+test all counts at all possible positions in the vector by
+comparing the subr with a much slower lisp implementation."
+ (let ((bv (test-bool-vector-bv-from-hex-string desc)))
+ (loop
+ for lf in '(nil t)
+ do (loop
+ for pos from 0 upto (length bv)
+ for cnt = (mock-bool-vector-count-consecutive bv lf pos)
+ for rcnt = (bool-vector-count-consecutive bv lf pos)
+ unless (eql cnt rcnt)
+ do (error "FAILED testcase %S %3S %3S %3S"
+ pos lf cnt rcnt)))))
+
+(defconst bool-vector-test-vectors
+'(""
+ "0"
+ "F"
+ "0F"
+ "F0"
+ "00000000000000000000000000000FFFFF0000000"
+ "44a50234053fba3340000023444a50234053fba33400000234"
+ "12341234123456123412346001234123412345612341234600"
+ "44a50234053fba33400000234"
+ "1234123412345612341234600"
+ "44a50234053fba33400000234"
+ "1234123412345612341234600"
+ "44a502340"
+ "123412341"
+ "0000000000000000000000000"
+ "FFFFFFFFFFFFFFFF1"))
+
+(ert-deftest bool-vector-count-consecutive ()
+ (mapc #'test-bool-vector-count-consecutive-tc
+ bool-vector-test-vectors))
+
+(defun test-bool-vector-apply-mock-op (mock a b c)
+ "Compute (slowly) the correct result of a bool-vector set operation."
+ (let (changed nv)
+ (assert (eql (length b) (length c)))
+ (if a (setf nv a)
+ (setf a (make-bool-vector (length b) nil))
+ (setf changed t))
+
+ (loop for i below (length b)
+ for mockr = (funcall mock
+ (if (aref b i) 1 0)
+ (if (aref c i) 1 0))
+ for r = (not (= 0 mockr))
+ do (progn
+ (unless (eq (aref a i) r)
+ (setf changed t))
+ (setf (aref a i) r)))
+ (if changed a)))
+
+(defun test-bool-vector-binop (mock real)
+ "Test a binary set operation."
+ (loop for s1 in bool-vector-test-vectors
+ for bv1 = (test-bool-vector-bv-from-hex-string s1)
+ for vecs2 = (cl-remove-if-not
+ (lambda (x) (eql (length x) (length s1)))
+ bool-vector-test-vectors)
+ do (loop for s2 in vecs2
+ for bv2 = (test-bool-vector-bv-from-hex-string s2)
+ for mock-result = (test-bool-vector-apply-mock-op
+ mock nil bv1 bv2)
+ for real-result = (funcall real bv1 bv2)
+ do (progn
+ (should (equal mock-result real-result))))))
+
+(ert-deftest bool-vector-intersection-op ()
+ (test-bool-vector-binop
+ #'logand
+ #'bool-vector-intersection))
+
+(ert-deftest bool-vector-union-op ()
+ (test-bool-vector-binop
+ #'logior
+ #'bool-vector-union))
+
+(ert-deftest bool-vector-xor-op ()
+ (test-bool-vector-binop
+ #'logxor
+ #'bool-vector-exclusive-or))
+
+(ert-deftest bool-vector-set-difference-op ()
+ (test-bool-vector-binop
+ (lambda (a b) (logand a (lognot b)))
+ #'bool-vector-set-difference))
+
+(ert-deftest bool-vector-change-detection ()
+ (let* ((vc1 (test-bool-vector-bv-from-hex-string "abcdef"))
+ (vc2 (test-bool-vector-bv-from-hex-string "012345"))
+ (vc3 (make-bool-vector (length vc1) nil))
+ (c1 (bool-vector-union vc1 vc2 vc3))
+ (c2 (bool-vector-union vc1 vc2 vc3)))
+ (should (equal c1 (test-bool-vector-apply-mock-op
+ #'logior
+ nil
+ vc1 vc2)))
+ (should (not c2))))
+
+(ert-deftest bool-vector-not ()
+ (let* ((v1 (test-bool-vector-bv-from-hex-string "FFFF3"))
+ (v2 (test-bool-vector-bv-from-hex-string "0000C"))
+ (v3 (bool-vector-not v1)))
+ (should (equal v2 v3))))
+
+;; Tests for variable bindings
+
+(defvar binding-test-buffer-A (get-buffer-create "A"))
+(defvar binding-test-buffer-B (get-buffer-create "B"))
+
+(defvar binding-test-always-local 'always)
+(make-variable-buffer-local 'binding-test-always-local)
+
+(defvar binding-test-some-local 'some)
+(with-current-buffer binding-test-buffer-A
+ (set (make-local-variable 'binding-test-some-local) 'local))
+
+(ert-deftest binding-test-manual ()
+ "A test case from the elisp manual."
+ (save-excursion
+ (set-buffer binding-test-buffer-A)
+ (let ((binding-test-some-local 'something-else))
+ (should (eq binding-test-some-local 'something-else))
+ (set-buffer binding-test-buffer-B)
+ (should (eq binding-test-some-local 'some)))
+ (should (eq binding-test-some-local 'some))
+ (set-buffer binding-test-buffer-A)
+ (should (eq binding-test-some-local 'local))))
+
+(ert-deftest binding-test-setq-default ()
+ "Test that a setq-default has no effect when there is a local binding."
+ (save-excursion
+ (set-buffer binding-test-buffer-B)
+ ;; This variable is not local in this buffer.
+ (let ((binding-test-some-local 'something-else))
+ (setq-default binding-test-some-local 'new-default))
+ (should (eq binding-test-some-local 'some))))
+
+(ert-deftest binding-test-makunbound ()
+ "Tests of makunbound, from the manual."
+ (save-excursion
+ (set-buffer binding-test-buffer-B)
+ (should (boundp 'binding-test-some-local))
+ (let ((binding-test-some-local 'outer))
+ (let ((binding-test-some-local 'inner))
+ (makunbound 'binding-test-some-local)
+ (should (not (boundp 'binding-test-some-local))))
+ (should (and (boundp 'binding-test-some-local)
+ (eq binding-test-some-local 'outer))))))
+
+(ert-deftest binding-test-defvar-bool ()
+ "Test DEFVAR_BOOL"
+ (let ((display-hourglass 5))
+ (should (eq display-hourglass t))))
+
+(ert-deftest binding-test-defvar-int ()
+ "Test DEFVAR_INT"
+ (should-error (setq gc-cons-threshold 5.0) :type 'wrong-type-argument))
+
+(ert-deftest binding-test-set-constant-t ()
+ "Test setting the constant t"
+ (should-error (setq t 'bob) :type 'setting-constant))
+
+(ert-deftest binding-test-set-constant-nil ()
+ "Test setting the constant nil"
+ (should-error (setq nil 'bob) :type 'setting-constant))
+
+(ert-deftest binding-test-set-constant-keyword ()
+ "Test setting a keyword constant"
+ (should-error (setq :keyword 'bob) :type 'setting-constant))
+
+(ert-deftest binding-test-set-constant-nil ()
+ "Test setting a keyword to itself"
+ (should (setq :keyword :keyword)))
+
+;; More tests to write -
+;; kill-local-variable
+;; defconst; can modify
+;; defvar and defconst modify the local binding [ doesn't matter for us ]
+;; various kinds of special internal forwarding objects
+;; a couple examples in manual, not enough
+;; variable aliases
+
+;; Tests for watchpoints
+
+(ert-deftest data-tests-variable-watchers ()
+ (defvar data-tests-var 0)
+ (let* ((watch-data nil)
+ (collect-watch-data
+ (lambda (&rest args) (push args watch-data))))
+ (cl-flet ((should-have-watch-data (data)
+ (should (equal (pop watch-data) data))
+ (should (null watch-data))))
+ (add-variable-watcher 'data-tests-var collect-watch-data)
+ (setq data-tests-var 1)
+ (should-have-watch-data '(data-tests-var 1 set nil))
+ (let ((data-tests-var 2))
+ (should-have-watch-data '(data-tests-var 2 let nil))
+ (setq data-tests-var 3)
+ (should-have-watch-data '(data-tests-var 3 set nil)))
+ (should-have-watch-data '(data-tests-var 1 unlet nil))
+ ;; `setq-default' on non-local variable is same as `setq'.
+ (setq-default data-tests-var 4)
+ (should-have-watch-data '(data-tests-var 4 set nil))
+ (makunbound 'data-tests-var)
+ (should-have-watch-data '(data-tests-var nil makunbound nil))
+ (setq data-tests-var 5)
+ (should-have-watch-data '(data-tests-var 5 set nil))
+ (remove-variable-watcher 'data-tests-var collect-watch-data)
+ (setq data-tests-var 6)
+ (should (null watch-data)))))
+
+(ert-deftest data-tests-varalias-watchers ()
+ (defvar data-tests-var0 0)
+ (defvar data-tests-var1 0)
+ (defvar data-tests-var2 0)
+ (defvar data-tests-var3 0)
+ (let* ((watch-data nil)
+ (collect-watch-data
+ (lambda (&rest args) (push args watch-data))))
+ (cl-flet ((should-have-watch-data (data)
+ (should (equal (pop watch-data) data))
+ (should (null watch-data))))
+ ;; Watch var0, then alias it.
+ (add-variable-watcher 'data-tests-var0 collect-watch-data)
+ (defvaralias 'data-tests-var0-alias 'data-tests-var0)
+ (setq data-tests-var0 1)
+ (should-have-watch-data '(data-tests-var0 1 set nil))
+ (setq data-tests-var0-alias 2)
+ (should-have-watch-data '(data-tests-var0 2 set nil))
+ ;; Alias var1, then watch var1-alias.
+ (defvaralias 'data-tests-var1-alias 'data-tests-var1)
+ (add-variable-watcher 'data-tests-var1-alias collect-watch-data)
+ (setq data-tests-var1 1)
+ (should-have-watch-data '(data-tests-var1 1 set nil))
+ (setq data-tests-var1-alias 2)
+ (should-have-watch-data '(data-tests-var1 2 set nil))
+ ;; Alias var2, then watch it.
+ (defvaralias 'data-tests-var2-alias 'data-tests-var2)
+ (add-variable-watcher 'data-tests-var2 collect-watch-data)
+ (setq data-tests-var2 1)
+ (should-have-watch-data '(data-tests-var2 1 set nil))
+ (setq data-tests-var2-alias 2)
+ (should-have-watch-data '(data-tests-var2 2 set nil))
+ ;; Watch var3-alias, then make it alias var3 (this removes the
+ ;; watcher flag).
+ (defvar data-tests-var3-alias 0)
+ (add-variable-watcher 'data-tests-var3-alias collect-watch-data)
+ (defvaralias 'data-tests-var3-alias 'data-tests-var3)
+ (should-have-watch-data '(data-tests-var3-alias
+ data-tests-var3 defvaralias nil))
+ (setq data-tests-var3 1)
+ (setq data-tests-var3-alias 2)
+ (should (null watch-data)))))
+
+(ert-deftest data-tests-local-variable-watchers ()
+ (defvar-local data-tests-lvar 0)
+ (let* ((buf1 (current-buffer))
+ (buf2 nil)
+ (watch-data nil)
+ (collect-watch-data
+ (lambda (&rest args) (push args watch-data))))
+ (cl-flet ((should-have-watch-data (data)
+ (should (equal (pop watch-data) data))
+ (should (null watch-data))))
+ (add-variable-watcher 'data-tests-lvar collect-watch-data)
+ (setq data-tests-lvar 1)
+ (should-have-watch-data `(data-tests-lvar 1 set ,buf1))
+ (let ((data-tests-lvar 2))
+ (should-have-watch-data `(data-tests-lvar 2 let ,buf1))
+ (setq data-tests-lvar 3)
+ (should-have-watch-data `(data-tests-lvar 3 set ,buf1)))
+ (should-have-watch-data `(data-tests-lvar 1 unlet ,buf1))
+ (setq-default data-tests-lvar 4)
+ (should-have-watch-data `(data-tests-lvar 4 set nil))
+ (with-temp-buffer
+ (setq buf2 (current-buffer))
+ (setq data-tests-lvar 1)
+ (should-have-watch-data `(data-tests-lvar 1 set ,buf2))
+ (let ((data-tests-lvar 2))
+ (should-have-watch-data `(data-tests-lvar 2 let ,buf2))
+ (setq data-tests-lvar 3)
+ (should-have-watch-data `(data-tests-lvar 3 set ,buf2)))
+ (should-have-watch-data `(data-tests-lvar 1 unlet ,buf2))
+ (kill-local-variable 'data-tests-lvar)
+ (should-have-watch-data `(data-tests-lvar nil makunbound ,buf2))
+ (setq data-tests-lvar 3.5)
+ (should-have-watch-data `(data-tests-lvar 3.5 set ,buf2))
+ (kill-all-local-variables)
+ (should-have-watch-data `(data-tests-lvar nil makunbound ,buf2)))
+ (setq-default data-tests-lvar 4)
+ (should-have-watch-data `(data-tests-lvar 4 set nil))
+ (makunbound 'data-tests-lvar)
+ (should-have-watch-data '(data-tests-lvar nil makunbound nil))
+ (setq data-tests-lvar 5)
+ (should-have-watch-data `(data-tests-lvar 5 set ,buf1))
+ (remove-variable-watcher 'data-tests-lvar collect-watch-data)
+ (setq data-tests-lvar 6)
+ (should (null watch-data)))))
diff --git a/test/src/decompress-tests.el b/test/src/decompress-tests.el
new file mode 100644
index 00000000000..f0264ec548d
--- /dev/null
+++ b/test/src/decompress-tests.el
@@ -0,0 +1,45 @@
+;;; decompress-tests.el --- Test suite for decompress.
+
+;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+;; Author: Lars Ingebrigtsen <larsi@gnus.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)
+
+(defvar zlib-tests-data-directory
+ (expand-file-name "data/decompress" (getenv "EMACS_TEST_DIRECTORY"))
+ "Directory containing zlib test data.")
+
+(ert-deftest zlib--decompress ()
+ "Test decompressing a gzipped file."
+ (when (and (fboundp 'zlib-available-p)
+ (zlib-available-p))
+ (should (string=
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally
+ (expand-file-name "foo.gz" zlib-tests-data-directory))
+ (zlib-decompress-region (point-min) (point-max))
+ (buffer-string))
+ "foo\n"))))
+
+(provide 'decompress-tests)
+
+;;; decompress-tests.el ends here.
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
new file mode 100644
index 00000000000..be490545747
--- /dev/null
+++ b/test/src/doc-tests.el
@@ -0,0 +1,92 @@
+;;; doc-tests.el --- Tests for doc.c
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Eli Zaretskii <eliz@gnu.org>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest doc-test-substitute-command-keys ()
+ ;; Bindings.
+ (should (string= (substitute-command-keys "foo \\[goto-char]") "foo M-g c"))
+ ;; Cannot use string= here, as that compares unibyte and multibyte
+ ;; strings not equal.
+ (should (compare-strings
+ (substitute-command-keys "\200 \\[goto-char]") nil nil
+ "\200 M-g c" nil nil))
+ ;; Literals.
+ (should (string= (substitute-command-keys "foo \\=\\[goto-char]")
+ "foo \\[goto-char]"))
+ (should (string= (substitute-command-keys "foo \\=\\=")
+ "foo \\="))
+ ;; Keymaps.
+ (should (string= (substitute-command-keys
+ "\\{minibuffer-local-must-match-map}")
+ "\
+key binding
+--- -------
+
+C-g abort-recursive-edit
+TAB minibuffer-complete
+C-j minibuffer-complete-and-exit
+RET minibuffer-complete-and-exit
+ESC Prefix Command
+SPC minibuffer-complete-word
+? minibuffer-completion-help
+<C-tab> file-cache-minibuffer-complete
+<XF86Back> previous-history-element
+<XF86Forward> next-history-element
+<down> next-line-or-history-element
+<next> next-history-element
+<prior> switch-to-completions
+<up> previous-line-or-history-element
+
+M-v switch-to-completions
+
+M-n next-history-element
+M-p previous-history-element
+M-r previous-matching-history-element
+M-s next-matching-history-element
+
+"))
+ (should (string=
+ (substitute-command-keys
+ "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]")
+ "C-g"))
+ ;; Allow any style of quotes, since the terminal might not support
+ ;; UTF-8.
+ (should (string-match
+ "\nUses keymap [`‘']foobar-map['’], which is not currently defined.\n"
+ (substitute-command-keys "\\{foobar-map}")))
+ ;; Quotes.
+ (should (let ((text-quoting-style 'grave))
+ (string= (substitute-command-keys "quotes `like this'")
+ "quotes `like this'")))
+ (should (let ((text-quoting-style 'grave))
+ (string= (substitute-command-keys "quotes ‘like this’")
+ "quotes ‘like this’")))
+ (should (let ((text-quoting-style 'straight))
+ (string= (substitute-command-keys "quotes `like this'")
+ "quotes 'like this'")))
+ ;; Bugs.
+ (should (string= (substitute-command-keys "\\[foobar") "\\[foobar"))
+ (should (string= (substitute-command-keys "\\=") "\\="))
+ )
+
+(provide 'doc-tests)
+;;; doc-tests.el ends here
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
new file mode 100644
index 00000000000..2f90d1e7495
--- /dev/null
+++ b/test/src/editfns-tests.el
@@ -0,0 +1,136 @@
+;;; editfns-tests.el -- tests for editfns.c
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; 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/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest format-properties ()
+ ;; Bug #23730
+ (should (ert-equal-including-properties
+ (format (propertize "%d" 'face '(:background "red")) 1)
+ #("1" 0 1 (face (:background "red")))))
+ (should (ert-equal-including-properties
+ (format (propertize "%2d" 'face '(:background "red")) 1)
+ #(" 1" 0 2 (face (:background "red")))))
+ (should (ert-equal-including-properties
+ (format (propertize "%02d" 'face '(:background "red")) 1)
+ #("01" 0 2 (face (:background "red")))))
+ (should (ert-equal-including-properties
+ (format (concat (propertize "%2d" 'x 'X)
+ (propertize "a" 'a 'A)
+ (propertize "b" 'b 'B))
+ 1)
+ #(" 1ab" 0 2 (x X) 2 3 (a A) 3 4 (b B))))
+
+ ;; Bug #5306
+ (should (ert-equal-including-properties
+ (format "%.10s"
+ (concat "1234567890aaaa"
+ (propertize "12345678901234567890" 'xxx 25)))
+ "1234567890"))
+ (should (ert-equal-including-properties
+ (format "%.10s"
+ (concat "123456789"
+ (propertize "12345678901234567890" 'xxx 25)))
+ #("1234567891" 9 10 (xxx 25))))
+
+ ;; Bug #23859
+ (should (ert-equal-including-properties
+ (format "%4s" (propertize "hi" 'face 'bold))
+ #(" hi" 2 4 (face bold))))
+
+ ;; Bug #23897
+ (should (ert-equal-including-properties
+ (format "%s" (concat (propertize "01234" 'face 'bold) "56789"))
+ #("0123456789" 0 5 (face bold))))
+ (should (ert-equal-including-properties
+ (format "%s" (concat (propertize "01" 'face 'bold)
+ (propertize "23" 'face 'underline)
+ "45"))
+ #("012345" 0 2 (face bold) 2 4 (face underline))))
+ ;; The last property range is extended to include padding on the
+ ;; right, but the first range is not extended to the left to include
+ ;; padding on the left!
+ (should (ert-equal-including-properties
+ (format "%12s" (concat (propertize "01234" 'face 'bold) "56789"))
+ #(" 0123456789" 2 7 (face bold))))
+ (should (ert-equal-including-properties
+ (format "%-12s" (concat (propertize "01234" 'face 'bold) "56789"))
+ #("0123456789 " 0 5 (face bold))))
+ (should (ert-equal-including-properties
+ (format "%10s" (concat (propertize "01" 'face 'bold)
+ (propertize "23" 'face 'underline)
+ "45"))
+ #(" 012345" 4 6 (face bold) 6 8 (face underline))))
+ (should (ert-equal-including-properties
+ (format "%-10s" (concat (propertize "01" 'face 'bold)
+ (propertize "23" 'face 'underline)
+ "45"))
+ #("012345 " 0 2 (face bold) 2 4 (face underline))))
+ (should (ert-equal-including-properties
+ (format "%-10s" (concat (propertize "01" 'face 'bold)
+ (propertize "23" 'face 'underline)
+ (propertize "45" 'face 'italic)))
+ #("012345 " 0 2 (face bold) 2 4 (face underline) 4 10 (face italic)))))
+
+;; Tests for bug#5131.
+(defun transpose-test-reverse-word (start end)
+ "Reverse characters in a word by transposing pairs of characters."
+ (let ((begm (make-marker))
+ (endm (make-marker)))
+ (set-marker begm start)
+ (set-marker endm end)
+ (while (> endm begm)
+ (progn (transpose-regions begm (1+ begm) endm (1+ endm) t)
+ (set-marker begm (1+ begm))
+ (set-marker endm (1- endm))))))
+
+(defun transpose-test-get-byte-positions (len)
+ "Validate character position to byte position translation."
+ (let ((bytes '()))
+ (dotimes (pos len)
+ (setq bytes (add-to-list 'bytes (position-bytes (1+ pos)) t)))
+ bytes))
+
+(ert-deftest transpose-ascii-regions-test ()
+ (with-temp-buffer
+ (erase-buffer)
+ (insert "abcd")
+ (transpose-test-reverse-word 1 4)
+ (should (string= (buffer-string) "dcba"))
+ (should (equal (transpose-test-get-byte-positions 5) '(1 2 3 4 5)))))
+
+(ert-deftest transpose-nonascii-regions-test-1 ()
+ (with-temp-buffer
+ (erase-buffer)
+ (insert "÷bcd")
+ (transpose-test-reverse-word 1 4)
+ (should (string= (buffer-string) "dcb÷"))
+ (should (equal (transpose-test-get-byte-positions 5) '(1 2 3 4 6)))))
+
+(ert-deftest transpose-nonascii-regions-test-2 ()
+ (with-temp-buffer
+ (erase-buffer)
+ (insert "÷ab\"äé")
+ (transpose-test-reverse-word 1 6)
+ (should (string= (buffer-string) "éä\"ba÷"))
+ (should (equal (transpose-test-get-byte-positions 7) '(1 3 5 6 7 8 10)))))
+
+;;; editfns-tests.el ends here
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
new file mode 100644
index 00000000000..fe08506ed25
--- /dev/null
+++ b/test/src/eval-tests.el
@@ -0,0 +1,50 @@
+;;; eval-tests.el --- unit tests for src/eval.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+
+;; 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:
+
+;; Unit tests for src/eval.c.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest eval-tests--bug24673 ()
+ "Checks that Bug#24673 has been fixed."
+ ;; This should not crash.
+ (should-error (funcall '(closure)) :type 'invalid-function))
+
+(ert-deftest eval-tests--bugs-24912-and-24913 ()
+ "Checks that Emacs doesn’t accept weird argument lists.
+Bug#24912 and Bug#24913."
+ (dolist (args '((&optional) (&rest) (&optional &rest) (&rest &optional)
+ (&optional &rest a) (&optional a &rest)
+ (&rest a &optional) (&rest &optional a)
+ (&optional &optional) (&optional &optional a)
+ (&optional a &optional b)
+ (&rest &rest) (&rest &rest a)
+ (&rest a &rest b)))
+ (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function)
+ (should-error (byte-compile-check-lambda-list args))
+ (let ((byte-compile-debug t))
+ (should-error (eval `(byte-compile (lambda ,args)) t)))))
+
+;;; eval-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
new file mode 100644
index 00000000000..c533bad3cdc
--- /dev/null
+++ b/test/src/fns-tests.el
@@ -0,0 +1,247 @@
+;;; fns-tests.el --- tests for src/fns.c
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; 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 'cl-lib)
+(eval-when-compile (require 'cl))
+
+(ert-deftest fns-tests-reverse ()
+ (should-error (reverse))
+ (should-error (reverse 1))
+ (should-error (reverse (make-char-table 'foo)))
+ (should (equal [] (reverse [])))
+ (should (equal [0] (reverse [0])))
+ (should (equal [1 2 3 4] (reverse (reverse [1 2 3 4]))))
+ (should (equal '(a b c d) (reverse (reverse '(a b c d)))))
+ (should (equal "xyzzy" (reverse (reverse "xyzzy"))))
+ (should (equal "こんにちは / コンニチハ" (reverse (reverse "こんにちは / コンニチハ")))))
+
+(ert-deftest fns-tests-nreverse ()
+ (should-error (nreverse))
+ (should-error (nreverse 1))
+ (should-error (nreverse (make-char-table 'foo)))
+ (should (equal (nreverse "xyzzy") "yzzyx"))
+ (let ((A []))
+ (nreverse A)
+ (should (equal A [])))
+ (let ((A [0]))
+ (nreverse A)
+ (should (equal A [0])))
+ (let ((A [1 2 3 4]))
+ (nreverse A)
+ (should (equal A [4 3 2 1])))
+ (let ((A [1 2 3 4]))
+ (nreverse A)
+ (nreverse A)
+ (should (equal A [1 2 3 4])))
+ (let* ((A [1 2 3 4])
+ (B (nreverse (nreverse A))))
+ (should (equal A B))))
+
+(ert-deftest fns-tests-reverse-bool-vector ()
+ (let ((A (make-bool-vector 10 nil)))
+ (dotimes (i 5) (aset A i t))
+ (should (equal [nil nil nil nil nil t t t t t] (vconcat (reverse A))))
+ (should (equal A (reverse (reverse A))))))
+
+(ert-deftest fns-tests-nreverse-bool-vector ()
+ (let ((A (make-bool-vector 10 nil)))
+ (dotimes (i 5) (aset A i t))
+ (nreverse A)
+ (should (equal [nil nil nil nil nil t t t t t] (vconcat A)))
+ (should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A))))))
+
+(ert-deftest fns-tests-compare-strings ()
+ (should-error (compare-strings))
+ (should-error (compare-strings "xyzzy" "xyzzy"))
+ (should (= (compare-strings "xyzzy" 0 10 "zyxxy" 0 5) -1))
+ (should-error (compare-strings "xyzzy" 0 5 "zyxxy" -1 2))
+ (should-error (compare-strings "xyzzy" 'foo nil "zyxxy" 0 1))
+ (should-error (compare-strings "xyzzy" 0 'foo "zyxxy" 2 3))
+ (should-error (compare-strings "xyzzy" 0 2 "zyxxy" 'foo 3))
+ (should-error (compare-strings "xyzzy" nil 3 "zyxxy" 4 'foo))
+ (should (eq (compare-strings "" nil nil "" nil nil) t))
+ (should (eq (compare-strings "" 0 0 "" 0 0) t))
+ (should (eq (compare-strings "test" nil nil "test" nil nil) t))
+ (should (eq (compare-strings "test" nil nil "test" nil nil t) t))
+ (should (eq (compare-strings "test" nil nil "test" nil nil nil) t))
+ (should (eq (compare-strings "Test" nil nil "test" nil nil t) t))
+ (should (= (compare-strings "Test" nil nil "test" nil nil) -1))
+ (should (= (compare-strings "Test" nil nil "test" nil nil) -1))
+ (should (= (compare-strings "test" nil nil "Test" nil nil) 1))
+ (should (= (compare-strings "foobaz" nil nil "barbaz" nil nil) 1))
+ (should (= (compare-strings "barbaz" nil nil "foobar" nil nil) -1))
+ (should (= (compare-strings "foobaz" nil nil "farbaz" nil nil) 2))
+ (should (= (compare-strings "farbaz" nil nil "foobar" nil nil) -2))
+ (should (eq (compare-strings "abcxyz" 0 2 "abcprq" 0 2) t))
+ (should (eq (compare-strings "abcxyz" 0 -3 "abcprq" 0 -3) t))
+ (should (= (compare-strings "abcxyz" 0 6 "abcprq" 0 6) 4))
+ (should (= (compare-strings "abcprq" 0 6 "abcxyz" 0 6) -4))
+ (should (eq (compare-strings "xyzzy" -3 4 "azza" -3 3) t))
+ (should (eq (compare-strings "こんにちはコンニチハ" nil nil "こんにちはコンニチハ" nil nil) t))
+ (should (= (compare-strings "んにちはコンニチハこ" nil nil "こんにちはコンニチハ" nil nil) 1))
+ (should (= (compare-strings "こんにちはコンニチハ" nil nil "んにちはコンニチハこ" nil nil) -1)))
+
+(defun fns-tests--collate-enabled-p ()
+ "Check whether collation functions are enabled."
+ (and
+ ;; When there is no collation library, collation functions fall back
+ ;; to their lexicographic counterparts. We don't need to test then.
+ (not (ignore-errors (string-collate-equalp "" "" t)))
+ ;; We use a locale, which might not be installed. Check it.
+ (ignore-errors
+ (string-collate-equalp
+ "" "" (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))))
+
+(ert-deftest fns-tests-collate-strings ()
+ (skip-unless (fns-tests--collate-enabled-p))
+
+ (should (string-collate-equalp "xyzzy" "xyzzy"))
+ (should-not (string-collate-equalp "xyzzy" "XYZZY"))
+
+ ;; In POSIX or C locales, collation order is lexicographic.
+ (should (string-collate-lessp "XYZZY" "xyzzy" "POSIX"))
+ ;; In a language specific locale, collation order is different.
+ (should (string-collate-lessp
+ "xyzzy" "XYZZY"
+ (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))
+
+ ;; Ignore case.
+ (should (string-collate-equalp "xyzzy" "XYZZY" nil t))
+
+ ;; Locale must be valid.
+ (should-error (string-collate-equalp "xyzzy" "xyzzy" "en_DE.UTF-8")))
+
+;; There must be a check for valid codepoints. (Check not implemented yet)
+; (should-error
+; (string-collate-equalp (string ?\x00110000) (string ?\x00110000)))
+;; Invalid UTF-8 sequences shall be indicated. How to create such strings?
+
+(ert-deftest fns-tests-sort ()
+ (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
+ '(-1 2 3 4 5 5 7 8 9)))
+ (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
+ '(9 8 7 5 5 4 3 2 -1)))
+ (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (< x y)))
+ [-1 2 3 4 5 5 7 8 9]))
+ (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (> x y)))
+ [9 8 7 5 5 4 3 2 -1]))
+ (should (equal
+ (sort
+ (vector
+ '(8 . "xxx") '(9 . "aaa") '(8 . "bbb") '(9 . "zzz")
+ '(9 . "ppp") '(8 . "ttt") '(8 . "eee") '(9 . "fff"))
+ (lambda (x y) (< (car x) (car y))))
+ [(8 . "xxx") (8 . "bbb") (8 . "ttt") (8 . "eee")
+ (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")])))
+
+(ert-deftest fns-tests-collate-sort ()
+ ;; See https://lists.gnu.org/archive/html/emacs-devel/2015-10/msg02505.html.
+ :expected-result (if (eq system-type 'cygwin) :failed :passed)
+ (skip-unless (fns-tests--collate-enabled-p))
+
+ ;; Punctuation and whitespace characters are relevant for POSIX.
+ (should
+ (equal
+ (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+ (lambda (a b) (string-collate-lessp a b "POSIX")))
+ '("1 1" "1 2" "1.1" "1.2" "11" "12")))
+ ;; Punctuation and whitespace characters are not taken into account
+ ;; for collation in other locales.
+ (should
+ (equal
+ (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+ (lambda (a b)
+ (let ((w32-collate-ignore-punctuation t))
+ (string-collate-lessp
+ a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))))
+ '("11" "1 1" "1.1" "12" "1 2" "1.2")))
+
+ ;; Diacritics are different letters for POSIX, they sort lexicographical.
+ (should
+ (equal
+ (sort '("Ævar" "Agustín" "Adrian" "Eli")
+ (lambda (a b) (string-collate-lessp a b "POSIX")))
+ '("Adrian" "Agustín" "Eli" "Ævar")))
+ ;; Diacritics are sorted between similar letters for other locales.
+ (should
+ (equal
+ (sort '("Ævar" "Agustín" "Adrian" "Eli")
+ (lambda (a b)
+ (let ((w32-collate-ignore-punctuation t))
+ (string-collate-lessp
+ a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))))
+ '("Adrian" "Ævar" "Agustín" "Eli"))))
+
+(ert-deftest fns-tests-string-version-lessp ()
+ (should (string-version-lessp "foo2.png" "foo12.png"))
+ (should (not (string-version-lessp "foo12.png" "foo2.png")))
+ (should (string-version-lessp "foo12.png" "foo20000.png"))
+ (should (not (string-version-lessp "foo20000.png" "foo12.png")))
+ (should (string-version-lessp "foo.png" "foo2.png"))
+ (should (not (string-version-lessp "foo2.png" "foo.png")))
+ (should (equal (sort '("foo12.png" "foo2.png" "foo1.png")
+ 'string-version-lessp)
+ '("foo1.png" "foo2.png" "foo12.png")))
+ (should (string-version-lessp "foo2" "foo1234"))
+ (should (not (string-version-lessp "foo1234" "foo2")))
+ (should (string-version-lessp "foo.png" "foo2"))
+ (should (string-version-lessp "foo1.25.5.png" "foo1.125.5"))
+ (should (string-version-lessp "2" "1245"))
+ (should (not (string-version-lessp "1245" "2"))))
+
+(ert-deftest fns-tests-func-arity ()
+ (should (equal (func-arity 'car) '(1 . 1)))
+ (should (equal (func-arity 'caar) '(1 . 1)))
+ (should (equal (func-arity 'format) '(1 . many)))
+ (require 'info)
+ (should (equal (func-arity 'Info-goto-node) '(1 . 3)))
+ (should (equal (func-arity (lambda (&rest x))) '(0 . many)))
+ (should (equal (func-arity (eval (lambda (x &optional y)) nil)) '(1 . 2)))
+ (should (equal (func-arity (eval (lambda (x &optional y)) t)) '(1 . 2)))
+ (should (equal (func-arity 'let) '(1 . unevalled))))
+
+(ert-deftest fns-tests-hash-buffer ()
+ (should (equal (sha1 "foo") "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"))
+ (should (equal (with-temp-buffer
+ (insert "foo")
+ (buffer-hash))
+ (sha1 "foo")))
+ ;; This tests whether the presence of a gap in the middle of the
+ ;; buffer is handled correctly.
+ (should (equal (with-temp-buffer
+ (insert "foo")
+ (goto-char 2)
+ (insert " ")
+ (backward-delete-char 1)
+ (buffer-hash))
+ (sha1 "foo"))))
+
+(ert-deftest fns-tests-mapcan ()
+ (should-error (mapcan))
+ (should-error (mapcan #'identity))
+ (should-error (mapcan #'identity (make-char-table 'foo)))
+ (should (equal (mapcan #'list '(1 2 3)) '(1 2 3)))
+ ;; `mapcan' is destructive
+ (let ((data '((foo) (bar))))
+ (should (equal (mapcan #'identity data) '(foo bar)))
+ (should (equal data '((foo bar) (bar))))))
diff --git a/test/src/font-tests.el b/test/src/font-tests.el
new file mode 100644
index 00000000000..f0f0d31efc7
--- /dev/null
+++ b/test/src/font-tests.el
@@ -0,0 +1,167 @@
+;;; font-tests.el --- Test suite for font-related functions.
+
+;; Copyright (C) 2011-2016 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)
+ ("Monospace Serif" ,(intern "Monospace Serif") 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:
+
+(provide 'font-tests)
+;;; font-tests.el ends here.
diff --git a/test/src/inotify-tests.el b/test/src/inotify-tests.el
new file mode 100644
index 00000000000..54977925f86
--- /dev/null
+++ b/test/src/inotify-tests.el
@@ -0,0 +1,64 @@
+;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+;; 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/>.
+
+;;; Code:
+
+(require 'ert)
+
+(declare-function inotify-add-watch "inotify.c" (file-name aspect callback))
+(declare-function inotify-rm-watch "inotify.c" (watch-descriptor))
+
+;; (ert-deftest filewatch-file-watch-aspects-check ()
+;; "Test whether `file-watch' properly checks the aspects."
+;; (let ((temp-file (make-temp-file "filewatch-aspects")))
+;; (should (stringp temp-file))
+;; (should-error (file-watch temp-file 'wrong nil)
+;; :type 'error)
+;; (should-error (file-watch temp-file '(modify t) nil)
+;; :type 'error)
+;; (should-error (file-watch temp-file '(modify all-modify) nil)
+;; :type 'error)
+;; (should-error (file-watch temp-file '(access wrong modify) nil)
+;; :type 'error)))
+
+(ert-deftest inotify-file-watch-simple ()
+ "Test if watching a normal file works."
+
+ (skip-unless (featurep 'inotify))
+ (let ((temp-file (make-temp-file "inotify-simple"))
+ (events 0))
+ (let ((wd
+ (inotify-add-watch temp-file t (lambda (_ev)
+ (setq events (1+ events))))))
+ (unwind-protect
+ (progn
+ (with-temp-file temp-file
+ (insert "Foo\n"))
+ (read-event nil nil 5)
+ (should (> events 0)))
+ (inotify-rm-watch wd)
+ (delete-file temp-file)))))
+
+(provide 'inotify-tests)
+
+;;; inotify-tests.el ends here.
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
new file mode 100644
index 00000000000..26d34858703
--- /dev/null
+++ b/test/src/keymap-tests.el
@@ -0,0 +1,50 @@
+;;; keymap-tests.el --- Test suite for src/keymap.c
+
+;; Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+;; Author: Juanma Barranquero <lekktu@gmail.com>
+
+;; 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 keymap-store_in_keymap-XFASTINT-on-non-characters ()
+ "Check for bug fixed in \"Fix assertion violation in define-key\",
+commit 86c19714b097aa477d339ed99ffb5136c755a046."
+ (let ((def (lookup-key Buffer-menu-mode-map [32])))
+ (unwind-protect
+ (progn
+ (should-not (eq def 'undefined))
+ ;; This will cause an assertion violation if the bug is present.
+ ;; We could run an inferior Emacs process and check for the return
+ ;; status, but in some environments an assertion failure triggers
+ ;; an abort dialog that requires user intervention anyway.
+ (define-key Buffer-menu-mode-map [(32 . 32)] 'undefined)
+ (should (eq (lookup-key Buffer-menu-mode-map [32]) 'undefined)))
+ (define-key Buffer-menu-mode-map [32] def))))
+
+(ert-deftest keymap-where-is-internal-test ()
+ "Make sure we don't crash when `where-is-preferred-modifier' is not a symbol."
+ (should
+ (equal (let ((where-is-preferred-modifier "alt"))
+ (where-is-internal 'execute-extended-command global-map t))
+ [#x8000078])))
+
+(provide 'keymap-tests)
+
+;;; keymap-tests.el ends here
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
new file mode 100644
index 00000000000..609f82ec20b
--- /dev/null
+++ b/test/src/lread-tests.el
@@ -0,0 +1,115 @@
+;;; lread-tests.el --- tests for lread.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+
+;; This file is part of GNU Emacs.
+
+;; 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:
+
+;; Unit tests for code in src/lread.c.
+
+;;; Code:
+
+(ert-deftest lread-char-number ()
+ (should (equal (read "?\\N{U+A817}") #xA817)))
+
+(ert-deftest lread-char-name-1 ()
+ (should (equal (read "?\\N{SYLOTI NAGRI LETTER \n DHO}")
+ #xA817)))
+(ert-deftest lread-char-name-2 ()
+ (should (equal (read "?\\N{BED}") #x1F6CF)))
+(ert-deftest lread-char-name-3 ()
+ (should (equal (read "?\\N{U+BED}") #xBED)))
+(ert-deftest lread-char-name-4 ()
+ (should (equal (read "?\\N{VARIATION SELECTOR-1}") #xFE00)))
+(ert-deftest lread-char-name-5 ()
+ (should (equal (read "?\\N{VARIATION SELECTOR-16}") #xFE0F)))
+(ert-deftest lread-char-name-6 ()
+ (should (equal (read "?\\N{VARIATION SELECTOR-17}") #xE0100)))
+(ert-deftest lread-char-name-7 ()
+ (should (equal (read "?\\N{VARIATION SELECTOR-256}") #xE01EF)))
+(ert-deftest lread-char-name-8 ()
+ (should (equal (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-F900}") #xF900)))
+(ert-deftest lread-char-name-9 ()
+ (should (equal (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-FAD9}") #xFAD9)))
+(ert-deftest lread-char-name-10 ()
+ (should (equal (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-2F800}") #x2F800)))
+(ert-deftest lread-char-name-11 ()
+ (should (equal (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-2FA1D}") #x2FA1D)))
+
+(ert-deftest lread-char-invalid-number ()
+ (should-error (read "?\\N{U+110000}") :type 'invalid-read-syntax))
+
+(ert-deftest lread-char-invalid-name-1 ()
+ (should-error (read "?\\N{DOES NOT EXIST}")) :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-2 ()
+ (should-error (read "?\\N{VARIATION SELECTOR-0}")) :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-3 ()
+ (should-error (read "?\\N{VARIATION SELECTOR-257}"))
+ :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-4 ()
+ (should-error (read "?\\N{VARIATION SELECTOR--0}"))
+ :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-5 ()
+ (should-error (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-F8FF}"))
+ :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-6 ()
+ (should-error (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-FADA}"))
+ :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-7 ()
+ (should-error (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-2F7FF}"))
+ :type 'invalid-read-syntax)
+(ert-deftest lread-char-invalid-name-8 ()
+ (should-error (read "?\\N{CJK COMPATIBILITY IDEOGRAPH-2FA1E}"))
+ :type 'invalid-read-syntax)
+
+(ert-deftest lread-char-non-ascii-name ()
+ (should-error (read "?\\N{LATIN CAPITAL LETTER Ø}")
+ :type 'invalid-read-syntax))
+
+(ert-deftest lread-char-empty-name ()
+ (should-error (read "?\\N{}") :type 'invalid-read-syntax))
+
+(ert-deftest lread-char-surrogate-1 ()
+ (should-error (read "?\\N{U+D800}") :type 'invalid-read-syntax))
+(ert-deftest lread-char-surrogate-2 ()
+ (should-error (read "?\\N{U+D801}") :type 'invalid-read-syntax))
+(ert-deftest lread-char-surrogate-3 ()
+ (should-error (read "?\\N{U+Dffe}") :type 'invalid-read-syntax))
+(ert-deftest lread-char-surrogate-4 ()
+ (should-error (read "?\\N{U+DFFF}") :type 'invalid-read-syntax))
+
+(ert-deftest lread-string-char-number-1 ()
+ (should (equal (read "\"a\\N{U+A817}b\"") "a\uA817b")))
+(ert-deftest lread-string-char-number-2 ()
+ (should-error (read "?\\N{0.5}") :type 'invalid-read-syntax))
+(ert-deftest lread-string-char-number-3 ()
+ (should-error (read "?\\N{U+-0}") :type 'invalid-read-syntax))
+
+(ert-deftest lread-string-char-name ()
+ (should (equal (read "\"a\\N{SYLOTI NAGRI LETTER DHO}b\"") "a\uA817b")))
+
+(ert-deftest lread-empty-int-literal ()
+ "Check that Bug#25120 is fixed."
+ (should-error (read "#b") :type 'invalid-read-syntax)
+ (should-error (read "#o") :type 'invalid-read-syntax)
+ (should-error (read "#x") :type 'invalid-read-syntax)
+ (should-error (read "#24r") :type 'invalid-read-syntax)
+ (should-error (read "#") :type 'invalid-read-syntax))
+
+;;; lread-tests.el ends here
diff --git a/test/src/marker-tests.el b/test/src/marker-tests.el
new file mode 100644
index 00000000000..18d49addb2f
--- /dev/null
+++ b/test/src/marker-tests.el
@@ -0,0 +1,60 @@
+;;; marker-tests.el --- tests for marker.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016 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)
+
+;; The following three tests assert that Emacs survives operations
+;; copying a marker whose character position differs from its byte
+;; position into a buffer whose character size equals its byte size
+;; (Bug#24368).
+
+(ert-deftest marker-set-window-start-from-other-buffer ()
+ "`set-window-start' from other buffer's marker."
+ (let ((text-quoting-style 'curve))
+ (describe-function 'describe-function))
+ (let* ((help (get-buffer "*Help*"))
+ (marker (with-current-buffer help
+ (copy-marker (point-max)))))
+ (should (set-window-start (selected-window) marker))))
+
+(ert-deftest marker-set-window-point-from-other-buffer ()
+ "`set-window-point' from another buffer's marker."
+ (let ((text-quoting-style 'curve))
+ (describe-function 'describe-function))
+ (let* ((help (get-buffer "*Help*"))
+ (marker (with-current-buffer help
+ (copy-marker (point-max)))))
+ (with-selected-window (get-buffer-window help)
+ (should (set-window-point (get-buffer-window "*scratch*") marker)))))
+
+(ert-deftest marker-goto-char-from-other-buffer ()
+ "`goto-char' from another buffer's marker."
+ (let ((text-quoting-style 'curve))
+ (describe-function 'describe-function))
+ (let ((marker-1 (make-marker))
+ (marker-2 (make-marker)))
+ (describe-function 'describe-function)
+ (with-current-buffer "*Help*"
+ (set-marker marker-1 (point-max)))
+ (set-marker marker-2 marker-1)
+ (should (goto-char marker-2))))
+
+;;; marker-tests.el ends here.
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
new file mode 100644
index 00000000000..82ac0373cb4
--- /dev/null
+++ b/test/src/minibuf-tests.el
@@ -0,0 +1,403 @@
+;;; minibuf-tests.el --- tests for minibuf.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016 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)
+
+
+;;; Support functions for `try-completion', `all-completion', and
+;;; `test-completion' tests.
+
+(defun minibuf-tests--strings-to-symbol-list (list)
+ (mapcar #'intern list))
+(defun minibuf-tests--strings-to-symbol-alist (list)
+ (let ((num 0))
+ (mapcar (lambda (str) (cons (intern str) (cl-incf num))) list)))
+(defun minibuf-tests--strings-to-string-alist (list)
+ (let ((num 0))
+ (mapcar (lambda (str) (cons str (cl-incf num))) list)))
+(defun minibuf-tests--strings-to-obarray (list)
+ (let ((ob (make-vector 7 0)))
+ (mapc (lambda (str) (intern str ob)) list)
+ ob))
+(defun minibuf-tests--strings-to-string-hashtable (list)
+ (let ((ht (make-hash-table :test #'equal))
+ (num 0))
+ (mapc (lambda (str) (puthash str (cl-incf num) ht)) list)
+ ht))
+(defun minibuf-tests--strings-to-symbol-hashtable (list)
+ (let ((ht (make-hash-table :test #'equal))
+ (num 0))
+ (mapc (lambda (str) (puthash (intern str) (cl-incf num) ht)) list)
+ ht))
+
+;;; Functions that produce a predicate (for *-completion functions)
+;;; which always returns non-nil for a given collection.
+
+(defun minibuf-tests--memq-of-collection (collection)
+ (lambda (elt) (memq elt collection)))
+(defun minibuf-tests--part-of-obarray (ob)
+ (lambda (sym) (eq (intern-soft (symbol-name sym) ob) sym)))
+(defun minibuf-tests--part-of-hashtable (table)
+ (lambda (k v) (equal (gethash k table) v)))
+
+
+;;; Testing functions that are agnostic to type of COLLECTION.
+
+(defun minibuf-tests--try-completion (xform-collection)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (should (equal (try-completion "a" abcdef) "abc"))
+ (should (equal (try-completion "a" +abba) "ab"))
+ (should (equal (try-completion "abc" +abba) t))
+ (should (equal (try-completion "abcd" +abba) nil))))
+
+(defun minibuf-tests--try-completion-pred (xform-collection collection-member)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (abcdef-member (funcall collection-member abcdef))
+ (+abba (funcall xform-collection '("abc" "abba" "def")))
+ (+abba-member (funcall collection-member +abba)))
+ (should (equal (try-completion "a" abcdef abcdef-member) "abc"))
+ (should (equal (try-completion "a" +abba +abba-member) "ab"))
+ (should (equal (try-completion "abc" +abba +abba-member) t))
+ (should (equal (try-completion "abcd" +abba +abba-member) nil))
+ (should-not (try-completion "a" abcdef #'ignore))
+ (should-not (try-completion "a" +abba #'ignore))
+ (should-not (try-completion "abc" +abba #'ignore))
+ (should-not (try-completion "abcd" +abba #'ignore))))
+
+(defun minibuf-tests--try-completion-regexp (xform-collection)
+ (let ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (let ((completion-regexp-list '(".")))
+ (should (equal (try-completion "a" abcdef) "abc"))
+ (should (equal (try-completion "a" +abba) "ab"))
+ (should (equal (try-completion "abc" +abba) t))
+ (should (equal (try-completion "abcd" +abba) nil)))
+ (let ((completion-regexp-list '("X")))
+ (should-not (try-completion "a" abcdef))
+ (should-not (try-completion "a" +abba))
+ (should-not (try-completion "abc" +abba))
+ (should-not (try-completion "abcd" +abba)))))
+
+(defun minibuf-tests--all-completions (xform-collection)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (should (equal (all-completions "a" abcdef) '("abc")))
+ (should (equal (all-completions "a" +abba) '("abc" "abba")))
+ (should (equal (all-completions "abc" +abba) '("abc")))
+ (should (equal (all-completions "abcd" +abba) nil))))
+
+(defun minibuf-tests--all-completions-pred (xform-collection collection-member)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (abcdef-member (funcall collection-member abcdef))
+ (+abba (funcall xform-collection '("abc" "abba" "def")))
+ (+abba-member (funcall collection-member +abba)))
+ (should (equal (all-completions "a" abcdef abcdef-member) '("abc")))
+ (should (equal (all-completions "a" +abba +abba-member) '("abc" "abba")))
+ (should (equal (all-completions "abc" +abba +abba-member) '("abc")))
+ (should (equal (all-completions "abcd" +abba +abba-member) nil))
+ (should-not (all-completions "a" abcdef #'ignore))
+ (should-not (all-completions "a" +abba #'ignore))
+ (should-not (all-completions "abc" +abba #'ignore))
+ (should-not (all-completions "abcd" +abba #'ignore))))
+
+(defun minibuf-tests--all-completions-regexp (xform-collection)
+ (let ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (let ((completion-regexp-list '(".")))
+ (should (equal (all-completions "a" abcdef) '("abc")))
+ (should (equal (all-completions "a" +abba) '("abc" "abba")))
+ (should (equal (all-completions "abc" +abba) '("abc")))
+ (should (equal (all-completions "abcd" +abba) nil)))
+ (let ((completion-regexp-list '("X")))
+ (should-not (all-completions "a" abcdef))
+ (should-not (all-completions "a" +abba))
+ (should-not (all-completions "abc" +abba))
+ (should-not (all-completions "abcd" +abba)))))
+
+(defun minibuf-tests--test-completion (xform-collection)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (should (test-completion "abc" abcdef))
+ (should (test-completion "def" +abba))
+ (should (test-completion "abba" +abba))
+ (should-not (test-completion "abcd" +abba))))
+
+(defun minibuf-tests--test-completion-pred (xform-collection collection-member)
+ (let* ((abcdef (funcall xform-collection '("abc" "def")))
+ (abcdef-member (funcall collection-member abcdef))
+ (+abba (funcall xform-collection '("abc" "abba" "def")))
+ (+abba-member (funcall collection-member +abba)))
+ (should (test-completion "abc" abcdef abcdef-member))
+ (should (test-completion "def" +abba +abba-member))
+ (should (test-completion "abba" +abba +abba-member))
+ (should-not (test-completion "abcd" +abba +abba-member))
+ (should-not (test-completion "abc" abcdef #'ignore))
+ (should-not (test-completion "def" +abba #'ignore))
+ (should-not (test-completion "abba" +abba #'ignore))
+ (should-not (test-completion "abcd" +abba #'ignore))))
+
+(defun minibuf-tests--test-completion-regexp (xform-collection)
+ (let ((abcdef (funcall xform-collection '("abc" "def")))
+ (+abba (funcall xform-collection '("abc" "abba" "def"))))
+ (let ((completion-regexp-list '(".")))
+ (should (test-completion "abc" abcdef))
+ (should (test-completion "def" +abba))
+ (should (test-completion "abba" +abba))
+ (should-not (test-completion "abcd" +abba)))
+ (let ((completion-regexp-list '("X")))
+ (should-not (test-completion "abc" abcdef))
+ (should-not (test-completion "def" +abba))
+ (should-not (test-completion "abba" +abba))
+ (should-not (test-completion "abcd" +abba)))))
+
+
+;;; Tests for `try-completion'.
+(ert-deftest try-completion-string-list ()
+ (minibuf-tests--try-completion #'identity))
+(ert-deftest try-completion-string-list-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'identity #'minibuf-tests--memq-of-collection))
+(ert-deftest try-completion-string-list-completion-regexp ()
+ (minibuf-tests--try-completion-regexp #'identity))
+
+(ert-deftest try-completion-symbol-list ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-symbol-list))
+(ert-deftest try-completion-symbol-list-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-symbol-list
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest try-completion-symbol-list-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-symbol-list))
+
+(ert-deftest try-completion-symbol-alist ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-symbol-alist))
+(ert-deftest try-completion-symbol-alist-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-symbol-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest try-completion-symbol-alist-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-symbol-alist))
+
+(ert-deftest try-completion-string-alist ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-string-alist))
+(ert-deftest try-completion-string-alist-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-string-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest try-completion-string-alist-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-string-alist))
+
+(ert-deftest try-completion-obarray ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-obarray))
+(ert-deftest try-completion-obarray-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-obarray
+ #'minibuf-tests--part-of-obarray))
+(ert-deftest try-completion-obarray-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-obarray))
+
+(ert-deftest try-completion-string-hashtable ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-string-hashtable))
+(ert-deftest try-completion-string-hashtable-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-string-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest try-completion-string-hashtable-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-string-hashtable))
+
+(ert-deftest try-completion-symbol-hashtable ()
+ (minibuf-tests--try-completion
+ #'minibuf-tests--strings-to-symbol-hashtable))
+(ert-deftest try-completion-symbol-hashtable-predicate ()
+ (minibuf-tests--try-completion-pred
+ #'minibuf-tests--strings-to-symbol-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest try-completion-symbol-hashtable-completion-regexp ()
+ (minibuf-tests--try-completion-regexp
+ #'minibuf-tests--strings-to-symbol-hashtable))
+
+
+;;; Tests for `all-completions'.
+
+(ert-deftest all-completions-string-list ()
+ (minibuf-tests--all-completions #'identity))
+(ert-deftest all-completions-string-list-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'identity #'minibuf-tests--memq-of-collection))
+(ert-deftest all-completions-string-list-completion-regexp ()
+ (minibuf-tests--all-completions-regexp #'identity))
+
+(ert-deftest all-completions-symbol-list ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-symbol-list))
+(ert-deftest all-completions-symbol-list-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-symbol-list
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest all-completions-symbol-list-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-symbol-list))
+
+(ert-deftest all-completions-symbol-alist ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-symbol-alist))
+(ert-deftest all-completions-symbol-alist-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-symbol-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest all-completions-symbol-alist-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-symbol-alist))
+
+(ert-deftest all-completions-string-alist ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-string-alist))
+(ert-deftest all-completions-string-alist-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-string-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest all-completions-string-alist-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-string-alist))
+
+(ert-deftest all-completions-obarray ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-obarray))
+(ert-deftest all-completions-obarray-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-obarray
+ #'minibuf-tests--part-of-obarray))
+(ert-deftest all-completions-obarray-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-obarray))
+
+(ert-deftest all-completions-string-hashtable ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-string-hashtable))
+(ert-deftest all-completions-string-hashtable-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-string-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest all-completions-string-hashtable-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-string-hashtable))
+
+(ert-deftest all-completions-symbol-hashtable ()
+ (minibuf-tests--all-completions
+ #'minibuf-tests--strings-to-symbol-hashtable))
+(ert-deftest all-completions-symbol-hashtable-predicate ()
+ (minibuf-tests--all-completions-pred
+ #'minibuf-tests--strings-to-symbol-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest all-completions-symbol-hashtable-completion-regexp ()
+ (minibuf-tests--all-completions-regexp
+ #'minibuf-tests--strings-to-symbol-hashtable))
+
+
+;;; Tests for `test-completion'.
+
+(ert-deftest test-completion-string-list ()
+ (minibuf-tests--test-completion #'identity))
+(ert-deftest test-completion-string-list-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'identity #'minibuf-tests--memq-of-collection))
+(ert-deftest test-completion-string-list-completion-regexp ()
+ (minibuf-tests--test-completion-regexp #'identity))
+
+(ert-deftest test-completion-symbol-list ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-symbol-list))
+(ert-deftest test-completion-symbol-list-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-symbol-list
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest test-completion-symbol-list-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-symbol-list))
+
+(ert-deftest test-completion-symbol-alist ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-symbol-alist))
+(ert-deftest test-completion-symbol-alist-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-symbol-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest test-completion-symbol-alist-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-symbol-alist))
+
+(ert-deftest test-completion-string-alist ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-string-alist))
+(ert-deftest test-completion-string-alist-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-string-alist
+ #'minibuf-tests--memq-of-collection))
+(ert-deftest test-completion-string-alist-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-string-alist))
+
+(ert-deftest test-completion-obarray ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-obarray))
+(ert-deftest test-completion-obarray-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-obarray
+ #'minibuf-tests--part-of-obarray))
+(ert-deftest test-completion-obarray-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-obarray))
+
+(ert-deftest test-completion-string-hashtable ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-string-hashtable))
+(ert-deftest test-completion-string-hashtable-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-string-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest test-completion-string-hashtable-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-string-hashtable))
+
+(ert-deftest test-completion-symbol-hashtable ()
+ (minibuf-tests--test-completion
+ #'minibuf-tests--strings-to-symbol-hashtable))
+(ert-deftest test-completion-symbol-hashtable-predicate ()
+ (minibuf-tests--test-completion-pred
+ #'minibuf-tests--strings-to-symbol-hashtable
+ #'minibuf-tests--part-of-hashtable))
+(ert-deftest test-completion-symbol-hashtable-completion-regexp ()
+ (minibuf-tests--test-completion-regexp
+ #'minibuf-tests--strings-to-symbol-hashtable))
+
+
+;;; minibuf-tests.el ends here
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
new file mode 100644
index 00000000000..1abfa53581c
--- /dev/null
+++ b/test/src/print-tests.el
@@ -0,0 +1,62 @@
+;;; print-tests.el --- tests for src/print.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; 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/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest print-hex-backslash ()
+ (should (string= (let ((print-escape-multibyte t)
+ (print-escape-newlines t))
+ (prin1-to-string "\u00A2\ff"))
+ "\"\\x00a2\\ff\"")))
+
+(ert-deftest terpri ()
+ (should (string= (with-output-to-string
+ (princ 'abc)
+ (should (terpri nil t)))
+ "abc\n"))
+ (should (string= (with-output-to-string
+ (should-not (terpri nil t))
+ (princ 'xyz))
+ "xyz"))
+ (message nil)
+ (if noninteractive
+ (progn (should (terpri nil t))
+ (should-not (terpri nil t))
+ (princ 'abc)
+ (should (terpri nil t))
+ (should-not (terpri nil t)))
+ (should (string= (progn (should-not (terpri nil t))
+ (princ 'abc)
+ (should (terpri nil t))
+ (current-message))
+ "abc\n")))
+ (let ((standard-output
+ (with-current-buffer (get-buffer-create "*terpri-test*")
+ (insert "--------")
+ (point-max-marker))))
+ (should (terpri nil t))
+ (should-not (terpri nil t))
+ (should (string= (with-current-buffer (marker-buffer standard-output)
+ (buffer-string))
+ "--------\n"))))
+
+(provide 'print-tests)
+;;; print-tests.el ends here
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
new file mode 100644
index 00000000000..8cc59bf9feb
--- /dev/null
+++ b/test/src/process-tests.el
@@ -0,0 +1,166 @@
+;;; process-tests.el --- Testing the process facilities
+
+;; Copyright (C) 2013-2016 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)
+;; process-tests.el ends here.
diff --git a/test/src/regex-resources/BOOST.tests b/test/src/regex-resources/BOOST.tests
new file mode 100644
index 00000000000..98fd3b6abf3
--- /dev/null
+++ b/test/src/regex-resources/BOOST.tests
@@ -0,0 +1,829 @@
+;
+;
+; this file contains a script of tests to run through regress.exe
+;
+; comments start with a semicolon and proceed to the end of the line
+;
+; changes to regular expression compile flags start with a "-" as the first
+; non-whitespace character and consist of a list of the printable names
+; of the flags, for example "match_default"
+;
+; Other lines contain a test to perform using the current flag status
+; the first token contains the expression to compile, the second the string
+; to match it against. If the second string is "!" then the expression should
+; not compile, that is the first string is an invalid regular expression.
+; This is then followed by a list of integers that specify what should match,
+; each pair represents the starting and ending positions of a subexpression
+; starting with the zeroth subexpression (the whole match).
+; A value of -1 indicates that the subexpression should not take part in the
+; match at all, if the first value is -1 then no part of the expression should
+; match the string.
+;
+; Tests taken from BOOST testsuite and adapted to glibc regex.
+;
+; Boost Software License - Version 1.0 - August 17th, 2003
+;
+; Permission is hereby granted, free of charge, to any person or organization
+; obtaining a copy of the software and accompanying documentation covered by
+; this license (the "Software") to use, reproduce, display, distribute,
+; execute, and transmit the Software, and to prepare derivative works of the
+; Software, and to permit third-parties to whom the Software is furnished to
+; do so, all subject to the following:
+;
+; The copyright notices in the Software and this entire statement, including
+; the above license grant, this restriction and the following disclaimer,
+; must be included in all copies of the Software, in whole or in part, and
+; all derivative works of the Software, unless such copies or derivative
+; works are solely in the form of machine-executable object code generated by
+; a source language processor.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+; FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+; SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+; FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+; DEALINGS IN THE SOFTWARE.
+;
+
+- match_default normal REG_EXTENDED
+
+;
+; try some really simple literals:
+a a 0 1
+Z Z 0 1
+Z aaa -1 -1
+Z xxxxZZxxx 4 5
+
+; and some simple brackets:
+(a) zzzaazz 3 4 3 4
+() zzz 0 0 0 0
+() "" 0 0 0 0
+( !
+) ) 0 1
+(aa !
+aa) baa)b 1 4
+a b -1 -1
+\(\) () 0 2
+\(a\) (a) 0 3
+\() () 0 2
+(\) !
+p(a)rameter ABCparameterXYZ 3 12 4 5
+[pq](a)rameter ABCparameterXYZ 3 12 4 5
+
+; now try escaped brackets:
+- match_default bk_parens REG_BASIC
+\(a\) zzzaazz 3 4 3 4
+\(\) zzz 0 0 0 0
+\(\) "" 0 0 0 0
+\( !
+\) !
+\(aa !
+aa\) !
+() () 0 2
+(a) (a) 0 3
+(\) !
+\() !
+
+; now move on to "." wildcards
+- match_default normal REG_EXTENDED REG_STARTEND
+. a 0 1
+. \n 0 1
+. \r 0 1
+. \0 0 1
+
+;
+; now move on to the repetion ops,
+; starting with operator *
+- match_default normal REG_EXTENDED
+a* b 0 0
+ab* a 0 1
+ab* ab 0 2
+ab* sssabbbbbbsss 3 10
+ab*c* a 0 1
+ab*c* abbb 0 4
+ab*c* accc 0 4
+ab*c* abbcc 0 5
+*a !
+\<* !
+\>* !
+\n* \n\n 0 2
+\** ** 0 2
+\* * 0 1
+
+; now try operator +
+ab+ a -1 -1
+ab+ ab 0 2
+ab+ sssabbbbbbsss 3 10
+ab+c+ a -1 -1
+ab+c+ abbb -1 -1
+ab+c+ accc -1 -1
+ab+c+ abbcc 0 5
++a !
+\<+ !
+\>+ !
+\n+ \n\n 0 2
+\+ + 0 1
+\+ ++ 0 1
+\++ ++ 0 2
+
+; now try operator ?
+- match_default normal REG_EXTENDED
+a? b 0 0
+ab? a 0 1
+ab? ab 0 2
+ab? sssabbbbbbsss 3 5
+ab?c? a 0 1
+ab?c? abbb 0 2
+ab?c? accc 0 2
+ab?c? abcc 0 3
+?a !
+\<? !
+\>? !
+\n? \n\n 0 1
+\? ? 0 1
+\? ?? 0 1
+\?? ?? 0 1
+
+; now try operator {}
+- match_default normal REG_EXTENDED
+a{2} a -1 -1
+a{2} aa 0 2
+a{2} aaa 0 2
+a{2,} a -1 -1
+a{2,} aa 0 2
+a{2,} aaaaa 0 5
+a{2,4} a -1 -1
+a{2,4} aa 0 2
+a{2,4} aaa 0 3
+a{2,4} aaaa 0 4
+a{2,4} aaaaa 0 4
+a{} !
+a{2 !
+a} a} 0 2
+\{\} {} 0 2
+
+- match_default normal REG_BASIC
+a\{2\} a -1 -1
+a\{2\} aa 0 2
+a\{2\} aaa 0 2
+a\{2,\} a -1 -1
+a\{2,\} aa 0 2
+a\{2,\} aaaaa 0 5
+a\{2,4\} a -1 -1
+a\{2,4\} aa 0 2
+a\{2,4\} aaa 0 3
+a\{2,4\} aaaa 0 4
+a\{2,4\} aaaaa 0 4
+{} {} 0 2
+
+; now test the alternation operator |
+- match_default normal REG_EXTENDED
+a|b a 0 1
+a|b b 0 1
+a(b|c) ab 0 2 1 2
+a(b|c) ac 0 2 1 2
+a(b|c) ad -1 -1 -1 -1
+a\| a| 0 2
+
+; now test the set operator []
+- match_default normal REG_EXTENDED
+; try some literals first
+[abc] a 0 1
+[abc] b 0 1
+[abc] c 0 1
+[abc] d -1 -1
+[^bcd] a 0 1
+[^bcd] b -1 -1
+[^bcd] d -1 -1
+[^bcd] e 0 1
+a[b]c abc 0 3
+a[ab]c abc 0 3
+a[^ab]c adc 0 3
+a[]b]c a]c 0 3
+a[[b]c a[c 0 3
+a[-b]c a-c 0 3
+a[^]b]c adc 0 3
+a[^-b]c adc 0 3
+a[b-]c a-c 0 3
+a[b !
+a[] !
+
+; then some ranges
+[b-e] a -1 -1
+[b-e] b 0 1
+[b-e] e 0 1
+[b-e] f -1 -1
+[^b-e] a 0 1
+[^b-e] b -1 -1
+[^b-e] e -1 -1
+[^b-e] f 0 1
+a[1-3]c a2c 0 3
+a[3-1]c !
+a[1-3-5]c !
+a[1- !
+
+; and some classes
+a[[:alpha:]]c abc 0 3
+a[[:unknown:]]c !
+a[[: !
+a[[:alpha !
+a[[:alpha:] !
+a[[:alpha,:] !
+a[[:]:]]b !
+a[[:-:]]b !
+a[[:alph:]] !
+a[[:alphabet:]] !
+[[:alnum:]]+ -%@a0X_- 3 6
+[[:alpha:]]+ -%@aX_0- 3 5
+[[:blank:]]+ "a \tb" 1 4
+[[:cntrl:]]+ a\n\tb 1 3
+[[:digit:]]+ a019b 1 4
+[[:graph:]]+ " a%b " 1 4
+[[:lower:]]+ AabC 1 3
+; This test fails with STLPort, disable for now as this is a corner case anyway...
+;[[:print:]]+ "\na b\n" 1 4
+[[:punct:]]+ " %-&\t" 1 4
+[[:space:]]+ "a \n\t\rb" 1 5
+[[:upper:]]+ aBCd 1 3
+[[:xdigit:]]+ p0f3Cx 1 5
+
+; now test flag settings:
+- escape_in_lists REG_NO_POSIX_TEST
+[\n] \n 0 1
+- REG_NO_POSIX_TEST
+
+; line anchors
+- match_default normal REG_EXTENDED
+^ab ab 0 2
+^ab xxabxx -1 -1
+ab$ ab 0 2
+ab$ abxx -1 -1
+- match_default match_not_bol match_not_eol normal REG_EXTENDED REG_NOTBOL REG_NOTEOL
+^ab ab -1 -1
+^ab xxabxx -1 -1
+ab$ ab -1 -1
+ab$ abxx -1 -1
+
+; back references
+- match_default normal REG_PERL
+a(b)\2c !
+a(b\1)c !
+a(b*)c\1d abbcbbd 0 7 1 3
+a(b*)c\1d abbcbd -1 -1
+a(b*)c\1d abbcbbbd -1 -1
+^(.)\1 abc -1 -1
+a([bc])\1d abcdabbd 4 8 5 6
+; strictly speaking this is at best ambiguous, at worst wrong, this is what most
+; re implimentations will match though.
+a(([bc])\2)*d abbccd 0 6 3 5 3 4
+
+a(([bc])\2)*d abbcbd -1 -1
+a((b)*\2)*d abbbd 0 5 1 4 2 3
+; perl only:
+(ab*)[ab]*\1 ababaaa 0 7 0 1
+(a)\1bcd aabcd 0 5 0 1
+(a)\1bc*d aabcd 0 5 0 1
+(a)\1bc*d aabd 0 4 0 1
+(a)\1bc*d aabcccd 0 7 0 1
+(a)\1bc*[ce]d aabcccd 0 7 0 1
+^(a)\1b(c)*cd$ aabcccd 0 7 0 1 4 5
+
+; posix only:
+- match_default extended REG_EXTENDED
+(ab*)[ab]*\1 ababaaa 0 7 0 1
+
+;
+; word operators:
+\w a 0 1
+\w z 0 1
+\w A 0 1
+\w Z 0 1
+\w _ 0 1
+\w } -1 -1
+\w ` -1 -1
+\w [ -1 -1
+\w @ -1 -1
+; non-word:
+\W a -1 -1
+\W z -1 -1
+\W A -1 -1
+\W Z -1 -1
+\W _ -1 -1
+\W } 0 1
+\W ` 0 1
+\W [ 0 1
+\W @ 0 1
+; word start:
+\<abcd " abcd" 2 6
+\<ab cab -1 -1
+\<ab "\nab" 1 3
+\<tag ::tag 2 5
+;word end:
+abc\> abc 0 3
+abc\> abcd -1 -1
+abc\> abc\n 0 3
+abc\> abc:: 0 3
+; word boundary:
+\babcd " abcd" 2 6
+\bab cab -1 -1
+\bab "\nab" 1 3
+\btag ::tag 2 5
+abc\b abc 0 3
+abc\b abcd -1 -1
+abc\b abc\n 0 3
+abc\b abc:: 0 3
+; within word:
+\B ab 1 1
+a\Bb ab 0 2
+a\B ab 0 1
+a\B a -1 -1
+a\B "a " -1 -1
+
+;
+; buffer operators:
+\`abc abc 0 3
+\`abc \nabc -1 -1
+\`abc " abc" -1 -1
+abc\' abc 0 3
+abc\' abc\n -1 -1
+abc\' "abc " -1 -1
+
+;
+; now follows various complex expressions designed to try and bust the matcher:
+a(((b)))c abc 0 3 1 2 1 2 1 2
+a(b|(c))d abd 0 3 1 2 -1 -1
+a(b|(c))d acd 0 3 1 2 1 2
+a(b*|c)d abbd 0 4 1 3
+; just gotta have one DFA-buster, of course
+a[ab]{20} aaaaabaaaabaaaabaaaab 0 21
+; and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] aaaaabaaaabaaaabaaaab 0 21
+; and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) aaaaabaaaabaaaabaaaabweeknights 0 31 21 24 24 31
+; one really big one
+1234567890123456789012345678901234567890123456789012345678901234567890 a1234567890123456789012345678901234567890123456789012345678901234567890b 1 71
+; fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn] xacegikmoq 1 8
+[ab][cd][ef][gh][ij][kl][mn][op] xacegikmoq 1 9
+[ab][cd][ef][gh][ij][kl][mn][op][qr] xacegikmoqy 1 10
+[ab][cd][ef][gh][ij][kl][mn][op][q] xacegikmoqy 1 10
+; and as parenthesis go past 9:
+(a)(b)(c)(d)(e)(f)(g)(h) zabcdefghi 1 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9
+(a)(b)(c)(d)(e)(f)(g)(h)(i) zabcdefghij 1 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10
+(a)(b)(c)(d)(e)(f)(g)(h)(i)(j) zabcdefghijk 1 11 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11
+(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k) zabcdefghijkl 1 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12
+(a)d|(b)c abc 1 3 -1 -1 1 2
+_+((www)|(ftp)|(mailto)):_* "_wwwnocolon _mailto:" 12 20 13 19 -1 -1 -1 -1 13 19
+
+; subtleties of matching
+;a(b)?c\1d acd 0 3 -1 -1
+; POSIX is about the following test:
+a(b)?c\1d acd -1 -1 -1 -1
+a(b?c)+d accd 0 4 2 3
+(wee|week)(knights|night) weeknights 0 10 0 3 3 10
+.* abc 0 3
+a(b|(c))d abd 0 3 1 2 -1 -1
+a(b|(c))d acd 0 3 1 2 1 2
+a(b*|c|e)d abbd 0 4 1 3
+a(b*|c|e)d acd 0 3 1 2
+a(b*|c|e)d ad 0 2 1 1
+a(b?)c abc 0 3 1 2
+a(b?)c ac 0 2 1 1
+a(b+)c abc 0 3 1 2
+a(b+)c abbbc 0 5 1 4
+a(b*)c ac 0 2 1 1
+(a|ab)(bc([de]+)f|cde) abcdef 0 6 0 1 1 6 3 5
+a([bc]?)c abc 0 3 1 2
+a([bc]?)c ac 0 2 1 1
+a([bc]+)c abc 0 3 1 2
+a([bc]+)c abcc 0 4 1 3
+a([bc]+)bc abcbc 0 5 1 3
+a(bb+|b)b abb 0 3 1 2
+a(bbb+|bb+|b)b abb 0 3 1 2
+a(bbb+|bb+|b)b abbb 0 4 1 3
+a(bbb+|bb+|b)bb abbb 0 4 1 2
+(.*).* abcdef 0 6 0 6
+(a*)* bc 0 0 0 0
+xyx*xz xyxxxxyxxxz 5 11
+
+; do we get the right subexpression when it is used more than once?
+a(b|c)*d ad 0 2 -1 -1
+a(b|c)*d abcd 0 4 2 3
+a(b|c)+d abd 0 3 1 2
+a(b|c)+d abcd 0 4 2 3
+a(b|c?)+d ad 0 2 1 1
+a(b|c){0,0}d ad 0 2 -1 -1
+a(b|c){0,1}d ad 0 2 -1 -1
+a(b|c){0,1}d abd 0 3 1 2
+a(b|c){0,2}d ad 0 2 -1 -1
+a(b|c){0,2}d abcd 0 4 2 3
+a(b|c){0,}d ad 0 2 -1 -1
+a(b|c){0,}d abcd 0 4 2 3
+a(b|c){1,1}d abd 0 3 1 2
+a(b|c){1,2}d abd 0 3 1 2
+a(b|c){1,2}d abcd 0 4 2 3
+a(b|c){1,}d abd 0 3 1 2
+a(b|c){1,}d abcd 0 4 2 3
+a(b|c){2,2}d acbd 0 4 2 3
+a(b|c){2,2}d abcd 0 4 2 3
+a(b|c){2,4}d abcd 0 4 2 3
+a(b|c){2,4}d abcbd 0 5 3 4
+a(b|c){2,4}d abcbcd 0 6 4 5
+a(b|c){2,}d abcd 0 4 2 3
+a(b|c){2,}d abcbd 0 5 3 4
+; perl only: these conflict with the POSIX test below
+;a(b|c?)+d abcd 0 4 3 3
+;a(b+|((c)*))+d abd 0 3 2 2 2 2 -1 -1
+;a(b+|((c)*))+d abcd 0 4 3 3 3 3 2 3
+
+; posix only:
+- match_default extended REG_EXTENDED REG_STARTEND
+
+a(b|c?)+d abcd 0 4 2 3
+a(b|((c)*))+d abcd 0 4 2 3 2 3 2 3
+a(b+|((c)*))+d abd 0 3 1 2 -1 -1 -1 -1
+a(b+|((c)*))+d abcd 0 4 2 3 2 3 2 3
+a(b|((c)*))+d ad 0 2 1 1 1 1 -1 -1
+a(b|((c)*))*d abcd 0 4 2 3 2 3 2 3
+a(b+|((c)*))*d abd 0 3 1 2 -1 -1 -1 -1
+a(b+|((c)*))*d abcd 0 4 2 3 2 3 2 3
+a(b|((c)*))*d ad 0 2 1 1 1 1 -1 -1
+
+- match_default normal REG_PERL
+; try to match C++ syntax elements:
+; line comment:
+//[^\n]* "++i //here is a line comment\n" 4 28
+; block comment:
+/\*([^*]|\*+[^*/])*\*+/ "/* here is a block comment */" 0 29 26 27
+/\*([^*]|\*+[^*/])*\*+/ "/**/" 0 4 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/***/" 0 5 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/****/" 0 6 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/*****/" 0 7 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/*****/*/" 0 7 -1 -1
+; preprossor directives:
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol" 0 19 -1 -1
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) #x" 0 25 -1 -1
+; perl only:
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) \\ \r\n foo();\\\r\n printf(#x);" 0 53 30 42
+; literals:
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFF 0 4 0 4 0 4 -1 -1 -1 -1 -1 -1 -1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 35 0 2 0 2 -1 -1 0 2 -1 -1 -1 -1 -1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFu 0 5 0 4 0 4 -1 -1 -1 -1 -1 -1 -1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFL 0 5 0 4 0 4 -1 -1 4 5 -1 -1 -1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFFFFFFFFFFFFFFFuint64 0 24 0 18 0 18 -1 -1 19 24 19 24 22 24
+; strings:
+'([^\\']|\\.)*' '\\x3A' 0 6 4 5
+'([^\\']|\\.)*' '\\'' 0 4 1 3
+'([^\\']|\\.)*' '\\n' 0 4 1 3
+
+; finally try some case insensitive matches:
+- match_default normal REG_EXTENDED REG_ICASE
+; upper and lower have no meaning here so they fail, however these
+; may compile with other libraries...
+;[[:lower:]] !
+;[[:upper:]] !
+0123456789@abcdefghijklmnopqrstuvwxyz\[\\\]\^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ\{\|\} 0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\} 0 72
+
+; known and suspected bugs:
+- match_default normal REG_EXTENDED
+\( ( 0 1
+\) ) 0 1
+\$ $ 0 1
+\^ ^ 0 1
+\. . 0 1
+\* * 0 1
+\+ + 0 1
+\? ? 0 1
+\[ [ 0 1
+\] ] 0 1
+\| | 0 1
+\\ \\ 0 1
+# # 0 1
+\# # 0 1
+a- a- 0 2
+\- - 0 1
+\{ { 0 1
+\} } 0 1
+0 0 0 1
+1 1 0 1
+9 9 0 1
+b b 0 1
+B B 0 1
+< < 0 1
+> > 0 1
+w w 0 1
+W W 0 1
+` ` 0 1
+' ' 0 1
+\n \n 0 1
+, , 0 1
+a a 0 1
+f f 0 1
+n n 0 1
+r r 0 1
+t t 0 1
+v v 0 1
+c c 0 1
+x x 0 1
+: : 0 1
+(\.[[:alnum:]]+){2} "w.a.b " 1 5 3 5
+
+- match_default normal REG_EXTENDED REG_ICASE
+a A 0 1
+A a 0 1
+[abc]+ abcABC 0 6
+[ABC]+ abcABC 0 6
+[a-z]+ abcABC 0 6
+[A-Z]+ abzANZ 0 6
+[a-Z]+ abzABZ 0 6
+[A-z]+ abzABZ 0 6
+[[:lower:]]+ abyzABYZ 0 8
+[[:upper:]]+ abzABZ 0 6
+[[:alpha:]]+ abyzABYZ 0 8
+[[:alnum:]]+ 09abyzABYZ 0 10
+
+; word start:
+\<abcd " abcd" 2 6
+\<ab cab -1 -1
+\<ab "\nab" 1 3
+\<tag ::tag 2 5
+;word end:
+abc\> abc 0 3
+abc\> abcd -1 -1
+abc\> abc\n 0 3
+abc\> abc:: 0 3
+
+; collating elements and rewritten set code:
+- match_default normal REG_EXTENDED REG_STARTEND
+;[[.zero.]] 0 0 1
+;[[.one.]] 1 0 1
+;[[.two.]] 2 0 1
+;[[.three.]] 3 0 1
+[[.a.]] baa 1 2
+;[[.right-curly-bracket.]] } 0 1
+;[[.NUL.]] \0 0 1
+[[:<:]z] !
+[a[:>:]] !
+[[=a=]] a 0 1
+;[[=right-curly-bracket=]] } 0 1
+- match_default normal REG_EXTENDED REG_STARTEND REG_ICASE
+[[.A.]] A 0 1
+[[.A.]] a 0 1
+[[.A.]-b]+ AaBb 0 4
+[A-[.b.]]+ AaBb 0 4
+[[.a.]-B]+ AaBb 0 4
+[a-[.B.]]+ AaBb 0 4
+- match_default normal REG_EXTENDED REG_STARTEND
+[[.a.]-c]+ abcd 0 3
+[a-[.c.]]+ abcd 0 3
+[[:alpha:]-a] !
+[a-[:alpha:]] !
+
+; try mutli-character ligatures:
+;[[.ae.]] ae 0 2
+;[[.ae.]] aE -1 -1
+;[[.AE.]] AE 0 2
+;[[.Ae.]] Ae 0 2
+;[[.ae.]-b] a -1 -1
+;[[.ae.]-b] b 0 1
+;[[.ae.]-b] ae 0 2
+;[a-[.ae.]] a 0 1
+;[a-[.ae.]] b -1 -1
+;[a-[.ae.]] ae 0 2
+- match_default normal REG_EXTENDED REG_STARTEND REG_ICASE
+;[[.ae.]] AE 0 2
+;[[.ae.]] Ae 0 2
+;[[.AE.]] Ae 0 2
+;[[.Ae.]] aE 0 2
+;[[.AE.]-B] a -1 -1
+;[[.Ae.]-b] b 0 1
+;[[.Ae.]-b] B 0 1
+;[[.ae.]-b] AE 0 2
+
+- match_default normal REG_EXTENDED REG_STARTEND REG_NO_POSIX_TEST
+\s+ "ab ab" 2 5
+\S+ " abc " 2 5
+
+- match_default normal REG_EXTENDED REG_STARTEND
+\`abc abc 0 3
+\`abc aabc -1 -1
+abc\' abc 0 3
+abc\' abcd -1 -1
+abc\' abc\n\n -1 -1
+abc\' abc 0 3
+
+; extended repeat checking to exercise new algorithms:
+ab.*xy abxy_ 0 4
+ab.*xy ab_xy_ 0 5
+ab.*xy abxy 0 4
+ab.*xy ab_xy 0 5
+ab.* ab 0 2
+ab.* ab__ 0 4
+
+ab.{2,5}xy ab__xy_ 0 6
+ab.{2,5}xy ab____xy_ 0 8
+ab.{2,5}xy ab_____xy_ 0 9
+ab.{2,5}xy ab__xy 0 6
+ab.{2,5}xy ab_____xy 0 9
+ab.{2,5} ab__ 0 4
+ab.{2,5} ab_______ 0 7
+ab.{2,5}xy ab______xy -1 -1
+ab.{2,5}xy ab_xy -1 -1
+
+ab.*?xy abxy_ 0 4
+ab.*?xy ab_xy_ 0 5
+ab.*?xy abxy 0 4
+ab.*?xy ab_xy 0 5
+ab.*? ab 0 2
+ab.*? ab__ 0 4
+
+ab.{2,5}?xy ab__xy_ 0 6
+ab.{2,5}?xy ab____xy_ 0 8
+ab.{2,5}?xy ab_____xy_ 0 9
+ab.{2,5}?xy ab__xy 0 6
+ab.{2,5}?xy ab_____xy 0 9
+ab.{2,5}? ab__ 0 4
+ab.{2,5}? ab_______ 0 7
+ab.{2,5}?xy ab______xy -1 -1
+ab.{2,5}xy ab_xy -1 -1
+
+; again but with slower algorithm variant:
+- match_default REG_EXTENDED
+; now again for single character repeats:
+
+ab_*xy abxy_ 0 4
+ab_*xy ab_xy_ 0 5
+ab_*xy abxy 0 4
+ab_*xy ab_xy 0 5
+ab_* ab 0 2
+ab_* ab__ 0 4
+
+ab_{2,5}xy ab__xy_ 0 6
+ab_{2,5}xy ab____xy_ 0 8
+ab_{2,5}xy ab_____xy_ 0 9
+ab_{2,5}xy ab__xy 0 6
+ab_{2,5}xy ab_____xy 0 9
+ab_{2,5} ab__ 0 4
+ab_{2,5} ab_______ 0 7
+ab_{2,5}xy ab______xy -1 -1
+ab_{2,5}xy ab_xy -1 -1
+
+ab_*?xy abxy_ 0 4
+ab_*?xy ab_xy_ 0 5
+ab_*?xy abxy 0 4
+ab_*?xy ab_xy 0 5
+ab_*? ab 0 2
+ab_*? ab__ 0 4
+
+ab_{2,5}?xy ab__xy_ 0 6
+ab_{2,5}?xy ab____xy_ 0 8
+ab_{2,5}?xy ab_____xy_ 0 9
+ab_{2,5}?xy ab__xy 0 6
+ab_{2,5}?xy ab_____xy 0 9
+ab_{2,5}? ab__ 0 4
+ab_{2,5}? ab_______ 0 7
+ab_{2,5}?xy ab______xy -1 -1
+ab_{2,5}xy ab_xy -1 -1
+
+; and again for sets:
+ab[_,;]*xy abxy_ 0 4
+ab[_,;]*xy ab_xy_ 0 5
+ab[_,;]*xy abxy 0 4
+ab[_,;]*xy ab_xy 0 5
+ab[_,;]* ab 0 2
+ab[_,;]* ab__ 0 4
+
+ab[_,;]{2,5}xy ab__xy_ 0 6
+ab[_,;]{2,5}xy ab____xy_ 0 8
+ab[_,;]{2,5}xy ab_____xy_ 0 9
+ab[_,;]{2,5}xy ab__xy 0 6
+ab[_,;]{2,5}xy ab_____xy 0 9
+ab[_,;]{2,5} ab__ 0 4
+ab[_,;]{2,5} ab_______ 0 7
+ab[_,;]{2,5}xy ab______xy -1 -1
+ab[_,;]{2,5}xy ab_xy -1 -1
+
+ab[_,;]*?xy abxy_ 0 4
+ab[_,;]*?xy ab_xy_ 0 5
+ab[_,;]*?xy abxy 0 4
+ab[_,;]*?xy ab_xy 0 5
+ab[_,;]*? ab 0 2
+ab[_,;]*? ab__ 0 4
+
+ab[_,;]{2,5}?xy ab__xy_ 0 6
+ab[_,;]{2,5}?xy ab____xy_ 0 8
+ab[_,;]{2,5}?xy ab_____xy_ 0 9
+ab[_,;]{2,5}?xy ab__xy 0 6
+ab[_,;]{2,5}?xy ab_____xy 0 9
+ab[_,;]{2,5}? ab__ 0 4
+ab[_,;]{2,5}? ab_______ 0 7
+ab[_,;]{2,5}?xy ab______xy -1 -1
+ab[_,;]{2,5}xy ab_xy -1 -1
+
+; and again for tricky sets with digraphs:
+;ab[_[.ae.]]*xy abxy_ 0 4
+;ab[_[.ae.]]*xy ab_xy_ 0 5
+;ab[_[.ae.]]*xy abxy 0 4
+;ab[_[.ae.]]*xy ab_xy 0 5
+;ab[_[.ae.]]* ab 0 2
+;ab[_[.ae.]]* ab__ 0 4
+
+;ab[_[.ae.]]{2,5}xy ab__xy_ 0 6
+;ab[_[.ae.]]{2,5}xy ab____xy_ 0 8
+;ab[_[.ae.]]{2,5}xy ab_____xy_ 0 9
+;ab[_[.ae.]]{2,5}xy ab__xy 0 6
+;ab[_[.ae.]]{2,5}xy ab_____xy 0 9
+;ab[_[.ae.]]{2,5} ab__ 0 4
+;ab[_[.ae.]]{2,5} ab_______ 0 7
+;ab[_[.ae.]]{2,5}xy ab______xy -1 -1
+;ab[_[.ae.]]{2,5}xy ab_xy -1 -1
+
+;ab[_[.ae.]]*?xy abxy_ 0 4
+;ab[_[.ae.]]*?xy ab_xy_ 0 5
+;ab[_[.ae.]]*?xy abxy 0 4
+;ab[_[.ae.]]*?xy ab_xy 0 5
+;ab[_[.ae.]]*? ab 0 2
+;ab[_[.ae.]]*? ab__ 0 2
+
+;ab[_[.ae.]]{2,5}?xy ab__xy_ 0 6
+;ab[_[.ae.]]{2,5}?xy ab____xy_ 0 8
+;ab[_[.ae.]]{2,5}?xy ab_____xy_ 0 9
+;ab[_[.ae.]]{2,5}?xy ab__xy 0 6
+;ab[_[.ae.]]{2,5}?xy ab_____xy 0 9
+;ab[_[.ae.]]{2,5}? ab__ 0 4
+;ab[_[.ae.]]{2,5}? ab_______ 0 4
+;ab[_[.ae.]]{2,5}?xy ab______xy -1 -1
+;ab[_[.ae.]]{2,5}xy ab_xy -1 -1
+
+; new bugs detected in spring 2003:
+- normal match_continuous REG_NO_POSIX_TEST
+b abc 1 2
+
+() abc 0 0 0 0
+^() abc 0 0 0 0
+^()+ abc 0 0 0 0
+^(){1} abc 0 0 0 0
+^(){2} abc 0 0 0 0
+^((){2}) abc 0 0 0 0 0 0
+() "" 0 0 0 0
+()\1 "" 0 0 0 0
+()\1 a 0 0 0 0
+a()\1b ab 0 2 1 1
+a()b\1 ab 0 2 1 1
+
+; subtleties of matching with no sub-expressions marked
+- normal match_nosubs REG_NO_POSIX_TEST
+a(b?c)+d accd 0 4
+(wee|week)(knights|night) weeknights 0 10
+.* abc 0 3
+a(b|(c))d abd 0 3
+a(b|(c))d acd 0 3
+a(b*|c|e)d abbd 0 4
+a(b*|c|e)d acd 0 3
+a(b*|c|e)d ad 0 2
+a(b?)c abc 0 3
+a(b?)c ac 0 2
+a(b+)c abc 0 3
+a(b+)c abbbc 0 5
+a(b*)c ac 0 2
+(a|ab)(bc([de]+)f|cde) abcdef 0 6
+a([bc]?)c abc 0 3
+a([bc]?)c ac 0 2
+a([bc]+)c abc 0 3
+a([bc]+)c abcc 0 4
+a([bc]+)bc abcbc 0 5
+a(bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abbb 0 4
+a(bbb+|bb+|b)bb abbb 0 4
+(.*).* abcdef 0 6
+(a*)* bc 0 0
+
+- normal nosubs REG_NO_POSIX_TEST
+a(b?c)+d accd 0 4
+(wee|week)(knights|night) weeknights 0 10
+.* abc 0 3
+a(b|(c))d abd 0 3
+a(b|(c))d acd 0 3
+a(b*|c|e)d abbd 0 4
+a(b*|c|e)d acd 0 3
+a(b*|c|e)d ad 0 2
+a(b?)c abc 0 3
+a(b?)c ac 0 2
+a(b+)c abc 0 3
+a(b+)c abbbc 0 5
+a(b*)c ac 0 2
+(a|ab)(bc([de]+)f|cde) abcdef 0 6
+a([bc]?)c abc 0 3
+a([bc]?)c ac 0 2
+a([bc]+)c abc 0 3
+a([bc]+)c abcc 0 4
+a([bc]+)bc abcbc 0 5
+a(bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abbb 0 4
+a(bbb+|bb+|b)bb abbb 0 4
+(.*).* abcdef 0 6
+(a*)* bc 0 0
+
diff --git a/test/src/regex-resources/PCRE.tests b/test/src/regex-resources/PCRE.tests
new file mode 100644
index 00000000000..0fb9cadafc9
--- /dev/null
+++ b/test/src/regex-resources/PCRE.tests
@@ -0,0 +1,2386 @@
+# PCRE version 4.4 21-August-2003
+
+# Tests taken from PCRE and modified to suit glibc regex.
+#
+# PCRE LICENCE
+# ------------
+#
+# PCRE is a library of functions to support regular expressions whose syntax
+# and semantics are as close as possible to those of the Perl 5 language.
+#
+# Written by: Philip Hazel <ph10@cam.ac.uk>
+#
+# University of Cambridge Computing Service,
+# Cambridge, England. Phone: +44 1223 334714.
+#
+# Copyright (c) 1997-2003 University of Cambridge
+#
+# Permission is granted to anyone to use this software for any purpose on any
+# computer system, and to redistribute it freely, subject to the following
+# restrictions:
+#
+# 1. This software 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.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. In practice, this means that if you use
+# PCRE in software that you distribute to others, commercially or
+# otherwise, you must put a sentence like this
+#
+# Regular expression support is provided by the PCRE library package,
+# which is open source software, written by Philip Hazel, and copyright
+# by the University of Cambridge, England.
+#
+# somewhere reasonably visible in your documentation and in any relevant
+# files or online help data or similar. A reference to the ftp site for
+# the source, that is, to
+#
+# ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
+#
+# should also be given in the documentation. However, this condition is not
+# intended to apply to whole chains of software. If package A includes PCRE,
+# it must acknowledge it, but if package B is software that includes package
+# A, the condition is not imposed on package B (unless it uses PCRE
+# independently).
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. If PCRE is embedded in any software that is released under the GNU
+# General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL),
+# then the terms of that licence shall supersede any condition above with
+# which it is incompatible.
+#
+# The documentation for PCRE, supplied in the "doc" directory, is distributed
+# under the same terms as the software itself.
+#
+# End
+#
+
+/the quick brown fox/
+ the quick brown fox
+ 0: the quick brown fox
+ The quick brown FOX
+No match
+ What do you know about the quick brown fox?
+ 0: the quick brown fox
+ What do you know about THE QUICK BROWN FOX?
+No match
+
+/The quick brown fox/i
+ the quick brown fox
+ 0: the quick brown fox
+ The quick brown FOX
+ 0: The quick brown FOX
+ What do you know about the quick brown fox?
+ 0: the quick brown fox
+ What do you know about THE QUICK BROWN FOX?
+ 0: THE QUICK BROWN FOX
+
+/a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/
+ abxyzpqrrrabbxyyyypqAzz
+ 0: abxyzpqrrrabbxyyyypqAzz
+ abxyzpqrrrabbxyyyypqAzz
+ 0: abxyzpqrrrabbxyyyypqAzz
+ aabxyzpqrrrabbxyyyypqAzz
+ 0: aabxyzpqrrrabbxyyyypqAzz
+ aaabxyzpqrrrabbxyyyypqAzz
+ 0: aaabxyzpqrrrabbxyyyypqAzz
+ aaaabxyzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzpqrrrabbxyyyypqAzz
+ abcxyzpqrrrabbxyyyypqAzz
+ 0: abcxyzpqrrrabbxyyyypqAzz
+ aabcxyzpqrrrabbxyyyypqAzz
+ 0: aabcxyzpqrrrabbxyyyypqAzz
+ aaabcxyzpqrrrabbxyyyypAzz
+ 0: aaabcxyzpqrrrabbxyyyypAzz
+ aaabcxyzpqrrrabbxyyyypqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqAzz
+ aaabcxyzpqrrrabbxyyyypqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqAzz
+ aaabcxyzpqrrrabbxyyyypqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqAzz
+ aaabcxyzpqrrrabbxyyyypqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqAzz
+ aaabcxyzpqrrrabbxyyyypqqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz
+ aaabcxyzpqrrrabbxyyyypqqqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz
+ aaaabcxyzpqrrrabbxyyyypqAzz
+ 0: aaaabcxyzpqrrrabbxyyyypqAzz
+ abxyzzpqrrrabbxyyyypqAzz
+ 0: abxyzzpqrrrabbxyyyypqAzz
+ aabxyzzzpqrrrabbxyyyypqAzz
+ 0: aabxyzzzpqrrrabbxyyyypqAzz
+ aaabxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaabxyzzzzpqrrrabbxyyyypqAzz
+ aaaabxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzzzzpqrrrabbxyyyypqAzz
+ abcxyzzpqrrrabbxyyyypqAzz
+ 0: abcxyzzpqrrrabbxyyyypqAzz
+ aabcxyzzzpqrrrabbxyyyypqAzz
+ 0: aabcxyzzzpqrrrabbxyyyypqAzz
+ aaabcxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaabcxyzzzzpqrrrabbxyyyypqAzz
+ aaaabcxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz
+ aaaabcxyzzzzpqrrrabbbxyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz
+ aaaabcxyzzzzpqrrrabbbxyyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz
+ aaabcxyzpqrrrabbxyyyypABzz
+ 0: aaabcxyzpqrrrabbxyyyypABzz
+ aaabcxyzpqrrrabbxyyyypABBzz
+ 0: aaabcxyzpqrrrabbxyyyypABBzz
+ >>>aaabxyzpqrrrabbxyyyypqAzz
+ 0: aaabxyzpqrrrabbxyyyypqAzz
+ >aaaabxyzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzpqrrrabbxyyyypqAzz
+ >>>>abcxyzpqrrrabbxyyyypqAzz
+ 0: abcxyzpqrrrabbxyyyypqAzz
+ *** Failers
+No match
+ abxyzpqrrabbxyyyypqAzz
+No match
+ abxyzpqrrrrabbxyyyypqAzz
+No match
+ abxyzpqrrrabxyyyypqAzz
+No match
+ aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz
+No match
+ aaaabcxyzzzzpqrrrabbbxyyypqAzz
+No match
+ aaabcxyzpqrrrabbxyyyypqqqqqqqAzz
+No match
+
+/^(abc){1,2}zz/
+ abczz
+ 0: abczz
+ 1: abc
+ abcabczz
+ 0: abcabczz
+ 1: abc
+ *** Failers
+No match
+ zz
+No match
+ abcabcabczz
+No match
+ >>abczz
+No match
+
+/^(b+|a){1,2}c/
+ bc
+ 0: bc
+ 1: b
+ bbc
+ 0: bbc
+ 1: bb
+ bbbc
+ 0: bbbc
+ 1: bbb
+ bac
+ 0: bac
+ 1: a
+ bbac
+ 0: bbac
+ 1: a
+ aac
+ 0: aac
+ 1: a
+ abbbbbbbbbbbc
+ 0: abbbbbbbbbbbc
+ 1: bbbbbbbbbbb
+ bbbbbbbbbbbac
+ 0: bbbbbbbbbbbac
+ 1: a
+ *** Failers
+No match
+ aaac
+No match
+ abbbbbbbbbbbac
+No match
+
+/^[]cde]/
+ ]thing
+ 0: ]
+ cthing
+ 0: c
+ dthing
+ 0: d
+ ething
+ 0: e
+ *** Failers
+No match
+ athing
+No match
+ fthing
+No match
+
+/^[^]cde]/
+ athing
+ 0: a
+ fthing
+ 0: f
+ *** Failers
+ 0: *
+ ]thing
+No match
+ cthing
+No match
+ dthing
+No match
+ ething
+No match
+
+/^[0-9]+$/
+ 0
+ 0: 0
+ 1
+ 0: 1
+ 2
+ 0: 2
+ 3
+ 0: 3
+ 4
+ 0: 4
+ 5
+ 0: 5
+ 6
+ 0: 6
+ 7
+ 0: 7
+ 8
+ 0: 8
+ 9
+ 0: 9
+ 10
+ 0: 10
+ 100
+ 0: 100
+ *** Failers
+No match
+ abc
+No match
+
+/^.*nter/
+ enter
+ 0: enter
+ inter
+ 0: inter
+ uponter
+ 0: uponter
+
+/^xxx[0-9]+$/
+ xxx0
+ 0: xxx0
+ xxx1234
+ 0: xxx1234
+ *** Failers
+No match
+ xxx
+No match
+
+/^.+[0-9][0-9][0-9]$/
+ x123
+ 0: x123
+ xx123
+ 0: xx123
+ 123456
+ 0: 123456
+ *** Failers
+No match
+ 123
+No match
+ x1234
+ 0: x1234
+
+/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/
+ abc!pqr=apquxz.ixr.zzz.ac.uk
+ 0: abc!pqr=apquxz.ixr.zzz.ac.uk
+ 1: abc
+ 2: pqr
+ *** Failers
+No match
+ !pqr=apquxz.ixr.zzz.ac.uk
+No match
+ abc!=apquxz.ixr.zzz.ac.uk
+No match
+ abc!pqr=apquxz:ixr.zzz.ac.uk
+No match
+ abc!pqr=apquxz.ixr.zzz.ac.ukk
+No match
+
+/:/
+ Well, we need a colon: somewhere
+ 0: :
+ *** Fail if we don't
+No match
+
+/([0-9a-f:]+)$/i
+ 0abc
+ 0: 0abc
+ 1: 0abc
+ abc
+ 0: abc
+ 1: abc
+ fed
+ 0: fed
+ 1: fed
+ E
+ 0: E
+ 1: E
+ ::
+ 0: ::
+ 1: ::
+ 5f03:12C0::932e
+ 0: 5f03:12C0::932e
+ 1: 5f03:12C0::932e
+ fed def
+ 0: def
+ 1: def
+ Any old stuff
+ 0: ff
+ 1: ff
+ *** Failers
+No match
+ 0zzz
+No match
+ gzzz
+No match
+ Any old rubbish
+No match
+
+/^.*\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/
+ .1.2.3
+ 0: .1.2.3
+ 1: 1
+ 2: 2
+ 3: 3
+ A.12.123.0
+ 0: A.12.123.0
+ 1: 12
+ 2: 123
+ 3: 0
+ *** Failers
+No match
+ .1.2.3333
+No match
+ 1.2.3
+No match
+ 1234.2.3
+No match
+
+/^([0-9]+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/
+ 1 IN SOA non-sp1 non-sp2(
+ 0: 1 IN SOA non-sp1 non-sp2(
+ 1: 1
+ 2: non-sp1
+ 3: non-sp2
+ 1 IN SOA non-sp1 non-sp2 (
+ 0: 1 IN SOA non-sp1 non-sp2 (
+ 1: 1
+ 2: non-sp1
+ 3: non-sp2
+ *** Failers
+No match
+ 1IN SOA non-sp1 non-sp2(
+No match
+
+/^[a-zA-Z0-9][a-zA-Z0-9-]*(\.[a-zA-Z0-9][a-zA-z0-9-]*)*\.$/
+ a.
+ 0: a.
+ Z.
+ 0: Z.
+ 2.
+ 0: 2.
+ ab-c.pq-r.
+ 0: ab-c.pq-r.
+ 1: .pq-r
+ sxk.zzz.ac.uk.
+ 0: sxk.zzz.ac.uk.
+ 1: .uk
+ x-.y-.
+ 0: x-.y-.
+ 1: .y-
+ *** Failers
+No match
+ -abc.peq.
+No match
+
+/^\*\.[a-z]([a-z0-9-]*[a-z0-9]+)?(\.[a-z]([a-z0-9-]*[a-z0-9]+)?)*$/
+ *.a
+ 0: *.a
+ *.b0-a
+ 0: *.b0-a
+ 1: 0-a
+ *.c3-b.c
+ 0: *.c3-b.c
+ 1: 3-b
+ 2: .c
+ *.c-a.b-c
+ 0: *.c-a.b-c
+ 1: -a
+ 2: .b-c
+ 3: -c
+ *** Failers
+No match
+ *.0
+No match
+ *.a-
+No match
+ *.a-b.c-
+No match
+ *.c-a.0-c
+No match
+
+/^[0-9a-f](\.[0-9a-f])*$/i
+ a.b.c.d
+ 0: a.b.c.d
+ 1: .d
+ A.B.C.D
+ 0: A.B.C.D
+ 1: .D
+ a.b.c.1.2.3.C
+ 0: a.b.c.1.2.3.C
+ 1: .C
+
+/^".*"\s*(;.*)?$/
+ "1234"
+ 0: "1234"
+ "abcd" ;
+ 0: "abcd" ;
+ 1: ;
+ "" ; rhubarb
+ 0: "" ; rhubarb
+ 1: ; rhubarb
+ *** Failers
+No match
+ "1234" : things
+No match
+
+/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/
+ abcdefhijklm
+ 0: abcdefhijklm
+ 1: abc
+ 2: bc
+ 3: c
+ 4: def
+ 5: ef
+ 6: f
+ 7: hij
+ 8: ij
+ 9: j
+10: klm
+11: lm
+12: m
+
+/^a*\w/
+ z
+ 0: z
+ az
+ 0: az
+ aaaz
+ 0: aaaz
+ a
+ 0: a
+ aa
+ 0: aa
+ aaaa
+ 0: aaaa
+ a+
+ 0: a
+ aa+
+ 0: aa
+
+/^a+\w/
+ az
+ 0: az
+ aaaz
+ 0: aaaz
+ aa
+ 0: aa
+ aaaa
+ 0: aaaa
+ aa+
+ 0: aa
+
+/^[0-9]{8}\w{2,}/
+ 1234567890
+ 0: 1234567890
+ 12345678ab
+ 0: 12345678ab
+ 12345678__
+ 0: 12345678__
+ *** Failers
+No match
+ 1234567
+No match
+
+/^[aeiou0-9]{4,5}$/
+ uoie
+ 0: uoie
+ 1234
+ 0: 1234
+ 12345
+ 0: 12345
+ aaaaa
+ 0: aaaaa
+ *** Failers
+No match
+ 123456
+No match
+
+/\`(abc|def)=(\1){2,3}\'/
+ abc=abcabc
+ 0: abc=abcabc
+ 1: abc
+ 2: abc
+ def=defdefdef
+ 0: def=defdefdef
+ 1: def
+ 2: def
+ *** Failers
+No match
+ abc=defdef
+No match
+
+/(cat(a(ract|tonic)|erpillar)) \1()2(3)/
+ cataract cataract23
+ 0: cataract cataract23
+ 1: cataract
+ 2: aract
+ 3: ract
+ 4:
+ 5: 3
+ catatonic catatonic23
+ 0: catatonic catatonic23
+ 1: catatonic
+ 2: atonic
+ 3: tonic
+ 4:
+ 5: 3
+ caterpillar caterpillar23
+ 0: caterpillar caterpillar23
+ 1: caterpillar
+ 2: erpillar
+ 3: <unset>
+ 4:
+ 5: 3
+
+
+/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/
+ From abcd Mon Sep 01 12:33:02 1997
+ 0: From abcd Mon Sep 01 12:33
+ 1: abcd
+
+/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}[0-9]{1,2}\s+[0-9][0-9]:[0-9][0-9]/
+ From abcd Mon Sep 01 12:33:02 1997
+ 0: From abcd Mon Sep 01 12:33
+ 1: Sep
+ From abcd Mon Sep 1 12:33:02 1997
+ 0: From abcd Mon Sep 1 12:33
+ 1: Sep
+ *** Failers
+No match
+ From abcd Sep 01 12:33:02 1997
+No match
+
+/^(a)\1{2,3}(.)/
+ aaab
+ 0: aaab
+ 1: a
+ 2: b
+ aaaab
+ 0: aaaab
+ 1: a
+ 2: b
+ aaaaab
+ 0: aaaaa
+ 1: a
+ 2: a
+ aaaaaab
+ 0: aaaaa
+ 1: a
+ 2: a
+
+/^[ab]{1,3}(ab*|b)/
+ aabbbbb
+ 0: aabbbbb
+ 1: abbbbb
+
+/^(cow|)\1(bell)/
+ cowcowbell
+ 0: cowcowbell
+ 1: cow
+ 2: bell
+ bell
+ 0: bell
+ 1:
+ 2: bell
+ *** Failers
+No match
+ cowbell
+No match
+
+/^(a|)\1+b/
+ aab
+ 0: aab
+ 1: a
+ aaaab
+ 0: aaaab
+ 1: a
+ b
+ 0: b
+ 1:
+ *** Failers
+No match
+ ab
+No match
+
+/^(a|)\1{2}b/
+ aaab
+ 0: aaab
+ 1: a
+ b
+ 0: b
+ 1:
+ *** Failers
+No match
+ ab
+No match
+ aab
+No match
+ aaaab
+No match
+
+/^(a|)\1{2,3}b/
+ aaab
+ 0: aaab
+ 1: a
+ aaaab
+ 0: aaaab
+ 1: a
+ b
+ 0: b
+ 1:
+ *** Failers
+No match
+ ab
+No match
+ aab
+No match
+ aaaaab
+No match
+
+/ab{1,3}bc/
+ abbbbc
+ 0: abbbbc
+ abbbc
+ 0: abbbc
+ abbc
+ 0: abbc
+ *** Failers
+No match
+ abc
+No match
+ abbbbbc
+No match
+
+/([^.]*)\.([^:]*):[T ]+(.*)/
+ track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/([^.]*)\.([^:]*):[T ]+(.*)/i
+ track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/([^.]*)\.([^:]*):[t ]+(.*)/i
+ track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/^abc$/
+ abc
+ 0: abc
+ *** Failers
+No match
+
+/[-az]+/
+ az-
+ 0: az-
+ *** Failers
+ 0: a
+ b
+No match
+
+/[az-]+/
+ za-
+ 0: za-
+ *** Failers
+ 0: a
+ b
+No match
+
+/[a-z]+/
+ abcdxyz
+ 0: abcdxyz
+
+/[0-9-]+/
+ 12-34
+ 0: 12-34
+ *** Failers
+No match
+ aaa
+No match
+
+/(abc)\1/i
+ abcabc
+ 0: abcabc
+ 1: abc
+ ABCabc
+ 0: ABCabc
+ 1: ABC
+ abcABC
+ 0: abcABC
+ 1: abc
+
+/a{0}bc/
+ bc
+ 0: bc
+
+/^([^a])([^b])([^c]*)([^d]{3,4})/
+ baNOTccccd
+ 0: baNOTcccc
+ 1: b
+ 2: a
+ 3: NOT
+ 4: cccc
+ baNOTcccd
+ 0: baNOTccc
+ 1: b
+ 2: a
+ 3: NOT
+ 4: ccc
+ baNOTccd
+ 0: baNOTcc
+ 1: b
+ 2: a
+ 3: NO
+ 4: Tcc
+ bacccd
+ 0: baccc
+ 1: b
+ 2: a
+ 3:
+ 4: ccc
+ *** Failers
+ 0: *** Failers
+ 1: *
+ 2: *
+ 3: * Fail
+ 4: ers
+ anything
+No match
+ baccd
+No match
+
+/[^a]/
+ Abc
+ 0: A
+
+/[^a]/i
+ Abc
+ 0: b
+
+/[^a]+/
+ AAAaAbc
+ 0: AAA
+
+/[^a]+/i
+ AAAaAbc
+ 0: bc
+
+/[^k]$/
+ abc
+ 0: c
+ *** Failers
+ 0: s
+ abk
+No match
+
+/[^k]{2,3}$/
+ abc
+ 0: abc
+ kbc
+ 0: bc
+ kabc
+ 0: abc
+ *** Failers
+ 0: ers
+ abk
+No match
+ akb
+No match
+ akk
+No match
+
+/^[0-9]{8,}@.+[^k]$/
+ 12345678@a.b.c.d
+ 0: 12345678@a.b.c.d
+ 123456789@x.y.z
+ 0: 123456789@x.y.z
+ *** Failers
+No match
+ 12345678@x.y.uk
+No match
+ 1234567@a.b.c.d
+No match
+
+/(a)\1{8,}/
+ aaaaaaaaa
+ 0: aaaaaaaaa
+ 1: a
+ aaaaaaaaaa
+ 0: aaaaaaaaaa
+ 1: a
+ *** Failers
+No match
+ aaaaaaa
+No match
+
+/[^a]/
+ aaaabcd
+ 0: b
+ aaAabcd
+ 0: A
+
+/[^a]/i
+ aaaabcd
+ 0: b
+ aaAabcd
+ 0: b
+
+/[^az]/
+ aaaabcd
+ 0: b
+ aaAabcd
+ 0: A
+
+/[^az]/i
+ aaaabcd
+ 0: b
+ aaAabcd
+ 0: b
+
+/P[^*]TAIRE[^*]{1,6}LL/
+ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx
+ 0: PSTAIREISLL
+
+/P[^*]TAIRE[^*]{1,}LL/
+ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx
+ 0: PSTAIREISLL
+
+/(\.[0-9][0-9][1-9]?)[0-9]+/
+ 1.230003938
+ 0: .230003938
+ 1: .23
+ 1.875000282
+ 0: .875000282
+ 1: .875
+ 1.235
+ 0: .235
+ 1: .23
+
+/\b(foo)\s+(\w+)/i
+ Food is on the foo table
+ 0: foo table
+ 1: foo
+ 2: table
+
+/foo(.*)bar/
+ The food is under the bar in the barn.
+ 0: food is under the bar in the bar
+ 1: d is under the bar in the
+
+/(.*)([0-9]*)/
+ I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 53147
+ 2:
+
+/(.*)([0-9]+)/
+ I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 5314
+ 2: 7
+
+/(.*)([0-9]+)$/
+ I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 5314
+ 2: 7
+
+/(.*)\b([0-9]+)$/
+ I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers:
+ 2: 53147
+
+/(.*[^0-9])([0-9]+)$/
+ I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers:
+ 2: 53147
+
+/[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]][[:digit:]][[:digit:]]/
+ 01/01/2000
+ 0: 01/01/2000
+
+/^(a){0,0}/
+ bcd
+ 0:
+ abc
+ 0:
+ aab
+ 0:
+
+/^(a){0,1}/
+ bcd
+ 0:
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: a
+ 1: a
+
+/^(a){0,2}/
+ bcd
+ 0:
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+
+/^(a){0,3}/
+ bcd
+ 0:
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+ aaa
+ 0: aaa
+ 1: a
+
+/^(a){0,}/
+ bcd
+ 0:
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+ aaa
+ 0: aaa
+ 1: a
+ aaaaaaaa
+ 0: aaaaaaaa
+ 1: a
+
+/^(a){1,1}/
+ bcd
+No match
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: a
+ 1: a
+
+/^(a){1,2}/
+ bcd
+No match
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+
+/^(a){1,3}/
+ bcd
+No match
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+ aaa
+ 0: aaa
+ 1: a
+
+/^(a){1,}/
+ bcd
+No match
+ abc
+ 0: a
+ 1: a
+ aab
+ 0: aa
+ 1: a
+ aaa
+ 0: aaa
+ 1: a
+ aaaaaaaa
+ 0: aaaaaaaa
+ 1: a
+
+/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/
+ 123456654321
+ 0: 123456654321
+
+/^[[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]]/
+ 123456654321
+ 0: 123456654321
+
+/^[abc]{12}/
+ abcabcabcabc
+ 0: abcabcabcabc
+
+/^[a-c]{12}/
+ abcabcabcabc
+ 0: abcabcabcabc
+
+/^(a|b|c){12}/
+ abcabcabcabc
+ 0: abcabcabcabc
+ 1: c
+
+/^[abcdefghijklmnopqrstuvwxy0123456789]/
+ n
+ 0: n
+ *** Failers
+No match
+ z
+No match
+
+/abcde{0,0}/
+ abcd
+ 0: abcd
+ *** Failers
+No match
+ abce
+No match
+
+/ab[cd]{0,0}e/
+ abe
+ 0: abe
+ *** Failers
+No match
+ abcde
+No match
+
+/ab(c){0,0}d/
+ abd
+ 0: abd
+ *** Failers
+No match
+ abcd
+No match
+
+/a(b*)/
+ a
+ 0: a
+ 1:
+ ab
+ 0: ab
+ 1: b
+ abbbb
+ 0: abbbb
+ 1: bbbb
+ *** Failers
+ 0: a
+ 1:
+ bbbbb
+No match
+
+/ab[0-9]{0}e/
+ abe
+ 0: abe
+ *** Failers
+No match
+ ab1e
+No match
+
+/(A|B)*CD/
+ CD
+ 0: CD
+
+/(AB)*\1/
+ ABABAB
+ 0: ABABAB
+ 1: AB
+
+/([0-9]+)(\w)/
+ 12345a
+ 0: 12345a
+ 1: 12345
+ 2: a
+ 12345+
+ 0: 12345
+ 1: 1234
+ 2: 5
+
+/(abc|)+/
+ abc
+ 0: abc
+ 1: abc
+ abcabc
+ 0: abcabc
+ 1: abc
+ abcabcabc
+ 0: abcabcabc
+ 1: abc
+ xyz
+ 0:
+ 1:
+
+/([a]*)*/
+ a
+ 0: a
+ 1: a
+ aaaaa
+ 0: aaaaa
+ 1: aaaaa
+
+/([ab]*)*/
+ a
+ 0: a
+ 1: a
+ b
+ 0: b
+ 1: b
+ ababab
+ 0: ababab
+ 1: ababab
+ aaaabcde
+ 0: aaaab
+ 1: aaaab
+ bbbb
+ 0: bbbb
+ 1: bbbb
+
+/([^a]*)*/
+ b
+ 0: b
+ 1: b
+ bbbb
+ 0: bbbb
+ 1: bbbb
+ aaa
+ 0:
+
+/([^ab]*)*/
+ cccc
+ 0: cccc
+ 1: cccc
+ abab
+ 0:
+
+/abc/
+ abc
+ 0: abc
+ xabcy
+ 0: abc
+ ababc
+ 0: abc
+ *** Failers
+No match
+ xbc
+No match
+ axc
+No match
+ abx
+No match
+
+/ab*c/
+ abc
+ 0: abc
+
+/ab*bc/
+ abc
+ 0: abc
+ abbc
+ 0: abbc
+ abbbbc
+ 0: abbbbc
+
+/.{1}/
+ abbbbc
+ 0: a
+
+/.{3,4}/
+ abbbbc
+ 0: abbb
+
+/ab{0,}bc/
+ abbbbc
+ 0: abbbbc
+
+/ab+bc/
+ abbc
+ 0: abbc
+ *** Failers
+No match
+ abc
+No match
+ abq
+No match
+
+/ab+bc/
+ abbbbc
+ 0: abbbbc
+
+/ab{1,}bc/
+ abbbbc
+ 0: abbbbc
+
+/ab{1,3}bc/
+ abbbbc
+ 0: abbbbc
+
+/ab{3,4}bc/
+ abbbbc
+ 0: abbbbc
+
+/ab{4,5}bc/
+ *** Failers
+No match
+ abq
+No match
+ abbbbc
+No match
+
+/ab?bc/
+ abbc
+ 0: abbc
+ abc
+ 0: abc
+
+/ab{0,1}bc/
+ abc
+ 0: abc
+
+/ab?c/
+ abc
+ 0: abc
+
+/ab{0,1}c/
+ abc
+ 0: abc
+
+/^abc$/
+ abc
+ 0: abc
+ *** Failers
+No match
+ abbbbc
+No match
+ abcc
+No match
+
+/^abc/
+ abcc
+ 0: abc
+
+/abc$/
+ aabc
+ 0: abc
+ *** Failers
+No match
+ aabc
+ 0: abc
+ aabcd
+No match
+
+/^/
+ abc
+ 0:
+
+/$/
+ abc
+ 0:
+
+/a.c/
+ abc
+ 0: abc
+ axc
+ 0: axc
+
+/a.*c/
+ axyzc
+ 0: axyzc
+
+/a[bc]d/
+ abd
+ 0: abd
+ *** Failers
+No match
+ axyzd
+No match
+ abc
+No match
+
+/a[b-d]e/
+ ace
+ 0: ace
+
+/a[b-d]/
+ aac
+ 0: ac
+
+/a[-b]/
+ a-
+ 0: a-
+
+/a[b-]/
+ a-
+ 0: a-
+
+/a[]]b/
+ a]b
+ 0: a]b
+
+/a[^bc]d/
+ aed
+ 0: aed
+ *** Failers
+No match
+ abd
+No match
+ abd
+No match
+
+/a[^-b]c/
+ adc
+ 0: adc
+
+/a[^]b]c/
+ adc
+ 0: adc
+ *** Failers
+No match
+ a-c
+ 0: a-c
+ a]c
+No match
+
+/\ba\b/
+ a-
+ 0: a
+ -a
+ 0: a
+ -a-
+ 0: a
+
+/\by\b/
+ *** Failers
+No match
+ xy
+No match
+ yz
+No match
+ xyz
+No match
+
+/\Ba\B/
+ *** Failers
+ 0: a
+ a-
+No match
+ -a
+No match
+ -a-
+No match
+
+/\By\b/
+ xy
+ 0: y
+
+/\by\B/
+ yz
+ 0: y
+
+/\By\B/
+ xyz
+ 0: y
+
+/\w/
+ a
+ 0: a
+
+/\W/
+ -
+ 0: -
+ *** Failers
+ 0: *
+ -
+ 0: -
+ a
+No match
+
+/a\sb/
+ a b
+ 0: a b
+
+/a\Sb/
+ a-b
+ 0: a-b
+ *** Failers
+No match
+ a-b
+ 0: a-b
+ a b
+No match
+
+/[0-9]/
+ 1
+ 0: 1
+
+/[^0-9]/
+ -
+ 0: -
+ *** Failers
+ 0: *
+ -
+ 0: -
+ 1
+No match
+
+/ab|cd/
+ abc
+ 0: ab
+ abcd
+ 0: ab
+
+/()ef/
+ def
+ 0: ef
+ 1:
+
+/a\(b/
+ a(b
+ 0: a(b
+
+/a\(*b/
+ ab
+ 0: ab
+ a((b
+ 0: a((b
+
+/((a))/
+ abc
+ 0: a
+ 1: a
+ 2: a
+
+/(a)b(c)/
+ abc
+ 0: abc
+ 1: a
+ 2: c
+
+/a+b+c/
+ aabbabc
+ 0: abc
+
+/a{1,}b{1,}c/
+ aabbabc
+ 0: abc
+
+/(a+|b)*/
+ ab
+ 0: ab
+ 1: b
+
+/(a+|b){0,}/
+ ab
+ 0: ab
+ 1: b
+
+/(a+|b)+/
+ ab
+ 0: ab
+ 1: b
+
+/(a+|b){1,}/
+ ab
+ 0: ab
+ 1: b
+
+/(a+|b)?/
+ ab
+ 0: a
+ 1: a
+
+/(a+|b){0,1}/
+ ab
+ 0: a
+ 1: a
+
+/[^ab]*/
+ cde
+ 0: cde
+
+/abc/
+ *** Failers
+No match
+ b
+No match
+
+
+/a*/
+
+
+/([abc])*d/
+ abbbcd
+ 0: abbbcd
+ 1: c
+
+/([abc])*bcd/
+ abcd
+ 0: abcd
+ 1: a
+
+/a|b|c|d|e/
+ e
+ 0: e
+
+/(a|b|c|d|e)f/
+ ef
+ 0: ef
+ 1: e
+
+/abcd*efg/
+ abcdefg
+ 0: abcdefg
+
+/ab*/
+ xabyabbbz
+ 0: ab
+ xayabbbz
+ 0: a
+
+/(ab|cd)e/
+ abcde
+ 0: cde
+ 1: cd
+
+/[abhgefdc]ij/
+ hij
+ 0: hij
+
+/(abc|)ef/
+ abcdef
+ 0: ef
+ 1:
+
+/(a|b)c*d/
+ abcd
+ 0: bcd
+ 1: b
+
+/(ab|ab*)bc/
+ abc
+ 0: abc
+ 1: a
+
+/a([bc]*)c*/
+ abc
+ 0: abc
+ 1: bc
+
+/a([bc]*)(c*d)/
+ abcd
+ 0: abcd
+ 1: bc
+ 2: d
+
+/a([bc]+)(c*d)/
+ abcd
+ 0: abcd
+ 1: bc
+ 2: d
+
+/a([bc]*)(c+d)/
+ abcd
+ 0: abcd
+ 1: b
+ 2: cd
+
+/a[bcd]*dcdcde/
+ adcdcde
+ 0: adcdcde
+
+/a[bcd]+dcdcde/
+ *** Failers
+No match
+ abcde
+No match
+ adcdcde
+No match
+
+/(ab|a)b*c/
+ abc
+ 0: abc
+ 1: ab
+
+/((a)(b)c)(d)/
+ abcd
+ 0: abcd
+ 1: abc
+ 2: a
+ 3: b
+ 4: d
+
+/[a-zA-Z_][a-zA-Z0-9_]*/
+ alpha
+ 0: alpha
+
+/^a(bc+|b[eh])g|.h$/
+ abh
+ 0: bh
+
+/(bc+d$|ef*g.|h?i(j|k))/
+ effgz
+ 0: effgz
+ 1: effgz
+ ij
+ 0: ij
+ 1: ij
+ 2: j
+ reffgz
+ 0: effgz
+ 1: effgz
+ *** Failers
+No match
+ effg
+No match
+ bcdd
+No match
+
+/((((((((((a))))))))))/
+ a
+ 0: a
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+10: a
+
+/((((((((((a))))))))))\9/
+ aa
+ 0: aa
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+10: a
+
+/(((((((((a)))))))))/
+ a
+ 0: a
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+
+/multiple words of text/
+ *** Failers
+No match
+ aa
+No match
+ uh-uh
+No match
+
+/multiple words/
+ multiple words, yeah
+ 0: multiple words
+
+/(.*)c(.*)/
+ abcde
+ 0: abcde
+ 1: ab
+ 2: de
+
+/\((.*), (.*)\)/
+ (a, b)
+ 0: (a, b)
+ 1: a
+ 2: b
+
+/abcd/
+ abcd
+ 0: abcd
+
+/a(bc)d/
+ abcd
+ 0: abcd
+ 1: bc
+
+/a[-]?c/
+ ac
+ 0: ac
+
+/(abc)\1/
+ abcabc
+ 0: abcabc
+ 1: abc
+
+/([a-c]*)\1/
+ abcabc
+ 0: abcabc
+ 1: abc
+
+/(a)|\1/
+ a
+ 0: a
+ 1: a
+ *** Failers
+ 0: a
+ 1: a
+ ab
+ 0: a
+ 1: a
+ x
+No match
+
+/abc/i
+ ABC
+ 0: ABC
+ XABCY
+ 0: ABC
+ ABABC
+ 0: ABC
+ *** Failers
+No match
+ aaxabxbaxbbx
+No match
+ XBC
+No match
+ AXC
+No match
+ ABX
+No match
+
+/ab*c/i
+ ABC
+ 0: ABC
+
+/ab*bc/i
+ ABC
+ 0: ABC
+ ABBC
+ 0: ABBC
+
+/ab+bc/i
+ *** Failers
+No match
+ ABC
+No match
+ ABQ
+No match
+
+/ab+bc/i
+ ABBBBC
+ 0: ABBBBC
+
+/^abc$/i
+ ABC
+ 0: ABC
+ *** Failers
+No match
+ ABBBBC
+No match
+ ABCC
+No match
+
+/^abc/i
+ ABCC
+ 0: ABC
+
+/abc$/i
+ AABC
+ 0: ABC
+
+/^/i
+ ABC
+ 0:
+
+/$/i
+ ABC
+ 0:
+
+/a.c/i
+ ABC
+ 0: ABC
+ AXC
+ 0: AXC
+
+/a.*c/i
+ *** Failers
+No match
+ AABC
+ 0: AABC
+ AXYZD
+No match
+
+/a[bc]d/i
+ ABD
+ 0: ABD
+
+/a[b-d]e/i
+ ACE
+ 0: ACE
+ *** Failers
+No match
+ ABC
+No match
+ ABD
+No match
+
+/a[b-d]/i
+ AAC
+ 0: AC
+
+/a[-b]/i
+ A-
+ 0: A-
+
+/a[b-]/i
+ A-
+ 0: A-
+
+/a[]]b/i
+ A]B
+ 0: A]B
+
+/a[^bc]d/i
+ AED
+ 0: AED
+
+/a[^-b]c/i
+ ADC
+ 0: ADC
+ *** Failers
+No match
+ ABD
+No match
+ A-C
+No match
+
+/a[^]b]c/i
+ ADC
+ 0: ADC
+
+/ab|cd/i
+ ABC
+ 0: AB
+ ABCD
+ 0: AB
+
+/()ef/i
+ DEF
+ 0: EF
+ 1:
+
+/$b/i
+ *** Failers
+No match
+ A]C
+No match
+ B
+No match
+
+/a\(b/i
+ A(B
+ 0: A(B
+
+/a\(*b/i
+ AB
+ 0: AB
+ A((B
+ 0: A((B
+
+/((a))/i
+ ABC
+ 0: A
+ 1: A
+ 2: A
+
+/(a)b(c)/i
+ ABC
+ 0: ABC
+ 1: A
+ 2: C
+
+/a+b+c/i
+ AABBABC
+ 0: ABC
+
+/a{1,}b{1,}c/i
+ AABBABC
+ 0: ABC
+
+/(a+|b)*/i
+ AB
+ 0: AB
+ 1: B
+
+/(a+|b){0,}/i
+ AB
+ 0: AB
+ 1: B
+
+/(a+|b)+/i
+ AB
+ 0: AB
+ 1: B
+
+/(a+|b){1,}/i
+ AB
+ 0: AB
+ 1: B
+
+/(a+|b)?/i
+ AB
+ 0: A
+ 1: A
+
+/(a+|b){0,1}/i
+ AB
+ 0: A
+ 1: A
+
+/[^ab]*/i
+ CDE
+ 0: CDE
+
+/([abc])*d/i
+ ABBBCD
+ 0: ABBBCD
+ 1: C
+
+/([abc])*bcd/i
+ ABCD
+ 0: ABCD
+ 1: A
+
+/a|b|c|d|e/i
+ E
+ 0: E
+
+/(a|b|c|d|e)f/i
+ EF
+ 0: EF
+ 1: E
+
+/abcd*efg/i
+ ABCDEFG
+ 0: ABCDEFG
+
+/ab*/i
+ XABYABBBZ
+ 0: AB
+ XAYABBBZ
+ 0: A
+
+/(ab|cd)e/i
+ ABCDE
+ 0: CDE
+ 1: CD
+
+/[abhgefdc]ij/i
+ HIJ
+ 0: HIJ
+
+/^(ab|cd)e/i
+ ABCDE
+No match
+
+/(abc|)ef/i
+ ABCDEF
+ 0: EF
+ 1:
+
+/(a|b)c*d/i
+ ABCD
+ 0: BCD
+ 1: B
+
+/(ab|ab*)bc/i
+ ABC
+ 0: ABC
+ 1: A
+
+/a([bc]*)c*/i
+ ABC
+ 0: ABC
+ 1: BC
+
+/a([bc]*)(c*d)/i
+ ABCD
+ 0: ABCD
+ 1: BC
+ 2: D
+
+/a([bc]+)(c*d)/i
+ ABCD
+ 0: ABCD
+ 1: BC
+ 2: D
+
+/a([bc]*)(c+d)/i
+ ABCD
+ 0: ABCD
+ 1: B
+ 2: CD
+
+/a[bcd]*dcdcde/i
+ ADCDCDE
+ 0: ADCDCDE
+
+/a[bcd]+dcdcde/i
+
+/(ab|a)b*c/i
+ ABC
+ 0: ABC
+ 1: AB
+
+/((a)(b)c)(d)/i
+ ABCD
+ 0: ABCD
+ 1: ABC
+ 2: A
+ 3: B
+ 4: D
+
+/[a-zA-Z_][a-zA-Z0-9_]*/i
+ ALPHA
+ 0: ALPHA
+
+/^a(bc+|b[eh])g|.h$/i
+ ABH
+ 0: BH
+
+/(bc+d$|ef*g.|h?i(j|k))/i
+ EFFGZ
+ 0: EFFGZ
+ 1: EFFGZ
+ IJ
+ 0: IJ
+ 1: IJ
+ 2: J
+ REFFGZ
+ 0: EFFGZ
+ 1: EFFGZ
+ *** Failers
+No match
+ ADCDCDE
+No match
+ EFFG
+No match
+ BCDD
+No match
+
+/((((((((((a))))))))))/i
+ A
+ 0: A
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+10: A
+
+/((((((((((a))))))))))\9/i
+ AA
+ 0: AA
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+10: A
+
+/(((((((((a)))))))))/i
+ A
+ 0: A
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+
+/multiple words of text/i
+ *** Failers
+No match
+ AA
+No match
+ UH-UH
+No match
+
+/multiple words/i
+ MULTIPLE WORDS, YEAH
+ 0: MULTIPLE WORDS
+
+/(.*)c(.*)/i
+ ABCDE
+ 0: ABCDE
+ 1: AB
+ 2: DE
+
+/\((.*), (.*)\)/i
+ (A, B)
+ 0: (A, B)
+ 1: A
+ 2: B
+
+/abcd/i
+ ABCD
+ 0: ABCD
+
+/a(bc)d/i
+ ABCD
+ 0: ABCD
+ 1: BC
+
+/a[-]?c/i
+ AC
+ 0: AC
+
+/(abc)\1/i
+ ABCABC
+ 0: ABCABC
+ 1: ABC
+
+/([a-c]*)\1/i
+ ABCABC
+ 0: ABCABC
+ 1: ABC
+
+/((foo)|(bar))*/
+ foobar
+ 0: foobar
+ 1: bar
+ 2: foo
+ 3: bar
+
+/^(.+)?B/
+ AB
+ 0: AB
+ 1: A
+
+/^([^a-z])|(\^)$/
+ .
+ 0: .
+ 1: .
+
+/^[<>]&/
+ <&OUT
+ 0: <&
+
+/^(){3,5}/
+ abc
+ 0:
+ 1:
+
+/^(a+)*ax/
+ aax
+ 0: aax
+ 1: a
+
+/^((a|b)+)*ax/
+ aax
+ 0: aax
+ 1: a
+ 2: a
+
+/^((a|bc)+)*ax/
+ aax
+ 0: aax
+ 1: a
+ 2: a
+
+/(a|x)*ab/
+ cab
+ 0: ab
+
+/(a)*ab/
+ cab
+ 0: ab
+
+/(ab)[0-9]\1/i
+ Ab4ab
+ 0: Ab4ab
+ 1: Ab
+ ab4Ab
+ 0: ab4Ab
+ 1: ab
+
+/foo\w*[0-9]{4}baz/
+ foobar1234baz
+ 0: foobar1234baz
+
+/(\w+:)+/
+ one:
+ 0: one:
+ 1: one:
+
+/((\w|:)+::)?(\w+)$/
+ abcd
+ 0: abcd
+ 1: <unset>
+ 2: <unset>
+ 3: abcd
+ xy:z:::abcd
+ 0: xy:z:::abcd
+ 1: xy:z:::
+ 2: :
+ 3: abcd
+
+/^[^bcd]*(c+)/
+ aexycd
+ 0: aexyc
+ 1: c
+
+/(a*)b+/
+ caab
+ 0: aab
+ 1: aa
+
+/((\w|:)+::)?(\w+)$/
+ abcd
+ 0: abcd
+ 1: <unset>
+ 2: <unset>
+ 3: abcd
+ xy:z:::abcd
+ 0: xy:z:::abcd
+ 1: xy:z:::
+ 2: :
+ 3: abcd
+ *** Failers
+ 0: Failers
+ 1: <unset>
+ 2: <unset>
+ 3: Failers
+ abcd:
+No match
+ abcd:
+No match
+
+/^[^bcd]*(c+)/
+ aexycd
+ 0: aexyc
+ 1: c
+
+/((Z)+|A)*/
+ ZABCDEFG
+ 0: ZA
+ 1: A
+ 2: Z
+
+/(Z()|A)*/
+ ZABCDEFG
+ 0: ZA
+ 1: A
+ 2:
+
+/(Z(())|A)*/
+ ZABCDEFG
+ 0: ZA
+ 1: A
+ 2:
+ 3:
+
+/(.*)[0-9]+\1/
+ abc123abc
+ 0: abc123abc
+ 1: abc
+ abc123bc
+ 0: bc123bc
+ 1: bc
+
+/((.*))[0-9]+\1/
+ abc123abc
+ 0: abc123abc
+ 1: abc
+ 2: abc
+ abc123bc
+ 0: bc123bc
+ 1: bc
+ 2: bc
+
+/^a{2,5}$/
+ aa
+ 0: aa
+ aaa
+ 0: aaa
+ aaaa
+ 0: aaaa
+ aaaaa
+ 0: aaaaa
+ *** Failers
+No match
+ a
+No match
+ b
+No match
+ aaaaab
+No match
+ aaaaaa
diff --git a/test/src/regex-resources/PTESTS b/test/src/regex-resources/PTESTS
new file mode 100644
index 00000000000..68acc314d37
--- /dev/null
+++ b/test/src/regex-resources/PTESTS
@@ -0,0 +1,341 @@
+# 2.8.2 Regular Expression General Requirement
+2¦4¦bb*¦abbbc¦
+2¦2¦bb*¦ababbbc¦
+7¦9¦A#*::¦A:A#:qA::qA#::qA##::q¦
+1¦5¦A#*::¦A##::A#::qA::qA#:q¦
+# 2.8.3.1.2 BRE Special Characters
+# GA108
+2¦2¦\.¦a.c¦
+2¦2¦\[¦a[c¦
+2¦2¦\\¦a\c¦
+2¦2¦\*¦a*c¦
+2¦2¦\^¦a^c¦
+2¦2¦\$¦a$c¦
+7¦11¦X\*Y\*8¦Y*8X*8X*Y*8¦
+# GA109
+2¦2¦[.]¦a.c¦
+2¦2¦[[]¦a[c¦
+-1¦-1¦[[]¦ac¦
+2¦2¦[\]¦a\c¦
+1¦1¦[\a]¦abc¦
+2¦2¦[\.]¦a\.c¦
+2¦2¦[\.]¦a.\c¦
+2¦2¦[*]¦a*c¦
+2¦2¦[$]¦a$c¦
+2¦2¦[X*Y8]¦7*8YX¦
+# GA110
+2¦2¦*¦a*c¦
+3¦4¦*a¦*b*a*c¦
+1¦5¦**9=¦***9=9¦
+# GA111
+1¦1¦^*¦*bc¦
+-1¦-1¦^*¦a*c¦
+-1¦-1¦^*¦^*ab¦
+1¦5¦^**9=¦***9=¦
+-1¦-1¦^*5<*9¦5<9*5<*9¦
+# GA112
+2¦3¦\(*b\)¦a*b¦
+-1¦-1¦\(*b\)¦ac¦
+1¦6¦A\(**9\)=¦A***9=79¦
+# GA113(1)
+1¦3¦\(^*ab\)¦*ab¦
+-1¦-1¦\(^*ab\)¦^*ab¦
+-1¦-1¦\(^*b\)¦a*b¦
+-1¦-1¦\(^*b\)¦^*b¦
+### GA113(2) GNU regex implements GA113(1)
+##-1¦-1¦\(^*ab\)¦*ab¦
+##-1¦-1¦\(^*ab\)¦^*ab¦
+##1¦1¦\(^*b\)¦b¦
+##1¦3¦\(^*b\)¦^^b¦
+# GA114
+1¦3¦a^b¦a^b¦
+1¦3¦a\^b¦a^b¦
+1¦1¦^^¦^bc¦
+2¦2¦\^¦a^c¦
+1¦1¦[c^b]¦^abc¦
+1¦1¦[\^ab]¦^ab¦
+2¦2¦[\^ab]¦c\d¦
+-1¦-1¦[^^]¦^¦
+1¦3¦\(a^b\)¦a^b¦
+1¦3¦\(a\^b\)¦a^b¦
+2¦2¦\(\^\)¦a^b¦
+# GA115
+3¦3¦$$¦ab$¦
+-1¦-1¦$$¦$ab¦
+2¦3¦$c¦a$c¦
+2¦2¦[$]¦a$c¦
+1¦2¦\$a¦$a¦
+3¦3¦\$$¦ab$¦
+2¦6¦A\([34]$[34]\)B¦XA4$3BY¦
+# 2.8.3.1.3 Periods in BREs
+# GA116
+1¦1¦.¦abc¦
+-1¦-1¦.ab¦abc¦
+1¦3¦ab.¦abc¦
+1¦3¦a.b¦a,b¦
+-1¦-1¦.......¦PqRs6¦
+1¦7¦.......¦PqRs6T8¦
+# 2.8.3.2 RE Bracket Expression
+# GA118
+2¦2¦[abc]¦xbyz¦
+-1¦-1¦[abc]¦xyz¦
+2¦2¦[abc]¦xbay¦
+# GA119
+2¦2¦[^a]¦abc¦
+4¦4¦[^]cd]¦cd]ef¦
+2¦2¦[^abc]¦axyz¦
+-1¦-1¦[^abc]¦abc¦
+3¦3¦[^[.a.]b]¦abc¦
+3¦3¦[^[=a=]b]¦abc¦
+2¦2¦[^-ac]¦abcde-¦
+2¦2¦[^ac-]¦abcde-¦
+3¦3¦[^a-b]¦abcde¦
+3¦3¦[^a-bd-e]¦dec¦
+2¦2¦[^---]¦-ab¦
+16¦16¦[^a-zA-Z0-9]¦pqrstVWXYZ23579#¦
+# GA120(1)
+3¦3¦[]a]¦cd]ef¦
+1¦1¦[]-a]¦a_b¦
+3¦3¦[][.-.]-0]¦ab0-]¦
+1¦1¦[]^a-z]¦string¦
+# GA120(2)
+4¦4¦[^]cd]¦cd]ef¦
+0¦0¦[^]]*¦]]]]]]]]X¦
+0¦0¦[^]]*¦]]]]]]]]¦
+9¦9¦[^]]\{1,\}¦]]]]]]]]X¦
+-1¦-1¦[^]]\{1,\}¦]]]]]]]]¦
+# GA120(3)
+3¦3¦[c[.].]d]¦ab]cd¦
+2¦8¦[a-z]*[[.].]][A-Z]*¦Abcd]DEFg¦
+# GA121
+2¦2¦[[.a.]b]¦Abc¦
+1¦1¦[[.a.]b]¦aBc¦
+-1¦-1¦[[.a.]b]¦ABc¦
+3¦3¦[^[.a.]b]¦abc¦
+3¦3¦[][.-.]-0]¦ab0-]¦
+3¦3¦[A-[.].]c]¦ab]!¦
+# GA122
+-2¦-2¦[[.ch.]]¦abc¦
+-2¦-2¦[[.ab.][.CD.][.EF.]]¦yZabCDEFQ9¦
+# GA125
+2¦2¦[[=a=]b]¦Abc¦
+1¦1¦[[=a=]b]¦aBc¦
+-1¦-1¦[[=a=]b]¦ABc¦
+3¦3¦[^[=a=]b]¦abc¦
+# GA126
+#W the expected result for [[:alnum:]]* is 2-7 which is wrong
+0¦0¦[[:alnum:]]*¦ aB28gH¦
+2¦7¦[[:alnum:]][[:alnum:]]*¦ aB28gH¦
+#W the expected result for [^[:alnum:]]* is 2-5 which is wrong
+0¦0¦[^[:alnum:]]*¦2 ,a¦
+2¦5¦[^[:alnum:]][^[:alnum:]]*¦2 ,a¦
+#W the expected result for [[:alpha:]]* is 2-5 which is wrong
+0¦0¦[[:alpha:]]*¦ aBgH2¦
+2¦5¦[[:alpha:]][[:alpha:]]*¦ aBgH2¦
+1¦6¦[^[:alpha:]]*¦2 8,a¦
+1¦2¦[[:blank:]]*¦ ¦
+1¦8¦[^[:blank:]]*¦aB28gH, ¦
+1¦2¦[[:cntrl:]]*¦  ¦
+1¦8¦[^[:cntrl:]]*¦aB2 8gh,¦
+#W the expected result for [[:digit:]]* is 2-3 which is wrong
+0¦0¦[[:digit:]]*¦a28¦
+2¦3¦[[:digit:]][[:digit:]]*¦a28¦
+1¦8¦[^[:digit:]]*¦aB gH,¦
+1¦7¦[[:graph:]]*¦aB28gH, ¦
+1¦3¦[^[:graph:]]*¦ ,¦
+1¦2¦[[:lower:]]*¦agB¦
+1¦8¦[^[:lower:]]*¦B2 8H,a¦
+1¦8¦[[:print:]]*¦aB2 8gH, ¦
+1¦2¦[^[:print:]]*¦  ¦
+#W the expected result for [[:punct:]]* is 2-2 which is wrong
+0¦0¦[[:punct:]]*¦a,2¦
+2¦3¦[[:punct:]][[:punct:]]*¦a,,2¦
+1¦9¦[^[:punct:]]*¦aB2 8gH¦
+1¦3¦[[:space:]]*¦ ¦
+#W the expected result for [^[:space:]]* is 2-9 which is wrong
+0¦0¦[^[:space:]]*¦ aB28gH, ¦
+2¦9¦[^[:space:]][^[:space:]]*¦ aB28gH, ¦
+#W the expected result for [[:upper:]]* is 2-3 which is wrong
+0¦0¦[[:upper:]]*¦aBH2¦
+2¦3¦[[:upper:]][[:upper:]]*¦aBH2¦
+1¦8¦[^[:upper:]]*¦a2 8g,B¦
+#W the expected result for [[:xdigit:]]* is 2-5 which is wrong
+0¦0¦[[:xdigit:]]*¦gaB28h¦
+2¦5¦[[:xdigit:]][[:xdigit:]]*¦gaB28h¦
+#W the expected result for [^[:xdigit:]]* is 2-7 which is wrong
+2¦7¦[^[:xdigit:]][^[:xdigit:]]*¦a gH,2¦
+# GA127
+-2¦-2¦[b-a]¦abc¦
+1¦1¦[a-c]¦bbccde¦
+2¦2¦[a-b]¦-bc¦
+3¦3¦[a-z0-9]¦AB0¦
+3¦3¦[^a-b]¦abcde¦
+3¦3¦[^a-bd-e]¦dec¦
+1¦1¦[]-a]¦a_b¦
+2¦2¦[+--]¦a,b¦
+2¦2¦[--/]¦a.b¦
+2¦2¦[^---]¦-ab¦
+3¦3¦[][.-.]-0]¦ab0-]¦
+3¦3¦[A-[.].]c]¦ab]!¦
+2¦6¦bc[d-w]xy¦abchxyz¦
+# GA129
+1¦1¦[a-cd-f]¦dbccde¦
+-1¦-1¦[a-ce-f]¦dBCCdE¦
+2¦4¦b[n-zA-M]Y¦absY9Z¦
+2¦4¦b[n-zA-M]Y¦abGY9Z¦
+# GA130
+3¦3¦[-xy]¦ac-¦
+2¦4¦c[-xy]D¦ac-D+¦
+2¦2¦[--/]¦a.b¦
+2¦4¦c[--/]D¦ac.D+b¦
+2¦2¦[^-ac]¦abcde-¦
+1¦3¦a[^-ac]c¦abcde-¦
+3¦3¦[xy-]¦zc-¦
+2¦4¦c[xy-]7¦zc-786¦
+2¦2¦[^ac-]¦abcde-¦
+2¦4¦a[^ac-]c¦5abcde-¦
+2¦2¦[+--]¦a,b¦
+2¦4¦a[+--]B¦Xa,By¦
+2¦2¦[^---]¦-ab¦
+4¦6¦X[^---]Y¦X-YXaYXbY¦
+# 2.8.3.3 BREs Matching Multiple Characters
+# GA131
+3¦4¦cd¦abcdeabcde¦
+1¦2¦ag*b¦abcde¦
+-1¦-1¦[a-c][e-f]¦abcdef¦
+3¦4¦[a-c][e-f]¦acbedf¦
+4¦8¦abc*XYZ¦890abXYZ#*¦
+4¦9¦abc*XYZ¦890abcXYZ#*¦
+4¦15¦abc*XYZ¦890abcccccccXYZ#*¦
+-1¦-1¦abc*XYZ¦890abc*XYZ#*¦
+# GA132
+2¦4¦\(*bc\)¦a*bc¦
+1¦2¦\(ab\)¦abcde¦
+1¦10¦\(a\(b\(c\(d\(e\(f\(g\)h\(i\(j\)\)\)\)\)\)\)\)¦abcdefghijk¦
+3¦8¦43\(2\(6\)*0\)AB¦654320ABCD¦
+3¦9¦43\(2\(7\)*0\)AB¦6543270ABCD¦
+3¦12¦43\(2\(7\)*0\)AB¦6543277770ABCD¦
+# GA133
+1¦10¦\(a\(b\(c\(d\(e\(f\(g\)h\(i\(j\)\)\)\)\)\)\)\)¦abcdefghijk¦
+-1¦-1¦\(a\(b\(c\(d\(e\(f\(g\)h\(i\(k\)\)\)\)\)\)\)\)¦abcdefghijk¦
+# GA134
+2¦4¦\(bb*\)¦abbbc¦
+2¦2¦\(bb*\)¦ababbbc¦
+1¦6¦a\(.*b\)¦ababbbc¦
+1¦2¦a\(b*\)¦ababbbc¦
+1¦20¦a\(.*b\)c¦axcaxbbbcsxbbbbbbbbc¦
+# GA135
+1¦7¦\(a\(b\(c\(d\(e\)\)\)\)\)\4¦abcdededede¦
+#W POSIX does not really specify whether a\(b\)*c\1 matches acb.
+#W back references are supposed to expand to the last match, but what
+#W if there never was a match as in this case?
+-1¦-1¦a\(b\)*c\1¦acb¦
+1¦11¦\(a\(b\(c\(d\(e\(f\(g\)h\(i\(j\)\)\)\)\)\)\)\)\9¦abcdefghijjk¦
+# GA136
+#W These two tests have the same problem as the test in GA135. No match
+#W of a subexpression, why should the back reference be usable?
+#W 1 2 a\(b\)*c\1 acb
+#W 4 7 a\(b\(c\(d\(f\)*\)\)\)\4¦xYzabcdePQRST
+-1¦-1¦a\(b\)*c\1¦acb¦
+-1¦-1¦a\(b\(c\(d\(f\)*\)\)\)\4¦xYzabcdePQRST¦
+# GA137
+-2¦-2¦\(a\(b\)\)\3¦foo¦
+-2¦-2¦\(a\(b\)\)\(a\(b\)\)\5¦foo¦
+# GA138
+1¦2¦ag*b¦abcde¦
+1¦10¦a.*b¦abababvbabc¦
+2¦5¦b*c¦abbbcdeabbbbbbcde¦
+2¦5¦bbb*c¦abbbcdeabbbbbbcde¦
+1¦5¦a\(b\)*c\1¦abbcbbb¦
+-1¦-1¦a\(b\)*c\1¦abbdbd¦
+0¦0¦\([a-c]*\)\1¦abcacdef¦
+1¦6¦\([a-c]*\)\1¦abcabcabcd¦
+1¦2¦a^*b¦ab¦
+1¦5¦a^*b¦a^^^b¦
+# GA139
+1¦2¦a\{2\}¦aaaa¦
+1¦7¦\([a-c]*\)\{0,\}¦aabcaab¦
+1¦2¦\(a\)\1\{1,2\}¦aabc¦
+1¦3¦\(a\)\1\{1,2\}¦aaaabc¦
+#W the expression \(\(a\)\1\)\{1,2\} is ill-formed, using \2
+1¦4¦\(\(a\)\2\)\{1,2\}¦aaaabc¦
+# GA140
+1¦2¦a\{2\}¦aaaa¦
+-1¦-1¦a\{2\}¦abcd¦
+0¦0¦a\{0\}¦aaaa¦
+1¦64¦a\{64\}¦aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa¦
+# GA141
+1¦7¦\([a-c]*\)\{0,\}¦aabcaab¦
+#W the expected result for \([a-c]*\)\{2,\} is failure which isn't correct
+1¦3¦\([a-c]*\)\{2,\}¦abcdefg¦
+1¦3¦\([a-c]*\)\{1,\}¦abcdefg¦
+-1¦-1¦a\{64,\}¦aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa¦
+# GA142
+1¦3¦a\{2,3\}¦aaaa¦
+-1¦-1¦a\{2,3\}¦abcd¦
+0¦0¦\([a-c]*\)\{0,0\}¦foo¦
+1¦63¦a\{1,63\}¦aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa¦
+# 2.8.3.4 BRE Precedence
+# GA143
+#W There are numerous bugs in the original version.
+2¦19¦\^\[[[.].]]\\(\\1\\)\*\\{1,2\\}\$¦a^[]\(\1\)*\{1,2\}$b¦
+1¦6¦[[=*=]][[=\=]][[=]=]][[===]][[...]][[:punct:]]¦*\]=.;¦
+1¦6¦[$\(*\)^]*¦$\()*^¦
+1¦1¦[\1]¦1¦
+1¦1¦[\{1,2\}]¦{¦
+#W the expected result for \(*\)*\1* is 2-2 which isn't correct
+0¦0¦\(*\)*\1*¦a*b*11¦
+2¦3¦\(*\)*\1*b¦a*b*11¦
+#W the expected result for \(a\(b\{1,2\}\)\{1,2\}\) is 1-5 which isn't correct
+1¦3¦\(a\(b\{1,2\}\)\{1,2\}\)¦abbab¦
+1¦5¦\(a\(b\{1,2\}\)\)\{1,2\}¦abbab¦
+1¦1¦^\(^\(^a$\)$\)$¦a¦
+1¦2¦\(a\)\1$¦aa¦
+1¦3¦ab*¦abb¦
+1¦4¦ab\{2,4\}¦abbbc¦
+# 2.8.3.5 BRE Expression Anchoring
+# GA144
+1¦1¦^a¦abc¦
+-1¦-1¦^b¦abc¦
+-1¦-1¦^[a-zA-Z]¦99Nine¦
+1¦4¦^[a-zA-Z]*¦Nine99¦
+# GA145(1)
+1¦2¦\(^a\)\1¦aabc¦
+-1¦-1¦\(^a\)\1¦^a^abc¦
+1¦2¦\(^^a\)¦^a¦
+1¦1¦\(^^\)¦^^¦
+1¦3¦\(^abc\)¦abcdef¦
+-1¦-1¦\(^def\)¦abcdef¦
+### GA145(2) GNU regex implements GA145(1)
+##-1¦-1¦\(^a\)\1¦aabc¦
+##1¦4¦\(^a\)\1¦^a^abc¦
+##-1¦-1¦\(^^a\)¦^a¦
+##1¦2¦\(^^\)¦^^¦
+# GA146
+3¦3¦a$¦cba¦
+-1¦-1¦a$¦abc¦
+5¦7¦[a-z]*$¦99ZZxyz¦
+#W the expected result for [a-z]*$ is failure which isn't correct
+10¦9¦[a-z]*$¦99ZZxyz99¦
+3¦3¦$$¦ab$¦
+-1¦-1¦$$¦$ab¦
+3¦3¦\$$¦ab$¦
+# GA147(1)
+-1¦-1¦\(a$\)\1¦bcaa¦
+-1¦-1¦\(a$\)\1¦ba$¦
+-1¦-1¦\(ab$\)¦ab$¦
+1¦2¦\(ab$\)¦ab¦
+4¦6¦\(def$\)¦abcdef¦
+-1¦-1¦\(abc$\)¦abcdef¦
+### GA147(2) GNU regex implements GA147(1)
+##-1¦-1¦\(a$\)\1¦bcaa¦
+##2¦5¦\(a$\)\1¦ba$a$¦
+##-1¦-1¦\(ab$\)¦ab¦
+##1¦3¦\(ab$\)¦ab$¦
+# GA148
+0¦0¦^$¦¦
+1¦3¦^abc$¦abc¦
+-1¦-1¦^xyz$¦^xyz^¦
+-1¦-1¦^234$¦^234$¦
+1¦9¦^[a-zA-Z0-9]*$¦2aA3bB9zZ¦
+-1¦-1¦^[a-z0-9]*$¦2aA3b#B9zZ¦
diff --git a/test/src/regex-resources/TESTS b/test/src/regex-resources/TESTS
new file mode 100644
index 00000000000..f2c98864058
--- /dev/null
+++ b/test/src/regex-resources/TESTS
@@ -0,0 +1,167 @@
+0:(.*)*\1:xx
+0:^:
+0:$:
+0:^$:
+0:^a$:a
+0:abc:abc
+1:abc:xbc
+1:abc:axc
+1:abc:abx
+0:abc:xabcy
+0:abc:ababc
+0:ab*c:abc
+0:ab*bc:abc
+0:ab*bc:abbc
+0:ab*bc:abbbbc
+0:ab+bc:abbc
+1:ab+bc:abc
+1:ab+bc:abq
+0:ab+bc:abbbbc
+0:ab?bc:abbc
+0:ab?bc:abc
+1:ab?bc:abbbbc
+0:ab?c:abc
+0:^abc$:abc
+1:^abc$:abcc
+0:^abc:abcc
+1:^abc$:aabc
+0:abc$:aabc
+0:^:abc
+0:$:abc
+0:a.c:abc
+0:a.c:axc
+0:a.*c:axyzc
+1:a.*c:axyzd
+1:a[bc]d:abc
+0:a[bc]d:abd
+1:a[b-d]e:abd
+0:a[b-d]e:ace
+0:a[b-d]:aac
+0:a[-b]:a-
+0:a[b-]:a-
+2:a[b-a]:-
+2:a[]b:-
+2:a[:-
+0:a]:a]
+0:a[]]b:a]b
+0:a[^bc]d:aed
+1:a[^bc]d:abd
+0:a[^-b]c:adc
+1:a[^-b]c:a-c
+1:a[^]b]c:a]c
+0:a[^]b]c:adc
+0:ab|cd:abc
+0:ab|cd:abcd
+0:()ef:def
+0:()*:-
+2:*a:-
+2:^*:-
+2:$*:-
+2:(*)b:-
+1:$b:b
+2:a\:-
+0:a\(b:a(b
+0:a\(*b:ab
+0:a\(*b:a((b
+1:a\x:a\x
+1:abc):-
+2:(abc:-
+0:((a)):abc
+0:(a)b(c):abc
+0:a+b+c:aabbabc
+0:a**:-
+0:a*?:-
+0:(a*)*:-
+0:(a*)+:-
+0:(a|)*:-
+0:(a*|b)*:-
+0:(a+|b)*:ab
+0:(a+|b)+:ab
+0:(a+|b)?:ab
+0:[^ab]*:cde
+0:(^)*:-
+0:(ab|)*:-
+2:)(:-
+1:abc:
+1:abc:
+0:a*:
+0:([abc])*d:abbbcd
+0:([abc])*bcd:abcd
+0:a|b|c|d|e:e
+0:(a|b|c|d|e)f:ef
+0:((a*|b))*:-
+0:abcd*efg:abcdefg
+0:ab*:xabyabbbz
+0:ab*:xayabbbz
+0:(ab|cd)e:abcde
+0:[abhgefdc]ij:hij
+1:^(ab|cd)e:abcde
+0:(abc|)ef:abcdef
+0:(a|b)c*d:abcd
+0:(ab|ab*)bc:abc
+0:a([bc]*)c*:abc
+0:a([bc]*)(c*d):abcd
+0:a([bc]+)(c*d):abcd
+0:a([bc]*)(c+d):abcd
+0:a[bcd]*dcdcde:adcdcde
+1:a[bcd]+dcdcde:adcdcde
+0:(ab|a)b*c:abc
+0:((a)(b)c)(d):abcd
+0:[A-Za-z_][A-Za-z0-9_]*:alpha
+0:^a(bc+|b[eh])g|.h$:abh
+0:(bc+d$|ef*g.|h?i(j|k)):effgz
+0:(bc+d$|ef*g.|h?i(j|k)):ij
+1:(bc+d$|ef*g.|h?i(j|k)):effg
+1:(bc+d$|ef*g.|h?i(j|k)):bcdd
+0:(bc+d$|ef*g.|h?i(j|k)):reffgz
+1:((((((((((a)))))))))):-
+0:(((((((((a))))))))):a
+1:multiple words of text:uh-uh
+0:multiple words:multiple words, yeah
+0:(.*)c(.*):abcde
+1:\((.*),:(.*)\)
+1:[k]:ab
+0:abcd:abcd
+0:a(bc)d:abcd
+0:a[-]?c:ac
+0:(....).*\1:beriberi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Qaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mo'ammar Gadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Kaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Qadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moammar El Kadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Gadafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar al-Qadafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moamer El Kazzafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moamar al-Gaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar Al Qathafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Al Qathafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mo'ammar el-Gadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moamar El Kadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar al-Qadhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar al-Qadhdhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar Qadafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moamar Gaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar Qadhdhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Khaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar al-Khaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'amar al-Kadafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Ghaddafy
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Ghadafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Ghaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muamar Kaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Quathafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muammar Gheddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Muamar Al-Kaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moammar Khadafy
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Moammar Qudhafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mu'ammar al-Qaddafi
+0:M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]:Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi
+0:[[:digit:]]+:01234
+1:[[:alpha:]]+:01234
+0:^[[:digit:]]*$:01234
+1:^[[:digit:]]*$:01234a
+0:^[[:alnum:]]*$:01234a
+0:^[[:xdigit:]]*$:01234a
+1:^[[:xdigit:]]*$:01234g
+0:^[[:alnum:][:space:]]*$:Hello world
diff --git a/test/src/regex-tests.el b/test/src/regex-tests.el
new file mode 100644
index 00000000000..c4844c7cdbc
--- /dev/null
+++ b/test/src/regex-tests.el
@@ -0,0 +1,680 @@
+;;; regex-tests.el --- tests for regex.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015-2016 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)
+
+(defvar regex-tests--resources-dir
+ (concat (concat (file-name-directory (or load-file-name buffer-file-name))
+ "/regex-resources/"))
+ "Path to regex-resources directory next to the \"regex-tests.el\" file.")
+
+(ert-deftest regex-word-cc-fallback-test ()
+ "Test that ‘[[:cc:]]*x’ matches ‘x’ (bug#24020).
+
+Test that a regex of the form \"[[:cc:]]*x\" where CC is
+a character class which matches a multibyte character X, matches
+string \"x\".
+
+For example, ‘[[:word:]]*\u2620’ regex (note: \u2620 is a word
+character) must match a string \"\u2420\"."
+ (dolist (class '("[[:word:]]" "\\sw"))
+ (dolist (repeat '("*" "+"))
+ (dolist (suffix '("" "b" "bar" "\u2620"))
+ (dolist (string '("" "foo"))
+ (when (not (and (string-equal repeat "+")
+ (string-equal string "")))
+ (should (string-match (concat "^" class repeat suffix "$")
+ (concat string suffix)))))))))
+
+(defun regex--test-cc (name matching not-matching)
+ (let (case-fold-search)
+ (should (string-match-p (concat "^[[:" name ":]]*$") matching))
+ (should (string-match-p (concat "^[[:" name ":]]*?\u2622$")
+ (concat matching "\u2622")))
+ (should (string-match-p (concat "^[^[:" name ":]]*$") not-matching))
+ (should (string-match-p (concat "^[^[:" name ":]]*\u2622$")
+ (concat not-matching "\u2622")))
+ (with-temp-buffer
+ (insert matching)
+ (let ((p (point)))
+ (insert not-matching)
+ (goto-char (point-min))
+ (skip-chars-forward (concat "[:" name ":]"))
+ (should (equal (point) p))
+ (skip-chars-forward (concat "^[:" name ":]"))
+ (should (equal (point) (point-max)))
+ (goto-char (point-min))
+ (skip-chars-forward (concat "[:" name ":]\u2622"))
+ (should (or (equal (point) p) (equal (point) (1+ p))))))))
+
+(dolist (test '(("alnum" "abcABC012łąka" "-, \t\n")
+ ("alpha" "abcABCłąka" "-,012 \t\n")
+ ("digit" "012" "abcABCłąka-, \t\n")
+ ("xdigit" "0123aBc" "łąk-, \t\n")
+ ("upper" "ABCŁĄKA" "abc012-, \t\n")
+ ("lower" "abcłąka" "ABC012-, \t\n")
+
+ ("word" "abcABC012\u2620" "-, \t\n")
+
+ ("punct" ".,-" "abcABC012\u2620 \t\n")
+ ("cntrl" "\1\2\t\n" ".,-abcABC012\u2620 ")
+ ("graph" "abcłąka\u2620-," " \t\n\1")
+ ("print" "abcłąka\u2620-, " "\t\n\1")
+
+ ("space" " \t\n\u2001" "abcABCł0123")
+ ("blank" " \t" "\n\u2001")
+
+ ("ascii" "abcABC012 \t\n\1" "łą\u2620")
+ ("nonascii" "łą\u2622" "abcABC012 \t\n\1")
+ ("unibyte" "abcABC012 \t\n\1" "łą\u2622")
+ ("multibyte" "łą\u2622" "abcABC012 \t\n\1")))
+ (let ((name (intern (concat "regex-tests-" (car test) "-character-class")))
+ (doc (concat "Perform sanity test of regexes using " (car test)
+ " character class.
+
+Go over all the supported character classes and test whether the
+classes and their inversions match what they are supposed to
+match. The test is done using `string-match-p' as well as
+`skip-chars-forward'.")))
+ (eval `(ert-deftest ,name () ,doc ,(cons 'regex--test-cc test)) t)))
+
+
+(defmacro regex-tests-generic-line (comment-char test-file whitelist &rest body)
+ "Reads a line of the test file TEST-FILE, skipping
+comments (defined by COMMENT-CHAR), and evaluates the tests in
+this line as defined in the BODY. Line numbers in the WHITELIST
+are known failures, and are skipped."
+
+ `(with-temp-buffer
+ (modify-syntax-entry ?_ "w;; ") ; tests expect _ to be a word
+ (insert-file-contents (concat regex-tests--resources-dir ,test-file))
+ (let ((case-fold-search nil)
+ (line-number 1)
+ (whitelist-idx 0))
+
+ (goto-char (point-min))
+
+ (while (not (eobp))
+ (let ((start (point)))
+ (end-of-line)
+ (narrow-to-region start (point))
+
+ (goto-char (point-min))
+
+ (when
+ (and
+ ;; ignore comments
+ (save-excursion
+ (re-search-forward ,(concat "^[^" (string comment-char) "]") nil t))
+
+ ;; skip lines in the whitelist
+ (let ((whitelist-next
+ (condition-case nil
+ (aref ,whitelist whitelist-idx) (args-out-of-range nil))))
+ (cond
+ ;; whitelist exhausted. do process this line
+ ((null whitelist-next) t)
+
+ ;; we're not yet at the next whitelist element. do
+ ;; process this line
+ ((< line-number whitelist-next) t)
+
+ ;; we're past the next whitelist element. This
+ ;; shouldn't happen
+ ((> line-number whitelist-next)
+ (error
+ (format
+ "We somehow skipped the next whitelist element: line %d" whitelist-next)))
+
+ ;; we're at the next whitelist element. Skip this
+ ;; line, and advance the whitelist index
+ (t
+ (setq whitelist-idx (1+ whitelist-idx)) nil))))
+ ,@body)
+
+ (widen)
+ (forward-line)
+ (beginning-of-line)
+ (setq line-number (1+ line-number)))))))
+
+(defun regex-tests-compare (string what-failed bounds-ref &optional substring-ref)
+ "I just ran a search, looking at STRING. WHAT-FAILED describes
+what failed, if anything; valid values are 'search-failed,
+'compilation-failed and nil. I compare the beginning/end of each
+group with their expected values. This is done with either
+BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil.
+BOUNDS-REF is a sequence \[start-ref0 end-ref0 start-ref1
+end-ref1 ....] while SUBSTRING-REF is the expected substring
+obtained by indexing the input string by start/end-ref.
+
+If the search was supposed to fail then start-ref0/substring-ref0
+is 'search-failed. If the search wasn't even supposed to compile
+successfully, then start-ref0/substring-ref0 is
+'compilation-failed. If I only care about a match succeeding,
+this can be set to t.
+
+This function returns a string that describes the failure, or nil
+on success"
+
+ (when (or
+ (and bounds-ref substring-ref)
+ (not (or bounds-ref substring-ref)))
+ (error "Exactly one of bounds-ref and bounds-ref should be non-nil"))
+
+ (let ((what-failed-ref (car (or bounds-ref substring-ref))))
+
+ (cond
+ ((eq what-failed 'search-failed)
+ (cond
+ ((eq what-failed-ref 'search-failed)
+ nil)
+ ((eq what-failed-ref 'compilation-failed)
+ "Expected pattern failure; but no match")
+ (t
+ "Expected match; but no match")))
+
+ ((eq what-failed 'compilation-failed)
+ (cond
+ ((eq what-failed-ref 'search-failed)
+ "Expected no match; but pattern failure")
+ ((eq what-failed-ref 'compilation-failed)
+ nil)
+ (t
+ "Expected match; but pattern failure")))
+
+ ;; The regex match succeeded
+ ((eq what-failed-ref 'search-failed)
+ "Expected no match; but match")
+ ((eq what-failed-ref 'compilation-failed)
+ "Expected pattern failure; but match")
+
+ ;; The regex match succeeded, as expected. I now check all the
+ ;; bounds
+ (t
+ (let ((idx 0)
+ msg
+ ref next-ref-function compare-ref-function mismatched-ref-function)
+
+ (if bounds-ref
+ (setq ref bounds-ref
+ next-ref-function (lambda (x) (cddr x))
+ compare-ref-function (lambda (ref start-pos end-pos)
+ (or (eq (car ref) t)
+ (and (eq start-pos (car ref))
+ (eq end-pos (cadr ref)))))
+ mismatched-ref-function (lambda (ref start-pos end-pos)
+ (format
+ "beginning/end positions: %d/%s and %d/%s"
+ start-pos (car ref) end-pos (cadr ref))))
+ (setq ref substring-ref
+ next-ref-function (lambda (x) (cdr x))
+ compare-ref-function (lambda (ref start-pos end-pos)
+ (or (eq (car ref) t)
+ (string= (substring string start-pos end-pos) (car ref))))
+ mismatched-ref-function (lambda (ref start-pos end-pos)
+ (format
+ "beginning/end positions: %d/%s and %d/%s"
+ start-pos (car ref) end-pos (cadr ref)))))
+
+ (while (not (or (null ref) msg))
+
+ (let ((start (match-beginning idx))
+ (end (match-end idx)))
+
+ (when (not (funcall compare-ref-function ref start end))
+ (setq msg
+ (format
+ "Have expected match, but mismatch in group %d: %s" idx (funcall mismatched-ref-function ref start end))))
+
+ (setq ref (funcall next-ref-function ref)
+ idx (1+ idx))))
+
+ (or msg
+ nil))))))
+
+
+
+(defun regex-tests-match (pattern string bounds-ref &optional substring-ref)
+ "I match the given STRING against PATTERN. I compare the
+beginning/end of each group with their expected values.
+BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1 end-ref1
+....].
+
+If the search was supposed to fail then start-ref0 is
+'search-failed. If the search wasn't even supposed to compile
+successfully, then start-ref0 is 'compilation-failed.
+
+This function returns a string that describes the failure, or nil
+on success"
+
+ (if (string-match "\\[\\([\\.=]\\)..?\\1\\]" pattern)
+ ;; Skipping test: [.x.] and [=x=] forms not supported by emacs
+ nil
+
+ (regex-tests-compare
+ string
+ (condition-case nil
+ (if (string-match pattern string) nil 'search-failed)
+ ('invalid-regexp 'compilation-failed))
+ bounds-ref substring-ref)))
+
+
+(defconst regex-tests-re-even-escapes
+ "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*"
+ "Regex that matches an even number of \\ characters")
+
+(defconst regex-tests-re-odd-escapes
+ (concat regex-tests-re-even-escapes "\\\\")
+ "Regex that matches an odd number of \\ characters")
+
+
+(defun regex-tests-unextend (pattern)
+ "Basic conversion from extended regexes to emacs ones. This is
+mostly a hack that adds \\ to () and | and {}, and removes it if
+it already exists. We also change \\S (and \\s) to \\S- (and
+\\s-) because extended regexes see the former as whitespace, but
+emacs requires an extra symbol character"
+
+ (with-temp-buffer
+ (insert pattern)
+ (goto-char (point-min))
+
+ (while (re-search-forward "[()|{}]" nil t)
+ ;; point is past special character. If it is escaped, unescape
+ ;; it
+
+ (if (save-excursion
+ (re-search-backward (concat regex-tests-re-odd-escapes ".\\=") nil t))
+
+ ;; This special character is preceded by an odd number of \,
+ ;; so I unescape it by removing the last one
+ (progn
+ (forward-char -2)
+ (delete-char 1)
+ (forward-char 1))
+
+ ;; This special character is preceded by an even (possibly 0)
+ ;; number of \. I add an escape
+ (forward-char -1)
+ (insert "\\")
+ (forward-char 1)))
+
+ ;; convert \s to \s-
+ (goto-char (point-min))
+ (while (re-search-forward (concat regex-tests-re-odd-escapes "[Ss]") nil t)
+ (insert "-"))
+
+ (buffer-string)))
+
+(defun regex-tests-BOOST-frob-escapes (s ispattern)
+ "Mangle \\ the way it is done in frob_escapes() in
+regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted;
+\\\\, \\^, \{, \\|, \} are unescaped for the string (not
+pattern)"
+
+ ;; this is all similar to (regex-tests-unextend)
+ (with-temp-buffer
+ (insert s)
+
+ (let ((interpret-list (list "t" "n" "r")))
+ (while interpret-list
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "\\(" regex-tests-re-even-escapes "\\)"
+ "\\\\" (car interpret-list))
+ nil t)
+ (replace-match (concat "\\1" (car (read-from-string
+ (concat "\"\\" (car interpret-list) "\""))))))
+
+ (setq interpret-list (cdr interpret-list))))
+
+ (when (not ispattern)
+ ;; unescape \\, \^, \{, \|, \}
+ (let ((unescape-list (list "\\\\" "^" "{" "|" "}")))
+ (while unescape-list
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "\\(" regex-tests-re-even-escapes "\\)"
+ "\\\\" (car unescape-list))
+ nil t)
+ (replace-match (concat "\\1" (car unescape-list))))
+
+ (setq unescape-list (cdr unescape-list))))
+ )
+ (buffer-string)))
+
+
+
+
+(defconst regex-tests-BOOST-whitelist
+ [
+ ;; emacs is more stringent with regexes involving unbalanced )
+ 63 65 69
+
+ ;; in emacs, regex . doesn't match \n
+ 91
+
+ ;; emacs is more forgiving with * and ? that don't apply to
+ ;; characters
+ 107 108 109 122 123 124 140 141 142
+
+ ;; emacs accepts regexes with {}
+ 161
+
+ ;; emacs doesn't fail on bogus ranges such as [3-1] or [1-3-5]
+ 222 223
+
+ ;; emacs doesn't match (ab*)[ab]*\1 greedily: only 4 chars of
+ ;; ababaaa match
+ 284 294
+
+ ;; ambiguous groupings are ambiguous
+ 443 444 445 446 448 449 450
+
+ ;; emacs doesn't know how to handle weird ranges such as [a-Z] and
+ ;; [[:alpha:]-a]
+ 539 580 581
+
+ ;; emacs matches non-greedy regex ab.*? non-greedily
+ 639 677 712
+ ]
+ "Line numbers in the boost test that should be skipped. These
+are false-positive test failures that represent known/benign
+differences in behavior.")
+
+;; - Format
+;; - Comments are lines starting with ;
+;; - Lines starting with - set options passed to regcomp() and regexec():
+;; - if no "REG_BASIC" is found, with have an extended regex
+;; - These set a flag:
+;; - REG_ICASE
+;; - REG_NEWLINE (ignored by this function)
+;; - REG_NOTBOL
+;; - REG_NOTEOL
+;;
+;; - Test lines are
+;; pattern string start0 end0 start1 end1 ...
+;;
+;; - pattern, string can have escapes
+;; - string can have whitespace if enclosed in ""
+;; - if string is "!", then the pattern is supposed to fail compilation
+;; - start/end are of group0, group1, etc. group 0 is the full match
+;; - start<0 indicates "no match"
+;; - start is the 0-based index of the first character
+;; - end is the 0-based index of the first character past the group
+(defun regex-tests-BOOST ()
+ (let (failures
+ basic icase notbol noteol)
+ (regex-tests-generic-line
+ ?; "BOOST.tests" regex-tests-BOOST-whitelist
+ (if (save-excursion (re-search-forward "^-" nil t))
+ (setq basic (save-excursion (re-search-forward "REG_BASIC" nil t))
+ icase (save-excursion (re-search-forward "REG_ICASE" nil t))
+ notbol (save-excursion (re-search-forward "REG_NOTBOL" nil t))
+ noteol (save-excursion (re-search-forward "REG_NOTEOL" nil t)))
+
+ (save-excursion
+ (or (re-search-forward "\\(\\S-+\\)\\s-+\"\\(.*\\)\"\\s-+?\\(.+\\)" nil t)
+ (re-search-forward "\\(\\S-+\\)\\s-+\\(\\S-+\\)\\s-+?\\(.+\\)" nil t)
+ (re-search-forward "\\(\\S-+\\)\\s-+\\(!\\)" nil t)))
+
+ (let* ((pattern-raw (match-string 1))
+ (string-raw (match-string 2))
+ (positions-raw (match-string 3))
+ (pattern (regex-tests-BOOST-frob-escapes pattern-raw t))
+ (string (regex-tests-BOOST-frob-escapes string-raw nil))
+ (positions
+ (if (string= string "!")
+ (list 'compilation-failed 0)
+ (mapcar
+ (lambda (x)
+ (let ((x (string-to-number x)))
+ (if (< x 0) nil x)))
+ (split-string positions-raw)))))
+
+ (when (null (car positions))
+ (setcar positions 'search-failed))
+
+ (when (not basic)
+ (setq pattern (regex-tests-unextend pattern)))
+
+ ;; great. I now have all the data parsed. Let's use it to do
+ ;; stuff
+ (let* ((case-fold-search icase)
+ (msg (regex-tests-match pattern string positions)))
+
+ (if (and
+ ;; Skipping test: notbol/noteol not supported
+ (not notbol) (not noteol)
+
+ msg)
+
+ ;; store failure
+ (setq failures
+ (cons (format "line number %d: Regex '%s': %s"
+ line-number pattern msg)
+ failures)))))))
+
+ failures))
+
+(defconst regex-tests-PCRE-whitelist
+ [
+ ;; ambiguous groupings are ambiguous
+ 610 611 1154 1157 1160 1168 1171 1176 1179 1182 1185 1188 1193 1196 1203
+ ]
+ "Line numbers in the PCRE test that should be skipped. These
+are false-positive test failures that represent known/benign
+differences in behavior.")
+
+;; - Format
+;;
+;; regex
+;; input_string
+;; group_num: group_match | "No match"
+;; input_string
+;; group_num: group_match | "No match"
+;; input_string
+;; group_num: group_match | "No match"
+;; input_string
+;; group_num: group_match | "No match"
+;; ...
+(defun regex-tests-PCRE ()
+ (let (failures
+ pattern icase string what-failed matches-observed)
+ (regex-tests-generic-line
+ ?# "PCRE.tests" regex-tests-PCRE-whitelist
+
+ (cond
+
+ ;; pattern
+ ((save-excursion (re-search-forward "^/\\(.*\\)/\\(.*i?\\)$" nil t))
+ (setq icase (string= "i" (match-string 2))
+ pattern (regex-tests-unextend (match-string 1))))
+
+ ;; string. read it in, match against pattern, and save all the results
+ ((save-excursion (re-search-forward "^ \\(.*\\)" nil t))
+ (let ((case-fold-search icase))
+ (setq string (match-string 1)
+
+ ;; the regex match under test
+ what-failed
+ (condition-case nil
+ (if (string-match pattern string) nil 'search-failed)
+ ('invalid-regexp 'compilation-failed))
+
+ matches-observed
+ (cl-loop for x from 0 to 20
+ collect (and (not what-failed)
+ (or (match-string x string) "<unset>")))))
+ nil)
+
+ ;; verification line: failed match
+ ((save-excursion (re-search-forward "^No match" nil t))
+ (unless what-failed
+ (setq failures
+ (cons (format "line number %d: Regex '%s': Expected no match; but match"
+ line-number pattern)
+ failures))))
+
+ ;; verification line: succeeded match
+ ((save-excursion (re-search-forward "^ *\\([0-9]+\\): \\(.*\\)" nil t))
+ (let* ((match-ref (match-string 2))
+ (idx (string-to-number (match-string 1))))
+
+ (if what-failed
+ "Expected match; but no match"
+ (unless (string= match-ref (elt matches-observed idx))
+ (setq failures
+ (cons (format "line number %d: Regex '%s': Have expected match, but group %d is wrong: '%s'/'%s'"
+ line-number pattern
+ idx match-ref (elt matches-observed idx))
+ failures))))))
+
+ ;; reset
+ (t (setq pattern nil) nil)))
+
+ failures))
+
+(defconst regex-tests-PTESTS-whitelist
+ [
+ ;; emacs doesn't barf on weird ranges such as [b-a], but simply
+ ;; fails to match
+ 138
+
+ ;; emacs doesn't see DEL (0x78) as a [:cntrl:] character
+ 168
+ ]
+ "Line numbers in the PTESTS test that should be skipped. These
+are false-positive test failures that represent known/benign
+differences in behavior.")
+
+;; - Format
+;; - fields separated by ¦ (note: this is not a |)
+;; - start¦end¦pattern¦string
+;; - start is the 1-based index of the first character
+;; - end is the 1-based index of the last character
+(defun regex-tests-PTESTS ()
+ (let (failures)
+ (regex-tests-generic-line
+ ?# "PTESTS" regex-tests-PTESTS-whitelist
+ (let* ((fields (split-string (buffer-string) "¦"))
+
+ ;; string has 1-based index of first char in the
+ ;; match. -1 means "no match". -2 means "invalid
+ ;; regex".
+ ;;
+ ;; start-ref is 0-based index of first char in the
+ ;; match
+ ;;
+ ;; string==0 is a special case, and I have to treat
+ ;; it as start-ref = 0
+ (start-ref (let ((raw (string-to-number (elt fields 0))))
+ (cond
+ ((= raw -2) 'compilation-failed)
+ ((= raw -1) 'search-failed)
+ ((= raw 0) 0)
+ (t (1- raw)))))
+
+ ;; string has 1-based index of last char in the
+ ;; match. end-ref is 0-based index of first char past
+ ;; the match
+ (end-ref (string-to-number (elt fields 1)))
+ (pattern (elt fields 2))
+ (string (elt fields 3)))
+
+ (let ((msg (regex-tests-match pattern string (list start-ref end-ref))))
+ (when msg
+ (setq failures
+ (cons (format "line number %d: Regex '%s': %s"
+ line-number pattern msg)
+ failures))))))
+ failures))
+
+(defconst regex-tests-TESTS-whitelist
+ [
+ ;; emacs doesn't barf on weird ranges such as [b-a], but simply
+ ;; fails to match
+ 42
+
+ ;; emacs is more forgiving with * and ? that don't apply to
+ ;; characters
+ 57 58 59 60
+
+ ;; emacs is more stringent with regexes involving unbalanced )
+ 67
+ ]
+ "Line numbers in the TESTS test that should be skipped. These
+are false-positive test failures that represent known/benign
+differences in behavior.")
+
+;; - Format
+;; - fields separated by :. Watch for [\[:xxx:]]
+;; - expected:pattern:string
+;;
+;; expected:
+;; | 0 | successful match |
+;; | 1 | failed match |
+;; | 2 | regcomp() should fail |
+(defun regex-tests-TESTS ()
+ (let (failures)
+ (regex-tests-generic-line
+ ?# "TESTS" regex-tests-TESTS-whitelist
+ (if (save-excursion (re-search-forward "^\\([^:]+\\):\\(.*\\):\\([^:]*\\)$" nil t))
+ (let* ((what-failed
+ (let ((raw (string-to-number (match-string 1))))
+ (cond
+ ((= raw 2) 'compilation-failed)
+ ((= raw 1) 'search-failed)
+ (t t))))
+ (string (match-string 3))
+ (pattern (regex-tests-unextend (match-string 2))))
+
+ (let ((msg (regex-tests-match pattern string nil (list what-failed))))
+ (when msg
+ (setq failures
+ (cons (format "line number %d: Regex '%s': %s"
+ line-number pattern msg)
+ failures)))))
+
+ (error "Error parsing TESTS file line: '%s'" (buffer-string))))
+ failures))
+
+(ert-deftest regex-tests-BOOST ()
+ "Tests of the regular expression engine.
+This evaluates the BOOST test cases from glibc."
+ (should-not (regex-tests-BOOST)))
+
+(ert-deftest regex-tests-PCRE ()
+ "Tests of the regular expression engine.
+This evaluates the PCRE test cases from glibc."
+ (should-not (regex-tests-PCRE)))
+
+(ert-deftest regex-tests-PTESTS ()
+ "Tests of the regular expression engine.
+This evaluates the PTESTS test cases from glibc."
+ (should-not (regex-tests-PTESTS)))
+
+(ert-deftest regex-tests-TESTS ()
+ "Tests of the regular expression engine.
+This evaluates the TESTS test cases from glibc."
+ (should-not (regex-tests-TESTS)))
+
+;;; regex-tests.el ends here
diff --git a/test/src/textprop-tests.el b/test/src/textprop-tests.el
new file mode 100644
index 00000000000..ceb48d1b2db
--- /dev/null
+++ b/test/src/textprop-tests.el
@@ -0,0 +1,72 @@
+;;; textprop-tests.el --- Test suite for text properties.
+
+;; Copyright (C) 2015-2016 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)))))
+
+(provide 'textprop-tests)
+;; textprop-tests.el ends here.
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
new file mode 100644
index 00000000000..73da72e8369
--- /dev/null
+++ b/test/src/thread-tests.el
@@ -0,0 +1,247 @@
+;;; threads.el --- tests for threads.
+
+;; Copyright (C) 2012-2016 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:
+
+(ert-deftest threads-is-one ()
+ "test for existence of a thread"
+ (should (current-thread)))
+
+(ert-deftest threads-threadp ()
+ "test of threadp"
+ (should (threadp (current-thread))))
+
+(ert-deftest threads-type ()
+ "test of thread type"
+ (should (eq (type-of (current-thread)) 'thread)))
+
+(ert-deftest threads-name ()
+ "test for name of a thread"
+ (should
+ (string= "hi bob" (thread-name (make-thread #'ignore "hi bob")))))
+
+(ert-deftest threads-alive ()
+ "test for thread liveness"
+ (should
+ (thread-alive-p (make-thread #'ignore))))
+
+(ert-deftest threads-all-threads ()
+ "simple test for all-threads"
+ (should (listp (all-threads))))
+
+(defvar threads-test-global nil)
+
+(defun threads-test-thread1 ()
+ (setq threads-test-global 23))
+
+(ert-deftest threads-basic ()
+ "basic thread test"
+ (should
+ (progn
+ (setq threads-test-global nil)
+ (make-thread #'threads-test-thread1)
+ (while (not threads-test-global)
+ (thread-yield))
+ threads-test-global)))
+
+(ert-deftest threads-join ()
+ "test of thread-join"
+ (should
+ (progn
+ (setq threads-test-global nil)
+ (let ((thread (make-thread #'threads-test-thread1)))
+ (thread-join thread)
+ (and threads-test-global
+ (not (thread-alive-p thread)))))))
+
+(ert-deftest threads-join-self ()
+ "cannot thread-join the current thread"
+ (should-error (thread-join (current-thread))))
+
+(defvar threads-test-binding nil)
+
+(defun threads-test-thread2 ()
+ (let ((threads-test-binding 23))
+ (thread-yield))
+ (setq threads-test-global 23))
+
+(ert-deftest threads-let-binding ()
+ "simple test of threads and let bindings"
+ (should
+ (progn
+ (setq threads-test-global nil)
+ (make-thread #'threads-test-thread2)
+ (while (not threads-test-global)
+ (thread-yield))
+ (and (not threads-test-binding)
+ threads-test-global))))
+
+(ert-deftest threads-mutexp ()
+ "simple test of mutexp"
+ (should-not (mutexp 'hi)))
+
+(ert-deftest threads-mutexp-2 ()
+ "another simple test of mutexp"
+ (should (mutexp (make-mutex))))
+
+(ert-deftest threads-mutex-type ()
+ "type-of mutex"
+ (should (eq (type-of (make-mutex)) 'mutex)))
+
+(ert-deftest threads-mutex-lock-unlock ()
+ "test mutex-lock and unlock"
+ (should
+ (let ((mx (make-mutex)))
+ (mutex-lock mx)
+ (mutex-unlock mx)
+ t)))
+
+(ert-deftest threads-mutex-recursive ()
+ "test mutex-lock and unlock"
+ (should
+ (let ((mx (make-mutex)))
+ (mutex-lock mx)
+ (mutex-lock mx)
+ (mutex-unlock mx)
+ (mutex-unlock mx)
+ t)))
+
+(defvar threads-mutex nil)
+(defvar threads-mutex-key nil)
+
+(defun threads-test-mlock ()
+ (mutex-lock threads-mutex)
+ (setq threads-mutex-key 23)
+ (while threads-mutex-key
+ (thread-yield))
+ (mutex-unlock threads-mutex))
+
+(ert-deftest threads-mutex-contention ()
+ "test of mutex contention"
+ (should
+ (progn
+ (setq threads-mutex (make-mutex))
+ (setq threads-mutex-key nil)
+ (make-thread #'threads-test-mlock)
+ ;; Wait for other thread to get the lock.
+ (while (not threads-mutex-key)
+ (thread-yield))
+ ;; Try now.
+ (setq threads-mutex-key nil)
+ (mutex-lock threads-mutex)
+ (mutex-unlock threads-mutex)
+ t)))
+
+(defun threads-test-mlock2 ()
+ (setq threads-mutex-key 23)
+ (mutex-lock threads-mutex))
+
+(ert-deftest threads-mutex-signal ()
+ "test signaling a blocked thread"
+ (should
+ (progn
+ (setq threads-mutex (make-mutex))
+ (setq threads-mutex-key nil)
+ (mutex-lock threads-mutex)
+ (let ((thr (make-thread #'threads-test-mlock2)))
+ (while (not threads-mutex-key)
+ (thread-yield))
+ (thread-signal thr 'quit nil)
+ (thread-join thr))
+ t)))
+
+(defun threads-test-io-switch ()
+ (setq threads-test-global 23))
+
+(ert-deftest threads-io-switch ()
+ "test that accept-process-output causes thread switch"
+ (should
+ (progn
+ (setq threads-test-global nil)
+ (make-thread #'threads-test-io-switch)
+ (while (not threads-test-global)
+ (accept-process-output nil 1))
+ threads-test-global)))
+
+(ert-deftest threads-condvarp ()
+ "simple test of condition-variable-p"
+ (should-not (condition-variable-p 'hi)))
+
+(ert-deftest threads-condvarp-2 ()
+ "another simple test of condition-variable-p"
+ (should (condition-variable-p (make-condition-variable (make-mutex)))))
+
+(ert-deftest threads-condvar-type ()
+ "type-of condvar"
+ (should (eq (type-of (make-condition-variable (make-mutex)))
+ 'condition-variable)))
+
+(ert-deftest threads-condvar-mutex ()
+ "simple test of condition-mutex"
+ (should
+ (let ((m (make-mutex)))
+ (eq m (condition-mutex (make-condition-variable m))))))
+
+(ert-deftest threads-condvar-name ()
+ "simple test of condition-name"
+ (should
+ (eq nil (condition-name (make-condition-variable (make-mutex))))))
+
+(ert-deftest threads-condvar-name-2 ()
+ "another simple test of condition-name"
+ (should
+ (string= "hi bob"
+ (condition-name (make-condition-variable (make-mutex)
+ "hi bob")))))
+(defun call-error ()
+ "Call `error'."
+ (error "Error is called"))
+
+;; This signals an error internally; the error should be caught.
+(defun thread-custom ()
+ (defcustom thread-custom-face 'highlight
+ "Face used for thread customizations."
+ :type 'face
+ :group 'widget-faces))
+
+(ert-deftest thread-errors ()
+ "Test what happens when a thread signals an error."
+ (should (threadp (make-thread #'call-error "call-error")))
+ (should (threadp (make-thread #'thread-custom "thread-custom"))))
+
+(ert-deftest thread-sticky-point ()
+ "Test bug #25165 with point movement in cloned buffer."
+ (with-temp-buffer
+ (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
+ (goto-char (point-min))
+ (clone-indirect-buffer nil nil)
+ (forward-char 20)
+ (sit-for 1)
+ (should (= (point) 21))))
+
+(ert-deftest thread-signal-early ()
+ "Test signaling a thread as soon as it is started by the OS."
+ (let ((thread
+ (make-thread #'(lambda ()
+ (while t (thread-yield))))))
+ (thread-signal thread 'error nil)
+ (sit-for 1)
+ (should-not (thread-alive-p thread))))
+
+;;; threads.el ends here
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
new file mode 100644
index 00000000000..b1c786993e8
--- /dev/null
+++ b/test/src/undo-tests.el
@@ -0,0 +1,448 @@
+;;; undo-tests.el --- Tests of primitive-undo
+
+;; Copyright (C) 2012-2016 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
diff --git a/test/src/xml-tests.el b/test/src/xml-tests.el
new file mode 100644
index 00000000000..dc60197b59e
--- /dev/null
+++ b/test/src/xml-tests.el
@@ -0,0 +1,74 @@
+;;; libxml-parse-tests.el --- Test suite for libxml parsing.
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; Author: Ulf Jasper <ulf.jasper@web.de>
+;; 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:
+
+;;; Code:
+
+(require 'ert)
+
+(defvar libxml-tests--data-comments-preserved
+ `(;; simple case
+ ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
+ . (foo ((baz . "true")) "bar"))
+ ;; toplevel comments -- first document child must not get lost
+ (,(concat "<?xml version=\"1.0\"?><foo>bar</foo><!--comment-1-->"
+ "<!--comment-2-->")
+ . (top nil (foo nil "bar") (comment nil "comment-1")
+ (comment nil "comment-2")))
+ (,(concat "<?xml version=\"1.0\"?><!--comment-a--><foo a=\"b\">"
+ "<bar>blub</bar></foo><!--comment-b--><!--comment-c-->")
+ . (top nil (comment nil "comment-a") (foo ((a . "b")) (bar nil "blub"))
+ (comment nil "comment-b") (comment nil "comment-c"))))
+ "Alist of XML strings and their expected parse trees for preserved comments.")
+
+(defvar libxml-tests--data-comments-discarded
+ `(;; simple case
+ ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
+ . (foo ((baz . "true")) "bar"))
+ ;; toplevel comments -- first document child must not get lost
+ (,(concat "<?xml version=\"1.0\"?><foo>bar</foo><!--comment-1-->"
+ "<!--comment-2-->")
+ . (foo nil "bar"))
+ (,(concat "<?xml version=\"1.0\"?><!--comment-a--><foo a=\"b\">"
+ "<bar>blub</bar></foo><!--comment-b--><!--comment-c-->")
+ . (foo ((a . "b")) (bar nil "blub"))))
+ "Alist of XML strings and their expected parse trees for discarded comments.")
+
+
+(ert-deftest libxml-tests ()
+ "Test libxml."
+ (when (fboundp 'libxml-parse-xml-region)
+ (with-temp-buffer
+ (dolist (test libxml-tests--data-comments-preserved)
+ (erase-buffer)
+ (insert (car test))
+ (should (equal (cdr test)
+ (libxml-parse-xml-region (point-min) (point-max)))))
+ (dolist (test libxml-tests--data-comments-discarded)
+ (erase-buffer)
+ (insert (car test))
+ (should (equal (cdr test)
+ (libxml-parse-xml-region (point-min) (point-max) nil t)))))))
+
+;;; libxml-tests.el ends here