clucumber 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)))
|