[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/buttercup 497f6c2795 9/9: Merge branch 'byte-compiled'
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/buttercup 497f6c2795 9/9: Merge branch 'byte-compiled' |
Date: |
Wed, 10 Aug 2022 18:58:14 -0400 (EDT) |
branch: elpa/buttercup
commit 497f6c27951146692a4a07f0027cb08f70f0064e
Merge: 62176a39ee 1bb0ba9439
Author: Ola Nilsson <ola.nilsson@gmail.com>
Commit: Ola Nilsson <ola.nilsson@gmail.com>
Merge branch 'byte-compiled'
Cleanup and tests for #219.
* byte-compiled:
tests: Add tests for buttercup--enclosed-expr
Clean up buttercup--enclosed-expr
tests: Use buttercup--wrap-expr instead of make-list-of-closures
tests: Fix some buttercup-expect tests
tests: Create enclosed expressions with buttercup--wrap-expr
Refactor the expect macro
Fix: (buttercup--enclosed-expr) byte-code functions
---
buttercup.el | 88 +++++++++++++++++--------------
tests/test-buttercup.el | 136 +++++++++++++++++++++++++++++++++++-------------
2 files changed, 150 insertions(+), 74 deletions(-)
diff --git a/buttercup.el b/buttercup.el
index f32647b788..bf7f265162 100644
--- a/buttercup.el
+++ b/buttercup.el
@@ -57,33 +57,46 @@
(defun buttercup--enclosed-expr (fun)
"Given a zero-arg function FUN, return its unevaluated expression.
-The function MUST have one of the following forms:
-
-\(lambda () EXPR)
-\(lambda () (buttercup--mark-stackframe) EXPR)
-\(closure (ENVLIST) () EXPR)
-\(closure (ENVLIST) () (buttercup--mark-stackframe) EXPR)
-\(lambda () (quote EXPR) EXPR)
-\(closure (ENVLIST) () (quote EXPR) EXPR)
-
-and the return value will be EXPR, unevaluated. The latter 2
-forms are useful if EXPR is a macro call, in which case the
-`quote' ensures access to the un-expanded form."
+The function MUST be byte-compiled or have one of the following
+forms:
+
+\(closure (ENVLIST) () (quote EXPR) (buttercup--mark-stackframe) EXPANDED)
+\(lambda () (quote EXPR) (buttercup--mark-stackframe) EXPR)
+
+and the return value will be EXPR, unevaluated. The quoted EXPR
+is useful if EXPR is a macro call, in which case the `quote'
+ensures access to the un-expanded form."
+ (cl-assert (functionp fun) t "Expected FUN to be a function")
(pcase fun
- (`(closure ,(pred listp) nil ,expr) expr)
- (`(closure ,(pred listp) nil (buttercup--mark-stackframe) ,expr) expr)
- (`(closure ,(pred listp) nil (quote ,expr) . ,_rest) expr)
- (`(closure ,(pred listp) nil ,_expr . ,(pred identity))
- (error "Closure contains multiple expressions: %S" fun))
- (`(closure ,(pred listp) ,(pred identity) . ,(pred identity))
- (error "Closure has nonempty arglist: %S" fun))
- (`(lambda nil ,expr) expr)
- (`(lambda nil (buttercup--mark-stackframe) ,expr) expr)
- (`(lambda nil (quote ,expr) . ,_rest) expr)
- (`(lambda nil ,_expr . ,(pred identity))
- (error "Function contains multiple expressions: %S" fun))
- (`(lambda ,(pred identity) . ,(pred identity))
- (error "Function has nonempty arglist: %S" fun))
+ ;; This should be the normal case, a closure with unknown enclosed
+ ;; variables, empty arglist and a body containing
+ ;; * the quoted original expression
+ ;; * the stackframe marker
+ ;; * the macroexpanded original expression
+ (`(closure ,(pred listp) nil
+ (quote ,expr) (buttercup--mark-stackframe) ,_expanded)
+ expr)
+ ;; This a when FUN has not been evaluated. Probably never happens
+ ;; except when testing buttercup. Should probably do something
+ ;; about that.
+ ;; A lambda with an empty arglist and a body containing
+ ;; * the quoted original expression
+ ;; * the stackframe marker
+ ;; * the original expression
+ ;; In this case expr and expr2 should be equal (but not eq?) as
+ ;; expr2 has not been macroexpanded.
+ ((and `(lambda nil
+ (quote ,expr) (buttercup--mark-stackframe) ,expr2)
+ (guard (equal expr expr2)))
+ expr)
+ ;;; This is when FUN has been byte compiled, as when the entire
+ ;;; test file has been byte compiled. Check that it has an empty
+ ;;; arglist, that is all that is possible at this point. The
+ ;;; return value is byte compiled code, not the original
+ ;;; expressions. Also what is possible at this point.
+ ((and (pred byte-code-function-p) (guard (member (aref fun 0) '(nil 0))))
+ (aref fun 1))
+ ;; Error
(_ (error "Not a zero-arg one-expression closure: %S" fun))))
(defun buttercup--expr-and-value (fun)
@@ -123,6 +136,13 @@ a call to `save-match-data', as `format-spec' modifies
that."
(define-error 'buttercup-pending "Buttercup test is pending"
'buttercup-error-base)
+(defun buttercup--wrap-expr (expr)
+ "Wrap EXPR to be used by `buttercup-expect'."
+ `(lambda ()
+ (quote ,expr)
+ (buttercup--mark-stackframe)
+ ,expr))
+
(defmacro expect (arg &optional matcher &rest args)
"Expect a condition to be true.
@@ -137,19 +157,9 @@ This macro knows three forms:
\(expect ARG)
Fail the current test if ARG is not true."
- (let ((wrapped-args
- (mapcar (lambda (expr) `(lambda ()
- (quote ,expr)
- (buttercup--mark-stackframe)
- ,expr))
- args)))
- `(buttercup-expect
- (lambda ()
- (quote ,arg)
- (buttercup--mark-stackframe)
- ,arg)
- ,(or matcher :to-be-truthy)
- ,@wrapped-args)))
+ `(buttercup-expect ,(buttercup--wrap-expr arg)
+ ,(or matcher :to-be-truthy)
+ ,@(mapcar #'buttercup--wrap-expr args)))
(defun buttercup-expect (arg &optional matcher &rest args)
"The function for the `expect' macro.
diff --git a/tests/test-buttercup.el b/tests/test-buttercup.el
index b9456ffa4a..292b21d3cd 100644
--- a/tests/test-buttercup.el
+++ b/tests/test-buttercup.el
@@ -26,17 +26,12 @@
(require 'buttercup)
(require 'autoload)
(require 'ansi-color)
+(require 'bytecomp)
(require 'ert)
(require 'ert-x)
(require 'cl-lib)
(require 'imenu)
-(defun make-list-of-closures (items)
- "For each element of ITEMS, return a closure returning it."
- (mapcar (lambda (item)
- (lambda () item))
- items))
-
(defmacro with-local-buttercup (&rest body)
"Execute BODY with local buttercup state variables.
Keyword arguments kan be used to override the values of certain
@@ -144,6 +139,80 @@ text properties using `ansi-color-apply'."
;; print remaining text
(insert-owrt string))))))
+;;;;;;;;;;
+;;; helpers
+
+(describe "The buttercup--enclosed-expr function"
+ (describe "should handle"
+ (it "expressions wrapped by buttercup--wrap-expr"
+ (expect (buttercup--enclosed-expr (buttercup--wrap-expr '(ignore)))
+ :to-equal '(ignore)))
+ (it "a closure with expression copy?"
+ (expect (buttercup--enclosed-expr
+ (let ((_foo 1))
+ (lambda () '(ignore) (buttercup--mark-stackframe) (ignore))))
+ :to-equal '(ignore)))
+ (it "a lambda with expression copy?"
+ ;; I suspect there is nothing to make sure that the quoted
+ ;; expression matches the actual expression
+ (expect (buttercup--enclosed-expr
+ '(lambda () (quote (ignore)) (buttercup--mark-stackframe)
(ignore))))
+ :to-equal '(ignore))
+ (describe "byte compiled"
+ (it "lambda objects"
+ (expect (buttercup--enclosed-expr
+ (byte-compile-sexp '(lambda () '(ignore)
(buttercup--mark-stackframe) (ignore))))))
+ (it "wrapped expression"
+ (expect (buttercup--enclosed-expr (byte-compile-sexp
(buttercup--wrap-expr '(ignore))))))))
+ (describe "should error"
+ (it "on a simple closure"
+ (expect
+ (buttercup--enclosed-expr (let ((_foo 1)) (lambda () (ignore))))
+ :to-throw
+ 'error '("Not a zero-arg one-expression closure: (closure ((_foo . 1)
t) nil (ignore))")))
+ (it "on a closure with stackframe marker but no quoted expression"
+ (expect
+ (buttercup--enclosed-expr (let ((_foo 1)) (lambda ()
(buttercup--mark-stackframe) (ignore))))
+ :to-throw
+ 'error '("Not a zero-arg one-expression closure: (closure ((_foo . 1)
t) nil (buttercup--mark-stackframe) (ignore))")))
+ (it "for multi-statement closures"
+ (expect (buttercup--enclosed-expr
+ (lambda () '(+ 1 2) (buttercup--mark-stackframe) (+ 1 2)
(ignore)))
+ :to-throw
+ 'error
+ ;; The formatting differs in different versions of Emacs
+ (list (format "Not a zero-arg one-expression closure: %S"
+ '(closure (t) nil '(+ 1 2)
(buttercup--mark-stackframe) (+ 1 2) (ignore))))))
+ (it "for closures with non-empty argument lists"
+ (expect (buttercup--enclosed-expr
+ (lambda (foo) '(ignore foo) (buttercup--mark-stackframe)
(ignore foo)))
+ :to-throw
+ 'error
+ ;; The formatting differs in different versions of Emacs
+ (list (format "Not a zero-arg one-expression closure: %S"
+ '(closure (t) (foo) '(ignore foo)
(buttercup--mark-stackframe) (ignore foo))))))
+ (it "on simple lambda objects"
+ (expect (buttercup--enclosed-expr
+ '(lambda () (ignore)))
+ :to-throw))
+ (it "on a lambda with stackframe marker but no quoted expression"
+ (expect (buttercup--enclosed-expr
+ '(lambda () (buttercup--mark-stackframe) (ignore)))
+ :to-throw))
+ (it "for multi-statement lambdas"
+ (expect (buttercup--enclosed-expr
+ '(lambda () (+ 1 2) (ignore)))
+ :to-throw
+ 'error '("Not a zero-arg one-expression closure: (lambda nil (+
1 2) (ignore))")))
+ (it "for lambdas with non-empty argument lists"
+ (expect (buttercup--enclosed-expr
+ '(lambda (foo) (ignore foo)))
+ :to-throw
+ 'error '("Not a zero-arg one-expression closure: (lambda (foo)
(ignore foo))")))
+ (it "on byte-compiled functions with arguments"
+ (expect (buttercup--enclosed-expr
+ (byte-compile-sexp '(lambda (_a) '(ignore)
(buttercup--mark-stackframe) (ignore))))
+ :to-throw 'error))))
;;;;;;;;;;
;;; expect
@@ -182,31 +251,28 @@ text properties using `ansi-color-apply'."
(describe "with a function as a matcher argument"
(it "should not raise an error if the function returns true"
(expect (buttercup-expect
- (lambda () t)
+ (buttercup--wrap-expr t)
#'eq
- (lambda () t))
+ (buttercup--wrap-expr t))
:not :to-throw
'buttercup-failed))
(it "should raise an error if the function returns false"
(expect (buttercup-expect
- (lambda () t)
+ (buttercup--wrap-expr t)
#'eq
- (lambda () nil))
+ (buttercup--wrap-expr nil))
:to-throw
'buttercup-failed)))
(describe "with a matcher argument"
- (buttercup-define-matcher :always-true (_a) t)
- (buttercup-define-matcher :always-false (_a) nil)
-
(it "should not raise an error if the matcher returns true"
- (expect (buttercup-expect (lambda () 1) :always-true)
+ (expect (buttercup-expect (buttercup--wrap-expr (ignore)) #'always)
:not :to-throw
'buttercup-failed))
(it "should raise an error if the matcher returns false"
- (expect (buttercup-expect (lambda () 1) :always-false)
+ (expect (buttercup-expect (buttercup--wrap-expr t) #'ignore)
:to-throw
'buttercup-failed))))
@@ -243,7 +309,7 @@ text properties using `ansi-color-apply'."
(describe "The `buttercup-define-matcher' macro"
(it "should create a matcher usable by apply-matcher"
(expect (buttercup--apply-matcher
- :test-matcher (make-list-of-closures '(1 2)))
+ :test-matcher (mapcar #'buttercup--wrap-expr '(1 2)))
:to-equal
3)))
@@ -251,19 +317,19 @@ text properties using `ansi-color-apply'."
(it "should work with functions"
(expect (buttercup--apply-matcher
#'+
- (make-list-of-closures '(1 2)))
+ (mapcar #'buttercup--wrap-expr '(1 2)))
:to-equal
3))
(it "should work with matchers"
(expect (buttercup--apply-matcher
- :test-matcher (make-list-of-closures '(1 2)))
+ :test-matcher (mapcar #'buttercup--wrap-expr '(1 2)))
:to-equal
3))
(it "should fail if the matcher is not defined"
(expect (buttercup--apply-matcher
- :not-defined (make-list-of-closures '(1 2)))
+ :not-defined (mapcar #'buttercup--wrap-expr '(1 2)))
:to-throw)))
;;;;;;;;;;;;;;;;;;;;;
@@ -774,7 +840,7 @@ text properties using `ansi-color-apply'."
;;;;;;;;;
;;; Spies
-(describe "The Spy "
+(describe "The Spy"
(let (saved-test-function
saved-test-command
saved-test-function-throws-on-negative)
@@ -885,7 +951,7 @@ text properties using `ansi-color-apply'."
(it "returns false if the spy was not called"
(expect (buttercup--apply-matcher
:to-have-been-called
- (list (lambda () 'test-function)))
+ (list (buttercup--wrap-expr ''test-function)))
:to-be
nil))
@@ -893,7 +959,7 @@ text properties using `ansi-color-apply'."
(test-function 1 2 3)
(expect (buttercup--apply-matcher
:to-have-been-called
- (list (lambda () 'test-function)))
+ (list (buttercup--wrap-expr ''test-function)))
:to-be
t)))
@@ -904,7 +970,7 @@ text properties using `ansi-color-apply'."
(it "returns false if the spy was not called at all"
(expect (buttercup--apply-matcher
:to-have-been-called-with
- (make-list-of-closures '(test-function 1 2 3)))
+ (mapcar #'buttercup--wrap-expr '('test-function '1 '2 '3)))
:to-equal
(cons nil
"Expected `test-function' to have been called with (1 2
3), but it was not called at all")))
@@ -913,7 +979,7 @@ text properties using `ansi-color-apply'."
(test-function 3 2 1)
(expect (buttercup--apply-matcher
:to-have-been-called-with
- (make-list-of-closures '(test-function 1 2 3)))
+ (mapcar #'buttercup--wrap-expr '('test-function 1 2 3)))
:to-equal
(cons nil
"Expected `test-function' to have been called with (1 2
3), but it was called with (3 2 1)")))
@@ -922,7 +988,7 @@ text properties using `ansi-color-apply'."
(test-function 1 2 3)
(expect (buttercup--apply-matcher
:to-have-been-called-with
- (make-list-of-closures '(test-function 1 2 3)))
+ (mapcar #'buttercup--wrap-expr '('test-function 1 2 3)))
:to-be
t)))
@@ -933,7 +999,7 @@ text properties using `ansi-color-apply'."
(it "returns error if the spy was called less than expected"
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 1)))
+ (mapcar #'buttercup--wrap-expr '('test-function 1)))
:to-equal
(cons nil
"Expected `test-function' to have been called 1 time,
but it was called 0 times")))
@@ -943,7 +1009,7 @@ text properties using `ansi-color-apply'."
(test-function)
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 1)))
+ (mapcar #'buttercup--wrap-expr '('test-function 1)))
:to-equal
(cons nil
"Expected `test-function' to have been called 1 time,
but it was called 2 times")))
@@ -953,7 +1019,7 @@ text properties using `ansi-color-apply'."
(test-function)
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 2)))
+ (mapcar #'buttercup--wrap-expr '('test-function 2)))
:to-equal t))
(it "use plural words in error message"
@@ -961,7 +1027,7 @@ text properties using `ansi-color-apply'."
(test-function)
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 3)))
+ (mapcar #'buttercup--wrap-expr '('test-function 3)))
:to-equal
(cons nil
"Expected `test-function' to have been called 3 times,
but it was called 2 times")))
@@ -969,7 +1035,7 @@ text properties using `ansi-color-apply'."
(it "use singular expected word in error message"
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 1)))
+ (mapcar #'buttercup--wrap-expr '('test-function 1)))
:to-equal
(cons nil
"Expected `test-function' to have been called 1 time,
but it was called 0 times")))
@@ -978,7 +1044,7 @@ text properties using `ansi-color-apply'."
(test-function)
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function 2)))
+ (mapcar #'buttercup--wrap-expr '('test-function 2)))
:to-equal
(cons nil
"Expected `test-function' to have been called 2 times,
but it was called 1 time"))))
@@ -1082,7 +1148,7 @@ text properties using `ansi-color-apply'."
(expect (test-function-throws-on-negative -5) :to-throw)
(expect (buttercup--apply-matcher
:to-have-been-called
- (list (lambda () 'test-function-throws-on-negative)))
+ (list (buttercup--wrap-expr
''test-function-throws-on-negative)))
:to-be
t))
@@ -1091,7 +1157,7 @@ text properties using `ansi-color-apply'."
(expect (test-function-throws-on-negative -5) :to-throw)
(expect (buttercup--apply-matcher
:to-have-been-called-times
- (make-list-of-closures '(test-function-throws-on-negative 2)))
+ (mapcar #'buttercup--wrap-expr
'('test-function-throws-on-negative 2)))
:to-equal t))
(it "records args to the function whether it throw an error or not"
@@ -1099,12 +1165,12 @@ text properties using `ansi-color-apply'."
(expect (test-function-throws-on-negative -5) :to-throw)
(expect (buttercup--apply-matcher
:to-have-been-called-with
- (make-list-of-closures '(test-function-throws-on-negative 5)))
+ (mapcar #'buttercup--wrap-expr
'('test-function-throws-on-negative 5)))
:to-be
t)
(expect (buttercup--apply-matcher
:to-have-been-called-with
- (make-list-of-closures '(test-function-throws-on-negative
-5)))
+ (mapcar #'buttercup--wrap-expr
'('test-function-throws-on-negative -5)))
:to-be
t))
- [nongnu] elpa/buttercup updated (62176a39ee -> 497f6c2795), ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup ec4d94f7d5 3/9: tests: Create enclosed expressions with buttercup--wrap-expr, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup ef293a62df 1/9: Fix: (buttercup--enclosed-expr) byte-code functions, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup 8dda6ef8c9 2/9: Refactor the expect macro, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup 1bb0ba9439 8/9: Merge PR 219 into byte-compiled, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup 497f6c2795 9/9: Merge branch 'byte-compiled',
ELPA Syncer <=
- [nongnu] elpa/buttercup 4cbd106609 5/9: tests: Use buttercup--wrap-expr instead of make-list-of-closures, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup 435fc0d378 4/9: tests: Fix some buttercup-expect tests, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup 0e26b1bbed 6/9: Clean up buttercup--enclosed-expr, ELPA Syncer, 2022/08/10
- [nongnu] elpa/buttercup cdbb8b061d 7/9: tests: Add tests for buttercup--enclosed-expr, ELPA Syncer, 2022/08/10