diff options
| author | Stefan Monnier | 2015-12-04 12:59:21 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2015-12-04 12:59:21 -0500 |
| commit | c2917b02bfe1a33a283540d9609ffdb215b11999 (patch) | |
| tree | f5025afe4c1556f6a3453ec97b0d872c8b0f9465 | |
| parent | 30f3432e9519f61882faa303e7851e761d2d18ea (diff) | |
| download | emacs-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.el | 337 |
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." | |||
| 374 | Determines whether CONDITION matches TYPE and EXCLUDE-SUBTYPES, | 374 | Determines whether CONDITION matches TYPE and EXCLUDE-SUBTYPES, |
| 375 | and aborts the current test as failed if it doesn't." | 375 | and 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'. |
| 476 | Returns nil if they are." | 476 | Returns 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. | |||
| 961 | Selectors that do not, such as (member ...), just return the | 959 | Selectors that do not, such as (member ...), just return the |
| 962 | set implied by them without checking whether it is really | 960 | set implied by them without checking whether it is really |
| 963 | contained in UNIVERSE." | 961 | contained 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 | ||