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,354 @@
|
|
1
|
+
(in-package #:lift)
|
2
|
+
|
3
|
+
#|
|
4
|
+
|
5
|
+
(:report-property :if-exists :supersede)
|
6
|
+
(:report-property :unique-name nil)
|
7
|
+
(:report-property :format :html)
|
8
|
+
(:report-property :name "index")
|
9
|
+
(:report-property :relative-to db.agraph.tests)
|
10
|
+
|
11
|
+
For text based reports like :describe, the report name is the filename
|
12
|
+
where the report is placed or a stream (e.g., *standard-output*).
|
13
|
+
|
14
|
+
The :name property specifies the name and type.
|
15
|
+
|
16
|
+
There are three ways to specify the directory:
|
17
|
+
|
18
|
+
1. :full-name
|
19
|
+
2. :relative-to
|
20
|
+
3. the current directory (via *default-pathname-defaults*)
|
21
|
+
|
22
|
+
If :full-name is a pathname with a name and type, then these will be
|
23
|
+
used rather than :name. If :unique-name is true (and the destination
|
24
|
+
is not a stream), then the date and an integer tag will be added to the
|
25
|
+
name. E.g., the path `/tmp/lift-tests/report.txt` will become
|
26
|
+
`/tmp/lift-tests/report-2009-02-01-1.txt`.
|
27
|
+
|
28
|
+
|
29
|
+
For HTML, The report name specifies a _directory_. The :name property
|
30
|
+
is ignored.
|
31
|
+
|
32
|
+
There are three ways to specify the directory location.
|
33
|
+
|
34
|
+
1. :full-name
|
35
|
+
2. :relative-to
|
36
|
+
3. the current directory (via *default-pathname-defaults*)
|
37
|
+
|
38
|
+
In all cases, the report will go into
|
39
|
+
|
40
|
+
|#
|
41
|
+
|
42
|
+
(defgeneric generate-report-summary-pathname ()
|
43
|
+
)
|
44
|
+
|
45
|
+
(defgeneric handle-config-preference (name args)
|
46
|
+
)
|
47
|
+
|
48
|
+
|
49
|
+
(defvar *current-configuration-stream* nil)
|
50
|
+
|
51
|
+
(defvar *current-asdf-system-name* nil
|
52
|
+
"Holds the name of the system being tested when using the `:generic`
|
53
|
+
configuration.
|
54
|
+
|
55
|
+
LIFT needs this to run the `:generic` configuration because this is
|
56
|
+
how it determines which configuration file to load. If you use
|
57
|
+
`asdf:test-op` then this value will be set automatically.
|
58
|
+
Otherwise, you will need to set it yourself.")
|
59
|
+
|
60
|
+
(eval-when (:load-toplevel :execute)
|
61
|
+
(when (find-package :asdf)
|
62
|
+
(defmethod asdf:perform :around ((operation asdf:test-op) (c asdf:system))
|
63
|
+
(let ((*current-asdf-system-name* (asdf:component-name c)))
|
64
|
+
(call-next-method)))))
|
65
|
+
|
66
|
+
(defun lift-relative-pathname (pathname &optional (errorp nil))
|
67
|
+
"Merges pathname with either the path to the currently loading system
|
68
|
+
\(if there is one\) or the *default-pathname-defaults*."
|
69
|
+
(let* ((asdf-package (find-package :asdf))
|
70
|
+
(srp-symbol (and asdf-package
|
71
|
+
(find-symbol (symbol-name 'system-relative-pathname)
|
72
|
+
asdf-package)))
|
73
|
+
(srp (and *current-asdf-system-name* srp-symbol)))
|
74
|
+
(labels ((try-it (path)
|
75
|
+
(let ((pathname (merge-pathnames pathname path)))
|
76
|
+
(if errorp (and pathname (probe-file pathname)) pathname))))
|
77
|
+
(or (and srp (try-it (funcall srp *current-asdf-system-name* "")))
|
78
|
+
(try-it *default-pathname-defaults*)
|
79
|
+
(not errorp)
|
80
|
+
(and (not asdf-package)
|
81
|
+
(error "Unable to use :generic configuration option because ASDF is not loaded."))
|
82
|
+
(and (not srp-symbol)
|
83
|
+
(error "Unable to use :generic configuration option because asdf:system-relative-pathname is not function bound (maybe try updating ASDF?)"))
|
84
|
+
(and (not *current-asdf-system-name*)
|
85
|
+
(error "Unable to use :generic configuration option
|
86
|
+
because the current system cannot be determined. You can either
|
87
|
+
use asdf:test-op or bind *current-asdf-system-name* yourself."))))))
|
88
|
+
|
89
|
+
(defun find-generic-test-configuration (&optional (errorp nil))
|
90
|
+
(flet ((try-it (path)
|
91
|
+
(and path (probe-file path))))
|
92
|
+
(or (try-it (lift-relative-pathname "lift-local.config" errorp))
|
93
|
+
(try-it (lift-relative-pathname "lift-standard.config" errorp))
|
94
|
+
(and errorp
|
95
|
+
(error "Unable to use :generic configuration file neither lift-local.config nor lift-standard.config can be found.")))))
|
96
|
+
|
97
|
+
(defun report-summary-pathname ()
|
98
|
+
(unique-filename (generate-report-summary-pathname)))
|
99
|
+
|
100
|
+
(defmethod generate-report-summary-pathname ()
|
101
|
+
(lift-relative-pathname "test-results/summary.sav"))
|
102
|
+
|
103
|
+
#+(or)
|
104
|
+
(generate-report-summary-pathname)
|
105
|
+
|
106
|
+
(defun run-tests-from-file (path)
|
107
|
+
(let ((real-path (cond ((eq path :generic)
|
108
|
+
(setf path
|
109
|
+
(find-generic-test-configuration t)))
|
110
|
+
(t
|
111
|
+
(probe-file path)))))
|
112
|
+
(unless real-path
|
113
|
+
(error "Unable to find configuration file ~s" path))
|
114
|
+
(setf *test-result*
|
115
|
+
(let* ((*package* *package*)
|
116
|
+
(*read-eval* nil)
|
117
|
+
(result (make-test-result path :multiple))
|
118
|
+
(*lift-dribble-pathname* nil)
|
119
|
+
(*lift-debug-output* *debug-io*)
|
120
|
+
(*lift-standard-output* *standard-output*)
|
121
|
+
(*test-break-on-errors?* nil)
|
122
|
+
(*test-do-children?* t)
|
123
|
+
(*lift-equality-test* 'equal)
|
124
|
+
(*test-print-length* :follow-print)
|
125
|
+
(*test-print-level* :follow-print)
|
126
|
+
(*lift-if-dribble-exists* :append)
|
127
|
+
(*test-result* result))
|
128
|
+
(%run-tests-from-file path)))))
|
129
|
+
|
130
|
+
(defun %run-tests-from-file (path)
|
131
|
+
(with-open-file (*current-configuration-stream* path
|
132
|
+
:direction :input
|
133
|
+
:if-does-not-exist :error)
|
134
|
+
(let ((form nil)
|
135
|
+
(run-tests-p t))
|
136
|
+
(loop while (not (eq (setf form (read *current-configuration-stream*
|
137
|
+
nil :eof nil)) :eof))
|
138
|
+
collect
|
139
|
+
(handler-bind
|
140
|
+
((error (lambda (c) (format
|
141
|
+
*error-output*
|
142
|
+
"Error while running ~a from ~a: ~a"
|
143
|
+
form path c)
|
144
|
+
(pprint (get-backtrace c))
|
145
|
+
(invoke-debugger c))))
|
146
|
+
(destructuring-bind
|
147
|
+
(name &rest args)
|
148
|
+
form
|
149
|
+
(assert (typep name 'symbol) nil
|
150
|
+
"Each command must be a symbol and ~s is not." name)
|
151
|
+
(setf args (massage-arguments args))
|
152
|
+
(cond
|
153
|
+
;; check for preferences first (i.e., keywords)
|
154
|
+
((eq (symbol-package name)
|
155
|
+
(symbol-package :keyword))
|
156
|
+
;; must be a preference
|
157
|
+
(handle-config-preference name args))
|
158
|
+
((and run-tests-p (find-testsuite name :errorp nil))
|
159
|
+
(multiple-value-bind (_ restartedp)
|
160
|
+
(with-simple-restart (cancel-testing-from-configuration
|
161
|
+
"Cancel testing from file ~a" path)
|
162
|
+
(run-tests :suite name
|
163
|
+
:result *test-result*
|
164
|
+
:testsuite-initargs args))
|
165
|
+
(declare (ignore _))
|
166
|
+
;; no more testing; continue to process commands
|
167
|
+
(when restartedp
|
168
|
+
(setf run-tests-p nil))))
|
169
|
+
(t
|
170
|
+
(warn "Don't understand '~s' while reading from ~s"
|
171
|
+
form path))))))))
|
172
|
+
(values *test-result*))
|
173
|
+
|
174
|
+
(defun massage-arguments (args)
|
175
|
+
(loop for arg in args collect
|
176
|
+
(cond ((and (symbolp arg)
|
177
|
+
(string= (symbol-name arg) (symbol-name '*standard-output*)))
|
178
|
+
*standard-output*)
|
179
|
+
(t arg))))
|
180
|
+
|
181
|
+
(defmethod handle-config-preference ((name t) args)
|
182
|
+
(warn "Unknown preference ~s (with arguments ~s)"
|
183
|
+
name args))
|
184
|
+
|
185
|
+
(defmethod handle-config-preference ((name (eql :include)) args)
|
186
|
+
(%run-tests-from-file (merge-pathnames (first args)
|
187
|
+
*current-configuration-stream*)))
|
188
|
+
|
189
|
+
(defconfig-variable :dribble *lift-dribble-pathname*)
|
190
|
+
|
191
|
+
(defconfig-variable :debug-output *lift-debug-output*)
|
192
|
+
|
193
|
+
(defconfig-variable :standard-output *lift-standard-output*)
|
194
|
+
|
195
|
+
(defconfig-variable :break-on-errors? *test-break-on-errors?*)
|
196
|
+
|
197
|
+
(defconfig-variable :do-children? *test-do-children?*)
|
198
|
+
|
199
|
+
(defconfig-variable :equality-test *lift-equality-test*)
|
200
|
+
|
201
|
+
(defconfig-variable :print-length *test-print-length*)
|
202
|
+
|
203
|
+
(defconfig-variable :print-level *test-print-level*)
|
204
|
+
|
205
|
+
(defconfig-variable :print-suite-names *test-print-testsuite-names*)
|
206
|
+
|
207
|
+
(defconfig-variable :print-test-case-names *test-print-test-case-names*)
|
208
|
+
|
209
|
+
(defconfig-variable :if-dribble-exists *lift-if-dribble-exists*)
|
210
|
+
|
211
|
+
(defmethod handle-config-preference ((name (eql :report-property))
|
212
|
+
args)
|
213
|
+
(setf (test-result-property *test-result* (first args)) (second args)))
|
214
|
+
|
215
|
+
(defconfig-variable :profiling-threshold *profiling-threshold*)
|
216
|
+
|
217
|
+
(defconfig-variable :count-calls-p *count-calls-p*)
|
218
|
+
|
219
|
+
(defconfig-variable :log-pathname *lift-report-pathname*)
|
220
|
+
|
221
|
+
(defconfig-variable :maximum-failures *test-maximum-failure-count*)
|
222
|
+
(defconfig-variable :maximum-failure-count *test-maximum-failure-count*)
|
223
|
+
|
224
|
+
(defconfig-variable :maximum-errors *test-maximum-error-count*)
|
225
|
+
(defconfig-variable :maximum-error-count *test-maximum-error-count*)
|
226
|
+
|
227
|
+
(defgeneric report-pathname (method &optional result))
|
228
|
+
|
229
|
+
(defmethod report-pathname :around ((method (eql :html))
|
230
|
+
&optional (result *test-result*))
|
231
|
+
(cond ((and (test-result-property result :full-pathname)
|
232
|
+
(streamp (test-result-property result :full-pathname)))
|
233
|
+
(call-next-method))
|
234
|
+
(t
|
235
|
+
(let ((old-name (test-result-property result :name))
|
236
|
+
(old-full-pathname (test-result-property result :full-pathname))
|
237
|
+
(old-unique-name (test-result-property result :unique-name)))
|
238
|
+
(unwind-protect
|
239
|
+
(progn
|
240
|
+
(setf (test-result-property result :name) t
|
241
|
+
(test-result-property result :unique-name) nil)
|
242
|
+
(let ((destination (pathname-sans-name+type (call-next-method))))
|
243
|
+
(when old-name
|
244
|
+
(setf destination
|
245
|
+
(merge-pathnames
|
246
|
+
(make-pathname :directory `(:relative ,old-name))
|
247
|
+
destination)))
|
248
|
+
(print destination)
|
249
|
+
(merge-pathnames
|
250
|
+
(make-pathname :name "index" :type "html")
|
251
|
+
(pathname-sans-name+type
|
252
|
+
(if old-unique-name
|
253
|
+
(unique-directory destination)
|
254
|
+
destination)))))
|
255
|
+
(setf (test-result-property result :name) old-name
|
256
|
+
(test-result-property result :full-pathname)
|
257
|
+
old-full-pathname
|
258
|
+
(test-result-property result :unique-name)
|
259
|
+
old-unique-name))))))
|
260
|
+
|
261
|
+
#+(or)
|
262
|
+
(defmethod report-pathname :around ((method t) &optional (result *test-result*))
|
263
|
+
"Make sure that directories exist"
|
264
|
+
(let ((output (call-next-method)))
|
265
|
+
(cond ((streamp output)
|
266
|
+
output)
|
267
|
+
(t
|
268
|
+
(ensure-directories-exist output)
|
269
|
+
output))))
|
270
|
+
|
271
|
+
(defmethod report-pathname ((method t) &optional (result *test-result*))
|
272
|
+
(let* ((given-report-name (test-result-property result :name))
|
273
|
+
(report-type (string-downcase
|
274
|
+
(ensure-string
|
275
|
+
(test-result-property result :format))))
|
276
|
+
(report-name (or (and given-report-name
|
277
|
+
(not (eq given-report-name t))
|
278
|
+
(merge-pathnames
|
279
|
+
given-report-name
|
280
|
+
(make-pathname :type report-type)))
|
281
|
+
(format nil "report.~a" report-type)))
|
282
|
+
(via nil)
|
283
|
+
(dest (or (and (setf via :full-pathname)
|
284
|
+
(test-result-property result :full-pathname)
|
285
|
+
(streamp
|
286
|
+
(test-result-property result :full-pathname))
|
287
|
+
(test-result-property result :full-pathname))
|
288
|
+
(and (setf via :full-pathname)
|
289
|
+
(test-result-property result :full-pathname)
|
290
|
+
(not (streamp
|
291
|
+
(test-result-property result :full-pathname)))
|
292
|
+
(cond ((eq given-report-name t)
|
293
|
+
(test-result-property result :full-pathname))
|
294
|
+
((null given-report-name)
|
295
|
+
(merge-pathnames
|
296
|
+
(test-result-property result :full-pathname)
|
297
|
+
report-name))
|
298
|
+
(t
|
299
|
+
(merge-pathnames
|
300
|
+
(test-result-property result :full-pathname)
|
301
|
+
given-report-name))))
|
302
|
+
(and (setf via :relative-to)
|
303
|
+
(let ((relative-to
|
304
|
+
(test-result-property result :relative-to)))
|
305
|
+
(and relative-to
|
306
|
+
(asdf:find-system relative-to nil)
|
307
|
+
(asdf:system-relative-pathname
|
308
|
+
relative-to report-name))))
|
309
|
+
(and (setf via :current-directory)
|
310
|
+
(merge-pathnames
|
311
|
+
(make-pathname :defaults report-name)))))
|
312
|
+
(unique-name? (test-result-property result :unique-name)))
|
313
|
+
(values
|
314
|
+
(if (and unique-name? (not (streamp dest)))
|
315
|
+
(unique-filename dest)
|
316
|
+
dest)
|
317
|
+
via)))
|
318
|
+
|
319
|
+
(defmethod handle-config-preference ((name (eql :build-report))
|
320
|
+
args)
|
321
|
+
(declare (ignore args))
|
322
|
+
(let* ((format (or (test-result-property *test-result* :format)
|
323
|
+
:html))
|
324
|
+
(dest (report-pathname format *test-result*)))
|
325
|
+
(with-standard-io-syntax
|
326
|
+
(let ((*print-readably* nil))
|
327
|
+
(handler-bind
|
328
|
+
((error
|
329
|
+
(lambda (c)
|
330
|
+
(format *debug-io*
|
331
|
+
"Error ~a while generating report (format ~s) to ~a"
|
332
|
+
c format dest)
|
333
|
+
(format *debug-io*
|
334
|
+
"~%~%Backtrace~%~%~s"
|
335
|
+
(get-backtrace c)))))
|
336
|
+
(cond
|
337
|
+
((or (streamp dest)
|
338
|
+
(ensure-directories-exist dest)
|
339
|
+
(writable-directory-p dest))
|
340
|
+
(format *debug-io* "~&Sending report (format ~s) to ~a"
|
341
|
+
format dest)
|
342
|
+
(test-result-report
|
343
|
+
*test-result* dest format))
|
344
|
+
(t
|
345
|
+
(format *debug-io* "~&Unable to write report (format ~s) to ~a"
|
346
|
+
format dest))))))))
|
347
|
+
|
348
|
+
|
349
|
+
(defconfig :trace
|
350
|
+
"Start tracing each of the arguments to :trace."
|
351
|
+
(eval `(trace ,@args)))
|
352
|
+
|
353
|
+
(defconfig :untrace
|
354
|
+
(eval `(untrace ,@args)))
|
@@ -0,0 +1,117 @@
|
|
1
|
+
;;;;
|
2
|
+
;;; directly pullled from metatilities, sigh
|
3
|
+
|
4
|
+
(in-package #:lift)
|
5
|
+
;(in-package #:metatilities)
|
6
|
+
|
7
|
+
(define-condition source/target-file-error (file-error)
|
8
|
+
((pathname :reader source-pathname
|
9
|
+
:initarg :source-pathname)
|
10
|
+
(target-pathname :reader target-pathname
|
11
|
+
:initarg :target-pathname :initform nil))
|
12
|
+
(:report (lambda (c s)
|
13
|
+
(format s "Copy of ~S to ~S failed"
|
14
|
+
(source-pathname c) (target-pathname c))))
|
15
|
+
(:documentation "General condition for file errors that have a source and target."))
|
16
|
+
|
17
|
+
(define-condition source/target-target-already-exists-error (source/target-file-error)
|
18
|
+
()
|
19
|
+
(:report (lambda (c s)
|
20
|
+
(format s "File action failed because target ~S already exists"
|
21
|
+
(target-pathname c))))
|
22
|
+
(:documentation "This error is signaled when the target pathname already exists."))
|
23
|
+
|
24
|
+
(define-condition source/target-source-does-not-exist-error
|
25
|
+
(source/target-file-error)
|
26
|
+
()
|
27
|
+
(:report (lambda (c s)
|
28
|
+
(format s "File action failed because source ~S does not exist"
|
29
|
+
(source-pathname c))))
|
30
|
+
(:documentation "This error is signaled when the source file does not exist."))
|
31
|
+
|
32
|
+
(defun copy-file (from to &key (if-does-not-exist :error)
|
33
|
+
(if-exists :error))
|
34
|
+
"Copies the file designated by the non-wild pathname designator FROM
|
35
|
+
to the file designated by the non-wild pathname designator TO. The following
|
36
|
+
keyword parameters are supported:
|
37
|
+
|
38
|
+
* :if-exists
|
39
|
+
this can be either :supersede or :error (the default). If it is :error then
|
40
|
+
a source/target-target-already-exists-error will be signaled if the file designated
|
41
|
+
by the TO pathname already exists.
|
42
|
+
|
43
|
+
* :if-does-not-exist
|
44
|
+
this can be either :ignore or :error (the default). If it is :error then
|
45
|
+
a source/target-source-does-not-exist-error will be signaled if the FROM pathname
|
46
|
+
designator does not exist.
|
47
|
+
"
|
48
|
+
(assert (member if-exists '(:error :supersede))
|
49
|
+
nil
|
50
|
+
"The if-exists keyword parameter must be one of :error or :supersede. It is currently set to ~S"
|
51
|
+
if-exists)
|
52
|
+
(assert (member if-does-not-exist '(:error :ignore))
|
53
|
+
nil
|
54
|
+
"The if-does-not-exist keyword parameter must be one of :error or :ignore. It is currently set to ~S"
|
55
|
+
if-does-not-exist)
|
56
|
+
(ensure-directories-exist to)
|
57
|
+
(cond ((probe-file from)
|
58
|
+
#+:allegro
|
59
|
+
(excl.osi:copy-file
|
60
|
+
from to
|
61
|
+
:overwrite (if (eq if-exists :supersede) :ignore nil))
|
62
|
+
#-:allegro
|
63
|
+
(let ((element-type #-:cormanlisp '(unsigned-byte 8)
|
64
|
+
#+:cormanlisp 'unsigned-byte))
|
65
|
+
(with-open-file (in from :element-type element-type)
|
66
|
+
(with-open-file (out to :element-type element-type
|
67
|
+
:direction :output
|
68
|
+
:if-exists if-exists)
|
69
|
+
(unless out
|
70
|
+
(error (make-condition 'source/target-target-already-exists
|
71
|
+
:pathname from
|
72
|
+
:target-pathname to)))
|
73
|
+
(copy-stream in out))))
|
74
|
+
(values t))
|
75
|
+
(t
|
76
|
+
;; no source file!
|
77
|
+
(ecase if-does-not-exist
|
78
|
+
((:error) (error 'source/target-source-does-not-exist-error
|
79
|
+
:pathname from :target-pathname to))
|
80
|
+
((:ignore) nil)))))
|
81
|
+
|
82
|
+
(defun move-file (from to &rest args &key (if-does-not-exist :error)
|
83
|
+
(if-exists :error))
|
84
|
+
(declare (dynamic-extent args)
|
85
|
+
(ignore if-exists if-does-not-exist))
|
86
|
+
(when (apply #'copy-file from to args)
|
87
|
+
(delete-file from)))
|
88
|
+
|
89
|
+
;;; borrowed from asdf-install -- how did this ever work ?!
|
90
|
+
;; for non-SBCL we just steal this from SB-EXECUTABLE
|
91
|
+
#-(or :digitool)
|
92
|
+
(defvar *stream-buffer-size* 8192)
|
93
|
+
#-(or :digitool)
|
94
|
+
(defun copy-stream (from to)
|
95
|
+
"Copy into TO from FROM until end of the input stream, in blocks of
|
96
|
+
*stream-buffer-size*. The streams should have the same element type."
|
97
|
+
(unless (subtypep (stream-element-type to) (stream-element-type from))
|
98
|
+
(error "Incompatible streams ~A and ~A." from to))
|
99
|
+
(let ((buf (make-array *stream-buffer-size*
|
100
|
+
:element-type (stream-element-type from))))
|
101
|
+
(loop
|
102
|
+
(let ((pos #-(or :clisp :cmu) (read-sequence buf from)
|
103
|
+
#+:clisp (ext:read-byte-sequence buf from :no-hang nil)
|
104
|
+
#+:cmu (sys:read-n-bytes from buf 0 *stream-buffer-size* nil)))
|
105
|
+
(when (zerop pos) (return))
|
106
|
+
(write-sequence buf to :end pos)))))
|
107
|
+
|
108
|
+
#+:digitool
|
109
|
+
(defun copy-stream (from to)
|
110
|
+
"Perform copy and map EOL mode."
|
111
|
+
(multiple-value-bind (reader reader-arg) (ccl::stream-reader from)
|
112
|
+
(multiple-value-bind (writer writer-arg) (ccl::stream-writer to)
|
113
|
+
(let ((datum nil))
|
114
|
+
(loop (unless (setf datum (funcall reader reader-arg))
|
115
|
+
(return))
|
116
|
+
(funcall writer writer-arg datum))))))
|
117
|
+
|
@@ -0,0 +1,232 @@
|
|
1
|
+
(in-package #:lift)
|
2
|
+
|
3
|
+
(defgeneric find-testsuite (suite &key errorp)
|
4
|
+
(:documentation "Search for a testsuite named `suite`.
|
5
|
+
|
6
|
+
The search is conducted across all packages so `suite` can be
|
7
|
+
a symbol in any package. I.e., find-testsuite looks for testsuite
|
8
|
+
classes whose symbol-name is string= to `suite`. If `errorp` is
|
9
|
+
true, then find-testsuite can raise two possible errors:
|
10
|
+
|
11
|
+
* If more than one matching testsuite is found,
|
12
|
+
then an error of type `testsuite-ambiguous` will be raised.
|
13
|
+
* If no matching testsuites are found, then an error of type
|
14
|
+
`testsuite-not-defined` will be raised.
|
15
|
+
|
16
|
+
The default for `errorp` is nil."))
|
17
|
+
|
18
|
+
(defgeneric find-test-case (suite name &key errorp)
|
19
|
+
(:documentation "Search for a test-case named `name` in a
|
20
|
+
testsuite named `suite`.
|
21
|
+
|
22
|
+
The search is conducted across all packages so `suite` and `name`
|
23
|
+
can be symbols in any package. I.e., find-test-case looks for a
|
24
|
+
testsuites and test-cases whose symbol-names are string= to
|
25
|
+
`suite` and `name`. If `errorp` is
|
26
|
+
true, then find-test-case can raise two possible errors:
|
27
|
+
|
28
|
+
* If more than one matching test-case is found,
|
29
|
+
then an error of type `test-case-ambiguous` will be raised.
|
30
|
+
* If no matching test-cases are found, then an error of type
|
31
|
+
`test-case-not-defined` will be raised.
|
32
|
+
|
33
|
+
The default for `errorp` is nil. If `suite` is nil, then
|
34
|
+
find-test-case will search for matching test-cases across
|
35
|
+
all suites. This is equivalent to the behavior of [find-test-cases][]."))
|
36
|
+
|
37
|
+
(defgeneric find-test-cases (name &key errorp)
|
38
|
+
)
|
39
|
+
|
40
|
+
;;;;;
|
41
|
+
;; some introspection
|
42
|
+
|
43
|
+
(defun liftpropos (string &key (include-cases? nil))
|
44
|
+
"Returns a list of testsuites whose name contains `string`."
|
45
|
+
(let ((result nil)
|
46
|
+
(name-as-string (ensure-string string)))
|
47
|
+
(flet ((add-if-match (suite-name &optional (to-add suite-name))
|
48
|
+
(when (search name-as-string (ensure-string suite-name)
|
49
|
+
:test #'char-equal)
|
50
|
+
(push to-add result))))
|
51
|
+
(map-testsuites
|
52
|
+
(lambda (suite level)
|
53
|
+
(declare (ignore level))
|
54
|
+
(let ((suite-name (class-name suite)))
|
55
|
+
(add-if-match suite-name)
|
56
|
+
(when include-cases?
|
57
|
+
(loop for method-name in (testsuite-tests suite-name) do
|
58
|
+
(add-if-match
|
59
|
+
method-name (cons suite-name method-name))))))
|
60
|
+
'test-mixin))
|
61
|
+
(sort result #'string-lessp :key (lambda (it)
|
62
|
+
(typecase it
|
63
|
+
(atom it)
|
64
|
+
(cons (cdr it)))))))
|
65
|
+
|
66
|
+
(defun map-testsuites (fn start-at)
|
67
|
+
(let ((visited (make-hash-table)))
|
68
|
+
(labels ((do-it (suite level)
|
69
|
+
(unless (gethash suite visited)
|
70
|
+
(setf (gethash suite visited) t)
|
71
|
+
(funcall fn suite level)
|
72
|
+
(loop for subclass in (subclasses suite :proper? t) do
|
73
|
+
(do-it subclass (1+ level))))))
|
74
|
+
(do-it (find-class (find-testsuite start-at) nil) 0))))
|
75
|
+
|
76
|
+
(defun testsuites (&optional (start-at 'test-mixin))
|
77
|
+
"Returns a list of testsuite classes. The optional parameter provides
|
78
|
+
control over where in the test hierarchy the search begins."
|
79
|
+
(let ((result nil))
|
80
|
+
(map-testsuites (lambda (suite level)
|
81
|
+
(declare (ignore level))
|
82
|
+
(push suite result))
|
83
|
+
start-at)
|
84
|
+
(nreverse result)))
|
85
|
+
|
86
|
+
(defun print-tests (&key (include-cases? t) (start-at 'test-mixin) (stream t))
|
87
|
+
"Prints all of the defined test classes from :start-at on down."
|
88
|
+
(map-testsuites
|
89
|
+
(lambda (suite level)
|
90
|
+
(let ((indent (coerce (make-list (* level 3) :initial-element #\Space)
|
91
|
+
'string))
|
92
|
+
(name (class-name suite)))
|
93
|
+
(format stream "~&~a~s (~:d)"
|
94
|
+
indent
|
95
|
+
name
|
96
|
+
(length (testsuite-methods name)))
|
97
|
+
(when include-cases?
|
98
|
+
(loop for method-name in (testsuite-tests name) do
|
99
|
+
(format stream "~&~a ~a" indent method-name)))))
|
100
|
+
start-at))
|
101
|
+
|
102
|
+
(defun list-tests (&key (include-cases? t) (start-at 'test-mixin) (stream t))
|
103
|
+
"Lists all of the defined test classes from :start-at on down."
|
104
|
+
(mapc (lambda (subclass)
|
105
|
+
(let ((subclass-name (class-name subclass)))
|
106
|
+
(format stream "~&~s (~:d)"
|
107
|
+
subclass-name
|
108
|
+
(length (testsuite-methods subclass-name)))
|
109
|
+
(when include-cases?
|
110
|
+
(loop for method-name in (testsuite-tests subclass-name) do
|
111
|
+
(format stream "~& ~a" method-name)))))
|
112
|
+
(testsuites start-at))
|
113
|
+
(values))
|
114
|
+
|
115
|
+
(defun testsuite-test-count (testsuite)
|
116
|
+
(or (and *testsuite-test-count*
|
117
|
+
(prog1 *testsuite-test-count* (incf *testsuite-test-count*)))
|
118
|
+
(length (testsuite-methods testsuite))))
|
119
|
+
|
120
|
+
(defmethod find-testsuite ((suite symbol) &key (errorp nil))
|
121
|
+
(or (testsuite-p suite)
|
122
|
+
(find-testsuite (symbol-name suite) :errorp errorp)))
|
123
|
+
|
124
|
+
(defmethod find-testsuite ((suite-name string) &key (errorp nil))
|
125
|
+
(let* ((temp nil)
|
126
|
+
(possibilities (remove-duplicates
|
127
|
+
(loop for p in (list-all-packages)
|
128
|
+
when (and (setf temp (find-symbol suite-name p))
|
129
|
+
(find-class temp nil)
|
130
|
+
(subtypep temp 'test-mixin)) collect
|
131
|
+
temp))))
|
132
|
+
(cond ((null possibilities)
|
133
|
+
(when errorp
|
134
|
+
(error 'testsuite-not-defined :testsuite-name suite-name)))
|
135
|
+
((= (length possibilities) 1)
|
136
|
+
(first possibilities))
|
137
|
+
(t
|
138
|
+
(if errorp
|
139
|
+
(error 'testsuite-ambiguous
|
140
|
+
:testsuite-name suite-name
|
141
|
+
:possible-matches possibilities))
|
142
|
+
possibilities))))
|
143
|
+
|
144
|
+
(defun test-case-p (suite-class name)
|
145
|
+
(find-method #'lift-test nil `(,suite-class (eql ,name)) nil))
|
146
|
+
|
147
|
+
#+(or)
|
148
|
+
(test-case-p
|
149
|
+
(find-class (find-testsuite 'test-cluster-indexing-locally) nil)
|
150
|
+
'db.agraph.tests::index-them)
|
151
|
+
|
152
|
+
#+(or)
|
153
|
+
(find-test-case (find-class (find-testsuite 'test-cluster-indexing-locally))
|
154
|
+
'index-themxx)
|
155
|
+
|
156
|
+
(defmethod find-test-case ((suite symbol) name &key (errorp nil))
|
157
|
+
(find-test-case (find-class (find-testsuite suite)) name :errorp errorp))
|
158
|
+
|
159
|
+
(defmethod find-test-case ((suite null) name &key (errorp nil))
|
160
|
+
(find-test-cases name :errorp errorp))
|
161
|
+
|
162
|
+
(defmethod find-test-case ((suite test-mixin) name &key (errorp nil))
|
163
|
+
(find-test-case (class-of suite) name :errorp errorp))
|
164
|
+
|
165
|
+
(defmethod find-test-case ((suite-class standard-class) (name symbol)
|
166
|
+
&key (errorp nil))
|
167
|
+
(or (and (test-case-p suite-class name) name)
|
168
|
+
(find-test-case suite-class (symbol-name name) :errorp errorp)))
|
169
|
+
|
170
|
+
(defmethod find-test-case ((suite test-mixin) (name string)
|
171
|
+
&key (errorp nil))
|
172
|
+
(find-test-case (class-of suite) name :errorp errorp))
|
173
|
+
|
174
|
+
(defmethod find-test-case ((suite-class standard-class) (name string)
|
175
|
+
&key (errorp nil))
|
176
|
+
(let* ((temp nil)
|
177
|
+
(possibilities (remove-duplicates
|
178
|
+
(loop for p in (list-all-packages)
|
179
|
+
when (and (setf temp (find-symbol name p))
|
180
|
+
(test-case-p suite-class temp)) collect
|
181
|
+
temp))))
|
182
|
+
(cond ((null possibilities)
|
183
|
+
(when errorp
|
184
|
+
(error 'test-case-not-defined
|
185
|
+
:testsuite-name suite-class :test-case-name name)))
|
186
|
+
((= (length possibilities) 1)
|
187
|
+
(first possibilities))
|
188
|
+
(t
|
189
|
+
(when errorp
|
190
|
+
(error 'test-case-ambiguous
|
191
|
+
:testsuite-name suite-class
|
192
|
+
:test-case-name name
|
193
|
+
:possible-matches possibilities))))))
|
194
|
+
|
195
|
+
(defmethod find-test-cases ((name symbol) &key (errorp nil))
|
196
|
+
(find-test-cases (symbol-name name) :errorp errorp))
|
197
|
+
|
198
|
+
(defmethod find-test-cases ((name string) &key (errorp nil))
|
199
|
+
(let ((result nil))
|
200
|
+
(dolist (testsuite (testsuites))
|
201
|
+
(let* ((suitename (class-name testsuite))
|
202
|
+
(testname (find-symbol name (symbol-package suitename))))
|
203
|
+
(when (and testname
|
204
|
+
(test-case-p testsuite testname))
|
205
|
+
(push (cons suitename testname) result))))
|
206
|
+
(unless result
|
207
|
+
(when errorp
|
208
|
+
(error "not test-cases found")))
|
209
|
+
result))
|
210
|
+
|
211
|
+
(defun last-test-status ()
|
212
|
+
(cond ((typep *test-result* 'test-result)
|
213
|
+
(cond ((and (null (errors *test-result*))
|
214
|
+
(null (failures *test-result*)))
|
215
|
+
:success)
|
216
|
+
((and (errors *test-result*)
|
217
|
+
(failures *test-result*))
|
218
|
+
:errors-and-failures)
|
219
|
+
((errors *test-result*)
|
220
|
+
:errors)
|
221
|
+
((failures *test-result*)
|
222
|
+
:failures)))
|
223
|
+
(t
|
224
|
+
nil)))
|
225
|
+
|
226
|
+
(defun suite-tested-p (suite &key (result *test-result*))
|
227
|
+
(and result
|
228
|
+
(typep *test-result* 'test-result)
|
229
|
+
(slot-exists-p result 'suites-run)
|
230
|
+
(slot-boundp result 'suites-run)
|
231
|
+
(consp (suites-run result))
|
232
|
+
(find suite (suites-run result))))
|