clucumber 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +4 -9
  3. data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
  4. data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
  5. data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
  6. data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
  7. data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
  8. data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
  9. data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
  10. data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
  11. data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
  12. data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
  13. data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
  14. data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
  15. data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
  16. data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
  17. data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
  18. data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
  19. data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
  20. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
  21. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
  22. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
  23. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
  24. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
  25. data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
  26. data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
  27. data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
  28. data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
  29. data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
  30. data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
  31. data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
  32. data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
  33. data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
  34. data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
  35. data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
  36. data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
  37. data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
  38. data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
  39. data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
  40. data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
  41. data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
  42. data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
  43. data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
  44. data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
  45. data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
  46. data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
  47. data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
  48. data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
  49. data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
  50. data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
  51. data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
  52. data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
  53. data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
  54. data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
  55. data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
  56. data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
  57. data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
  58. data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
  59. data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
  60. data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
  61. data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
  62. data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
  63. data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
  64. data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
  65. data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
  66. data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
  67. data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
  68. data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
  69. data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
  70. data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
  71. data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
  72. data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
  73. data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
  74. data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
  75. data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
  76. data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
  77. data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
  78. data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
  79. data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
  80. data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
  81. data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
  82. data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
  83. data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
  84. data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
  85. data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
  86. data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
  87. data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
  88. data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
  89. data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
  90. data/lib/clucumber/vendor/lift/lift.asd +77 -0
  91. data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
  92. data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
  93. data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
  94. data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
  95. data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
  96. data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
  97. data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
  98. data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
  99. data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
  100. data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
  101. data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
  102. data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
  103. data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
  104. data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
  105. data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
  106. data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
  107. data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
  108. data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
  109. data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
  110. data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
  111. data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
  112. data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
  113. data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
  114. data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
  115. data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
  116. data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
  117. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
  118. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
  119. data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
  120. data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
  121. data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
  122. data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
  123. data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
  124. data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
  125. data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
  126. data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
  127. data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
  128. data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
  129. data/lib/clucumber/vendor/usocket/package.lisp +82 -0
  130. data/lib/clucumber/vendor/usocket/server.lisp +45 -0
  131. data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
  132. data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
  133. data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
  134. data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
  135. data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
  136. data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
  137. data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
  138. data/lib/clucumber.rb +29 -7
  139. 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 "&amp;" out))
480
+ ((#\<) (incf column) (write-string "&lt;" out))
481
+ ((#\>) (incf column) (write-string "&gt;" 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)))