diff --git a/40ants-doc-test.asd b/40ants-doc-test.asd index 34835d10..6f38bf5e 100644 --- a/40ants-doc-test.asd +++ b/40ants-doc-test.asd @@ -6,11 +6,6 @@ :pathname "test" :depends-on ("40ants-doc-test/test-transcribe" "40ants-doc-test/test") - ;; :components ((:module "test" - ;; :serial t - ;; :components ((:file "package") - ;; (:file "test-transcribe") - ;; (:file "test")))) :perform (test-op (op c) (unless (symbol-call :rove :run c) (error "Tests failed")))) diff --git a/Changes.org b/Changes.org index 812fb4aa..c9151ccd 100644 --- a/Changes.org +++ b/Changes.org @@ -5,3 +5,4 @@ file-subseq function was rewritten. * Locatives can be specified without a package prefix inside the defsection because all locative symbols now live in 40ANTS-DOC/LOCATIVES package. * Function update-asdf-system-readmes was renamed to update-asdf-system-readmes and now it generates only one README file +* Tests were rewritten to use Rove and to support (asdf:test-system :40ants-doc) diff --git a/src/builder.lisp b/src/builder.lisp index f9dc76bb..52aadb4c 100644 --- a/src/builder.lisp +++ b/src/builder.lisp @@ -338,9 +338,7 @@ (40ants-doc/builder/footer::emit-footer stream)) (unless (eq format :markdown) (let ((markdown-string (40ants-doc/page::with-temp-input-from-page (stream page) - (uiop:slurp-stream-string stream) - ;; (40ants-doc/utils::read-stream-into-string stream) - ))) + (uiop:slurp-stream-string stream)))) (40ants-doc/utils::delete-stream-spec (40ants-doc/page::page-temp-stream-spec page)) (40ants-doc/page::with-final-output-to-page (stream page) (when (40ants-doc/page::page-header-fn page) diff --git a/src/transcribe.lisp b/src/transcribe.lisp index 26f3c89c..6efffe45 100644 --- a/src/transcribe.lisp +++ b/src/transcribe.lisp @@ -22,7 +22,9 @@ #:read-prefixed-lines #:read-line* #:whitespacep) - (:import-from #:40ants-doc/reference)) + (:import-from #:40ants-doc/reference) + (:import-from #:40ants-doc/page) + (:import-from #:swank)) (in-package 40ants-doc/transcribe) (named-readtables:in-readtable pythonic-string-reader:pythonic-string-syntax) @@ -477,8 +479,7 @@ ;; There is no way to guarantee that FILE-POSITION will work ;; on a stream so let's just read the entire INPUT into a ;; string. - (with-input-from-string (stream ;; (40ants-doc/utils::read-stream-into-string input) - (uiop:slurp-stream-string input)) + (with-input-from-string (stream (uiop:slurp-stream-string input)) (funcall fn stream))) ((stringp input) (with-input-from-string (input input) diff --git a/src/utils.lisp b/src/utils.lisp index 6c5b3a3c..a8345c26 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -1,6 +1,7 @@ (uiop:define-package #:40ants-doc/utils (:use #:cl) - (:import-from #:40ants-doc/builder/vars)) + (:import-from #:40ants-doc/builder/vars) + (:import-from #:alexandria)) (in-package 40ants-doc/utils) @@ -13,18 +14,11 @@ #-(or sbcl allegro) (ignore-errors (symbol-value symbol))) -;; TODO: probably replace with uiop -;; (defun read-stream-into-string (stream &key (buffer-size 4096)) -;; (let ((*print-pretty* nil)) -;; (with-output-to-string (datum) -;; (let ((buffer (make-array buffer-size :element-type 'character))) -;; (loop for bytes-read = (read-sequence buffer stream) -;; do (write-sequence buffer datum :start 0 :end bytes-read) -;; while (= bytes-read buffer-size)))))) (defun subseq* (seq start) (subseq seq (min (length seq) start))) + (defun relativize-pathname (pathname reference-pathname) "Return a pathname that's equivalent to PATHNAME but relative to REFERENCE-PATHNAME if possible. Like ENOUGH-NAMESTRING, but inserts diff --git a/test/test-transcribe.lisp b/test/test-transcribe.lisp index 51fe5d21..ace004c4 100644 --- a/test/test-transcribe.lisp +++ b/test/test-transcribe.lisp @@ -1,62 +1,67 @@ (defpackage #:40ants-doc-test/test-transcribe (:use #:cl) (:import-from #:40ants-doc/utils) - (:import-from #:40ants-doc/transcribe)) + (:import-from #:40ants-doc/transcribe) + (:import-from #:rove + #:testing + #:ok + #:deftest)) (in-package 40ants-doc-test/test-transcribe) -(defun test-read-prefixed-lines () - (assert +(deftest test-read-prefixed-lines + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1")) (40ants-doc/utils::read-prefixed-lines stream ">"))) '("1" 1 nil t 2))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%")) (40ants-doc/utils::read-prefixed-lines stream ">"))) '("1" 1 nil t 3))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>")) (40ants-doc/utils::read-prefixed-lines stream ">"))) `(,(format nil "1~%") 2 nil t 4))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3")) (40ants-doc/utils::read-prefixed-lines stream ">"))) `(,(format nil "1~%2~%3") 3 nil t 9))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3~%xy~%")) (40ants-doc/utils::read-prefixed-lines stream ">"))) `(,(format nil "1~%2~%3") 3 "xy" nil 10))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3~%xy")) (40ants-doc/utils::read-prefixed-lines stream ">"))) `(,(format nil "1~%2~%3") 3 "xy" t 10))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1")) (40ants-doc/utils::read-prefixed-lines stream ">" :first-line-prefix ""))) '(">1" 1 nil t 2))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3")) (40ants-doc/utils::read-prefixed-lines stream ">" :first-line-prefix ""))) `(,(format nil ">1~%2~%3") 3 nil t 9))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3~%xy~%")) (40ants-doc/utils::read-prefixed-lines stream ">" :first-line-prefix ""))) `(,(format nil ">1~%2~%3") 3 "xy" nil 10))) - (assert + (ok (equal (multiple-value-list (with-input-from-string (stream (format nil ">1~%>2~%> 3~%xy")) (40ants-doc/utils::read-prefixed-lines stream ">" :first-line-prefix ""))) `(,(format nil ">1~%2~%3") 3 "xy" t 10)))) + (defclass bbb () ()) @@ -77,6 +82,7 @@ #+ecl (format stream "#")) + (defparameter *transcribe-test-cases* '((:input "1" :transcript (((1 "1") nil)) @@ -278,57 +284,61 @@ (values node t nil))) tree)) -(defun test-read-write-transcript () - (let ((*package* (find-package :40ants-doc-test/test-transcribe))) - (loop for test-case in *transcribe-test-cases* do - (format t "test case: ~S~%" test-case) - (destructuring-bind (&key input transcript output check-consistency - update-only (include-no-output update-only) - (include-no-value update-only) - default-syntax errors output-consistency-errors - values-consistency-errors) - test-case - (let ((output-consistency-errors* ()) - (values-consistency-errors* ()) - (errors* ())) - (catch 'here - (handler-bind - ((40ants-doc/transcribe::transcription-output-consistency-error - (lambda (e) - (push (40ants-doc/transcribe::transcription-error-file-position e) - output-consistency-errors*) - (continue))) - (40ants-doc/transcribe::transcription-values-consistency-error - (lambda (e) - (push (40ants-doc/transcribe::transcription-error-file-position e) - values-consistency-errors*) - (continue))) - (40ants-doc/transcribe::transcription-error - (lambda (e) - (push (40ants-doc/transcribe::transcription-error-file-position e) - errors*) - (throw 'here nil)))) - (let* ((input (format nil input)) - (output (when output (format nil output))) - (transcript (call-format-on-strings transcript)) - (transcript* (40ants-doc/transcribe::read-transcript input)) - (output* - (40ants-doc/transcribe::write-transcript - transcript* nil - :check-consistency check-consistency - :update-only update-only - :include-no-output include-no-output - :include-no-value include-no-value - :default-syntax default-syntax))) - (when transcript - (assert (equal transcript transcript*))) - (when output - (assert (equal output output*)))))) - (assert (equal (reverse errors*) errors)) - (assert (equal (reverse output-consistency-errors*) - output-consistency-errors)) - (assert (equal (reverse values-consistency-errors*) - values-consistency-errors))))))) +(deftest test-read-write-transcript + (loop with *package* = (find-package :40ants-doc-test/test-transcribe) + for test-case in *transcribe-test-cases* + do (testing (format nil "test case: ~S" test-case) + (destructuring-bind (&key input transcript output check-consistency + update-only (include-no-output update-only) + (include-no-value update-only) + default-syntax errors output-consistency-errors + values-consistency-errors) + test-case + (let ((output-consistency-errors* ()) + (values-consistency-errors* ()) + (errors* ())) + (catch 'here + (handler-bind + ((40ants-doc/transcribe::transcription-output-consistency-error + (lambda (e) + (push (40ants-doc/transcribe::transcription-error-file-position e) + output-consistency-errors*) + (continue))) + (40ants-doc/transcribe::transcription-values-consistency-error + (lambda (e) + (push (40ants-doc/transcribe::transcription-error-file-position e) + values-consistency-errors*) + (continue))) + (40ants-doc/transcribe::transcription-error + (lambda (e) + (push (40ants-doc/transcribe::transcription-error-file-position e) + errors*) + (throw 'here nil)))) + (let* ((input (format nil input)) + (output (when output (format nil output))) + (transcript (call-format-on-strings transcript)) + (transcript* (40ants-doc/transcribe::read-transcript input)) + (output* + (40ants-doc/transcribe::write-transcript + transcript* nil + :check-consistency check-consistency + :update-only update-only + :include-no-output include-no-output + :include-no-value include-no-value + :default-syntax default-syntax))) + (when transcript + (ok (equal transcript + transcript*))) + (when output + (ok (equal output + output*)))))) + (ok (equal (reverse errors*) + errors)) + (ok (equal (reverse output-consistency-errors*) + output-consistency-errors)) + (ok (equal (reverse values-consistency-errors*) + values-consistency-errors))))))) + (defparameter *transcribe-source-file* (asdf:system-relative-pathname @@ -338,17 +348,6 @@ (asdf:system-relative-pathname :40ants-doc-test "test/data/baseline/transcribe-transcription.lisp")) -(defun test-transcribe-from-source () - (check-transcription *transcribe-source-file* - *transcribe-transcription-file* - :check-consistency nil)) - -;;; Check that repeated transcription produces the same results. -(defun test-transcribe-stability () - (check-transcription *transcribe-transcription-file* - *transcribe-transcription-file* - :check-consistency t)) - (defun get-diff (baseline new-content) (uiop:with-temporary-file (:stream new :pathname new-path :direction :output) @@ -364,6 +363,7 @@ (defun check-transcription (source-file transcription-file &key check-consistency) + "Check that repeated transcription produces the same results." (let ((result (with-output-to-string (transcription) (with-open-file (source source-file) (40ants-doc/transcribe::transcribe source @@ -380,8 +380,14 @@ (alexandria:write-string-into-file result transcription-file :if-exists :rename-and-delete)))) -(defun test () - (test-read-prefixed-lines) - (test-read-write-transcript) - (test-transcribe-from-source) - (test-transcribe-stability)) + +(deftest test-transcribe-from-source + (check-transcription *transcribe-source-file* + *transcribe-transcription-file* + :check-consistency nil)) + + +(deftest test-transcribe-stability + (check-transcription *transcribe-transcription-file* + *transcribe-transcription-file* + :check-consistency t)) diff --git a/test/test.lisp b/test/test.lisp index 5a3c1e57..9982dd77 100644 --- a/test/test.lisp +++ b/test/test.lisp @@ -3,7 +3,11 @@ #:40ants-doc/locatives) (:import-from #:40ants-doc #:defsection) - (:import-from #:40ants-doc/doc)) + (:import-from #:40ants-doc/doc) + (:import-from #:rove + #:ok + #:deftest + #:testing)) (in-package 40ants-doc-test/test) @@ -185,90 +189,100 @@ (test-gf generic-function (defgeneric test-gf)) (test-gf (method () (number)) (defmethod test-gf)))) + (defun working-locative-p (locative) (declare (ignorable locative)) ;; AllegroCL doesn't store source location for DEFPACKAGE. #+allegro (not (eq locative 'package)) #-allegro t) -(defun test-navigation () - (loop for test-case in *navigation-test-cases* - do (destructuring-bind - (symbol locative prefix &optional alternative-prefix) test-case - (when (working-locative-p locative) - (let ((location (40ants-doc/source-api::find-source - (40ants-doc/locatives/base::locate symbol locative)))) - (assert (not (eq :error (first location))) () - "Could not find source location for (~S ~S)" - symbol locative) - (let* ((file (second (second location))) - (position (1- (second (third location)))) - (form (let ((*package* (find-package :40ants-doc-test/test))) - (read-form-from-file-position file position)))) - (assert - (or (alexandria:starts-with-subseq prefix form - :test #'equal) - (and alternative-prefix - (alexandria:starts-with-subseq - alternative-prefix form :test #'equal))) - () "Could not find prefix ~S~@[ or ~S~] ~ - at source location~%~S~%for reference (~S ~S).~%~ - Form found was:~%~S." - prefix alternative-prefix - location symbol locative form))))))) + +(deftest test-navigation + (dolist (test-case *navigation-test-cases*) + (destructuring-bind + (symbol locative prefix &optional alternative-prefix) test-case + (testing (format nil "(~S ~S)" + symbol locative) + (when (working-locative-p locative) + (let ((location (40ants-doc/source-api::find-source + (40ants-doc/locatives/base::locate symbol locative)))) + (ok (not (eq :error (first location))) + (format nil "Could not find source location for (~S ~S)" + symbol locative)) + (let* ((file (second (second location))) + (position (1- (second (third location)))) + (form (let ((*package* (find-package :40ants-doc-test/test))) + (read-form-from-file-position file position)))) + (ok + (or (alexandria:starts-with-subseq prefix form + :test #'equal) + (and alternative-prefix + (alexandria:starts-with-subseq + alternative-prefix form :test #'equal))) + (format nil "Could not find prefix ~S~@[ or ~S~] ~ + at source location~%~S~%for reference (~S ~S).~%~ + Form found was:~%~S." + prefix alternative-prefix + location symbol locative form))))))))) + (defun read-form-from-file-position (filename position) (with-open-file (stream filename :direction :input) (file-position stream position) (read stream))) -(defun test-replace-known-references () - (assert (string= "`FOO`" - (40ants-doc/markdown/transform::replace-known-references - "`FOO`" - :known-references ())))) - -(defun test-transform-tree () - (assert (equal '(1) - (40ants-doc/utils::transform-tree - (lambda (parent a) - (declare (ignore parent)) - (values a (listp a) nil)) - '(1)))) - - (assert (equal '(2 (3 (4 5))) - (40ants-doc/utils::transform-tree - (lambda (parent a) - (declare (ignore parent)) - (values (if (listp a) a (1+ a)) - (listp a) - nil)) - '(1 (2 (3 4)))))) - - (assert (equal '(1 2 (2 3 (3 4 4 5))) - (40ants-doc/utils::transform-tree - (lambda (parent a) - (declare (ignore parent)) - (values (if (listp a) - a - (list a (1+ a))) - (listp a) - (not (listp a)))) - '(1 (2 (3 4))))))) - -(defun test-macro-arg-names () - (assert (equal '(x a b c) - (40ants-doc/args::macro-arg-names - '((&key (x y)) (a b) &key (c d)))))) + +(deftest test-replace-known-references + (ok (string= "`FOO`" + (40ants-doc/markdown/transform::replace-known-references + "`FOO`" + :known-references ())))) + + +(deftest test-transform-tree + (ok (equal '(1) + (40ants-doc/utils::transform-tree + (lambda (parent a) + (declare (ignore parent)) + (values a (listp a) nil)) + '(1)))) + + (ok (equal '(2 (3 (4 5))) + (40ants-doc/utils::transform-tree + (lambda (parent a) + (declare (ignore parent)) + (values (if (listp a) a (1+ a)) + (listp a) + nil)) + '(1 (2 (3 4)))))) + + (ok (equal '(1 2 (2 3 (3 4 4 5))) + (40ants-doc/utils::transform-tree + (lambda (parent a) + (declare (ignore parent)) + (values (if (listp a) + a + (list a (1+ a))) + (listp a) + (not (listp a)))) + '(1 (2 (3 4))))))) + + +(deftest test-macro-arg-names + (ok (equal '(x a b c) + (40ants-doc/args::macro-arg-names + '((&key (x y)) (a b) &key (c d)))))) + (defun test-document (format) (let ((outputs (write-test-document-files (asdf:system-relative-pathname :40ants-doc "test/data/tmp/") format))) - (assert (= 4 (length outputs))) + (ok (= 4 (length outputs))) ;; the default page corresponding to :STREAM is empty - (assert (string= "" (first outputs))) - (assert (= 2 (count-if #'pathnamep outputs))) + (ok (string= "" (first outputs))) + (ok (= 2 (count-if #'pathnamep outputs))) + (dolist (output outputs) (when (pathnamep output) (let ((baseline (make-pathname @@ -283,6 +297,15 @@ output baseline) (update-test-document-baseline format))))))) + +(deftest test-markdown-document + (test-document :markdown)) + + +(deftest test-html-document + (test-document :html)) + + (defun write-test-document-files (basedir format) (flet ((rebase (pathname) (merge-pathnames pathname @@ -308,17 +331,3 @@ (write-test-document-files (asdf:system-relative-pathname :40ants-doc "test/data/baseline/") format)) - - -(defun test () - ;; ECL does not provide source locations for most things. - #-ecl - (test-navigation) - (test-replace-known-references) - (test-transform-tree) - (test-macro-arg-names) - (test-document :markdown) - (test-document :html)) - -#+nil -(test)