Skip to content

Commit

Permalink
Make the equality function configurable
Browse files Browse the repository at this point in the history
`cl:equalp` doesn't work for classes, so we make it configurable so we
can pass in e.g. `generic-cl:equalp`.

Closes #7
  • Loading branch information
simendsjo committed Mar 15, 2024
1 parent 0f8c229 commit 0b10835
Showing 1 changed file with 25 additions and 24 deletions.
49 changes: 25 additions & 24 deletions src/doctest.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
(defun string-equal-ignore-ws (string1 string2)
(string-equal (remove-ws string1) (remove-ws string2)))

(defun run-doctest (test-form expected-result expected-output output count)
(defun run-doctest (test-form expected-result expected-output output count &key (test #'equalp))
(let* ((test-form-signaled-condition nil)
(actual-output (make-array '(0) :element-type 'base-char
:fill-pointer 0
Expand Down Expand Up @@ -71,7 +71,7 @@
count test-form
(type-of (car actual-result)) (car actual-result)
(car expected-result))))
(unless (and (equalp actual-result expected-result)
(unless (and (funcall test actual-result expected-result)
expected-output-matches-actual-output)
(setf result nil)
(if expected-output-matches-actual-output
Expand All @@ -85,7 +85,7 @@
expected-output))))
result))

(defun run-doctests (docstring output)
(defun run-doctests (docstring output &key (test #'equalp))
"Run-doctests is used by the test functions to perform the actual work.
It returns the number of tests failed and passed and prints to <output>."
(let ((tests-failed 0)
Expand All @@ -109,12 +109,13 @@
(car expected-result)
expected-output
output
(incf count))
(incf count)
:test test)
(incf tests-passed)
(incf tests-failed))))))
(values tests-failed tests-passed)))

(defun test (thing &key (output t))
(defun test (thing &key (output t) (test #'equalp))
"Test extracts and tests code snippets embedded in the documentation string
of <thing>. It returns the number of tests failed and passed and prints a
description to <output>.
Expand Down Expand Up @@ -224,36 +225,36 @@
(cond ((null thing)
(values 0 0))
((stringp thing)
(test-docstring thing :output output))
(test-docstring thing :output output :test test))
((functionp thing)
(test-function thing :output output))
(test-function thing :output output :test test))
((pathnamep thing)
(test-file thing :output output))
(test-file thing :output output :test test))
((packagep thing)
(test-package thing :output output))
(test-package thing :output output :test test))
((symbolp thing)
(let ((total-failed 0)
(total-passed 0))
(flet ((collect (fn)
(multiple-value-bind (failed passed) (funcall fn)
(incf total-failed failed)
(incf total-passed passed))))
(collect (lambda () (test-variable thing :output output)))
(collect (lambda () (test-variable thing :output output :test test)))
(cond
((macro-function thing)
(collect (lambda () (test-macro thing :output output))))
(collect (lambda () (test-macro thing :output output :test test))))
((fboundp thing)
(collect (lambda () (test-function (symbol-function thing) :output output)))))
(collect (lambda () (test-function (symbol-function thing) :output output :test test)))))
(values total-failed total-passed))))
(t
(error "~&No suitable testing-function available for ~A~%" thing))))

(defun test-variable (thing &key (output t))
(test-docstring (documentation thing 'variable) :output output))
(defun test-variable (thing &key (output t) (test #'equalp))
(test-docstring (documentation thing 'variable) :output output :test test))

(defun test-docstring (documentation &key (output t))
(defun test-docstring (documentation &key (output t) (test #'equalp))
(with-input-from-string (docstring (or documentation ""))
(run-doctests docstring output)))
(run-doctests docstring output :test test)))

(defun parse-lambda-body (body)
(values (and (stringp (car body)) (cdr body) (pop body))
Expand All @@ -278,7 +279,7 @@
"")
name)))

(defun test-function (function &key (output t))
(defun test-function (function &key (output t) (test #'equalp))
"Test-function extracts and tests code snippets in <function>'s documentation
string. It returns the number of tests failed and passed and prints a
description to <output>.
Expand All @@ -287,11 +288,11 @@
(multiple-value-bind (documentation function-name) (extract-function-documentation-and-name function)
(if documentation
(multiple-value-bind (tests-failed tests-passed)
(test-docstring documentation :output output)
(test-docstring documentation :output output :test test)
(print-results function-name 'function output tests-failed tests-passed))
(values 0 0))))

(defun test-macro (macro &key (output t))
(defun test-macro (macro &key (output t) (test #'equalp))
"Test-macro extracts and tests code snippets in <macro>'s documentation string.
It returns the number of tests failed and passed and prints a description to
<output>.
Expand All @@ -300,29 +301,29 @@
(if (documentation macro 'function)
(let ((macro-name (third (multiple-value-list (function-lambda-expression (macro-function macro))))))
(multiple-value-bind (tests-failed tests-passed)
(test-docstring (documentation macro 'function) :output output)
(test-docstring (documentation macro 'function) :output output :test test)
(print-results macro-name 'macro output tests-failed tests-passed)))
(values 0 0)))


(defun test-file (filename &key (output t))
(defun test-file (filename &key (output t) (test #'equalp))
"Test-file extracts and tests code snippets in the contents of <filename>. It
returns the number of tests failed and passed and prints a description to
<output>.
See also the documentation string for test."
(multiple-value-bind (tests-failed tests-passed)
(with-open-file (docstring filename :direction :input)
(test-docstrting docstring :output output))
(test-docstrting docstring :output output :test test))
(print-results filename 'file output tests-failed tests-passed)))

(defun test-package (package &key (output t))
(defun test-package (package &key (output t) (test #'equalp))
(let ((total-failed 0)
(total-passed 0))
(let ((*package* (find-package package)))
(do-symbols (symbol (find-package package))
(when (eq *package* (symbol-package symbol))
(multiple-value-bind (tests-failed tests-passed) (test symbol :output output)
(multiple-value-bind (tests-failed tests-passed) (test symbol :output output :test test)
(incf total-failed tests-failed)
(incf total-passed tests-passed)))))
(values total-failed total-passed)))
Expand Down

0 comments on commit 0b10835

Please sign in to comment.