1 ;;;; miscellaneous tests of package-related stuff
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; While most of SBCL is derived from the CMU CL system, the test
7 ;;;; files (like this one) were written from scratch after the fork
10 ;;;; This software is in the public domain and is provided with
11 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
12 ;;;; more information.
14 (defun set-bad-package (x)
15 (declare (optimize (safety 0)))
18 (with-test (:name
:set-bad-package
)
19 (set-bad-package :cl-user
)
20 (assert-error (intern "FRED") type-error
))
22 (with-test (:name
:packages-sanely-nicknamed
)
23 (dolist (p (list-all-packages))
24 (let* ((nicks (package-nicknames p
))
25 (check (remove-duplicates nicks
:test
'string
=)))
26 (assert (= (length check
) (length nicks
))))))
29 (defvar *foo
* (find-package (coerce "FOO" 'base-string
)))
30 (rename-package "FOO" (make-array 0 :element-type nil
))
31 (assert (eq *foo
* (find-package "")))
32 (assert (delete-package ""))
35 (defvar *baz
* (rename-package "BAR" "BAZ"))
36 (assert (eq *baz
* (find-package "BAZ")))
37 (assert (delete-package *baz
*))
41 (package-error (c) (princ c
))
42 (:no-error
(&rest args
) (error "(EXPORT :FOO) returned ~S" args
)))
45 (assert (shadow #\a :foo
))
47 (defpackage :PACKAGE-DESIGNATOR-1
(:use
#.
(find-package :cl
)))
49 (defpackage :PACKAGE-DESIGNATOR-2
50 (:import-from
#.
(find-package :cl
) "+"))
52 (defpackage "EXAMPLE-INDIRECT"
53 (:import-from
"CL" "+"))
55 (defpackage "EXAMPLE-PACKAGE"
57 (:shadowing-import-from
"CL" "CAAR")
59 (:import-from
"CL" "CDR")
60 (:import-from
"EXAMPLE-INDIRECT" "+")
61 (:export
"CAR" "CDR" "EXAMPLE"))
63 (flet ((check-symbol (name expected-status expected-home-name
)
64 (multiple-value-bind (symbol status
)
65 (find-symbol name
"EXAMPLE-PACKAGE")
66 (let ((home (symbol-package symbol
))
67 (expected-home (find-package expected-home-name
)))
68 (assert (eql home expected-home
))
69 (assert (eql status expected-status
))))))
70 (check-symbol "CAR" :external
"EXAMPLE-PACKAGE")
71 (check-symbol "CDR" :external
"CL")
72 (check-symbol "EXAMPLE" :external
"EXAMPLE-PACKAGE")
73 (check-symbol "CAAR" :internal
"CL")
74 (check-symbol "+" :internal
"CL")
75 (check-symbol "CDDR" nil
"CL"))
77 (defpackage "TEST-ORIGINAL" (:nicknames
"A-NICKNAME"))
79 (assert-error (defpackage "A-NICKNAME"))
81 (assert (eql (find-package "A-NICKNAME")
82 (find-package "TEST-ORIGINAL")))
85 (defun sym (package name
)
86 (let ((package (or (find-package package
) package
)))
87 (multiple-value-bind (symbol status
)
88 (find-symbol name package
)
90 (package name symbol status
)
91 "No symbol with name ~A in ~S." name package symbol status
)
92 (values symbol status
))))
94 (defmacro with-name-conflict-resolution
((symbol &key restarted
)
96 "Resolves potential name conflict condition arising from FORM.
98 The conflict is resolved in favour of SYMBOL, a form which must
101 If RESTARTED is a symbol, it is bound for the BODY forms and set to T
102 if a restart was invoked."
103 (check-type restarted symbol
"a binding name")
104 (let ((%symbol
(copy-symbol 'symbol
)))
105 `(let (,@(when restarted
`((,restarted
)))
108 ((sb-ext:name-conflict
110 ,@(when restarted
`((setf ,restarted t
)))
111 (assert (member ,%symbol
(sb-ext:name-conflict-symbols condition
)))
112 (invoke-restart 'sb-ext
:resolve-conflict
,%symbol
))))
116 (defmacro with-packages
(specs &body forms
)
117 (let ((names (mapcar #'car specs
)))
120 (delete-packages ',names
)
121 ,@(mapcar (lambda (spec)
122 `(defpackage ,@spec
))
125 (delete-packages ',names
))))
127 (defun delete-packages (names)
129 (ignore-errors (delete-package p
))))
134 (with-test (:name
:use-package
.1)
135 (with-packages (("FOO" (:export
"SYM"))
136 ("BAR" (:export
"SYM"))
138 (with-name-conflict-resolution ((sym "BAR" "SYM") :restarted restartedp
)
139 (use-package '("FOO" "BAR") "BAZ")
141 (is (eq (sym "BAR" "SYM")
142 (sym "BAZ" "SYM"))))))
144 (with-test (:name
:use-package
.2)
145 (with-packages (("FOO" (:export
"SYM"))
146 ("BAZ" (:use
) (:intern
"SYM")))
147 (with-name-conflict-resolution ((sym "FOO" "SYM") :restarted restartedp
)
148 (use-package "FOO" "BAZ")
150 (is (eq (sym "FOO" "SYM")
151 (sym "BAZ" "SYM"))))))
153 (with-test (:name
:use-package
.2a
)
154 (with-packages (("FOO" (:export
"SYM"))
155 ("BAZ" (:use
) (:intern
"SYM")))
156 (with-name-conflict-resolution ((sym "BAZ" "SYM") :restarted restartedp
)
157 (use-package "FOO" "BAZ")
159 (is (equal (list (sym "BAZ" "SYM") :internal
)
160 (multiple-value-list (sym "BAZ" "SYM")))))))
162 (with-test (:name
:use-package-conflict-set
:fails-on
:sbcl
)
163 (with-packages (("FOO" (:export
"SYM"))
164 ("QUX" (:export
"SYM"))
165 ("BAR" (:intern
"SYM"))
166 ("BAZ" (:use
) (:import-from
"BAR" "SYM")))
167 (let ((conflict-set))
170 ((sb-ext:name-conflict
172 (setf conflict-set
(copy-list
173 (sb-ext:name-conflict-symbols condition
)))
175 (use-package '("FOO" "QUX") "BAZ")))
177 (sort conflict-set
#'string
<
178 :key
(lambda (symbol)
179 (package-name (symbol-package symbol
)))))
180 (is (equal (list (sym "BAR" "SYM") (sym "FOO" "SYM") (sym "QUX" "SYM"))
184 (with-test (:name
:export
.1)
185 (with-packages (("FOO" (:intern
"SYM"))
186 ("BAR" (:export
"SYM"))
187 ("BAZ" (:use
"FOO" "BAR")))
188 (with-name-conflict-resolution ((sym "FOO" "SYM") :restarted restartedp
)
189 (export (sym "FOO" "SYM") "FOO")
191 (is (eq (sym "FOO" "SYM")
192 (sym "BAZ" "SYM"))))))
194 (with-test (:name
:export
.1a
)
195 (with-packages (("FOO" (:intern
"SYM"))
196 ("BAR" (:export
"SYM"))
197 ("BAZ" (:use
"FOO" "BAR")))
198 (with-name-conflict-resolution ((sym "BAR" "SYM") :restarted restartedp
)
199 (export (sym "FOO" "SYM") "FOO")
201 (is (eq (sym "BAR" "SYM")
202 (sym "BAZ" "SYM"))))))
204 (with-test (:name
:export.ensure-exported
)
205 (with-packages (("FOO" (:intern
"SYM"))
206 ("BAR" (:export
"SYM"))
207 ("BAZ" (:use
"FOO" "BAR") (:IMPORT-FROM
"BAR" "SYM")))
208 (with-name-conflict-resolution ((sym "FOO" "SYM") :restarted restartedp
)
209 (export (sym "FOO" "SYM") "FOO")
211 (is (equal (list (sym "FOO" "SYM") :external
)
212 (multiple-value-list (sym "FOO" "SYM"))))
213 (is (eq (sym "FOO" "SYM")
214 (sym "BAZ" "SYM"))))))
216 (with-test (:name
:export
.3.intern
)
217 (with-packages (("FOO" (:intern
"SYM"))
218 ("BAZ" (:use
"FOO") (:intern
"SYM")))
219 (with-name-conflict-resolution ((sym "FOO" "SYM") :restarted restartedp
)
220 (export (sym "FOO" "SYM") "FOO")
222 (is (eq (sym "FOO" "SYM")
223 (sym "BAZ" "SYM"))))))
225 (with-test (:name
:export
.3a.intern
)
226 (with-packages (("FOO" (:intern
"SYM"))
227 ("BAZ" (:use
"FOO") (:intern
"SYM")))
228 (with-name-conflict-resolution ((sym "BAZ" "SYM") :restarted restartedp
)
229 (export (sym "FOO" "SYM") "FOO")
231 (is (equal (list (sym "BAZ" "SYM") :internal
)
232 (multiple-value-list (sym "BAZ" "SYM")))))))
235 (with-test (:name
:import-nil
.1)
236 (with-packages (("FOO" (:use
) (:intern
"NIL"))
237 ("BAZ" (:use
) (:intern
"NIL")))
238 (with-name-conflict-resolution ((sym "FOO" "NIL") :restarted restartedp
)
239 (import (list (sym "FOO" "NIL")) "BAZ")
241 (is (eq (sym "FOO" "NIL")
242 (sym "BAZ" "NIL"))))))
244 (with-test (:name
:import-nil
.2)
245 (with-packages (("BAZ" (:use
) (:intern
"NIL")))
246 (with-name-conflict-resolution ('CL
:NIL
:restarted restartedp
)
247 (import '(CL:NIL
) "BAZ")
250 (sym "BAZ" "NIL"))))))
252 (with-test (:name
:import-single-conflict
:fails-on
:sbcl
)
253 (with-packages (("FOO" (:export
"NIL"))
254 ("BAR" (:export
"NIL"))
256 (let ((conflict-sets '()))
258 ((sb-ext:name-conflict
260 (push (copy-list (sb-ext:name-conflict-symbols condition
))
262 (invoke-restart 'sb-ext
:resolve-conflict
'CL
:NIL
))))
263 (import (list 'CL
:NIL
(sym "FOO" "NIL") (sym "BAR" "NIL")) "BAZ"))
264 (is (eql 1 (length conflict-sets
)))
265 (is (eql 3 (length (first conflict-sets
)))))))
267 ;;; Make sure that resolving a name-conflict in IMPORT doesn't leave
268 ;;; multiple symbols of the same name in the package (this particular
269 ;;; scenario found in 1.0.38.9, but clearly a longstanding issue).
270 (with-test (:name
:import-conflict-resolution
)
271 (with-packages (("FOO" (:export
"NIL"))
273 (with-name-conflict-resolution ((sym "FOO" "NIL"))
274 (import (list 'CL
:NIL
(sym "FOO" "NIL")) "BAR"))
275 (do-symbols (sym "BAR")
276 (assert (eq sym
(sym "FOO" "NIL"))))))
279 (with-test (:name
:unintern
.1)
280 (with-packages (("FOO" (:export
"SYM"))
281 ("BAR" (:export
"SYM"))
282 ("BAZ" (:use
"FOO" "BAR") (:shadow
"SYM")))
283 (with-name-conflict-resolution ((sym "FOO" "SYM") :restarted restartedp
)
284 (unintern (sym "BAZ" "SYM") "BAZ")
286 (is (eq (sym "FOO" "SYM")
287 (sym "BAZ" "SYM"))))))
289 (with-test (:name
:unintern
.2)
290 (with-packages (("FOO" (:intern
"SYM")))
291 (unintern :sym
"FOO")
292 (assert (find-symbol "SYM" "FOO"))))
294 ;;; WITH-PACKAGE-ITERATOR error signalling had problems
295 (with-test (:name
:with-package-iterator.error
)
299 (eval '(with-package-iterator (sym :cl-user
:foo
)
302 ((and simple-condition program-error
) (c)
303 (assert (equal (list :foo
) (simple-condition-format-arguments c
)))
306 ;; X3J13 writeup HASH-TABLE-PACKAGE-GENERATORS says
307 ;; "An argument of NIL is treated as an empty list of packages."
308 ;; This used to fail with "NIL does not name a package"
309 (with-test (:name
:with-package-iterator-nil-list
)
310 (with-package-iterator (iter '() :internal
)
311 (assert (null (iter)))))
313 ;;; MAKE-PACKAGE error in another thread blocking FIND-PACKAGE & FIND-SYMBOL
314 (with-test (:name
:bug-511072
:skipped-on
'(not :sb-thread
))
315 (let* ((p (make-package :bug-511072
))
316 (sem1 (sb-thread:make-semaphore
))
317 (sem2 (sb-thread:make-semaphore
))
318 (t2 (make-join-thread (lambda ()
319 (handler-bind ((error (lambda (c)
320 (sb-thread:signal-semaphore sem1
)
321 (sb-thread:wait-on-semaphore sem2
)
323 (make-package :bug-511072
))))))
324 (declare (ignore p t2
))
325 (sb-thread:wait-on-semaphore sem1
)
327 (assert (eq 'cons
(read-from-string "CL:CONS"))))
328 (sb-thread:signal-semaphore sem2
)))
330 (defmacro handling
((condition restart-name
) form
)
331 `(handler-bind ((,condition
(lambda (c)
333 (invoke-restart ',restart-name
))))
337 (with-test (:name
:quick-name-conflict-resolution-import
)
341 (setf p1
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-IMPORT.1")
342 p2
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-IMPORT.2"))
344 (handling (name-conflict sb-impl
::dont-import-it
)
345 (import (intern "FOO" p2
) p1
))
346 (assert (not (eq (intern "FOO" p1
) (intern "FOO" p2
))))
347 (handling (name-conflict sb-impl
::shadowing-import-it
)
348 (import (intern "FOO" p2
) p1
))
349 (assert (eq (intern "FOO" p1
) (intern "FOO" p2
))))
350 (when p1
(delete-package p1
))
351 (when p2
(delete-package p2
)))))
353 (with-test (:name
:quick-name-conflict-resolution-export
.1)
357 (setf p1
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-EXPORT.1a")
358 p2
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-EXPORT.2a"))
361 (handling (name-conflict sb-impl
::keep-old
)
362 (export (intern "FOO" p2
) p2
))
363 (assert (not (eq (intern "FOO" p1
) (intern "FOO" p2
)))))
364 (when p1
(delete-package p1
))
365 (when p2
(delete-package p2
)))))
367 (with-test (:name
:quick-name-conflict-resolution-export
.2)
371 (setf p1
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-EXPORT.1b")
372 p2
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-EXPORT.2b"))
375 (handling (name-conflict sb-impl
::take-new
)
376 (export (intern "FOO" p2
) p2
))
377 (assert (eq (intern "FOO" p1
) (intern "FOO" p2
))))
378 (when p1
(delete-package p1
))
379 (when p2
(delete-package p2
)))))
381 (with-test (:name
:quick-name-conflict-resolution-use-package
.1)
385 (setf p1
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-USE-PACKAGE.1a")
386 p2
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-USE-PACKAGE.2a"))
389 (export (intern "FOO" p2
) p2
)
390 (export (intern "BAR" p2
) p2
)
391 (handling (name-conflict sb-impl
::keep-old
)
393 (assert (not (eq (intern "FOO" p1
) (intern "FOO" p2
))))
394 (assert (not (eq (intern "BAR" p1
) (intern "BAR" p2
)))))
395 (when p1
(delete-package p1
))
396 (when p2
(delete-package p2
)))))
398 (with-test (:name
:quick-name-conflict-resolution-use-package
.2)
402 (setf p1
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-USE-PACKAGE.1b")
403 p2
(make-package "QUICK-NAME-CONFLICT-RESOLUTION-USE-PACKAGE.2b"))
406 (export (intern "FOO" p2
) p2
)
407 (export (intern "BAR" p2
) p2
)
408 (handling (name-conflict sb-impl
::take-new
)
410 (assert (eq (intern "FOO" p1
) (intern "FOO" p2
)))
411 (assert (eq (intern "BAR" p1
) (intern "BAR" p2
))))
412 (when p1
(delete-package p1
))
413 (when p2
(delete-package p2
)))))
415 (with-test (:name
(:package-at-variance-restarts
:shadow
))
417 (*on-package-variance
* '(:error t
)))
420 (setf p
(eval `(defpackage :package-at-variance-restarts
.1
423 (handling (sb-kernel::package-at-variance-error sb-impl
::keep-them
)
424 (eval `(defpackage :package-at-variance-restarts
.1
426 (assert (not (eq 'cl
:cons
(intern "CONS" p
))))
427 (handling (sb-kernel::package-at-variance-error sb-impl
::drop-them
)
428 (eval `(defpackage :package-at-variance-restarts
.1
430 (assert (eq 'cl
:cons
(intern "CONS" p
))))
431 (when p
(delete-package p
)))))
433 (with-test (:name
(:package-at-variance-restarts
:use
))
435 (*on-package-variance
* '(:error t
)))
438 (setf p
(eval `(defpackage :package-at-variance-restarts
.2
440 (handling (sb-kernel::package-at-variance-error sb-impl
::keep-them
)
441 (eval `(defpackage :package-at-variance-restarts
.2
443 (assert (eq 'cl
:cons
(intern "CONS" p
)))
444 (handling (sb-kernel::package-at-variance-error sb-impl
::drop-them
)
445 (eval `(defpackage :package-at-variance-restarts
.2
447 (assert (not (eq 'cl
:cons
(intern "CONS" p
)))))
448 (when p
(delete-package p
)))))
450 (with-test (:name
(:package-at-variance-restarts
:export
))
452 (*on-package-variance
* '(:error t
)))
455 (setf p
(eval `(defpackage :package-at-variance-restarts
.4
457 (handling (sb-kernel::package-at-variance-error sb-impl
::keep-them
)
458 (eval `(defpackage :package-at-variance-restarts
.4)))
459 (assert (eq :external
(nth-value 1 (find-symbol "FOO" p
))))
460 (handling (sb-kernel::package-at-variance-error sb-impl
::drop-them
)
461 (eval `(defpackage :package-at-variance-restarts
.4)))
462 (assert (eq :internal
(nth-value 1 (find-symbol "FOO" p
)))))
463 (when p
(delete-package p
)))))
465 (with-test (:name
(:package-at-variance-restarts
:implement
))
467 (*on-package-variance
* '(:error t
)))
470 (setf p
(eval `(defpackage :package-at-variance-restarts
.5
471 (:implement
:sb-int
))))
472 (handling (sb-kernel::package-at-variance-error sb-impl
::keep-them
)
473 (eval `(defpackage :package-at-variance-restarts
.5)))
474 (assert (member p
(package-implemented-by-list :sb-int
)))
475 (handling (sb-kernel::package-at-variance-error sb-impl
::drop-them
)
476 (eval `(defpackage :package-at-variance-restarts
.5)))
477 (assert (not (member p
(package-implemented-by-list :sb-int
)))))
478 (when p
(delete-package p
)))))
480 (with-test (:name
(:delete-package
:implementation-package
))
484 (setf p1
(make-package "DELETE-PACKAGE/IMPLEMENTATION-PACKAGE.1")
485 p2
(make-package "DELETE-PACKAGE/IMPLEMENTATION-PACKAGE.2"))
486 (add-implementation-package p2 p1
)
487 (assert (= 1 (length (package-implemented-by-list p1
))))
489 (assert (= 0 (length (package-implemented-by-list p1
)))))
490 (when p1
(delete-package p1
))
491 (when p2
(delete-package p2
)))))
493 (with-test (:name
(:delete-package
:implementated-package
))
497 (setf p1
(make-package "DELETE-PACKAGE/IMPLEMENTED-PACKAGE.1")
498 p2
(make-package "DELETE-PACKAGE/IMPLEMENTED-PACKAGE.2"))
499 (add-implementation-package p2 p1
)
500 (assert (= 1 (length (package-implements-list p2
))))
502 (assert (= 0 (length (package-implements-list p2
)))))
503 (when p1
(delete-package p1
))
504 (when p2
(delete-package p2
)))))
506 (with-test (:name
:package-local-nicknames
)
508 (without-package-locks
509 (when (find-package :package-local-nicknames-test-1
)
510 (delete-package :package-local-nicknames-test-1
))
511 (when (find-package :package-local-nicknames-test-2
)
512 (delete-package :package-local-nicknames-test-2
)))
513 (eval `(defpackage :package-local-nicknames-test-1
514 (:local-nicknames
(:l
:cl
) (:sb
:sb-ext
))))
515 (eval `(defpackage :package-local-nicknames-test-2
518 (let ((alist (package-local-nicknames :package-local-nicknames-test-1
)))
519 (assert (equal (cons "L" (find-package "CL")) (assoc "L" alist
:test
'string
=)))
520 (assert (equal (cons "SB" (find-package "SB-EXT")) (assoc "SB" alist
:test
'string
=)))
521 (assert (eql 2 (length alist
))))
523 (let ((*package
* (find-package :package-local-nicknames-test-1
)))
524 (let ((cons0 (read-from-string "L:CONS"))
525 (exit0 (read-from-string "SB:EXIT"))
526 (cons1 (find-symbol "CONS" :l
))
527 (exit1 (find-symbol "EXIT" :sb
))
528 (cl (find-package :l
))
529 (sb (find-package :sb
)))
530 (assert (eq 'cons cons0
))
531 (assert (eq 'cons cons1
))
532 (assert (equal "L:CONS" (prin1-to-string cons0
)))
533 (assert (eq 'sb-ext
:exit exit0
))
534 (assert (eq 'sb-ext
:exit exit1
))
535 (assert (equal "SB:EXIT" (prin1-to-string exit0
)))
536 (assert (eq cl
(find-package :common-lisp
)))
537 (assert (eq sb
(find-package :sb-ext
)))))
538 ;; Can't add same name twice for different global names.
541 (add-package-local-nickname :l
:package-local-nicknames-test-2
542 :package-local-nicknames-test-1
)
545 ;; But same name twice is OK.
546 (add-package-local-nickname :l
:cl
:package-local-nicknames-test-1
)
548 (assert (remove-package-local-nickname :l
:package-local-nicknames-test-1
))
549 (let ((*package
* (find-package :package-local-nicknames-test-1
)))
550 (let ((exit0 (read-from-string "SB:EXIT"))
551 (exit1 (find-symbol "EXIT" :sb
))
552 (sb (find-package :sb
)))
553 (assert (eq 'sb-ext
:exit exit0
))
554 (assert (eq 'sb-ext
:exit exit1
))
555 (assert (equal "SB:EXIT" (prin1-to-string exit0
)))
556 (assert (eq sb
(find-package :sb-ext
)))
557 (assert (not (find-package :l
)))))
558 ;; Adding back as another package.
559 (assert (eq (find-package :package-local-nicknames-test-1
)
560 (add-package-local-nickname :l
:package-local-nicknames-test-2
561 :package-local-nicknames-test-1
)))
562 (let ((*package
* (find-package :package-local-nicknames-test-1
)))
563 (let ((cons0 (read-from-string "L:CONS"))
564 (exit0 (read-from-string "SB:EXIT"))
565 (cons1 (find-symbol "CONS" :l
))
566 (exit1 (find-symbol "EXIT" :sb
))
567 (cl (find-package :l
))
568 (sb (find-package :sb
)))
569 (assert (eq cons0 cons1
))
570 (assert (not (eq 'cons cons0
)))
571 (assert (eq (find-symbol "CONS" :package-local-nicknames-test-2
)
573 (assert (equal "L:CONS" (prin1-to-string cons0
)))
574 (assert (eq 'sb-ext
:exit exit0
))
575 (assert (eq 'sb-ext
:exit exit1
))
576 (assert (equal "SB:EXIT" (prin1-to-string exit0
)))
577 (assert (eq cl
(find-package :package-local-nicknames-test-2
)))
578 (assert (eq sb
(find-package :sb-ext
)))))
579 ;; Interaction with package locks.
580 (lock-package :package-local-nicknames-test-1
)
581 (assert (eq :package-oopsie
583 (add-package-local-nickname :c
:sb-c
:package-local-nicknames-test-1
)
584 (package-lock-violation ()
586 (assert (eq :package-oopsie
588 (remove-package-local-nickname :l
:package-local-nicknames-test-1
)
589 (package-lock-violation ()
591 (unlock-package :package-local-nicknames-test-1
)
592 (add-package-local-nickname :c
:sb-c
:package-local-nicknames-test-1
)
593 (remove-package-local-nickname :l
:package-local-nicknames-test-1
))
595 (defmacro with-tmp-packages
(bindings &body body
)
596 `(let ,(mapcar #'car bindings
)
599 (setf ,@(apply #'append bindings
))
601 ,@(mapcar (lambda (p)
602 `(when ,p
(delete-package ,p
)))
603 (mapcar #'car bindings
)))))
605 (with-test (:name
(:delete-package
:locally-nicknames-others
))
606 (with-tmp-packages ((p1 (make-package "LOCALLY-NICKNAMES-OTHERS"))
607 (p2 (make-package "LOCALLY-NICKNAMED-BY-OTHERS")))
608 (add-package-local-nickname :foo p2 p1
)
609 (assert (equal (list p1
) (package-locally-nicknamed-by-list p2
)))
611 (assert (not (package-locally-nicknamed-by-list p2
)))))
613 (with-test (:name
(:delete-package
:locally-nicknamed-by-others
))
614 (with-tmp-packages ((p1 (make-package "LOCALLY-NICKNAMES-OTHERS"))
615 (p2 (make-package "LOCALLY-NICKNAMED-BY-OTHERS")))
616 (add-package-local-nickname :foo p2 p1
)
617 (assert (package-local-nicknames p1
))
619 (assert (not (package-local-nicknames p1
)))))
621 (with-test (:name
:own-name-as-local-nickname
)
622 (with-tmp-packages ((p1 (make-package "OWN-NAME-AS-NICKNAME1"))
623 (p2 (make-package "OWN-NAME-AS-NICKNAME2")))
626 (add-package-local-nickname :own-name-as-nickname1 p2 p1
)
629 (handler-bind ((error #'continue
))
630 (add-package-local-nickname :own-name-as-nickname1 p2 p1
))
631 (assert (eq (intern "FOO" p2
)
632 (let ((*package
* p1
))
633 (intern "FOO" :own-name-as-nickname1
))))))
635 (with-test (:name
:own-nickname-as-local-nickname
)
636 (with-tmp-packages ((p1 (make-package "OWN-NICKNAME-AS-NICKNAME1"
637 :nicknames
'("OWN-NICKNAME")))
638 (p2 (make-package "OWN-NICKNAME-AS-NICKNAME2")))
641 (add-package-local-nickname :own-nickname p2 p1
)
644 (handler-bind ((error #'continue
))
645 (add-package-local-nickname :own-nickname p2 p1
))
646 (assert (eq (intern "FOO" p2
)
647 (let ((*package
* p1
))
648 (intern "FOO" :own-nickname
))))))
650 (with-test (:name
:delete-package-restart
)
654 ((sb-kernel:simple-package-error
658 (delete-package (gensym)))))
660 (assert (not result
))))
662 ;; WITH-PACKAGE-ITERATOR isn't well-exercised by tests (though LOOP uses it)
663 ;; so here's a basic correctness test with some complications involving
664 ;; shadowing symbols.
665 (make-package "P1" :use
'("SB-FORMAT"))
667 (export 'p1
::foo
'p1
)
668 (shadow "FORMAT-ERROR" 'p1
)
669 (make-package "A" :use
'("SB-FORMAT" "P1" "P2"))
670 (shadow '("PROG2" "FOO") 'a
)
672 (export 'p2
::(foo bar baz
) 'p2
)
673 (export 'a
::goodfun
'a
)
675 (with-test (:name
:with-package-iterator
)
676 (let ((tests '((:internal
) (:external
) (:inherited
)
677 (:internal
:inherited
)
678 (:internal
:external
)
679 (:external
:inherited
)
680 (:internal
:external
:inherited
)))
682 '(;; symbols visible in A
683 (a::prog2
:internal
"A")
684 (a::foo
:internal
"A")
685 (a:goodfun
:external
"A")
686 (p2:bar
:inherited
"A")
687 (p2:baz
:inherited
"A")
688 (sb-format:%compiler-walk-format-string
:inherited
"A")
689 (sb-format:format-error
:inherited
"A")
691 (p1:foo
:external
"P1")
692 (p1::format-error
:internal
"P1")
693 (sb-format:%compiler-walk-format-string
:inherited
"P1")
695 (p2::blah
:internal
"P2")
696 (p2:foo
:external
"P2")
697 (p2:bar
:external
"P2")
698 (p2:baz
:external
"P2"))))
699 ;; Compile a new function to test each combination of
700 ;; accessibility-kind since the macro doesn't eval them.
701 (dolist (access tests
)
702 ; (print `(testing ,access))
706 (with-package-iterator (iter '(p1 a p2
) ,@access
)
709 (multiple-value-bind (foundp sym access pkg
) (iter)
711 (push (list sym access
(package-name pkg
)) res
)
714 (let ((answer (funcall f
))
715 (expect (remove-if-not (lambda (x) (member (second x
) access
))
717 ;; exactly as many results as expected
718 (assert (equal (length answer
) (length expect
)))
719 ;; each result is right
720 (assert (equal (length (intersection answer expect
:test
#'equal
))
721 (length expect
))))))))
723 ;; Assert that changes in size of a package-hashtable's symbol vector
724 ;; do not cause WITH-PACKAGE-ITERATOR to crash. The vector shouldn't grow,
725 ;; because it is not permitted to INTERN new symbols, but it can shrink
726 ;; because it is expressly permitted to UNINTERN the current symbol.
727 ;; (In fact we allow INTERN, but that's beside the point)
728 (with-test (:name
:with-package-iterator-and-mutation
)
729 (flet ((table-size (pkg)
730 (length (sb-impl::package-hashtable-cells
731 (sb-impl::package-internal-symbols pkg
)))))
732 (let* ((p (make-package (string (gensym))))
733 (initial-table-size (table-size p
))
735 '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m")))
738 (let ((grown-table-size (table-size p
)))
739 (assert (> grown-table-size initial-table-size
))
741 (with-package-iterator (iter p
:internal
)
742 (loop (multiple-value-bind (foundp sym
) (iter)
748 (assert (= n
(length strings
)))
749 ;; while we're at it, assert that calling the iterator
750 ;; a couple more times returns nothing.
752 (assert (not (iter))))))
753 (let ((shrunk-table-size (table-size p
)))
754 (assert (< shrunk-table-size grown-table-size
)))))))
757 (with-test (:name
:do-symbols-block-scope
)
760 (do-symbols (s (or (find-package "FROB") (return nil
)))
764 (with-test (:name
:export-inaccessible-lookalike
)
767 (export (intern "A" "E2") 'e2
)
768 (multiple-value-bind (answer condition
)
769 (ignore-errors (export (intern "A" "E1") 'e2
))
770 (assert (and (not answer
)
771 (and (typep condition
'sb-kernel
:simple-package-error
)
772 (search "not accessible"
773 (simple-condition-format-control condition
)))))))
775 ;; Concurrent FIND-SYMBOL was adversely affected by package rehash.
776 ;; It's slightly difficult to show that this is fixed, because this
777 ;; test only sometimes failed prior to the fix. Now it never fails though.
778 (with-test (:name
:concurrent-find-symbol
:skipped-on
'(not :sb-thread
))
779 (let ((pkg (make-package (gensym)))
784 (let ((s (string (gensym "FRED"))))
788 (push (sb-thread:make-thread
792 (dotimes (i 10 n-missing
)
794 (unless (find-symbol name pkg
)
795 (incf n-missing
)))))))
798 ;; Interning new symbols can't cause the pre-determined
799 ;; 50 names to transiently disappear.
800 (let ((s (make-string 3))
801 (alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"))
802 (dotimes (i (expt 32 3))
803 (setf (char s
0) (char alphabet
(ldb (byte 5 10) i
))
804 (char s
1) (char alphabet
(ldb (byte 5 5) i
))
805 (char s
2) (char alphabet
(ldb (byte 5 0) i
)))
807 (let ((tot-missing 0))
808 (dolist (thread threads
(assert (zerop tot-missing
)))
809 (incf tot-missing
(sb-thread:join-thread thread
))))))