clucumber 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
- data/README.md +4 -9
- data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
- data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
- data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
- data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
- data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
- data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
- data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
- data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
- data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
- data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
- data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
- data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
- data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
- data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
- data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
- data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
- data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
- data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
- data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
- data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
- data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
- data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
- data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
- data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
- data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
- data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
- data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
- data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
- data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
- data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
- data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
- data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
- data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
- data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
- data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
- data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
- data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
- data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
- data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
- data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
- data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
- data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
- data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
- data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
- data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
- data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
- data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
- data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
- data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
- data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
- data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
- data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
- data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
- data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
- data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
- data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
- data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
- data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
- data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
- data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
- data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
- data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
- data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
- data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
- data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
- data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
- data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
- data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
- data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
- data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
- data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
- data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
- data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
- data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
- data/lib/clucumber/vendor/lift/lift.asd +77 -0
- data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
- data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
- data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
- data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
- data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
- data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
- data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
- data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
- data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
- data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
- data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
- data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
- data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
- data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
- data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
- data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
- data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
- data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
- data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
- data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
- data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
- data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
- data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
- data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
- data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
- data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
- data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
- data/lib/clucumber/vendor/usocket/package.lisp +82 -0
- data/lib/clucumber/vendor/usocket/server.lisp +45 -0
- data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
- data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
- data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
- data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
- data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
- data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
- data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
- data/lib/clucumber.rb +29 -7
- metadata +151 -5
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
(in-package #:lift)
|
|
2
|
+
|
|
3
|
+
;; dribble
|
|
4
|
+
;; full output for all tests on separate pages per suite? whatever.
|
|
5
|
+
;; test environment
|
|
6
|
+
|
|
7
|
+
#|
|
|
8
|
+
For *standard-input*: an input stream
|
|
9
|
+
|
|
10
|
+
For *error-output*, *standard-output*, and *trace-output*: an output stream.
|
|
11
|
+
|
|
12
|
+
For *debug-io*, *query-io*: a bidirectional stream.
|
|
13
|
+
|#
|
|
14
|
+
|
|
15
|
+
#|
|
|
16
|
+
(progn
|
|
17
|
+
(setf (test-result-property *test-result* :style-sheet) "test-style.css")
|
|
18
|
+
(setf (test-result-property *test-result* :title) "Test Results X")
|
|
19
|
+
(setf (test-result-property *test-result* :if-exists) :supersede)
|
|
20
|
+
(test-result-report *test-result* #p"/tmp/report.html" :html))
|
|
21
|
+
|
|
22
|
+
lift::(progn
|
|
23
|
+
(setf (test-result-property *test-result* :style-sheet) "test-style.css")
|
|
24
|
+
(setf (test-result-property *test-result* :title) "Merge LUBM 8000")
|
|
25
|
+
(setf (test-result-property *test-result* :if-exists) :error)
|
|
26
|
+
(test-result-report *test-result* #p "/fi/internal/people/gwking/agraph/testing/report/" :html))
|
|
27
|
+
|
|
28
|
+
lift::(progn
|
|
29
|
+
(setf (test-result-property *test-result* :style-sheet) "test-style.css")
|
|
30
|
+
(setf (test-result-property *test-result* :title) "lubm-50")
|
|
31
|
+
(setf (test-result-property *test-result* :unique-name) t)
|
|
32
|
+
(test-result-report *test-result* #p "/fi/internal/people/gwking/agraph/testing/report/2008-08-21-lubm-50-prolog" :html))
|
|
33
|
+
|
|
34
|
+
lift::(progn
|
|
35
|
+
(setf (test-result-property *test-result* :style-sheet)
|
|
36
|
+
"test-style.css")
|
|
37
|
+
(setf (test-result-property *test-result* :title)
|
|
38
|
+
"Ugh")
|
|
39
|
+
(setf (test-result-property *test-result* :if-exists)
|
|
40
|
+
:error)
|
|
41
|
+
(test-result-report *test-result* #p"report-20080813a.sav" :save))
|
|
42
|
+
|
|
43
|
+
(run-tests :suite '(lift-test test-cursors))
|
|
44
|
+
|
|
45
|
+
(run-tests :suite 'lift-test-ensure)
|
|
46
|
+
|
|
47
|
+
(test-result-property *test-result* :title)
|
|
48
|
+
|#
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
(defgeneric start-report-output (result stream format)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
(defgeneric summarize-test-result (result stream format)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
(defgeneric summarize-test-environment (result stream format)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
(defgeneric summarize-test-problems (result stream format)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
(defgeneric summarize-test-problems-of-type
|
|
64
|
+
(problems stream id heading)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
(defgeneric summarize-single-test
|
|
68
|
+
(format suite-name test-case-name data &key stream)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
(defgeneric generate-detailed-reports (result stream format)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
(defgeneric summarize-tests-run (result stream format)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
(defgeneric end-report-output (result stream format)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
(defgeneric html-header (stream title style-sheet)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
;; when it doubt, add a special
|
|
84
|
+
(defvar *report-environment* nil
|
|
85
|
+
"Used internally by LIFT reports.")
|
|
86
|
+
|
|
87
|
+
(defun make-report-environment ()
|
|
88
|
+
nil)
|
|
89
|
+
|
|
90
|
+
;; env variables need to be part saved in result
|
|
91
|
+
|
|
92
|
+
(defgeneric test-result-report (result output format
|
|
93
|
+
&key package &allow-other-keys)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
(defmethod test-result-report (result output format
|
|
97
|
+
&rest args
|
|
98
|
+
&key (package *package*) &allow-other-keys)
|
|
99
|
+
(declare (ignore args))
|
|
100
|
+
(let ((*report-environment* (make-report-environment))
|
|
101
|
+
(*package* (or (find-package package) *package*)))
|
|
102
|
+
(cond ((or (stringp output)
|
|
103
|
+
(pathnamep output))
|
|
104
|
+
(with-open-file (stream
|
|
105
|
+
output
|
|
106
|
+
:direction :output
|
|
107
|
+
:if-does-not-exist :create
|
|
108
|
+
:if-exists (or (test-result-property
|
|
109
|
+
result :if-exists)
|
|
110
|
+
:error))
|
|
111
|
+
(%test-result-report-stream result stream format)))
|
|
112
|
+
((streamp output)
|
|
113
|
+
(%test-result-report-stream result output format))
|
|
114
|
+
(t
|
|
115
|
+
(error "Don't know how to send a report to ~s" output)))))
|
|
116
|
+
|
|
117
|
+
(defun %test-result-report-stream (result stream format)
|
|
118
|
+
(start-report-output result stream format)
|
|
119
|
+
(summarize-test-result result stream format)
|
|
120
|
+
(summarize-test-environment result stream format)
|
|
121
|
+
(when (or (failures result) (errors result)
|
|
122
|
+
(expected-failures result) (expected-errors result))
|
|
123
|
+
(summarize-test-problems result stream format))
|
|
124
|
+
(summarize-tests-run result stream format)
|
|
125
|
+
(end-report-output result stream format)
|
|
126
|
+
(generate-detailed-reports result stream format))
|
|
127
|
+
|
|
128
|
+
(defmethod start-report-output (result stream format)
|
|
129
|
+
(declare (ignore result stream format))
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
(defmethod summarize-test-result (result stream format)
|
|
133
|
+
(declare (ignore format))
|
|
134
|
+
(format stream"~&Test results for: ~a~%"
|
|
135
|
+
(results-for result))
|
|
136
|
+
(let ((complete-success? (and (null (errors result))
|
|
137
|
+
(null (failures result)))))
|
|
138
|
+
(cond (complete-success?
|
|
139
|
+
(format stream"~&~A Successful test~:P~%"
|
|
140
|
+
(length (tests-run result))))
|
|
141
|
+
(t
|
|
142
|
+
(format stream "~&~A Test~:P~[~:;, ~:*~A Failure~:P~]~[~:;, ~:*~A Error~:P~].~%"
|
|
143
|
+
(length (tests-run result))
|
|
144
|
+
(length (failures result))
|
|
145
|
+
(length (errors result)))))))
|
|
146
|
+
|
|
147
|
+
(defmethod summarize-test-environment (result stream format)
|
|
148
|
+
(declare (ignore result stream format))
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
(defmethod summarize-test-problems (result stream format)
|
|
152
|
+
(declare (ignore result stream format))
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
(defmethod generate-detailed-reports (result stream format)
|
|
156
|
+
(declare (ignore result stream format))
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
(defmethod summarize-tests-run (result stream format)
|
|
160
|
+
(declare (ignore result stream format)))
|
|
161
|
+
|
|
162
|
+
(defmethod end-report-output (result stream format)
|
|
163
|
+
(declare (ignore result stream format))
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
#+(or)
|
|
167
|
+
(defun summarize-test-environment (result stream format)
|
|
168
|
+
(loop for symbol in (sort `((*lift-dribble-pathname*)
|
|
169
|
+
(*lift-debug-output* interpret-lift-stream)
|
|
170
|
+
(*lift-standard-output* interpret-lift-stream)
|
|
171
|
+
(*test-break-on-errors?*)
|
|
172
|
+
(*test-do-children?*)
|
|
173
|
+
(*lift-equality-test*)
|
|
174
|
+
(*test-print-length*)
|
|
175
|
+
(*test-print-level*)
|
|
176
|
+
(*lift-if-dribble-exists*))
|
|
177
|
+
'string-lessp :key 'first) do
|
|
178
|
+
|
|
179
|
+
(print)))
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
;; some cruft stolen from cl-markdown
|
|
183
|
+
(defvar *html-meta*
|
|
184
|
+
'((name (:author :description :copyright :keywords :date))
|
|
185
|
+
(http-equiv (:refresh :expires))))
|
|
186
|
+
|
|
187
|
+
(defmethod start-report-output (result stream (format (eql :html)))
|
|
188
|
+
(html-header
|
|
189
|
+
stream
|
|
190
|
+
(test-result-property result :title)
|
|
191
|
+
(test-result-property result :style-sheet)))
|
|
192
|
+
|
|
193
|
+
(defmethod html-header (stream title style-sheet)
|
|
194
|
+
(format stream "~&<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
|
|
195
|
+
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">")
|
|
196
|
+
(format stream "~&<html>~&<head>")
|
|
197
|
+
(when title
|
|
198
|
+
(format stream "~&<title>~a</title>" title))
|
|
199
|
+
(when style-sheet
|
|
200
|
+
(unless (search ".css" style-sheet)
|
|
201
|
+
(setf style-sheet (concatenate 'string style-sheet ".css")))
|
|
202
|
+
(format stream "~&<link type='text/css' href='~a' rel='stylesheet' />"
|
|
203
|
+
style-sheet))
|
|
204
|
+
(format stream "~&</head>~&<body>"))
|
|
205
|
+
|
|
206
|
+
(defmethod summarize-test-result (result stream (format (eql :html)))
|
|
207
|
+
(format stream "~&<div id=\"summary\">")
|
|
208
|
+
(format stream "~&<h1>Test results for: ~a</h1>~%"
|
|
209
|
+
(results-for result))
|
|
210
|
+
(let ((complete-success? (and (null (errors result))
|
|
211
|
+
(null (failures result)))))
|
|
212
|
+
(cond (complete-success?
|
|
213
|
+
(format stream "~&<h2>~A Successful test~:P</h2>~%"
|
|
214
|
+
(length (tests-run result))))
|
|
215
|
+
(t
|
|
216
|
+
(format stream
|
|
217
|
+
"~&<h2>~A Test~:P~[~:;, ~:*~A Failure~:P~]~[~:;, ~:*~A Error~:P~].</h2>~%"
|
|
218
|
+
(length (tests-run result))
|
|
219
|
+
(length (failures result))
|
|
220
|
+
(length (errors result)))))
|
|
221
|
+
|
|
222
|
+
(when (or (expected-errors result) (expected-failures result))
|
|
223
|
+
(format stream "~&<h3>~[~:;~:*Expected failure~p: ~:*~a~]~[~:;, ~]~[~:;~:*Expected error~p: ~:*~a~]</h3>~%"
|
|
224
|
+
(length (expected-failures result))
|
|
225
|
+
;; zero if only one or the other (so we don't need a separator...)
|
|
226
|
+
(* (length (expected-failures result))
|
|
227
|
+
(length (expected-errors result)))
|
|
228
|
+
(length (expected-errors result))))
|
|
229
|
+
|
|
230
|
+
(when (and (slot-boundp result 'end-time-universal)
|
|
231
|
+
(numberp (end-time-universal result))
|
|
232
|
+
(numberp (start-time-universal result)))
|
|
233
|
+
(format stream "~&<h3>Testing took: ~:d seconds</h3>"
|
|
234
|
+
(- (end-time-universal result)
|
|
235
|
+
(start-time-universal result))))
|
|
236
|
+
#+(or)
|
|
237
|
+
(when (and (numberp (real-end-time result))
|
|
238
|
+
(numberp (real-start-time result)))
|
|
239
|
+
(format stream "~&Time: ~,2f real-time"
|
|
240
|
+
(/ (- (real-end-time result) (real-start-time result))
|
|
241
|
+
internal-time-units-per-second))))
|
|
242
|
+
(format stream "~&</div>"))
|
|
243
|
+
|
|
244
|
+
(defmethod summarize-test-environment (result stream (format (eql :html)))
|
|
245
|
+
(declare (ignore result))
|
|
246
|
+
(format stream "~&<div id=\"environment\">")
|
|
247
|
+
|
|
248
|
+
(format stream "~&</div>"))
|
|
249
|
+
|
|
250
|
+
(defmethod summarize-test-problems (result stream (format (eql :html)))
|
|
251
|
+
(format stream "~&<div id=\"problem-summary\">")
|
|
252
|
+
(format stream "~&<h2>Problem Summary:</h2>")
|
|
253
|
+
(when (failures result)
|
|
254
|
+
(summarize-test-problems-of-type
|
|
255
|
+
(failures result) stream "failure-summary" "Failures"))
|
|
256
|
+
(when (errors result)
|
|
257
|
+
(summarize-test-problems-of-type
|
|
258
|
+
(errors result) stream "error-summary" "Errors"))
|
|
259
|
+
(when (expected-failures result)
|
|
260
|
+
(summarize-test-problems-of-type
|
|
261
|
+
(expected-failures result)
|
|
262
|
+
stream "expected-failure-summary" "Expected Failures"))
|
|
263
|
+
(when (expected-errors result)
|
|
264
|
+
(summarize-test-problems-of-type
|
|
265
|
+
(expected-errors result) stream "expected-failure-summary"
|
|
266
|
+
"Expected Errors"))
|
|
267
|
+
(format stream "~&</div>"))
|
|
268
|
+
|
|
269
|
+
(defmethod summarize-test-problems-of-type
|
|
270
|
+
(problems stream id heading)
|
|
271
|
+
(format stream "~&<div id=\"~a\">" id)
|
|
272
|
+
(format stream "~&<h3>~a</h3>" heading)
|
|
273
|
+
(report-tests-by-suite
|
|
274
|
+
(mapcar (lambda (problem)
|
|
275
|
+
`(,(type-of (testsuite problem))
|
|
276
|
+
,(test-method problem)
|
|
277
|
+
(:problem ,problem)))
|
|
278
|
+
problems) stream)
|
|
279
|
+
(format stream "~&</div>"))
|
|
280
|
+
|
|
281
|
+
(defmethod summarize-tests-run (result stream (format (eql :html)))
|
|
282
|
+
(format stream "~&<div id=\"results\">")
|
|
283
|
+
(format stream "~&<h2>Tests Run:</h2>")
|
|
284
|
+
(report-tests-by-suite (tests-run result) stream)
|
|
285
|
+
(format stream "~&</div>"))
|
|
286
|
+
|
|
287
|
+
(defun report-tests-by-suite (tests stream)
|
|
288
|
+
(let ((current-suite nil))
|
|
289
|
+
(loop for rest = (sort
|
|
290
|
+
;; FIXME - this is a hack intended to show tests
|
|
291
|
+
;; in the order they were run (even if it works, it's
|
|
292
|
+
;; bound to be fragile)
|
|
293
|
+
(copy-list tests)
|
|
294
|
+
#+(or) (nreverse (copy-list tests))
|
|
295
|
+
'string-lessp :key 'first) then (rest rest)
|
|
296
|
+
while rest
|
|
297
|
+
for (suite test-name datum) = (first rest) do
|
|
298
|
+
(unless (eq current-suite suite)
|
|
299
|
+
(when current-suite
|
|
300
|
+
(format stream "</div>"))
|
|
301
|
+
(setf current-suite suite)
|
|
302
|
+
(format stream "~&<div class=\"testsuite\">")
|
|
303
|
+
(let* ((this-suite-end (or
|
|
304
|
+
(position-if
|
|
305
|
+
(lambda (datum)
|
|
306
|
+
(not (eq current-suite (first datum))))
|
|
307
|
+
rest)
|
|
308
|
+
(length rest)))
|
|
309
|
+
(error-count (count-if
|
|
310
|
+
(lambda (datum)
|
|
311
|
+
(and (getf (third datum) :problem)
|
|
312
|
+
(typep (getf (third datum) :problem)
|
|
313
|
+
'test-error)))
|
|
314
|
+
rest
|
|
315
|
+
:end this-suite-end))
|
|
316
|
+
(failure-count (count-if
|
|
317
|
+
(lambda (datum)
|
|
318
|
+
(and (getf (third datum) :problem)
|
|
319
|
+
(typep (getf (third datum) :problem)
|
|
320
|
+
'test-failure)))
|
|
321
|
+
rest
|
|
322
|
+
:end this-suite-end))
|
|
323
|
+
(extra-class (cond ((and (= error-count 0) (= failure-count 0))
|
|
324
|
+
'testsuite-all-passed)
|
|
325
|
+
((> error-count 0)
|
|
326
|
+
'testsuite-some-errors)
|
|
327
|
+
(t
|
|
328
|
+
'testsuite-some-failures))))
|
|
329
|
+
(format stream "~&<div class=\"testsuite-title\"><table class=\"~a\"><tr><td>~a</td>" extra-class suite)
|
|
330
|
+
(format stream "<td class=\"testsuite-test-count\">~:d test~:p</td>"
|
|
331
|
+
this-suite-end)
|
|
332
|
+
(format stream "<td class=\"testsuite-summary\">")
|
|
333
|
+
(cond ((and (= error-count 0) (= failure-count 0))
|
|
334
|
+
(format stream "all passed"))
|
|
335
|
+
(t
|
|
336
|
+
(format stream "~[~:;~:*~:d failure~:p~]"
|
|
337
|
+
failure-count)
|
|
338
|
+
(when (and (> error-count 0) (> failure-count 0))
|
|
339
|
+
(format stream ", "))
|
|
340
|
+
(format stream "~[~:;~:*~a error~:p~]"
|
|
341
|
+
error-count)))
|
|
342
|
+
(format stream "</td></tr></table>")
|
|
343
|
+
(format stream "</div>")))
|
|
344
|
+
(format stream "~&<div class=\"test-case\">")
|
|
345
|
+
(let ((problem (getf datum :problem)))
|
|
346
|
+
(cond ((typep problem 'test-failure)
|
|
347
|
+
(format stream "~&<span class=\"test-name\"><a href=\"~a\" title=\"details\">~a</a></span>"
|
|
348
|
+
(details-link stream suite test-name)
|
|
349
|
+
test-name)
|
|
350
|
+
(format stream
|
|
351
|
+
"~&<span class=\"test-failure\">failure</span>" ))
|
|
352
|
+
((typep problem 'test-error)
|
|
353
|
+
(format stream "~&<span class=\"test-name\"><a href=\"~a\" title=\"details\">~a [during ~a]</a></span>"
|
|
354
|
+
(details-link stream suite test-name)
|
|
355
|
+
test-name
|
|
356
|
+
(test-step problem))
|
|
357
|
+
(format stream "~&<span class=\"test-error\">error</span>"))
|
|
358
|
+
(t
|
|
359
|
+
(format stream "~&<span class=\"test-name\">~a</span>"
|
|
360
|
+
test-name)
|
|
361
|
+
(let ((seconds (getf datum :seconds))
|
|
362
|
+
(conses (getf datum :conses)))
|
|
363
|
+
(when seconds
|
|
364
|
+
(format stream "<span class=\"test-time\">~,3f</span>"
|
|
365
|
+
seconds))
|
|
366
|
+
(when conses
|
|
367
|
+
(format stream "<span class=\"test-space\">~:d</span>"
|
|
368
|
+
conses)))))
|
|
369
|
+
(format stream "~&</div>")))
|
|
370
|
+
(when current-suite
|
|
371
|
+
(format stream "</div>"))))
|
|
372
|
+
|
|
373
|
+
(defun get-details-links-table ()
|
|
374
|
+
(let ((hash (getf *report-environment* :details-links)))
|
|
375
|
+
(or hash
|
|
376
|
+
(setf (getf *report-environment* :details-links)
|
|
377
|
+
(make-hash-table :test 'equal)))))
|
|
378
|
+
|
|
379
|
+
#+(or)
|
|
380
|
+
(get-details-links-table)
|
|
381
|
+
|
|
382
|
+
(defun details-link (stream suite name)
|
|
383
|
+
(declare (ignore stream))
|
|
384
|
+
(let* ((hash (get-details-links-table)))
|
|
385
|
+
(or (gethash (cons suite name) hash)
|
|
386
|
+
(progn
|
|
387
|
+
(incf (getf *report-environment* :details-links-count 0))
|
|
388
|
+
(setf (gethash (cons suite name) hash)
|
|
389
|
+
(make-pathname
|
|
390
|
+
:name (format nil "details-~a"
|
|
391
|
+
(getf *report-environment* :details-links-count))
|
|
392
|
+
:type "html"))))))
|
|
393
|
+
|
|
394
|
+
(defmethod end-report-output (result stream (format (eql :html)))
|
|
395
|
+
(let ((style-sheet (test-result-property result :style-sheet)))
|
|
396
|
+
(when style-sheet
|
|
397
|
+
(ignore-errors
|
|
398
|
+
(copy-file (asdf:system-relative-pathname
|
|
399
|
+
'lift "resources/test-style.css")
|
|
400
|
+
(make-pathname
|
|
401
|
+
:name (pathname-name style-sheet)
|
|
402
|
+
:type (pathname-type style-sheet)
|
|
403
|
+
:defaults (pathname stream))
|
|
404
|
+
:if-exists :supersede))))
|
|
405
|
+
(html-footer stream))
|
|
406
|
+
|
|
407
|
+
(defun html-footer (stream)
|
|
408
|
+
(format stream "<div id=\"footer\">")
|
|
409
|
+
(format stream "~&generated on ~a"
|
|
410
|
+
#+allegro
|
|
411
|
+
(excl:locale-print-time
|
|
412
|
+
(get-universal-time)
|
|
413
|
+
:fmt "%B %d, %Y %T GMT%z" :stream nil)
|
|
414
|
+
#-allegro
|
|
415
|
+
(get-universal-time))
|
|
416
|
+
(format stream "</div>")
|
|
417
|
+
(format stream "~&</body></html>"))
|
|
418
|
+
|
|
419
|
+
(defmethod generate-detailed-reports (result stream (format (eql :html)))
|
|
420
|
+
(loop for (suite test-name datum) in (tests-run result)
|
|
421
|
+
when (getf datum :problem) do
|
|
422
|
+
(let ((output-pathname (merge-pathnames
|
|
423
|
+
(details-link stream suite test-name)
|
|
424
|
+
stream)))
|
|
425
|
+
(ensure-directories-exist output-pathname)
|
|
426
|
+
(let ((*print-right-margin* 64))
|
|
427
|
+
(with-open-file (out output-pathname
|
|
428
|
+
:direction :output
|
|
429
|
+
:if-does-not-exist :create
|
|
430
|
+
:if-exists :supersede)
|
|
431
|
+
(html-header
|
|
432
|
+
out
|
|
433
|
+
(format nil "Test ~a details | ~a"
|
|
434
|
+
test-name (test-result-property result :title))
|
|
435
|
+
(test-result-property result :style-sheet))
|
|
436
|
+
(format out "~&<h2>Test ~a details</h2>" test-name)
|
|
437
|
+
(format out "~&<a href=\"~a\">Back</a>"
|
|
438
|
+
(namestring (make-pathname :name (pathname-name stream)
|
|
439
|
+
:type (pathname-type stream))))
|
|
440
|
+
(format out "~&<pre>")
|
|
441
|
+
(format out "~a"
|
|
442
|
+
(wrap-encode-pre
|
|
443
|
+
(with-output-to-string (s)
|
|
444
|
+
(print-test-problem "" (getf datum :problem) s t))
|
|
445
|
+
:width (test-result-property
|
|
446
|
+
*test-result* :print-width 60)))
|
|
447
|
+
(format out "~&</pre>")
|
|
448
|
+
(html-footer out))))))
|
|
449
|
+
|
|
450
|
+
#+(or)
|
|
451
|
+
(defmethod summarize-test-environment (result stream format)
|
|
452
|
+
(loop for symbol in (sort `((*lift-dribble-pathname*)
|
|
453
|
+
(*lift-debug-output* interpret-lift-stream)
|
|
454
|
+
(*lift-standard-output* interpret-lift-stream)
|
|
455
|
+
(*test-break-on-errors?*)
|
|
456
|
+
(*test-do-children?*)
|
|
457
|
+
(*lift-equality-test*)
|
|
458
|
+
(*test-print-length*)
|
|
459
|
+
(*test-print-level*)
|
|
460
|
+
(*lift-if-dribble-exists*))
|
|
461
|
+
'string-lessp :key 'first) do
|
|
462
|
+
|
|
463
|
+
(print)))
|
|
464
|
+
|
|
465
|
+
(defun wrap-encode-pre (string &key (width 80))
|
|
466
|
+
;; Copied from CL-Markdown
|
|
467
|
+
;; Copied from HTML-Encode
|
|
468
|
+
;;?? this is very consy
|
|
469
|
+
;;?? crappy name
|
|
470
|
+
(declare (simple-string string))
|
|
471
|
+
(let ((output (make-array (truncate (length string) 2/3)
|
|
472
|
+
:element-type 'character
|
|
473
|
+
:adjustable t
|
|
474
|
+
:fill-pointer 0))
|
|
475
|
+
(column 0))
|
|
476
|
+
(with-output-to-string (out output)
|
|
477
|
+
(loop for char across string
|
|
478
|
+
do (case char
|
|
479
|
+
((#\&) (incf column) (write-string "&" out))
|
|
480
|
+
((#\<) (incf column) (write-string "<" out))
|
|
481
|
+
((#\>) (incf column) (write-string ">" out))
|
|
482
|
+
((#\Tab #\Space #\Return #\Newline)
|
|
483
|
+
(cond ((or (>= column width)
|
|
484
|
+
(char= char #\Return)
|
|
485
|
+
(char= char #\Newline))
|
|
486
|
+
(setf column 0)
|
|
487
|
+
(terpri out))
|
|
488
|
+
((char= char #\Space)
|
|
489
|
+
(incf column)
|
|
490
|
+
(write-char char out))
|
|
491
|
+
((char= char #\Tab)
|
|
492
|
+
(incf column 4)
|
|
493
|
+
(write-string " " out))))
|
|
494
|
+
(t (incf column) (write-char char out)))))
|
|
495
|
+
(coerce output 'simple-string)))
|
|
496
|
+
|
|
497
|
+
;;;;;
|
|
498
|
+
|
|
499
|
+
(defmethod summarize-test-result (result stream (format (eql :describe)))
|
|
500
|
+
(describe result stream))
|
|
501
|
+
|
|
502
|
+
(defmethod summarize-tests-run (result stream (format (eql :describe)))
|
|
503
|
+
(declare (ignore result stream))
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
;;;;;
|
|
507
|
+
|
|
508
|
+
(defmethod summarize-test-result (result stream (format (eql :save)))
|
|
509
|
+
(flet ((add-property (name)
|
|
510
|
+
(when (slot-boundp result name)
|
|
511
|
+
(format stream "~&\(~s ~a\)"
|
|
512
|
+
(intern (symbol-name name) :keyword)
|
|
513
|
+
(slot-value result name)))))
|
|
514
|
+
(format stream "\(~%")
|
|
515
|
+
(add-property 'results-for)
|
|
516
|
+
(format stream "~&\(:date-time ~a\)" (get-universal-time))
|
|
517
|
+
(add-property 'real-start-time-universal)
|
|
518
|
+
(add-property 'start-time-universal)
|
|
519
|
+
(add-property 'end-time-universal)
|
|
520
|
+
(add-property 'real-end-time-universal)
|
|
521
|
+
(format stream "~&\(:tests-run ")
|
|
522
|
+
(loop for (suite name data) in
|
|
523
|
+
;; FIXME - this is a hack intended to show tests
|
|
524
|
+
;; in the order they were run (even if it works, it's
|
|
525
|
+
;; bound to be fragile)
|
|
526
|
+
(copy-list (tests-run result)) do
|
|
527
|
+
(summarize-single-test format suite name data :stream stream))
|
|
528
|
+
(format stream "~&\)")
|
|
529
|
+
(format stream "~&\)")))
|
|
530
|
+
|
|
531
|
+
#+(or)
|
|
532
|
+
(progn
|
|
533
|
+
(setf (test-result-property *test-result* :if-exists) :supersede)
|
|
534
|
+
(test-result-report *test-result* #p"/tmp/report.save" :save))
|
|
535
|
+
|
|
536
|
+
(defun symbol->turtle (symbol)
|
|
537
|
+
(let ((upcase? nil))
|
|
538
|
+
(coerce
|
|
539
|
+
(loop for char across (string-downcase (symbol-name symbol))
|
|
540
|
+
when (char= char #\-) do (setf upcase? t)
|
|
541
|
+
else collect (if upcase?
|
|
542
|
+
(prog1 (char-upcase char)
|
|
543
|
+
(setf upcase? nil))
|
|
544
|
+
char))
|
|
545
|
+
'string)))
|
|
546
|
+
|
|
547
|
+
(defun turtlefy (thing)
|
|
548
|
+
(typecase thing
|
|
549
|
+
(string thing)
|
|
550
|
+
(pathname (namestring thing))
|
|
551
|
+
(number
|
|
552
|
+
(etypecase thing
|
|
553
|
+
(integer (format nil "\"~a\"^^xsd:integer" thing))
|
|
554
|
+
(double-float (format nil "\"~f\"^^xsd:double" thing))
|
|
555
|
+
(single-float (format nil "\"~f\"^^xsd:single" thing))))
|
|
556
|
+
(symbol (symbol-name thing))
|
|
557
|
+
(t (format nil "\"~a\"" thing))))
|
|
558
|
+
|
|
559
|
+
(defun ensure-symbol (thing)
|
|
560
|
+
(etypecase thing
|
|
561
|
+
(symbol thing)
|
|
562
|
+
(string (intern thing))))
|
|
563
|
+
|
|
564
|
+
#+(or)
|
|
565
|
+
(symbol->turtle 'real-start-time-universal)
|
|
566
|
+
|
|
567
|
+
(defun date->turtle (&key (datetime (get-universal-time)) (include-time? nil))
|
|
568
|
+
(multiple-value-bind
|
|
569
|
+
(second minute hour day month year day-of-the-week)
|
|
570
|
+
(decode-universal-time datetime)
|
|
571
|
+
(declare (ignore day-of-the-week))
|
|
572
|
+
(let ((date-part (format nil "~d-~2,'0d-~2,'0d" year month day))
|
|
573
|
+
(time-part (and include-time?
|
|
574
|
+
(format nil "T-~2,'0d:~2,'0d:~2,'0d"
|
|
575
|
+
hour minute second)))
|
|
576
|
+
(data-type (if include-time?
|
|
577
|
+
"xsd:dateTime" "xsd:date")))
|
|
578
|
+
(concatenate 'string "\"" date-part time-part "\"" "^^" data-type))))
|
|
579
|
+
|
|
580
|
+
;; http://www.dajobe.org/2004/01/turtle/
|
|
581
|
+
(defmethod summarize-test-result (result stream (format (eql :turtle)))
|
|
582
|
+
(labels ((convert-value (value type)
|
|
583
|
+
(ecase type
|
|
584
|
+
(string (turtlefy value))
|
|
585
|
+
(symbol (ensure-symbol value))
|
|
586
|
+
(date (date->turtle :datetime value))
|
|
587
|
+
(dateTime (date->turtle :datetime value :include-time? t))))
|
|
588
|
+
(add-property (name type)
|
|
589
|
+
(let ((value (slot-value result name)))
|
|
590
|
+
(when value
|
|
591
|
+
(format stream "~&:~a ~s ;"
|
|
592
|
+
(symbol->turtle name)
|
|
593
|
+
(convert-value value type))))))
|
|
594
|
+
(format stream
|
|
595
|
+
"~&@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .~%")
|
|
596
|
+
(format stream
|
|
597
|
+
"~&@prefix : <http://www.metabang.com/2007/04/lift#> .~%")
|
|
598
|
+
(format stream "\[~%")
|
|
599
|
+
(add-property 'results-for 'string)
|
|
600
|
+
(add-property 'real-start-time 'dateTime)
|
|
601
|
+
(add-property 'start-time 'dateTime)
|
|
602
|
+
(add-property 'end-time 'dateTime)
|
|
603
|
+
(add-property 'real-end-time 'dateTime)
|
|
604
|
+
(format stream "~&\:testsRun (")
|
|
605
|
+
(loop for (suite name data) in
|
|
606
|
+
;; FIXME - this is a hack intended to show tests
|
|
607
|
+
;; in the order they were run (even if it works, it's
|
|
608
|
+
;; bound to be fragile)
|
|
609
|
+
(copy-list (tests-run result))
|
|
610
|
+
#+(or)
|
|
611
|
+
(nreverse (copy-list (tests-run result))) do
|
|
612
|
+
(labels ((write-datum (name type &key (source data))
|
|
613
|
+
(let* ((key (intern (symbol-name name) :keyword))
|
|
614
|
+
(value (getf source key)))
|
|
615
|
+
(when value
|
|
616
|
+
(format stream "~& :~a ~a ;"
|
|
617
|
+
(symbol->turtle name)
|
|
618
|
+
(convert-value value type)))))
|
|
619
|
+
(prop (name type)
|
|
620
|
+
(write-datum name type :source (getf data :properties))))
|
|
621
|
+
(format stream "~&\[ ")
|
|
622
|
+
(format stream ":testSuite ~s ;" (symbol-name suite))
|
|
623
|
+
(format stream "~& :testName ~s ;" (symbol-name name))
|
|
624
|
+
;; FIXME - we could make these extensible
|
|
625
|
+
(write-datum 'start-time 'dateTime)
|
|
626
|
+
(write-datum 'end-time 'dateTime)
|
|
627
|
+
(write-datum 'result 'string)
|
|
628
|
+
(write-datum 'seconds 'string)
|
|
629
|
+
(write-datum 'conses 'string)
|
|
630
|
+
(loop for stuff in (getf data :properties) by #'cddr do
|
|
631
|
+
(prop stuff 'string))
|
|
632
|
+
(format stream " \]")))
|
|
633
|
+
(format stream " ) ~&\] . ")))
|
|
634
|
+
|
|
635
|
+
#+(or)
|
|
636
|
+
(progn
|
|
637
|
+
(setf (test-result-property *test-result* :if-exists) :supersede)
|
|
638
|
+
(test-result-report *test-result* #p"/tmp/report.n3" :turtle))
|
|
639
|
+
|
|
640
|
+
;;;;
|
|
641
|
+
|
|
642
|
+
(defmacro append-to-report ((var output-to) &body body)
|
|
643
|
+
(let ((gclosep (gensym "closep"))
|
|
644
|
+
(gstream (gensym "stream")))
|
|
645
|
+
`(let* ((,gclosep nil)
|
|
646
|
+
(,gstream ,output-to)
|
|
647
|
+
(,var (etypecase ,gstream
|
|
648
|
+
(stream ,gstream)
|
|
649
|
+
((or pathname string)
|
|
650
|
+
(setf ,gclosep t)
|
|
651
|
+
(open ,gstream
|
|
652
|
+
:if-does-not-exist :create
|
|
653
|
+
:if-exists :append
|
|
654
|
+
:direction :output)))))
|
|
655
|
+
(unwind-protect
|
|
656
|
+
(labels ((out (key value)
|
|
657
|
+
(when value
|
|
658
|
+
(let ((*print-readably* nil))
|
|
659
|
+
(format out "~&\(~s ~s\)" key value)))))
|
|
660
|
+
(declare (ignorable (function out)))
|
|
661
|
+
(progn ,@body))
|
|
662
|
+
(when ,gclosep
|
|
663
|
+
(close ,var))))))
|
|
664
|
+
|
|
665
|
+
(defvar *lift-report-header-hook* nil)
|
|
666
|
+
|
|
667
|
+
(defvar *lift-report-footer-hook* nil)
|
|
668
|
+
|
|
669
|
+
(defvar *lift-report-detail-hook* nil)
|
|
670
|
+
|
|
671
|
+
(defun write-report-header (stream result args)
|
|
672
|
+
(append-to-report (out stream)
|
|
673
|
+
(format out "~&\(")
|
|
674
|
+
(out :results-for (results-for result))
|
|
675
|
+
(out :arguments args)
|
|
676
|
+
(out :features (copy-list *features*))
|
|
677
|
+
(out :datetime (get-universal-time))
|
|
678
|
+
(loop for hook in *lift-report-header-hook* do
|
|
679
|
+
(funcall hook out result))
|
|
680
|
+
(format out "~&\)~%")))
|
|
681
|
+
|
|
682
|
+
(defun write-report-footer (stream result)
|
|
683
|
+
(append-to-report (out stream)
|
|
684
|
+
(format out "~&\(")
|
|
685
|
+
(out :test-case-count (length (tests-run result)))
|
|
686
|
+
(out :test-suite-count (length (suites-run result)))
|
|
687
|
+
(out :failure-count (length (failures result)))
|
|
688
|
+
(out :error-count (length (errors result)))
|
|
689
|
+
(out :expected-failure-count (length (expected-failures result)))
|
|
690
|
+
(out :expected-error-count (length (expected-errors result)))
|
|
691
|
+
(out :start-time-universal (start-time-universal result))
|
|
692
|
+
(when (slot-boundp result 'end-time-universal)
|
|
693
|
+
(out :end-time-universal (end-time-universal result)))
|
|
694
|
+
(out :errors (collect-testsuite-summary result :errors))
|
|
695
|
+
(out :failures (collect-testsuite-summary result :failures))
|
|
696
|
+
(out :expected-errors
|
|
697
|
+
(collect-testsuite-summary result :expected-errors))
|
|
698
|
+
(out :expected-failures
|
|
699
|
+
(collect-testsuite-summary result :expected-failures))
|
|
700
|
+
(loop for hook in *lift-report-footer-hook* do
|
|
701
|
+
(funcall hook out result))
|
|
702
|
+
(format out "~&\)~%")))
|
|
703
|
+
|
|
704
|
+
(defmethod summarize-single-test :around
|
|
705
|
+
(format suite-name test-case-name data &key stream)
|
|
706
|
+
(append-to-report (out stream)
|
|
707
|
+
(call-next-method format suite-name test-case-name data :stream out)))
|
|
708
|
+
|
|
709
|
+
(defmethod summarize-single-test
|
|
710
|
+
((format (eql :save)) suite-name test-case-name data
|
|
711
|
+
&key (stream *standard-output*))
|
|
712
|
+
(labels ((out (key value)
|
|
713
|
+
(when value
|
|
714
|
+
(format stream "~&\(~s ~s\)" key value)))
|
|
715
|
+
(write-datum (name &key (source data))
|
|
716
|
+
(let* ((key (intern (symbol-name name) :keyword))
|
|
717
|
+
(value (getf source key)))
|
|
718
|
+
(out key value)))
|
|
719
|
+
(prop (name)
|
|
720
|
+
(write-datum name :source (getf data :properties))))
|
|
721
|
+
(format stream "~&\(~%")
|
|
722
|
+
(format stream "~&\(:suite ~a\)" suite-name)
|
|
723
|
+
(format stream "~&\(:name ~a\)" test-case-name)
|
|
724
|
+
;; FIXME - we could make these extensible
|
|
725
|
+
(write-datum 'start-time-universal)
|
|
726
|
+
(write-datum 'end-time-universal)
|
|
727
|
+
(write-datum 'result)
|
|
728
|
+
(write-datum 'seconds)
|
|
729
|
+
(write-datum 'conses)
|
|
730
|
+
(loop for stuff in (getf data :properties) by #'cddr do
|
|
731
|
+
(prop stuff))
|
|
732
|
+
(cond ((getf data :problem)
|
|
733
|
+
(let ((problem (getf data :problem)))
|
|
734
|
+
(out :problem-kind (test-problem-kind problem))
|
|
735
|
+
(out :problem-step (test-step problem))
|
|
736
|
+
(out :problem-condition
|
|
737
|
+
(let ((*print-readably* nil))
|
|
738
|
+
(format nil "~s" (test-condition problem))))
|
|
739
|
+
(out :problem-condition-description
|
|
740
|
+
(format nil "~a" (test-condition problem)))
|
|
741
|
+
(when (slot-exists-p problem 'backtrace)
|
|
742
|
+
(out :problem-backtrace (backtrace problem)))))
|
|
743
|
+
(t
|
|
744
|
+
(out :result t)))
|
|
745
|
+
(loop for hook in *lift-report-detail-hook* do
|
|
746
|
+
(funcall hook stream data))
|
|
747
|
+
(format stream "\)~%")))
|
|
748
|
+
|
|
749
|
+
;;;;
|
|
750
|
+
|
|
751
|
+
(defun collect-testsuite-summary (result kind)
|
|
752
|
+
(let ((list (slot-value result (intern (symbol-name kind)
|
|
753
|
+
(find-package :lift)))))
|
|
754
|
+
(flet ((encode-symbol (symbol)
|
|
755
|
+
(cons (symbol-name symbol)
|
|
756
|
+
(package-name (symbol-package symbol)))))
|
|
757
|
+
(mapcar (lambda (glitch)
|
|
758
|
+
(list (encode-symbol (type-of (testsuite glitch)))
|
|
759
|
+
(encode-symbol (test-method glitch))))
|
|
760
|
+
list))))
|
|
761
|
+
|
|
762
|
+
#+(or)
|
|
763
|
+
(collect-testsuite-summary lift:*test-result* :failures)
|
|
764
|
+
|
|
765
|
+
;;;;;
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
#+allegro
|
|
770
|
+
(defun cancel-current-profile (&key force?)
|
|
771
|
+
(when (prof::current-profile-actual prof::*current-profile*)
|
|
772
|
+
(unless force?
|
|
773
|
+
(assert (member (prof:profiler-status) '(:inactive))))
|
|
774
|
+
(prof:stop-profiler)
|
|
775
|
+
(setf prof::*current-profile* (prof::make-current-profile))))
|
|
776
|
+
|
|
777
|
+
#+allegro
|
|
778
|
+
(defun current-profile-sample-count ()
|
|
779
|
+
(ecase (prof::profiler-status :verbose nil)
|
|
780
|
+
((:inactive :analyzed) 0)
|
|
781
|
+
((:suspended :saved)
|
|
782
|
+
(slot-value (prof::current-profile-actual prof::*current-profile*)
|
|
783
|
+
'prof::samples))
|
|
784
|
+
(:sampling (warn "Can't determine count while sampling"))))
|
|
785
|
+
|
|
786
|
+
#+allegro
|
|
787
|
+
(defun show-flat-profile (output)
|
|
788
|
+
(let ((prof:*significance-threshold*
|
|
789
|
+
(or *profiling-threshold* 0.01)))
|
|
790
|
+
(prof:show-flat-profile :stream output)))
|
|
791
|
+
|
|
792
|
+
#+allegro
|
|
793
|
+
(defun show-call-graph (output)
|
|
794
|
+
(let ((prof:*significance-threshold*
|
|
795
|
+
(or *profiling-threshold* 0.01)))
|
|
796
|
+
(prof:show-call-graph :stream output)))
|
|
797
|
+
|
|
798
|
+
#+allegro
|
|
799
|
+
(defun show-call-counts (output)
|
|
800
|
+
(format output "~%~%Call counts~%")
|
|
801
|
+
(let ((*standard-output* output))
|
|
802
|
+
(prof:show-call-counts)))
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
#-allegro
|
|
806
|
+
(defun show-flat-profile (output)
|
|
807
|
+
(format output "~%~%Flat profile: unavailable for this Lisp~%"))
|
|
808
|
+
|
|
809
|
+
#-allegro
|
|
810
|
+
(defun show-call-graph (output)
|
|
811
|
+
(format output "~%~%Call graph: unavailable for this Lisp~%"))
|
|
812
|
+
|
|
813
|
+
#-allegro
|
|
814
|
+
(defun show-call-counts (output)
|
|
815
|
+
(format output "~%~%Call counts: unavailable for this Lisp~%"))
|
|
816
|
+
|
|
817
|
+
#+allegro
|
|
818
|
+
(defun with-profile-report-fn
|
|
819
|
+
(name style fn body &key
|
|
820
|
+
(log-name *benchmark-log-path*)
|
|
821
|
+
(count-calls-p *count-calls-p*)
|
|
822
|
+
(timeout nil))
|
|
823
|
+
(assert (member style '(:time :space :count-only)))
|
|
824
|
+
(cancel-current-profile :force? t)
|
|
825
|
+
(let* ((seconds 0.0) (conses 0)
|
|
826
|
+
error
|
|
827
|
+
results
|
|
828
|
+
(profile-fn (make-profiled-function fn)))
|
|
829
|
+
(unwind-protect
|
|
830
|
+
(multiple-value-bind (result measures errorp)
|
|
831
|
+
(while-measuring (t measure-seconds measure-space)
|
|
832
|
+
(handler-case
|
|
833
|
+
(with-timeout (timeout)
|
|
834
|
+
(funcall profile-fn style count-calls-p))
|
|
835
|
+
(timeout-error
|
|
836
|
+
(c)
|
|
837
|
+
(declare (ignore c)))
|
|
838
|
+
(error (c)
|
|
839
|
+
(error c))))
|
|
840
|
+
(setf seconds (first measures) conses (second measures)
|
|
841
|
+
results result error errorp))
|
|
842
|
+
;; cleanup / ensure we get report
|
|
843
|
+
(generate-profile-log-entry log-name name seconds conses results error)
|
|
844
|
+
(when (> (current-profile-sample-count) 0)
|
|
845
|
+
(let ((pathname (unique-filename
|
|
846
|
+
(merge-pathnames
|
|
847
|
+
(make-pathname
|
|
848
|
+
:type "prof"
|
|
849
|
+
:name (format nil "~a-~a-" name style))
|
|
850
|
+
log-name))))
|
|
851
|
+
(write-profile-report pathname name style body
|
|
852
|
+
seconds conses error count-calls-p))))
|
|
853
|
+
(values-list (if (atom results) (list results) results))))
|
|
854
|
+
|
|
855
|
+
(defun write-profile-report (pathname name style body seconds conses
|
|
856
|
+
error count-calls-p)
|
|
857
|
+
(format t "~&Profiling output being sent to ~a" pathname)
|
|
858
|
+
(with-open-file (output pathname
|
|
859
|
+
:direction :output
|
|
860
|
+
:if-does-not-exist :create
|
|
861
|
+
:if-exists :append)
|
|
862
|
+
(format output "~&Profile data for ~a" name)
|
|
863
|
+
(format output "~&Date: ~a" (date-stamp :include-time? t))
|
|
864
|
+
(format output "~& Total time: ~,2F; Total space: ~:d \(~:*~d\)"
|
|
865
|
+
seconds conses)
|
|
866
|
+
(format output "~%~%")
|
|
867
|
+
(when error
|
|
868
|
+
(format output "~&Error occured during profiling: ~a~%~%" error))
|
|
869
|
+
(let ((*standard-output* output))
|
|
870
|
+
(when *current-test*
|
|
871
|
+
(write-profile-information *current-test*)))
|
|
872
|
+
(when body
|
|
873
|
+
(format output "~&Profiling: ~%")
|
|
874
|
+
(let ((*print-length* 10)
|
|
875
|
+
(*print-level* 10))
|
|
876
|
+
(dolist (form body)
|
|
877
|
+
(pprint form output)))
|
|
878
|
+
(format output "~%~%"))
|
|
879
|
+
(when (or (eq :time style)
|
|
880
|
+
(eq :space style))
|
|
881
|
+
(show-flat-profile output)
|
|
882
|
+
(show-call-graph output)
|
|
883
|
+
(when count-calls-p
|
|
884
|
+
(show-call-counts output)))
|
|
885
|
+
#+allegro
|
|
886
|
+
(when *functions-to-profile*
|
|
887
|
+
(loop for thing in *functions-to-profile* do
|
|
888
|
+
(let ((*standard-output* output)
|
|
889
|
+
(*print-readably* nil))
|
|
890
|
+
(handler-case
|
|
891
|
+
(cond ((thing-names-generic-function-p thing)
|
|
892
|
+
(format output "~%~%Disassemble generic-function ~s:~%"
|
|
893
|
+
thing)
|
|
894
|
+
(prof:disassemble-profile thing)
|
|
895
|
+
(mapc
|
|
896
|
+
(lambda (m)
|
|
897
|
+
(format t "~2%~a~%"
|
|
898
|
+
(make-string 60 :initial-element #\-))
|
|
899
|
+
(format t "~&Method: ~a~2%" m)
|
|
900
|
+
(prof:disassemble-profile (clos:method-function m)))
|
|
901
|
+
(clos:generic-function-methods
|
|
902
|
+
(symbol-function thing))))
|
|
903
|
+
(t
|
|
904
|
+
(format output "~%~%Disassemble function ~s:~%"
|
|
905
|
+
thing)
|
|
906
|
+
(prof:disassemble-profile thing)))
|
|
907
|
+
(error (c)
|
|
908
|
+
(format
|
|
909
|
+
output "~2%Error ~a while trying to disassemble-profile ~s~2%"
|
|
910
|
+
c thing))))))))
|
|
911
|
+
|
|
912
|
+
;; stolen from cl-markdown and modified
|
|
913
|
+
(defun thing-names-generic-function-p (thing)
|
|
914
|
+
(and (symbolp thing)
|
|
915
|
+
(fboundp thing)
|
|
916
|
+
(typep (symbol-function thing) 'standard-generic-function)))
|