Fix ispell-tests issues discovered on Solaris 10

* lisp/textmodes/ispell.el: Export minimum versions for engines.
(ispell--minversion-alist): Define versions alist.
(ispell-check-version): Use public version alist.
* test/lisp/textmodes/ispell-tests/ispell-tests-common.el:
(ispell-tests--parse-v): Parse engine versions.
(ispell-tests--valid-version-triple?): Add version verification.
(ispell-tests--broken-system?): Add predicate for excluding broken
systems.
*test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
(ispell/aspell/ispell-check-version/works)
(ispell/aspell/ispell-word/english/correct)
(ispell/aspell/ispell-word/english/incorrect):
* test/lisp/textmodes/ispell-tests/ispell-tests.el
(ispell/ispell-valid-dictionary-list/aspell): Add Aspell triple check.
(ispell/ispell-pdict-save/unmodified)
(ispell/ispell-lookup-words/simple)
(ispell/ispell-complete-word/ispell-completion-at-point): Disable
on Solaris.  (Bug#81472)
This commit is contained in:
Lockywolf 2026-08-21 18:30:16 +08:00 committed by Eli Zaretskii
parent f3d4c95f0a
commit 476200e4dd
4 changed files with 90 additions and 10 deletions

View file

@ -655,6 +655,14 @@ Standard dict names are defined in `ispell-dictionary-base-alist'.")
;;; The following are used by ispell, and should not be changed.
;;; **********************************************************************
(defconst ispell--minversion-alist
`((Aspell "0.60")
(Hunspell "1.1.6")
(Enchant "2.1.0")
(,(intern "International Ispell") "3.1.12"))
"Alist of the form (engine version) declaring minimally permitted versions."
)
(defun ispell-check-version (&optional interactivep)
"Ensure that `ispell-program-name' is valid and has the correct version.
Return version number if called interactively, or if INTERACTIVEP is non-nil.
@ -729,10 +737,14 @@ Otherwise return the library directory name, if that is defined."
nil t)
(match-string 1)))))
(let* ((aspell8-minver "0.60")
(ispell-minver "3.1.12")
(hunspell8-minver "1.1.6")
(enchant-minver "2.1.0")
(let* ((aspell8-minver (car (alist-get 'Aspell
ispell--minversion-alist)))
(ispell-minver (car (alist-get 'International\ Ispell
ispell--minversion-alist)))
(hunspell8-minver (car (alist-get 'Hunspell
ispell--minversion-alist)))
(enchant-minver (car (alist-get 'Enchant
ispell--minversion-alist)))
(minver (cond
((not (version<= ispell-minver ispell-program-version))
ispell-minver)

View file

@ -37,9 +37,11 @@
(ert-deftest ispell/aspell/ispell-check-version/works ()
"Test that aspell is correctly detected."
(skip-unless (and (executable-find "aspell")
(with-temp-buffer
(call-process "aspell" nil t nil "-vv")
(search-backward "but really Aspell"))))
(with-temp-buffer
(call-process "aspell" nil t nil "-vv")
(search-backward "but really Aspell"))
(ispell-tests--valid-version-triple?
(ispell-tests--parse-v "aspell"))))
(ispell-tests--letopt ((ispell-program-name "aspell"))
(setq ispell-last-program-name (time-to-seconds))
(setf ispell-program-name "aspell")
@ -72,6 +74,8 @@
(skip-unless (equal
0
(call-process "aspell" nil nil nil "-vv")))
(skip-unless (ispell-tests--valid-version-triple?
(ispell-tests--parse-v "aspell")))
(skip-unless (equal
0
(with-temp-buffer
@ -104,6 +108,8 @@
(skip-unless (equal
0
(call-process "aspell" nil nil nil "-vv")))
(skip-unless (ispell-tests--valid-version-triple?
(ispell-tests--parse-v "aspell")))
(skip-unless (equal
0
(with-temp-buffer

View file

@ -26,6 +26,7 @@
(require 'ert)
(require 'ert-x)
(require 'ispell)
(defvar ispell-tests--data-directory
(let ((ert-resource-directory-trim-right-regexp "-tests/.*-tests-common\\.el"))
@ -36,6 +37,49 @@
(expand-file-name "fake-aspell-new.bash" ispell-tests--data-directory)
"Path to the mock backend.")
(defun ispell-tests--parse-v (path)
"Parse a spellchecking backend's at PATH -v.
Return proto version, engine type, and version
(i.e., aspell, hunspell, enchant)."
(or (executable-find path)
(error "ispell command (%s) is not runnable" path))
(with-temp-buffer
(call-process path nil t nil "-v")
(goto-char (point-min))
(forward-line 1)
(when (not (eobp))
(delete-region (point) (point-max)))
(goto-char (point-min))
(search-forward "International Ispell Version ") ; last space is important!
(let* ((proto-version (let* ((s (point))
(e (progn (search-forward " ")
(backward-char)
(point))))
(buffer-substring s e)))
(engine (condition-case nil
(let ((s (progn (search-forward "but really ")
(point)))
(e (progn (search-forward " ")
(backward-char)
(point))))
(buffer-substring s e))
(error "International Ispell")))
(engine-version (if (string-equal engine "International Ispell")
proto-version
(let ((s (progn (forward-char)
(point)))
(e (progn (search-forward ")")
(backward-char)
(point))))
(buffer-substring s e)))))
(list proto-version engine engine-version))))
(defun ispell-tests--valid-version-triple? (triple)
"Check if spellchecker version TRIPLE is valid."
(let ((engine (nth 1 triple))
(engine-version (nth 2 triple)))
(version<= (car (alist-get (intern engine) ispell--minversion-alist))
engine-version)))
(let* ((backend-binaries (list "ispell" "aspell" "hunspell" "enchant-2" fake-aspell-path))
(filter-binaries (seq-filter
@ -44,7 +88,9 @@
(executable-find b)
(equal 0
(with-temp-buffer
(call-process b nil t nil "-a")))))
(call-process b nil t nil "-a")))
(ispell-tests--valid-version-triple?
(ispell-tests--parse-v b))))
backend-binaries)))
(defun ispell-tests--some-backend-available-p ()
@ -55,9 +101,20 @@
(defun ispell-tests--some-backend ()
"Return the string of some available backend."
(let ((retval (car filter-binaries)))
(message "available backend is:%s" retval)
retval)))
(defun ispell-tests--broken-system? ()
"On some systems Emacs works, but ispell does not.
Such systems are usually so old that their users are expected to
do debugging anyway. This function returns true if such a system
is detected.
1. Solaris has broken grep, which ispell.el relies upon."
(or (with-temp-buffer
(call-process "uname" nil t nil "-s")
(search-backward "SunOS"))
;; add other broken stuff here
))
(defun ispell-tests--some-valid-dictionary (backend)
"Return some dictionary name working for BACKEND."
(cond ((string-equal backend "ispell")

View file

@ -316,6 +316,8 @@ file is present in `ispell-library-directory'."
For aspell, `ispell-valid-dictionary-list' computes an intersection of
`ispell-dictionary-alist' and `ispell--aspell-found-dictionaries'."
(skip-unless (executable-find "aspell"))
(skip-unless (ispell-tests--valid-version-triple?
(ispell-tests--parse-v "aspell")))
(skip-unless (with-temp-buffer
(call-process "aspell" nil t nil "dicts")
(> (length (buffer-string)) 2)))
@ -1368,6 +1370,7 @@ One correct an one incorrect in the same buffer."
(ert-deftest ispell/ispell-lookup-words/simple ()
"Test if `ispell-lookup-words' is runnable."
(skip-unless (not (ispell-tests--broken-system?)))
(with-environment-variables (("HOME" temporary-file-directory))
(let* ((default-directory temporary-file-directory)
(tempfile (make-temp-file "emacs-ispell.el-test" nil nil ispell-tests--constants/completion)))
@ -1389,6 +1392,7 @@ One correct an one incorrect in the same buffer."
(ert-deftest ispell/ispell-complete-word/ispell-completion-at-point ()
"Test if `ispell-complete-word' and `ispell-completion-at-point' are runnable."
(skip-unless (not (ispell-tests--broken-system?)))
(with-environment-variables (("HOME" temporary-file-directory))
(let* ((default-directory temporary-file-directory)
(tempfile (make-temp-file "emacs-ispell.el-test" nil nil ispell-tests--constants/completion)))
@ -1420,9 +1424,10 @@ One correct an one incorrect in the same buffer."
(ert-deftest ispell/ispell-complete-word-interior-frag/simple ()
"Test if `ispell-complete-word-interior-frag' is runnable."
(skip-unless (not (ispell-tests--broken-system?)))
(with-environment-variables (("HOME" temporary-file-directory))
(let* ((default-directory temporary-file-directory)
(tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveguides")))
(tempfile (make-temp-file "emacs-ispell.el-test" nil nil ispell-tests--constants/completion)))
(ispell-tests--letopt
((ispell-program-name (ispell-tests--some-backend))
(ispell-complete-word-dict tempfile))