t/package.m4: Delete generated file.
[runlisp] / tests.at
CommitLineData
e29834b8
MW
1### -*-autotest-*-
2###
3### Test script for `runlisp'
4###
5### (c) 2020 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This file is part of Runlisp, a tool for invoking Common Lisp scripts.
11###
12### Runlisp is free software: you can redistribute it and/or modify it
13### under the terms of the GNU General Public License as published by the
14### Free Software Foundation; either version 3 of the License, or (at your
15### option) any later version.
16###
17### Runlisp is distributed in the hope that it will be useful, but WITHOUT
18### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19### FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20### for more details.
21###
22### You should have received a copy of the GNU General Public License
23### along with Runlisp. If not, see <https://www.gnu.org/licenses/>.
24
25m4_define([RUNLISP_PATH], [$abs_top_builddir/runlisp])
26
27m4_define([_FOREACH], [dnl
28m4_if([$#], [1], [_foreach_func($1)],
29 [_foreach_func($1)[]_FOREACH(m4_shift($@))])])
30m4_define([FOREACH], [dnl
31m4_pushdef([_foreach_func], [$2])dnl
32_FOREACH($1)[]dnl
33m4_popdef([_foreach_func])])
34
35m4_define([LISP_SYSTEMS],
36 [sbcl, sbcl/noimage,
37 ccl, ccl/noimage,
38 clisp, clisp/noimage,
39 ecl, ecl/noimage,
40 cmucl, cmucl/noimage,
41 abcl, abcl/noimage])
42
8996f767
MW
43m4_define([SETUP_RUNLISP_ENV],
44[RUNLISP_SYSCONFIG=$abs_top_srcdir/runlisp-base.conf; export RUNLISP_SYSCONFIG
45RUNLISP_SYSCONFIG_DIR=/notexist; export RUNLISP_SYSCONFIG_DIR
46RUNLISP_IMAGEDIR=$abs_top_builddir; export RUNLISP_IMAGEDIR
47RUNLISP_EVAL=$abs_top_srcdir/eval.lisp; export RUNLISP_EVAL
48unset RUNLISP_USERCONFIG
49])
50
e29834b8 51m4_define([PREPARE_LISP_TEST],
8996f767
MW
52[SETUP_RUNLISP_ENV
53lisp=$1
2c39b5e6 54LISP=$m4_translit(m4_bpatsubst([$1], [/.*$], []), [a-z], [A-Z])
e29834b8
MW
55AT_SKIP_IF([test "x$LISP" = x])
56case $lisp in
57 */*) opt=${lisp#*/} lisp=${lisp%%/*} ;;
58 *) opt="" ;;
59esac
8996f767 60case /$opt/ in */noimage/*) RUNLISP_IMAGEDIR=./notexist ;; esac])
e29834b8
MW
61
62m4_define([WHICH_LISP],
63[(or #+sbcl "sbcl" #+ccl "ccl" #+clisp "clisp"
64 #+ecl "ecl" #+cmu "cmucl" #+abcl "abcl"
65 "unknown")])
66
67m4_define([NL], [
68])
69
e29834b8
MW
70###--------------------------------------------------------------------------
71### A basic smoke test.
72
73## Check that the system basically works, by running a trivial test program.
74## Also try to verify that we're not running user or site startup code,
75## though this is hard to do in general.
76FOREACH([LISP_SYSTEMS],
77[AT_SETUP([$1 smoke])
78AT_KEYWORDS([script smoke $1])
79PREPARE_LISP_TEST([$1])
80
81## Prepare a user-init file which will break the test if it's run by printing
82## something unexpected.
83mkdir HOME
84case $lisp in
85 sbcl) initfile=.sbclrc ;;
86 ccl) initfile=.ccl-init.lisp ;;
87 clisp) initfile=.clisprc.lisp ;;
88 ecl) initfile=.eclrc ;;
89 cmucl) initfile=.cmucl-init.lisp ;;
90 abcl) initfile=.abclrc ;;
91esac
92cat >HOME/$initfile <<EOF
93(format t "*** I should not be seen~%")
94EOF
95HOME=$(pwd)/HOME; export HOME
96
97## Prepare the script.
98cat >test-script <<EOF
99[#!] RUNLISP_PATH -L$lisp
100
101;; Print a greeting to \`*standard-output*', identifying the Lisp system, so
102;; that we can tell whether we called the right one.
103(format t "Hello from ~A (~A)!~%" (lisp-implementation-type) WHICH_LISP)
104
105#! this should be a comment everywhere
106
107;; Make sure that \`*error-output*' is hooked up properly.
108(format *error-output* "to stderr~%")
109
110;; Make sure that \`*standard-input*' is hooked up properly, by reading a line
111;; and echoing it.
112(format t "from stdin: ~S~%" (read-line))
113
114;; Check that \`:runlisp-script' is set in \`*features*'. If not, \`assert'
115;; will at least write a complaint to some stream, which will fail the test.
116(assert (member :runlisp-script *features*))
117
118;; Check that there are no symbols present (interned or imported) in the
119;; \`common-lisp-user' package. Obviously, we must avoid interning any
120;; ourselves. Alas, ABCL and ECL pollute \`cl-user' out of the box. (ECL
8996f767
MW
121;; does this deliberately; ABCL's ``adjoin.lisp' lacks an \`in-package'
122;; form.)
e29834b8
MW
123(let ((#1=#:syms (sort (loop :for #2=#:s :being :the :present-symbols
124 :of *package*
125 :collect #2#)
126 #'string<)))
127 (format t "package \`~A' [~:[ok~;has unexpected symbols ~:*~S~]]~%"
128 (package-name *package*) #1#))
129
130;; Print the program name and command-line arguments.
131(format t "program name = ~S~%~
132 arguments = ~:S~%"
133 (uiop:argv0)
134 uiop:*command-line-arguments*)
135EOF
136chmod +x test-script
137
138case $lisp in
139 sbcl) impl="SBCL" ;;
140 ccl) impl="Clozure Common Lisp" ;;
141 clisp) impl="CLISP" ;;
142 ecl) impl="ECL" ;;
143 cmucl) impl="CMU Common Lisp" ;;
144 abcl) impl="Armed Bear Common Lisp" ;;
145 *) AT_FAIL_IF([:]) ;;
146esac
147
148## Prepare an input file.
149echo some random text >stdin
150
151## Prepare the reference stdout and stderr.
152cat >stdout.ref <<EOF
153Hello from $impl ($lisp)!
154from stdin: "some random text"
155package \`COMMON-LISP-USER' ok
156program name = "./test-script"
157arguments = ("--eval" "nonsense" "--" "more" "args" "here")
158EOF
159cat >stderr.ref <<EOF
160to stderr
161EOF
162
163AT_CHECK([echo "lisp=$lisp opt=$opt"; env | grep RUNLISP | sort],, [stdout])
164AT_CHECK([./test-script --eval nonsense -- more args here <stdin],,
165 [stdout], [stderr])
166AT_CHECK([diff -u stdout.ref stdout])
167AT_CHECK([diff -u stderr.ref stderr])
168AT_CLEANUP])
169
170###--------------------------------------------------------------------------
171### Check error handling.
172
173FOREACH([LISP_SYSTEMS],
174[AT_SETUP([$1 errors])
175AT_KEYWORDS([script error $1])
176PREPARE_LISP_TEST([$1])
177
178## A simple script which signals an error without catching it.
179cat >test <<EOF
180[#!] RUNLISP_PATH -L$lisp
181(error "just kill me now")
182EOF
183chmod +x test
184
185## As long as it exits with a nonzero status, I'm happy. Some Lisps
186## desperately want to drop the user into an interactive debugger, which is
187## possibly useful for a developer, but an end user is now faced with a
188## confusing internal error message /and/ a confusing prompt which won't go
189## away. The output may still be confusing and (certainly in CCL's case)
190## voluminous, but that's not significantly worse than Tcl or Java.
191./test >out >err; rc=$?
192AT_FAIL_IF([test $rc = 0])
193
194AT_CLEANUP])
195
196###--------------------------------------------------------------------------
197### Check eval mode.
198
199### Eval mode is implemented centrally through a script, so we don't need to
200### test it separately for each Lisp implementation.
201
202AT_SETUP([eval mode])
203AT_KEYWORDS([eval common])
8996f767 204SETUP_RUNLISP_ENV
e29834b8
MW
205
206## A very basic smoke test.
207AT_CHECK([RUNLISP_PATH -e '(format t "Just another Lisp hacker!~%")'],,
208[Just another Lisp hacker!
209])
210
211## The `:runlisp-script' keyword should /not/ be in `*features*'.
212traceon
213AT_CHECK([RUNLISP_PATH -p '(find :runlisp-script *features*)'],, [NIL
214])
215
216## Check a mixture of all the kinds of evaluation. We'll need a stunt script
217## to make this work. Also check that the individual forms are read and
218## evaluated one at a time, so that each one can affect the way the reader
219## interprets the next.
220cat >script.lisp <<EOF
221#! just want to check that Lisp doesn't choke on a shebang line here
222(format t "And we're running the script...~%~
223 Command-line arguments: ~:S~%~
224 Symbols in package \`~A': ~:S~%"
225 uiop:*command-line-arguments*
226 (package-name *package*)
227 (sort (loop :for #2=#:s :being :the :present-symbols :of *package*
228 :collect #2#)
229 #'string<))
230EOF
231AT_CHECK([RUNLISP_PATH \
232 -e '(defpackage [#:]runlisp-test (:export [#:]foo))
233 (defvar runlisp-test:foo 1)' \
234 -p runlisp-test:foo \
235 -e '(incf runlisp-test:foo)' \
236 -l script.lisp \
237 -p runlisp-test:foo \
238 -- -e one two three],,
239[1
240And we're running the script...
241Command-line arguments: ("-e" "one" "two" "three")
242Symbols in package `COMMON-LISP-USER': ()
2432
244])
245
246AT_CLEANUP
247
248###--------------------------------------------------------------------------
249### Check Lisp system selection and preference work.
250
251AT_SETUP([preferences])
252AT_KEYWORDS([prefs common])
8996f767 253SETUP_RUNLISP_ENV
e29834b8
MW
254
255## Before we can make this happen, we need to decide on three Lisp systems,
256## two of which actually work, and one other. These are ordered by startup
257## speed.
258unset lisp0 lisp1 badlisp; win=nil
259set -- cmucl sbcl ccl clisp ecl abcl
260while :; do
261 case $# in 0) break ;; esac
262 lisp=$1; shift
263 if RUNLISP_PATH -L$lisp -enil 2>/dev/null; then good=t; else good=nil; fi
264 case ${lisp0+t},${badlisp+t},$good in
265 ,*,t) lisp0=$lisp ;;
266 t,*,t) lisp1=$lisp win=t; break ;;
267 *,,nil) badlisp=$lisp ;;
268 esac
269done
270AT_CHECK([case $win in nil) exit 77 ;; esac])
271case ${badlisp+t} in t) ;; *) badlisp=$1 ;; esac
272BADLISP=$(echo $badlisp | tr a-z A-Z)
273eval $BADLISP=/notexist/definitely-wrong
274export $BADLISP
275echo Primary Lisp = $lisp0
276echo Secondary Lisp = $lisp1
277echo Bad Lisp = $badlisp
278
279## Check that our selection worked.
280AT_CHECK_UNQUOTED([RUNLISP_PATH -L$lisp0 -p 'WHICH_LISP'],, ["$lisp0"NL])
281AT_CHECK_UNQUOTED([RUNLISP_PATH -L$lisp1 -p 'WHICH_LISP'],, ["$lisp1"NL])
282AT_CHECK([RUNLISP_PATH -L$badlisp -p 'WHICH_LISP'], [127],,
8996f767 283[runlisp: no acceptable Lisp systems found[]NL])
e29834b8
MW
284
285## Unset all of the user preference mechanisms.
e29834b8
MW
286here=$(pwd)
287mkdir HOME config
288HOME=$here/HOME XDG_CONFIG_HOME=$here/config; export HOME XDG_CONFIG_HOME
289
290## We generally take the first one listed that exists.
291AT_CHECK_UNQUOTED([RUNLISP_PATH -L$lisp0,$lisp1 -p 'WHICH_LISP'],, ["$lisp0"NL])
292AT_CHECK_UNQUOTED([RUNLISP_PATH -L$lisp1,$lisp0 -p 'WHICH_LISP'],, ["$lisp1"NL])
293AT_CHECK_UNQUOTED([RUNLISP_PATH -L$badlisp,$lisp0,$lisp1 -p 'WHICH_LISP'],,
294 ["$lisp0"NL])
295
296## Check parsing of embedded options.
297for i in 0 1; do
298 j=$(( 1 - $i )); eval lisp=\$lisp$i olisp=\$lisp$j
299 cat >script$i <<EOF
300[#!] RUNLISP_PATH
301;;; -z @RUNLISP: -L$lisp -*- -z -*- -L$olisp -- -z
302(prin1 WHICH_LISP) (terpri)
303EOF
304 chmod +x script$i
305 AT_CHECK_UNQUOTED([./script$i],, ["$lisp"NL])
306done
307
308## Preferences will override the order of acceptable implementations.
8996f767
MW
309AT_CHECK_UNQUOTED([RUNLISP_PREFER=$badlisp,$lisp0 ./script0],, ["$lisp0"NL])
310AT_CHECK_UNQUOTED([RUNLISP_PREFER=$badlisp,$lisp0 ./script1],, ["$lisp0"NL])
e29834b8
MW
311
312## But doesn't affect the preference order of unmentioned Lisps.
8996f767
MW
313AT_CHECK_UNQUOTED([RUNLISP_PREFER=$badlisp ./script0],, ["$lisp0"NL])
314AT_CHECK_UNQUOTED([RUNLISP_PREFER=$badlisp ./script1],, ["$lisp1"NL])
e29834b8
MW
315
316## Test configuration files and interactions with the environment.
8996f767 317for conf in HOME/.runlisp.conf config/runlisp.conf; do
e29834b8
MW
318 for i in 0 1; do
319 j=$(( 1 - $i )); eval lisp=\$lisp$i olisp=\$lisp$j
320 cat >$conf <<EOF
8996f767
MW
321;;; -*-conf-*-
322prefer = $lisp
e29834b8
MW
323EOF
324
325 ## Basic check.
326 AT_CHECK_UNQUOTED([./script0],, ["$lisp"NL])
327 AT_CHECK_UNQUOTED([./script1],, ["$lisp"NL])
328
8996f767
MW
329 ## Environment variable overrides.
330 AT_CHECK_UNQUOTED([RUNLISP_PREFER=$olisp ./script0],, ["$olisp"NL])
331 AT_CHECK_UNQUOTED([RUNLISP_PREFER=$olisp ./script1],, ["$olisp"NL])
e29834b8
MW
332
333 done
334 rm -f $conf
335done
336
337
338
339AT_CLEANUP
340
341###----- That's all, folks --------------------------------------------------