1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
3 ;;; foreign-globals.lisp --- Tests on foreign globals.
5 ;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira(@)common-lisp.net>
7 ;;; Permission is hereby granted, free of charge, to any person
8 ;;; obtaining a copy of this software and associated documentation
9 ;;; files (the "Software"), to deal in the Software without
10 ;;; restriction, including without limitation the rights to use, copy,
11 ;;; modify, merge, publish, distribute, sublicense, and/or sell copies
12 ;;; of the Software, and to permit persons to whom the Software is
13 ;;; furnished to do so, subject to the following conditions:
15 ;;; The above copyright notice and this permission notice shall be
16 ;;; included in all copies or substantial portions of the Software.
18 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 ;;; DEALINGS IN THE SOFTWARE.
28 (in-package #:cffi-tests
)
30 (defcvar ("var_char" *char-var
*) :char
)
31 (defcvar "var_unsigned_char" :unsigned-char
)
32 (defcvar "var_short" :short
)
33 (defcvar "var_unsigned_short" :unsigned-short
)
34 (defcvar "var_int" :int
)
35 (defcvar "var_unsigned_int" :unsigned-int
)
36 (defcvar "var_long" :long
)
37 (defcvar "var_unsigned_long" :unsigned-long
)
38 (defcvar "var_float" :float
)
39 (defcvar "var_double" :double
)
40 (defcvar "var_pointer" :pointer
)
41 (defcvar "var_string" :string
)
42 (defcvar "var_long_long" :long-long
)
43 (defcvar "var_unsigned_long_long" :unsigned-long-long
)
45 ;;; The expected failures marked below result from this odd behaviour:
47 ;;; (foreign-symbol-pointer "var_char") => NIL
49 ;;; (foreign-symbol-pointer "var_char" :library 'libtest)
50 ;;; => #<Pointer to type :VOID = #xF7F50740>
52 ;;; Why is this happening? --luis
54 (mapc (lambda (x) (pushnew x rtest
::*expected-failures
*))
55 '(foreign-globals.ref.char foreign-globals.get-var-pointer
.1
56 foreign-globals.get-var-pointer
.2 foreign-globals.symbol-name
57 foreign-globals.read-only
.1 ))
59 (deftest foreign-globals.ref.char
63 (deftest foreign-globals.ref.unsigned-char
67 (deftest foreign-globals.ref.short
71 (deftest foreign-globals.ref.unsigned-short
75 (deftest foreign-globals.ref.int
79 (deftest foreign-globals.ref.unsigned-int
83 (deftest foreign-globals.ref.long
87 (deftest foreign-globals.ref.unsigned-long
91 (deftest foreign-globals.ref.float
95 (deftest foreign-globals.ref.double
99 (deftest foreign-globals.ref.pointer
100 (null-pointer-p *var-pointer
*)
103 (deftest foreign-globals.ref.string
105 "Hello, foreign world!")
107 #+openmcl
(push 'foreign-globals.set.long-long rtest
::*expected-failures
*)
109 (deftest foreign-globals.ref.long-long
111 -
9223372036854775807)
113 (deftest foreign-globals.ref.unsigned-long-long
114 *var-unsigned-long-long
*
115 18446744073709551615)
117 ;; The *.set.* tests restore the old values so that the *.ref.*
118 ;; don't fail when re-run.
119 (defmacro with-old-value-restored
((place) &body body
)
120 (let ((old (gensym)))
121 `(let ((,old
,place
))
124 (setq ,place
,old
)))))
126 (deftest foreign-globals.set.int
127 (with-old-value-restored (*var-int
*)
132 (deftest foreign-globals.set.string
133 (with-old-value-restored (*var-string
*)
134 (setq *var-string
* "Ehxosxangxo")
137 ;; free the string we just allocated
138 (foreign-free (mem-ref (get-var-pointer '*var-string
*) :pointer
))))
141 (deftest foreign-globals.set.long-long
142 (with-old-value-restored (*var-long-long
*)
143 (setq *var-long-long
* -
9223000000000005808)
145 -
9223000000000005808)
147 (deftest foreign-globals.get-var-pointer
.1
148 (pointerp (get-var-pointer '*char-var
*))
151 (deftest foreign-globals.get-var-pointer
.2
152 (mem-ref (get-var-pointer '*char-var
*) :char
)
157 (defcvar "UPPERCASEINT1" :int
)
158 (defcvar "UPPER_CASE_INT1" :int
)
159 (defcvar "MiXeDCaSeInT1" :int
)
160 (defcvar "MiXeD_CaSe_InT1" :int
)
162 (deftest foreign-globals.ref.uppercaseint1
166 (deftest foreign-globals.ref.upper-case-int1
170 (deftest foreign-globals.ref.mixedcaseint1
174 (deftest foreign-globals.ref.mixed-case-int1
178 (when (string= (symbol-name 'nil
) "NIL")
179 (let ((*readtable
* (copy-readtable)))
180 (setf (readtable-case *readtable
*) :invert
)
181 (eval (read-from-string "(defcvar \"UPPERCASEINT2\" :int)"))
182 (eval (read-from-string "(defcvar \"UPPER_CASE_INT2\" :int)"))
183 (eval (read-from-string "(defcvar \"MiXeDCaSeInT2\" :int)"))
184 (eval (read-from-string "(defcvar \"MiXeD_CaSe_InT2\" :int)"))
185 (setf (readtable-case *readtable
*) :preserve
)
186 (eval (read-from-string "(DEFCVAR \"UPPERCASEINT3\" :INT)"))
187 (eval (read-from-string "(DEFCVAR \"UPPER_CASE_INT3\" :INT)"))
188 (eval (read-from-string "(DEFCVAR \"MiXeDCaSeInT3\" :INT)"))
189 (eval (read-from-string "(DEFCVAR \"MiXeD_CaSe_InT3\" :INT)"))))
192 ;;; EVAL gets rid of SBCL's unreachable code warnings.
193 (when (string= (symbol-name (eval nil
)) "nil")
194 (let ((*readtable
* (copy-readtable)))
195 (setf (readtable-case *readtable
*) :invert
)
196 (eval (read-from-string "(DEFCVAR \"UPPERCASEINT2\" :INT)"))
197 (eval (read-from-string "(DEFCVAR \"UPPER_CASE_INT2\" :INT)"))
198 (eval (read-from-string "(DEFCVAR \"MiXeDCaSeInT2\" :INT)"))
199 (eval (read-from-string "(DEFCVAR \"MiXeD_CaSe_InT2\" :INT)"))
200 (setf (readtable-case *readtable
*) :downcase
)
201 (eval (read-from-string "(defcvar \"UPPERCASEINT3\" :int)"))
202 (eval (read-from-string "(defcvar \"UPPER_CASE_INT3\" :int)"))
203 (eval (read-from-string "(defcvar \"MiXeDCaSeInT3\" :int)"))
204 (eval (read-from-string "(defcvar \"MiXeD_CaSe_InT3\" :int)"))))
206 (deftest foreign-globals.ref.uppercaseint2
210 (deftest foreign-globals.ref.upper-case-int2
214 (deftest foreign-globals.ref.mixedcaseint2
218 (deftest foreign-globals.ref.mixed-case-int2
222 (deftest foreign-globals.ref.uppercaseint3
226 (deftest foreign-globals.ref.upper-case-int3
230 (deftest foreign-globals.ref.mixedcaseint3
234 (deftest foreign-globals.ref.mixed-case-int3
239 ;;; gracefully accept symbols in defcvar
241 (defcvar *var-char
* :char
)
242 (defcvar var-char
:char
)
244 (deftest foreign-globals.symbol-name
245 (values *var-char
* var-char
)
250 #-cffi-sys
::flat-namespace
252 (deftest foreign-globals.namespace
.1
254 (mem-ref (foreign-symbol-pointer "var_char" :library
'libtest
) :char
)
255 (foreign-symbol-pointer "var_char" :library
'libtest2
))
258 (deftest foreign-globals.namespace
.2
260 (mem-ref (foreign-symbol-pointer "ns_var" :library
'libtest
) :boolean
)
261 (mem-ref (foreign-symbol-pointer "ns_var" :library
'libtest2
) :boolean
))
264 ;; For its "default" module, Lispworks seems to cache lookups from
265 ;; the newest module tried. If a lookup happens to have failed
266 ;; subsequent lookups will fail even the symbol exists in other
267 ;; modules. So this test fails.
269 (pushnew 'foreign-globals.namespace
.3 regression-test
::*expected-failures
*)
271 (deftest foreign-globals.namespace
.3
273 (foreign-symbol-pointer "var_char" :library
'libtest2
)
274 (mem-ref (foreign-symbol-pointer "var_char") :char
))
277 (defcvar ("ns_var" *ns-var1
* :library libtest
) :boolean
)
278 (defcvar ("ns_var" *ns-var2
* :library libtest2
) :boolean
)
280 (deftest foreign-globals.namespace
.4
281 (values *ns-var1
* *ns-var2
*)
286 (defcvar ("var_char" *var-char-ro
* :read-only t
) :char
289 (deftest foreign-globals.read-only
.1
290 (values *var-char-ro
*
291 (ignore-errors (setf *var-char-ro
* 12)))
294 (deftest defcvar.docstring
295 (documentation '*var-char-ro
* 'variable
)
300 ;;; RT: FOREIGN-SYMBOL-POINTER shouldn't signal an error when passed
301 ;;; an undefined variable.
302 (deftest foreign-globals.undefined
.1
303 (foreign-symbol-pointer "surely-undefined?")
306 (deftest foreign-globals.error
.1
307 (handler-case (foreign-symbol-pointer 'not-a-string
)