mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
The change in d788babebf to respect
scope of mufflings inadvertently removed warnings from a number of
cases, including type and extent declarations and setq forms. Restore
them, fixing in the sources a few instances of undefined declarations
that have crept in, and an instance in our tests whose behaviour
inexplicably changed somehow. This also changes the condition kind of
a free, unknown dynamic extent declaration on a variable to a full
warning (it was a style warning before).
629 lines
16 KiB
Bash
629 lines
16 KiB
Bash
#!/bin/sh
|
|
|
|
# This software is part of the SBCL system. See the README file for
|
|
# more information.
|
|
#
|
|
# While most of SBCL is derived from the CMU CL system, the test
|
|
# files (like this one) were written from scratch after the fork
|
|
# from CMU CL.
|
|
#
|
|
# This software is in the public domain and is provided with
|
|
# absolutely no warranty. See the COPYING and CREDITS files for
|
|
# more information.
|
|
|
|
. ./expect.sh
|
|
|
|
use_test_subdirectory
|
|
|
|
# It's unclear why the majority of these tests are written in shell script when
|
|
# many look as though they would be perfectly happy as lisp tests.
|
|
# This test, on the other hand, would have a tough time as a lisp test,
|
|
# because it needs to make a symlink which would either mean calling run-program
|
|
# or using alien-funcall on symlink(). Shell is easier.
|
|
mkdir -p inscrutable/f00
|
|
echo '(defun zook (x) (declare (integer x)) (length x))' > inscrutable/f00/f00_xyz_bad
|
|
ln -s inscrutable/f00/f00_xyz_bad good.lisp
|
|
run_sbcl --eval '(setq *default-pathname-defaults* #P"")' \
|
|
--eval '(compile-file "good.lisp" :verbose t)' --quit >stdout.out 2>stderr.out
|
|
egrep -q 'compiling file ".*good' stdout.out
|
|
stdout_ok=$?
|
|
egrep -q 'file:.+good' stderr.out
|
|
stderr_ok=$?
|
|
if [ $stdout_ok = 0 -a $stderr_ok = 0 ] ; then
|
|
rm -r good.* stdout.out stderr.out inscrutable
|
|
echo "untruenames: PASS"
|
|
else
|
|
cat stdout.out stderr.out
|
|
echo "untruenames: FAIL"
|
|
exit $EXIT_LOSE
|
|
fi
|
|
|
|
## FIXME: all these tests need to be more silent. Too much noise to parse
|
|
|
|
tmpfilename="$TEST_FILESTEM.lisp"
|
|
|
|
# This should fail, as type inference should show that the call to FOO
|
|
# will return something of the wrong type.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (list x))
|
|
(defun bar (x) (1+ (foo x)))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should fail, as type inference should show that the call to FOO
|
|
# has a wrong number of args.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (or x (foo x x)))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should fail, as we define a function multiply in the same file
|
|
# (CLHS 3.2.2.3).
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (list x))
|
|
(defun foo (x) (cons x x))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This shouldn't fail, as the inner FLETs should not be treated as
|
|
# having the same name.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x)
|
|
(flet ((baz (y) (load y)))
|
|
(declare (notinline baz))
|
|
(baz x)))
|
|
(defun bar (x)
|
|
(flet ((baz (y) (load y)))
|
|
(declare (notinline baz))
|
|
(baz x)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This shouldn't fail because it's not really a multiple definition
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defun foo (x) x))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# Likewise
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(eval-when (:compile-toplevel)
|
|
(defun foo (x) x))
|
|
(defun foo (x) x)
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This shouldn't fail despite the apparent type mismatch, because of
|
|
# the NOTINLINE declamation.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (list x))
|
|
(declaim (notinline foo))
|
|
(defun bar (x) (1+ (foo x)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This shouldn't fail, but did until sbcl-0.8.10.4x
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(declaim (inline foo))
|
|
(defun foo (x)
|
|
(1+ x))
|
|
(defun bar (y)
|
|
(list (foo y) (if (> y 1) (funcall (if (> y 0) #'foo #'identity) y))))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This shouldn't fail despite the apparent type mismatch, because of
|
|
# the NOTINLINE declaration.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (list x))
|
|
(defun bar (x)
|
|
(declare (notinline foo))
|
|
(1+ (foo x)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This in an ideal world would fail (that is, return with FAILURE-P
|
|
# set), but at present it doesn't.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (list x))
|
|
(defun bar (x)
|
|
(declare (notinline foo))
|
|
(locally
|
|
(declare (inline foo))
|
|
(1+ (foo x))))
|
|
EOF
|
|
# expect_failed_compile $tmpfilename
|
|
|
|
# This used to not warn, because the VALUES derive-type optimizer was
|
|
# insufficiently precise.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (declare (ignore x)) (values))
|
|
(defun bar (x) (1+ (foo x)))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# Even after making the VALUES derive-type optimizer more precise, the
|
|
# following should still be clean.
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x) (declare (ignore x)) (values))
|
|
(defun bar (x) (car x))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# NOTINLINE on known functions shouldn't inhibit type inference
|
|
# (spotted by APD sbcl-devel 2003-06-14)
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x)
|
|
(declare (notinline list))
|
|
(1+ (list x)))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# ERROR wants to check its format string for sanity...
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x)
|
|
(when x
|
|
(error "~S")))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# ... but it (ERROR) shouldn't complain about being unable to optimize
|
|
# when it's uncertain about its argument's type
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defun foo (x)
|
|
(error x))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
# test case from Rudi for some CLOS WARNINGness that shouldn't have
|
|
# been there
|
|
cat > $tmpfilename <<EOF
|
|
(eval-when (:compile-toplevel)
|
|
(setf sb-ext:*evaluator-mode* :compile))
|
|
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defstruct buffer-state
|
|
(output-index 0)))
|
|
|
|
(defclass buffered-stream-mixin ()
|
|
((buffer-state :initform (make-buffer-state))))
|
|
|
|
(defgeneric frob (stream))
|
|
(defmethod frob ((stream t))
|
|
nil)
|
|
(defmethod frob ((stream buffered-stream-mixin))
|
|
(symbol-macrolet
|
|
((index (buffer-state-output-index (slot-value stream 'buffer-state))))
|
|
(setf index 0))
|
|
(call-next-method))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# undeclared unbound variables should cause a full warning, as they
|
|
# invoke undefined behaviour
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo () x)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (special *x*))
|
|
(defun foo () *x*)
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo () (declare (special x)) x)
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# MUFFLE-CONDITIONS tests
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo ()
|
|
(declare (muffle-conditions style-warning))
|
|
(bar))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo ()
|
|
(declare (muffle-conditions code-deletion-note))
|
|
(if t (foo) (foo)))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo (x y)
|
|
(declare (muffle-conditions compiler-note))
|
|
(declare (optimize speed))
|
|
(+ x y))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (muffle-conditions compiler-note))
|
|
(defun foo (x y)
|
|
(declare (optimize speed))
|
|
(+ x y))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (optimize debug)
|
|
(muffle-conditions compiler-note))
|
|
(defun foo (x y)
|
|
(declare (optimize speed))
|
|
(+ x y))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (muffle-conditions compiler-note))
|
|
(defun foo (x y)
|
|
(declare (unmuffle-conditions compiler-note))
|
|
(declare (optimize speed))
|
|
(+ x y))
|
|
EOF
|
|
expect_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
# undefined variable causes a WARNING
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (muffle-conditions warning))
|
|
(declaim (unmuffle-conditions style-warning))
|
|
(defun foo () x)
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# top level LOCALLY behaves nicely
|
|
cat > $tmpfilename <<EOF
|
|
(locally
|
|
(declare (muffle-conditions warning))
|
|
(defun foo () x))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(locally
|
|
(declare (muffle-conditions warning))
|
|
(defun foo () x))
|
|
(defun bar () x)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (optimize debug))
|
|
(locally
|
|
(declare (muffle-conditions warning))
|
|
(defun foo () x))
|
|
(defun bar () x)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo ()
|
|
(locally (declare (muffle-conditions warning))
|
|
(+ x x))
|
|
x)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should fail, and fail nicely -- not eg. loop trying to dump
|
|
# references to the unbound variable.
|
|
cat > $tmpfilename <<EOF
|
|
(defmacro macro-with-unbound-variables (foo)
|
|
\`(print ,bar))
|
|
|
|
(macro-with-unbound-variables 'xxx)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should fail, as the MAKE-LOAD-FORM must be used for
|
|
# externalizing conditions, and the method for CONDITION must signal
|
|
# an error.
|
|
cat > $tmpfilename <<EOF
|
|
(defvar *oops* #.(make-condition 'condition))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should fail, as the MAKE-LOAD-FORM must be used for objects,
|
|
# and the method for STANDARD.OBJECT is required to signal an error.
|
|
cat > $tmpfilename <<EOF
|
|
(defvar *oops* #.(make-instance 'standard-object))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# This should be clean
|
|
cat > $tmpfilename <<EOF
|
|
(defvar *string* (make-string 10 :element-type 'base-char))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
# This should style-warn (but not warn or otherwise fail) as the call
|
|
# to FORMAT has too many arguments, which is bad style but not
|
|
# otherwise fatal.
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo (a b)
|
|
(format nil "abc~~def" a b))
|
|
EOF
|
|
expect_warned_compile $tmpfilename
|
|
|
|
# Tests that destructive-functions on known-constant data cause
|
|
# compile-time warnings.
|
|
cat > $tmpfilename <<EOF
|
|
(let ((string "foo"))
|
|
(defun foo ()
|
|
(setf string "bar")))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo ()
|
|
(let (result)
|
|
(nreverse result)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun bar ()
|
|
(let ((result ""))
|
|
(nreverse result)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(let ((string "foo"))
|
|
(defun foo ()
|
|
(replace string "bar")))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo ()
|
|
(setf (char "bar" 0) #\1))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(let ((foo '(1 2 3)))
|
|
(defun foo ()
|
|
(nconc foo foo)))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
x
|
|
y
|
|
z
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(declaim (optimize (speed 3) (space 0) (safety 0)))
|
|
|
|
(defun foo (bar)
|
|
(last bar))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defstruct foo
|
|
(bar #p"/tmp/"))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defstruct foox)
|
|
(defmethod make-load-form ((foo foox) &optional env)
|
|
(declare (ignore env))
|
|
'(make-foox)))
|
|
(defstruct bar
|
|
(foo #.(make-foox)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun something (x) x)
|
|
...
|
|
(defun something-more (x) x)
|
|
EOF
|
|
expect_aborted_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(if t (locally))
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defconstant cl-package (find-package :cl))
|
|
(defun cl-symbol-p (x)
|
|
(eq (symbol-package x) cl-package))
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(and (eval-when (:compile-toplevel) (error "oops AND")))
|
|
(or (eval-when (:compile-toplevel) (error "oops OR")))
|
|
(cond (t (eval-when (:compile-toplevel) (error "oops COND"))))
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
# Test correct fasl-dumping of literals in arglist defaulting.
|
|
# (LP Bug #310132)
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
;; These are CLHS examples from the dictionary entry for MAKE-LOAD-FORM.
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defstruct my-struct a b c)
|
|
(defmethod make-load-form ((s my-struct) &optional environment)
|
|
(make-load-form-saving-slots s :environment environment))
|
|
(defclass my-class ()
|
|
((x :initarg :x :reader obj-x)
|
|
(y :initarg :y :reader obj-y)
|
|
(dist :accessor obj-dist)))
|
|
(defmethod make-load-form ((self my-class) &optional environment)
|
|
(make-load-form-saving-slots self
|
|
:slot-names '(x y)
|
|
:environment environment)))
|
|
|
|
(defun bar1 (&optional (x #.(make-my-struct)))
|
|
x)
|
|
|
|
(defun bar2 (&optional (x #.(make-instance 'my-class)))
|
|
x)
|
|
|
|
;; Packages are externalizable.
|
|
(defun bar3 (&optional (x #.*package*))
|
|
x)
|
|
|
|
(assert (typep (bar1) 'my-struct))
|
|
(assert (typep (bar2) 'my-class))
|
|
(assert (eq (bar3) *package*))
|
|
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
(defmacro foo () (error "ERROR at macroexpansion time."))
|
|
(defun bar () (foo))
|
|
EOF
|
|
expect_condition_during_compile sb-c:compiler-error $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(eval-when (:compile-toplevel)
|
|
(error "ERROR within EVAL-WHEN."))
|
|
EOF
|
|
expect_condition_during_compile simple-error $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(defun slot-name-incf (s)
|
|
(with-slots (no-such-slot) s
|
|
(incf no-such-slot)))
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
(defun foo ()
|
|
(declare (muffle-conditions warning))
|
|
(let ((em 0d0))
|
|
(declare (type double-float em))
|
|
(dotimes (i 42)
|
|
(setf em (float (1+ i))))))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
(defun foo ()
|
|
(declare (muffle-conditions warning))
|
|
(flet ((foo ()
|
|
(declare (values fixnum))
|
|
nil))
|
|
(foo)))
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
(defun foo (x)
|
|
(declare (muffle-conditions warning)
|
|
(type (vector (mod 7) 1) x))
|
|
(setf (aref x 0) 8)
|
|
x)
|
|
EOF
|
|
expect_clean_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
(declaim (notinline foo))
|
|
(let ((i 0)) (defun foo (x) (incf i x)))
|
|
(defun bar (x) (foo x))
|
|
EOF
|
|
fail_on_condition_during_compile sb-ext:compiler-note $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(in-package :cl-user)
|
|
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defclass subclass (superclass) ((zslot2 :initarg :zslot2 :accessor zslot2))))
|
|
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defclass superclass () ((c :initarg c :accessor c))))
|
|
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(sb-kernel::%invalidate-layout (sb-pcl::class-wrapper (find-class 'subclass))))
|
|
|
|
;; This test file is weird. It expects to see warnings from a COMPILE inside
|
|
;; a method body that is compiled (and not necessarily invoked).
|
|
;; To force the warnings to happen, we have to force the method to get called,
|
|
;; which we can do by asking a SUBTYPEP question.
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(defmethod sb-mop:finalize-inheritance :after (class)
|
|
(eval '(defmethod z (x) (abcde)))
|
|
(funcall (compile nil '(lambda () (defun zz (x) (defgh))))))
|
|
(assert (not (sb-kernel:csubtypep (sb-kernel:specifier-type 'subclass)
|
|
(sb-kernel:specifier-type 'condition)))))
|
|
|
|
(defun subclass-p (x)
|
|
(typep x 'subclass))
|
|
EOF
|
|
expect_warned_compile $tmpfilename
|
|
|
|
cat > $tmpfilename <<EOF
|
|
(let ((a (load-time-value (funcall (lambda () 128)))))
|
|
(declare (fixnum a))
|
|
(print a)
|
|
(terpri))
|
|
EOF
|
|
expect_clean_cload $tmpfilename
|
|
|
|
# Test compiler warning generation for unbound variables from type declaration...
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo (bar)
|
|
(declare (type vector baz))
|
|
(length bar))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# ... extent declaration ...
|
|
cat > $tmpfilename <<EOF
|
|
(defun foo (n)
|
|
(declare (type (mod 32) n))
|
|
(let ((vect (make-array n :element-type 'fixnum)))
|
|
(declare (dynamic-extent vec))
|
|
(1+ (length vect))))
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# ... and setq
|
|
cat > $tmpfilename <<EOF
|
|
(setq nonexistent t)
|
|
EOF
|
|
expect_failed_compile $tmpfilename
|
|
|
|
# success
|
|
exit $EXIT_TEST_WIN
|