emacs/test/lisp/emacs-lisp/gv-tests.el
Basil L. Contovounesios 9da2efb670 Audit some plist uses with new predicate argument
* doc/lispref/lists.texi (Plist Access): Improve description of
default predicate.
* lisp/emacs-lisp/cl-extra.el (cl-getf, cl--set-getf): Assume
plist-member always returns a cons.
* lisp/emacs-lisp/gv.el (plist-get): Support new optional predicate
argument (bug#47425#91).
* lisp/emacs-lisp/map.el: Bump minor version.
(map--dispatch): Remove now that bug#58563 is fixed.  Break two
remaining uses out into corresponding cl-defmethods.
(map--plist-p): Add docstring.
(map--plist-has-predicate, map--plist-member-1, map--plist-member)
(map--plist-put-1, map--plist-put): New definitions for supporting
predicate argument backward compatibly.
(map-elt): Fix generalized variable getter under a
predicate (bug#58531).  Use predicate when given a plist.
(map-put): Avoid gratuitous warnings when called without the hidden
predicate argument.  Improve obsoletion message.
(map-put!): Use predicate when given a plist.
(map-contains-key): Ditto.  Declare forgotten
advertised-calling-convention (bug#58531#19).
(map--put): Group definition in file together with that of map-put!.
* lisp/files-x.el (connection-local-normalize-criteria): Simplify
using mapcan + plist-get.
* lisp/net/eudc.el (eudc--plist-member): New convenience function.
(eudc-plist-member, eudc-plist-get, eudc-lax-plist-get): Use it
instead of open-coding plist-member.
* src/fns.c (Fplist_get, plist_get, Fplist_put, plist_put): Pass the
plist element as the first argument to the predicate, for
consistency with assoc + alist-get.
(Fplist_member, plist_member): Move from widget to plist section.
Open-code the EQ case in plist_member, and call it from
Fplist_member in that case, rather than the other way around.

* test/lisp/apropos-tests.el (apropos-tests-format-plist): Avoid
polluting obarray.
* test/lisp/emacs-lisp/cl-extra-tests.el (cl-getf): Extend test with
generalized variables, degenerate plists, and improper lists.
* test/lisp/emacs-lisp/gv-tests.el: Byte-compile file; in the
meantime bug#24402 seems to have been fixed or worked around.
(gv-setter-edebug): Inhibit printing messages.
(gv-plist-get): Avoid modifying constant literals.  Also test with a
predicate argument.
* test/lisp/emacs-lisp/map-tests.el (with-maps-do): Simplify
docstring.
(test-map-elt-testfn): Rename...
(test-map-elt-testfn-alist): ...to this.  Also test with a predicate
argument.
(test-map-elt-testfn-plist, test-map-elt-gv, test-map-elt-signature)
(test-map-put!-plist, test-map-put!-signature)
(test-map-contains-key-signature, test-map-plist-member)
(test-map-plist-put): New tests.
(test-map-contains-key-testfn): Also test with a predicate argument.
(test-map-setf-alist-overwrite-key, test-map-setf-plist-insert-key)
(test-map-setf-plist-overwrite-key): Avoid modifying constant
literals.
(test-hash-table-setf-insert-key)
(test-hash-table-setf-overwrite-key): Fix indentation.
(test-setf-map-with-function): Make test more precise.
* test/lisp/net/eudc-tests.el: New file.
* test/lisp/subr-tests.el (test-plistp): Extend test with circular
list.
* test/src/fns-tests.el (test-cycle-equal, test-cycle-nconc): Move
from plist section to circular list section.
(plist-put/odd-number-of-elements): Avoid modifying constant
literals.
(plist-member/improper-list): Simplify.
(test-plist): Move to plist section.  Also test with a predicate
argument.
2022-10-22 19:33:12 +03:00

198 lines
8.3 KiB
EmacsLisp

;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
;; Copyright (C) 2017-2022 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 <https://www.gnu.org/licenses/>.
;;; Code:
(require 'edebug)
(require 'ert)
(require 'ert-x)
(eval-when-compile (require 'cl-lib))
(cl-defmacro gv-tests--in-temp-dir ((elvar elcvar)
(&rest filebody)
&rest body)
(declare (indent 2))
`(ert-with-temp-directory default-directory
(let ((,elvar "gv-test-deffoo.el")
(,elcvar "gv-test-deffoo.elc"))
(with-temp-file ,elvar
(insert ";; -*- lexical-binding: t; -*-\n")
(dolist (form ',filebody)
(pp form (current-buffer))))
,@body)))
(ert-deftest gv-define-expander-in-file ()
(gv-tests--in-temp-dir (el elc)
((gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval))
(defvar gv-test-pair (cons 1 2))
(setf (gv-test-foo gv-test-pair) 99)
(message "%d" (car gv-test-pair)))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc)
(should (equal (buffer-string) "99\n")))))
(ert-deftest gv-define-expander-in-file-twice ()
(gv-tests--in-temp-dir (el elc)
((gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval))
(defvar gv-test-pair (cons 1 2))
(setf (gv-test-foo gv-test-pair) 99)
(gv-define-setter gv-test-foo (newval cons)
`(setcdr ,cons ,newval))
(setf (gv-test-foo gv-test-pair) 42)
(message "%S" gv-test-pair))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc)
(should (equal (buffer-string) "(99 . 42)\n")))))
(ert-deftest gv-dont-define-expander-in-file ()
;; The expander is defined while we are compiling the file, even
;; though it's inside (when nil ...) because the compiler won't
;; analyze the conditional.
:expected-result :failed
(gv-tests--in-temp-dir (el elc)
((when nil (gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval)))
(defvar gv-test-pair (cons 1 2))
(setf (gv-test-foo gv-test-pair) 99)
(message "%d" (car gv-test-pair)))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch"
"--eval" (prin1-to-string
`(let ((backtrace-on-error-noninteractive nil))
(byte-compile-file ,el)))
"-l" elc)
(should (equal (buffer-string)
"Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
(ert-deftest gv-define-expander-in-function ()
;; The expander is not defined while we are compiling the file, the
;; compiler won't handle gv definitions not at top-level.
:expected-result :failed
(gv-tests--in-temp-dir (el elc)
((defun foo ()
(gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval))
t)
(defvar gv-test-pair (cons 1 2))
(setf (gv-test-foo gv-test-pair) 99)
(message "%d" (car gv-test-pair)))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc)
(should (equal (buffer-string) "99\n")))))
(ert-deftest gv-define-expander-out-of-file ()
(gv-tests--in-temp-dir (el elc)
((gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval))
(defvar gv-test-pair (cons 1 2)))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc
"--eval"
(prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
(message "%d" (car gv-test-pair)))))
(should (equal (buffer-string) "99\n")))))
(ert-deftest gv-dont-define-expander-other-file ()
(gv-tests--in-temp-dir (el elc)
((if nil (gv-define-setter gv-test-foo (newval cons)
`(setcar ,cons ,newval)))
(defvar gv-test-pair (cons 1 2)))
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc
"--eval"
(prin1-to-string
'(let ((backtrace-on-error-noninteractive nil))
(setf (gv-test-foo gv-test-pair) 99)
(message "%d" (car gv-test-pair)))))
(should (string-match
"\\`Symbol.s function definition is void: \\\\(setf\\\\ gv-test-foo\\\\)\n\\'"
(buffer-string))))))
(ert-deftest gv-setter-edebug ()
"Check that a setter can be defined and edebugged together with
its getter (Bug#41853)."
(with-temp-buffer
(let ((edebug-all-defs t)
(edebug-initial-mode 'Go-nonstop))
(dolist (form '((defun gv-setter-edebug-help (b) b)
(defun gv-setter-edebug-get (a b)
(get a (gv-setter-edebug-help b)))
(gv-define-setter gv-setter-edebug-get (x a b)
`(setf (get ,a (gv-setter-edebug-help ,b)) ,x))
(push 123 (gv-setter-edebug-get 'gv-setter-edebug
'gv-setter-edebug-prop))))
(print form (current-buffer)))
;; Silence "Edebug: foo" messages.
(let ((inhibit-message t))
;; Only check whether evaluation works in general.
(eval-buffer))))
(should (equal (get 'gv-setter-edebug 'gv-setter-edebug-prop) '(123))))
(ert-deftest gv-plist-get ()
;; Simple `setf' usage for `plist-get'.
(let ((target (list :a "a" :b "b" :c "c")))
(setf (plist-get target :b) "modify")
(should (equal target '(:a "a" :b "modify" :c "c")))
(setf (plist-get target ":a" #'string=) "mogrify")
(should (equal target '(:a "mogrify" :b "modify" :c "c"))))
;; Other function (`cl-rotatef') usage for `plist-get'.
(let ((target (list :a "a" :b "b" :c "c")))
(cl-rotatef (plist-get target :b) (plist-get target :c))
(should (equal target '(:a "a" :b "c" :c "b")))
(cl-rotatef (plist-get target ":a" #'string=)
(plist-get target ":b" #'string=))
(should (equal target '(:a "c" :b "a" :c "b"))))
;; Add new key value pair at top of list if `setf' for missing key.
(let ((target (list :a "a" :b "b" :c "c")))
(setf (plist-get target :d) "modify")
(should (equal target '(:d "modify" :a "a" :b "b" :c "c")))
(setf (plist-get target :e #'string=) "mogrify")
(should (equal target '(:e "mogrify" :d "modify" :a "a" :b "b" :c "c"))))
;; Rotate with missing value.
;; The value corresponding to the missing key is assumed to be nil.
(let ((target (list :a "a" :b "b" :c "c")))
(cl-rotatef (plist-get target :b) (plist-get target :d))
(should (equal target '(:d "b" :a "a" :b nil :c "c")))
(cl-rotatef (plist-get target ":e" #'string=)
(plist-get target ":d" #'string=))
(should (equal target '(":e" "b" :d nil :a "a" :b nil :c "c")))))
;;; gv-tests.el ends here