aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2015-12-04 12:59:21 -0500
committerStefan Monnier2015-12-04 12:59:21 -0500
commitc2917b02bfe1a33a283540d9609ffdb215b11999 (patch)
treef5025afe4c1556f6a3453ec97b0d872c8b0f9465
parent30f3432e9519f61882faa303e7851e761d2d18ea (diff)
downloademacs-c2917b02bfe1a33a283540d9609ffdb215b11999.tar.gz
emacs-c2917b02bfe1a33a283540d9609ffdb215b11999.zip
* lisp/emacs-lisp/ert.el: Prefer pcase over cl-typecase
* lisp/emacs-lisp/ert.el (ert--should-error-handle-error) (ert--explain-format-atom, ert--explain-equal-rec) (ert--print-backtrace, ert-test-result-type-p, ert-select-tests) (ert--insert-human-readable-selector): Prefer pcase over cl-typecase.
-rw-r--r--lisp/emacs-lisp/ert.el337
1 files changed, 167 insertions, 170 deletions
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index d572d544e11..a75b23bbc15 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -374,9 +374,9 @@ Returns nil."
374Determines whether CONDITION matches TYPE and EXCLUDE-SUBTYPES, 374Determines whether CONDITION matches TYPE and EXCLUDE-SUBTYPES,
375and aborts the current test as failed if it doesn't." 375and aborts the current test as failed if it doesn't."
376 (let ((signaled-conditions (get (car condition) 'error-conditions)) 376 (let ((signaled-conditions (get (car condition) 'error-conditions))
377 (handled-conditions (cl-etypecase type 377 (handled-conditions (pcase-exhaustive type
378 (list type) 378 ((pred listp) type)
379 (symbol (list type))))) 379 ((pred symbolp) (list type)))))
380 (cl-assert signaled-conditions) 380 (cl-assert signaled-conditions)
381 (unless (cl-intersection signaled-conditions handled-conditions) 381 (unless (cl-intersection signaled-conditions handled-conditions)
382 (ert-fail (append 382 (ert-fail (append
@@ -466,18 +466,18 @@ Errors during evaluation are caught and handled like nil."
466 466
467(defun ert--explain-format-atom (x) 467(defun ert--explain-format-atom (x)
468 "Format the atom X for `ert--explain-equal'." 468 "Format the atom X for `ert--explain-equal'."
469 (cl-typecase x 469 (pcase x
470 (character (list x (format "#x%x" x) (format "?%c" x))) 470 ((pred characterp) (list x (format "#x%x" x) (format "?%c" x)))
471 (fixnum (list x (format "#x%x" x))) 471 ((pred integerp) (list x (format "#x%x" x)))
472 (t x))) 472 (_ x)))
473 473
474(defun ert--explain-equal-rec (a b) 474(defun ert--explain-equal-rec (a b)
475 "Return a programmer-readable explanation of why A and B are not `equal'. 475 "Return a programmer-readable explanation of why A and B are not `equal'.
476Returns nil if they are." 476Returns nil if they are."
477 (if (not (equal (type-of a) (type-of b))) 477 (if (not (equal (type-of a) (type-of b)))
478 `(different-types ,a ,b) 478 `(different-types ,a ,b)
479 (cl-etypecase a 479 (pcase-exhaustive a
480 (cons 480 ((pred consp)
481 (let ((a-proper-p (ert--proper-list-p a)) 481 (let ((a-proper-p (ert--proper-list-p a))
482 (b-proper-p (ert--proper-list-p b))) 482 (b-proper-p (ert--proper-list-p b)))
483 (if (not (eql (not a-proper-p) (not b-proper-p))) 483 (if (not (eql (not a-proper-p) (not b-proper-p)))
@@ -502,24 +502,26 @@ Returns nil if they are."
502 `(cdr ,cdr-x) 502 `(cdr ,cdr-x)
503 (cl-assert (equal a b) t) 503 (cl-assert (equal a b) t)
504 nil)))))))) 504 nil))))))))
505 (array (if (not (equal (length a) (length b))) 505 ((pred arrayp)
506 `(arrays-of-different-length ,(length a) ,(length b) 506 (if (not (equal (length a) (length b)))
507 ,a ,b 507 `(arrays-of-different-length ,(length a) ,(length b)
508 ,@(unless (char-table-p a) 508 ,a ,b
509 `(first-mismatch-at 509 ,@(unless (char-table-p a)
510 ,(cl-mismatch a b :test 'equal)))) 510 `(first-mismatch-at
511 (cl-loop for i from 0 511 ,(cl-mismatch a b :test 'equal))))
512 for ai across a 512 (cl-loop for i from 0
513 for bi across b 513 for ai across a
514 for xi = (ert--explain-equal-rec ai bi) 514 for bi across b
515 do (when xi (cl-return `(array-elt ,i ,xi))) 515 for xi = (ert--explain-equal-rec ai bi)
516 finally (cl-assert (equal a b) t)))) 516 do (when xi (cl-return `(array-elt ,i ,xi)))
517 (atom (if (not (equal a b)) 517 finally (cl-assert (equal a b) t))))
518 (if (and (symbolp a) (symbolp b) (string= a b)) 518 ((pred atomp)
519 `(different-symbols-with-the-same-name ,a ,b) 519 (if (not (equal a b))
520 `(different-atoms ,(ert--explain-format-atom a) 520 (if (and (symbolp a) (symbolp b) (string= a b))
521 ,(ert--explain-format-atom b))) 521 `(different-symbols-with-the-same-name ,a ,b)
522 nil))))) 522 `(different-atoms ,(ert--explain-format-atom a)
523 ,(ert--explain-format-atom b)))
524 nil)))))
523 525
524(defun ert--explain-equal (a b) 526(defun ert--explain-equal (a b)
525 "Explainer function for `equal'." 527 "Explainer function for `equal'."
@@ -694,23 +696,20 @@ and is displayed in front of the value of MESSAGE-FORM."
694 (print-level 8) 696 (print-level 8)
695 (print-length 50)) 697 (print-length 50))
696 (dolist (frame backtrace) 698 (dolist (frame backtrace)
697 (cl-ecase (car frame) 699 (pcase-exhaustive frame
698 ((nil) 700 (`(nil ,special-operator . ,arg-forms)
699 ;; Special operator. 701 ;; Special operator.
700 (cl-destructuring-bind (special-operator &rest arg-forms) 702 (insert
701 (cdr frame) 703 (format " %S\n" (cons special-operator arg-forms))))
702 (insert 704 (`(t ,fn . ,args)
703 (format " %S\n" (cons special-operator arg-forms)))))
704 ((t)
705 ;; Function call. 705 ;; Function call.
706 (cl-destructuring-bind (fn &rest args) (cdr frame) 706 (insert (format " %S(" fn))
707 (insert (format " %S(" fn)) 707 (cl-loop for firstp = t then nil
708 (cl-loop for firstp = t then nil 708 for arg in args do
709 for arg in args do 709 (unless firstp
710 (unless firstp 710 (insert " "))
711 (insert " ")) 711 (insert (format "%S" arg)))
712 (insert (format "%S" arg))) 712 (insert ")\n"))))))
713 (insert ")\n")))))))
714 713
715;; A container for the state of the execution of a single test and 714;; A container for the state of the execution of a single test and
716;; environment data needed during its execution. 715;; environment data needed during its execution.
@@ -894,33 +893,32 @@ t -- Always matches.
894 RESULT." 893 RESULT."
895 ;; It would be easy to add `member' and `eql' types etc., but I 894 ;; It would be easy to add `member' and `eql' types etc., but I
896 ;; haven't bothered yet. 895 ;; haven't bothered yet.
897 (cl-etypecase result-type 896 (pcase-exhaustive result-type
898 ((member nil) nil) 897 ('nil nil)
899 ((member t) t) 898 ('t t)
900 ((member :failed) (ert-test-failed-p result)) 899 (:failed (ert-test-failed-p result))
901 ((member :passed) (ert-test-passed-p result)) 900 (:passed (ert-test-passed-p result))
902 ((member :skipped) (ert-test-skipped-p result)) 901 (:skipped (ert-test-skipped-p result))
903 (cons 902 (`(,operator . ,operands)
904 (cl-destructuring-bind (operator &rest operands) result-type 903 (cl-ecase operator
905 (cl-ecase operator 904 (and
906 (and 905 (cl-case (length operands)
907 (cl-case (length operands) 906 (0 t)
908 (0 t) 907 (t
909 (t 908 (and (ert-test-result-type-p result (car operands))
910 (and (ert-test-result-type-p result (car operands)) 909 (ert-test-result-type-p result `(and ,@(cdr operands)))))))
911 (ert-test-result-type-p result `(and ,@(cdr operands))))))) 910 (or
912 (or 911 (cl-case (length operands)
913 (cl-case (length operands) 912 (0 nil)
914 (0 nil) 913 (t
915 (t 914 (or (ert-test-result-type-p result (car operands))
916 (or (ert-test-result-type-p result (car operands)) 915 (ert-test-result-type-p result `(or ,@(cdr operands)))))))
917 (ert-test-result-type-p result `(or ,@(cdr operands))))))) 916 (not
918 (not 917 (cl-assert (eql (length operands) 1))
919 (cl-assert (eql (length operands) 1)) 918 (not (ert-test-result-type-p result (car operands))))
920 (not (ert-test-result-type-p result (car operands)))) 919 (satisfies
921 (satisfies 920 (cl-assert (eql (length operands) 1))
922 (cl-assert (eql (length operands) 1)) 921 (funcall (car operands) result))))))
923 (funcall (car operands) result)))))))
924 922
925(defun ert-test-result-expected-p (test result) 923(defun ert-test-result-expected-p (test result)
926 "Return non-nil if TEST's expected result type matches RESULT." 924 "Return non-nil if TEST's expected result type matches RESULT."
@@ -961,95 +959,96 @@ as (satisfies ...), strings, :new, etc. make use of UNIVERSE.
961Selectors that do not, such as (member ...), just return the 959Selectors that do not, such as (member ...), just return the
962set implied by them without checking whether it is really 960set implied by them without checking whether it is really
963contained in UNIVERSE." 961contained in UNIVERSE."
964 ;; This code needs to match the etypecase in 962 ;; This code needs to match the cases in
965 ;; `ert-insert-human-readable-selector'. 963 ;; `ert-insert-human-readable-selector'.
966 (cl-etypecase selector 964 (pcase-exhaustive selector
967 ((member nil) nil) 965 ('nil nil)
968 ((member t) (cl-etypecase universe 966 ('t (pcase-exhaustive universe
969 (list universe) 967 ((pred listp) universe)
970 ((member t) (ert-select-tests "" universe)))) 968 (`t (ert-select-tests "" universe))))
971 ((member :new) (ert-select-tests 969 (:new (ert-select-tests
972 `(satisfies ,(lambda (test) 970 `(satisfies ,(lambda (test)
973 (null (ert-test-most-recent-result test)))) 971 (null (ert-test-most-recent-result test))))
974 universe)) 972 universe))
975 ((member :failed) (ert-select-tests 973 (:failed (ert-select-tests
976 `(satisfies ,(lambda (test) 974 `(satisfies ,(lambda (test)
977 (ert-test-result-type-p 975 (ert-test-result-type-p
978 (ert-test-most-recent-result test) 976 (ert-test-most-recent-result test)
979 ':failed))) 977 ':failed)))
980 universe)) 978 universe))
981 ((member :passed) (ert-select-tests 979 (:passed (ert-select-tests
982 `(satisfies ,(lambda (test) 980 `(satisfies ,(lambda (test)
983 (ert-test-result-type-p 981 (ert-test-result-type-p
984 (ert-test-most-recent-result test) 982 (ert-test-most-recent-result test)
985 ':passed))) 983 ':passed)))
986 universe)) 984 universe))
987 ((member :expected) (ert-select-tests 985 (:expected (ert-select-tests
988 `(satisfies 986 `(satisfies
989 ,(lambda (test) 987 ,(lambda (test)
990 (ert-test-result-expected-p 988 (ert-test-result-expected-p
991 test 989 test
992 (ert-test-most-recent-result test)))) 990 (ert-test-most-recent-result test))))
993 universe)) 991 universe))
994 ((member :unexpected) (ert-select-tests `(not :expected) universe)) 992 (:unexpected (ert-select-tests `(not :expected) universe))
995 (string 993 ((pred stringp)
996 (cl-etypecase universe 994 (pcase-exhaustive universe
997 ((member t) (mapcar #'ert-get-test 995 (`t (mapcar #'ert-get-test
998 (apropos-internal selector #'ert-test-boundp))) 996 (apropos-internal selector #'ert-test-boundp)))
999 (list (cl-remove-if-not (lambda (test) 997 ((pred listp)
1000 (and (ert-test-name test) 998 (cl-remove-if-not (lambda (test)
1001 (string-match selector 999 (and (ert-test-name test)
1002 (symbol-name 1000 (string-match selector
1003 (ert-test-name test))))) 1001 (symbol-name
1004 universe)))) 1002 (ert-test-name test)))))
1005 (ert-test (list selector)) 1003 universe))))
1006 (symbol 1004 ((pred ert-test-p) (list selector))
1005 ((pred symbolp)
1007 (cl-assert (ert-test-boundp selector)) 1006 (cl-assert (ert-test-boundp selector))
1008 (list (ert-get-test selector))) 1007 (list (ert-get-test selector)))
1009 (cons 1008 (`(,operator . ,operands)
1010 (cl-destructuring-bind (operator &rest operands) selector 1009 (cl-ecase operator
1011 (cl-ecase operator 1010 (member
1012 (member 1011 (mapcar (lambda (purported-test)
1013 (mapcar (lambda (purported-test) 1012 (pcase-exhaustive purported-test
1014 (cl-etypecase purported-test 1013 ((pred symbolp)
1015 (symbol (cl-assert (ert-test-boundp purported-test)) 1014 (cl-assert (ert-test-boundp purported-test))
1016 (ert-get-test purported-test)) 1015 (ert-get-test purported-test))
1017 (ert-test purported-test))) 1016 ((pred ert-test-p) purported-test)))
1018 operands)) 1017 operands))
1019 (eql 1018 (eql
1020 (cl-assert (eql (length operands) 1)) 1019 (cl-assert (eql (length operands) 1))
1021 (ert-select-tests `(member ,@operands) universe)) 1020 (ert-select-tests `(member ,@operands) universe))
1022 (and 1021 (and
1023 ;; Do these definitions of AND, NOT and OR satisfy de 1022 ;; Do these definitions of AND, NOT and OR satisfy de
1024 ;; Morgan's laws? Should they? 1023 ;; Morgan's laws? Should they?
1025 (cl-case (length operands) 1024 (cl-case (length operands)
1026 (0 (ert-select-tests 't universe)) 1025 (0 (ert-select-tests 't universe))
1027 (t (ert-select-tests `(and ,@(cdr operands)) 1026 (t (ert-select-tests `(and ,@(cdr operands))
1028 (ert-select-tests (car operands) 1027 (ert-select-tests (car operands)
1029 universe))))) 1028 universe)))))
1030 (not 1029 (not
1031 (cl-assert (eql (length operands) 1)) 1030 (cl-assert (eql (length operands) 1))
1032 (let ((all-tests (ert-select-tests 't universe))) 1031 (let ((all-tests (ert-select-tests 't universe)))
1033 (cl-set-difference all-tests 1032 (cl-set-difference all-tests
1034 (ert-select-tests (car operands) 1033 (ert-select-tests (car operands)
1035 all-tests)))) 1034 all-tests))))
1036 (or 1035 (or
1037 (cl-case (length operands) 1036 (cl-case (length operands)
1038 (0 (ert-select-tests 'nil universe)) 1037 (0 (ert-select-tests 'nil universe))
1039 (t (cl-union (ert-select-tests (car operands) universe) 1038 (t (cl-union (ert-select-tests (car operands) universe)
1040 (ert-select-tests `(or ,@(cdr operands)) 1039 (ert-select-tests `(or ,@(cdr operands))
1041 universe))))) 1040 universe)))))
1042 (tag 1041 (tag
1043 (cl-assert (eql (length operands) 1)) 1042 (cl-assert (eql (length operands) 1))
1044 (let ((tag (car operands))) 1043 (let ((tag (car operands)))
1045 (ert-select-tests `(satisfies 1044 (ert-select-tests `(satisfies
1046 ,(lambda (test) 1045 ,(lambda (test)
1047 (member tag (ert-test-tags test)))) 1046 (member tag (ert-test-tags test))))
1048 universe))) 1047 universe)))
1049 (satisfies 1048 (satisfies
1050 (cl-assert (eql (length operands) 1)) 1049 (cl-assert (eql (length operands) 1))
1051 (cl-remove-if-not (car operands) 1050 (cl-remove-if-not (car operands)
1052 (ert-select-tests 't universe)))))))) 1051 (ert-select-tests 't universe)))))))
1053 1052
1054(defun ert--insert-human-readable-selector (selector) 1053(defun ert--insert-human-readable-selector (selector)
1055 "Insert a human-readable presentation of SELECTOR into the current buffer." 1054 "Insert a human-readable presentation of SELECTOR into the current buffer."
@@ -1058,26 +1057,24 @@ contained in UNIVERSE."
1058 ;; `most-recent-result' slots of test case objects in (eql ...) or 1057 ;; `most-recent-result' slots of test case objects in (eql ...) or
1059 ;; (member ...) selectors. 1058 ;; (member ...) selectors.
1060 (cl-labels ((rec (selector) 1059 (cl-labels ((rec (selector)
1061 ;; This code needs to match the etypecase in 1060 ;; This code needs to match the cases in
1062 ;; `ert-select-tests'. 1061 ;; `ert-select-tests'.
1063 (cl-etypecase selector 1062 (pcase-exhaustive selector
1064 ((or (member nil t 1063 ((or
1065 :new :failed :passed 1064 ;; 'nil 't :new :failed :passed :expected :unexpected
1066 :expected :unexpected) 1065 (pred stringp)
1067 string 1066 (pred symbolp))
1068 symbol)
1069 selector) 1067 selector)
1070 (ert-test 1068 ((pred ert-test-p)
1071 (if (ert-test-name selector) 1069 (if (ert-test-name selector)
1072 (make-symbol (format "<%S>" (ert-test-name selector))) 1070 (make-symbol (format "<%S>" (ert-test-name selector)))
1073 (make-symbol "<unnamed test>"))) 1071 (make-symbol "<unnamed test>")))
1074 (cons 1072 (`(,operator . ,operands)
1075 (cl-destructuring-bind (operator &rest operands) selector 1073 (pcase operator
1076 (cl-ecase operator 1074 ((or 'eql 'and 'not 'or)
1077 ((member eql and not or) 1075 `(,operator ,@(mapcar #'rec operands)))
1078 `(,operator ,@(mapcar #'rec operands))) 1076 ((or 'tag 'satisfies)
1079 ((member tag satisfies) 1077 selector))))))
1080 selector)))))))
1081 (insert (format "%S" (rec selector))))) 1078 (insert (format "%S" (rec selector)))))
1082 1079
1083 1080