1 (defpackage "SB-POSIX-TESTS"
2 (:use "COMMON-LISP" "SB-RT"))
4 (in-package "SB-POSIX-TESTS")
6 (defvar *test-directory*
7 (ensure-directories-exist
8 (merge-pathnames (make-pathname :directory '(:relative "test-lab"))
9 (make-pathname :directory
10 (pathname-directory *load-truename*)))))
12 (defvar *current-directory* *default-pathname-defaults*)
14 (defvar *this-file* *load-truename*)
16 (eval-when (:compile-toplevel :load-toplevel)
17 (defconstant +mode-rwx-all+ (logior sb-posix::s-irusr sb-posix::s-iwusr sb-posix::s-ixusr
18 sb-posix::s-irgrp sb-posix::s-iwgrp sb-posix::s-ixgrp
19 sb-posix::s-iroth sb-posix::s-iwoth sb-posix::s-ixoth)))
22 (sb-posix:chdir *test-directory*)
26 (sb-posix:chdir (namestring *test-directory*))
34 (sb-posix:chdir #p"/")
38 (sb-posix:chdir *current-directory*)
41 (deftest chdir.error.1
42 (let ((dne (make-pathname :directory '(:relative "chdir.does-not-exist"))))
44 (sb-posix:chdir (merge-pathnames dne *test-directory*))
45 (sb-posix:syscall-error (c)
46 (sb-posix:syscall-errno c))))
49 (deftest chdir.error.2
51 (sb-posix:chdir *this-file*)
52 (sb-posix:syscall-error (c)
53 (sb-posix:syscall-errno c)))
57 (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.1"))))
59 (sb-posix:mkdir (merge-pathnames dne *test-directory*) 0)
60 ;; FIXME: no delete-directory in CL, but using our own operators
61 ;; is probably not ideal
62 (ignore-errors (sb-posix:rmdir (merge-pathnames dne *test-directory*)))))
66 (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.2"))))
68 (sb-posix:mkdir (namestring (merge-pathnames dne *test-directory*)) 0)
69 (ignore-errors (sb-posix:rmdir (merge-pathnames dne *test-directory*)))))
72 (deftest mkdir.error.1
74 (sb-posix:mkdir *test-directory* 0)
75 (sb-posix:syscall-error (c)
76 (sb-posix:syscall-errno c)))
79 (deftest mkdir.error.2
81 (sb-posix:mkdir "/" 0)
82 (sb-posix:syscall-error (c)
83 (sb-posix:syscall-errno c)))
84 #-bsd #.sb-posix::eexist
85 #+bsd #.sb-posix::eisdir)
87 (deftest mkdir.error.3
89 (sb-posix:mkdir "/almost-certainly-does-not-exist" 0)
90 (sb-posix:syscall-error (c)
91 (sb-posix:syscall-errno c)))
95 (let ((dne (make-pathname :directory '(:relative "rmdir.does-not-exist.1"))))
96 (ensure-directories-exist (merge-pathnames dne *test-directory*))
97 (sb-posix:rmdir (merge-pathnames dne *test-directory*)))
101 (let ((dne (make-pathname :directory '(:relative "rmdir.does-not-exist.2"))))
102 (ensure-directories-exist (merge-pathnames dne *test-directory*))
103 (sb-posix:rmdir (namestring (merge-pathnames dne *test-directory*))))
106 (deftest rmdir.error.1
107 (let ((dne (make-pathname :directory '(:relative "rmdir.dne.error.1"))))
109 (sb-posix:rmdir (merge-pathnames dne *test-directory*))
110 (sb-posix:syscall-error (c)
111 (sb-posix:syscall-errno c))))
114 (deftest rmdir.error.2
116 (sb-posix:rmdir *this-file*)
117 (sb-posix:syscall-error (c)
118 (sb-posix:syscall-errno c)))
121 #-sunos ; Apparently gives EINVAL on SunOS 8, which doesn't make sense
122 (deftest rmdir.error.3
125 (sb-posix:syscall-error (c)
126 (sb-posix:syscall-errno c)))
127 #-bsd #.sb-posix::ebusy
128 #+bsd #.sb-posix::eisdir)
130 (deftest rmdir.error.4
131 (let* ((dir (ensure-directories-exist
133 (make-pathname :directory '(:relative "rmdir.error.4"))
135 (file (make-pathname :name "foo" :defaults dir)))
136 (with-open-file (s file :direction :output)
137 (write "" :stream s))
140 (sb-posix:syscall-error (c)
143 (let ((errno (sb-posix:syscall-errno c)))
144 ;; documented by POSIX
145 (or (= errno sb-posix::eexist) (= errno sb-posix::enotempty))))))
148 (deftest rmdir.error.5
149 (let* ((dir (merge-pathnames
150 (make-pathname :directory '(:relative "rmdir.error.5"))
152 (dir2 (merge-pathnames
153 (make-pathname :directory '(:relative "unremovable"))
155 (sb-posix:mkdir dir +mode-rwx-all+)
156 (sb-posix:mkdir dir2 +mode-rwx-all+)
157 (sb-posix:chmod dir 0)
159 (sb-posix:rmdir dir2)
160 (sb-posix:syscall-error (c)
161 (sb-posix:chmod dir (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
162 (sb-posix:rmdir dir2)
164 (sb-posix:syscall-errno c))))
168 (let* ((stat (sb-posix:stat *test-directory*))
169 (mode (sb-posix::stat-mode stat)))
170 ;; FIXME: Ugly ::s everywhere
171 (logand mode (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec)))
172 #.(logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
175 (let* ((stat (sb-posix:stat "/"))
176 (mode (sb-posix::stat-mode stat)))
177 ;; it's logically possible for / to be writeable by others... but
178 ;; if it is, either someone is playing with strange security
179 ;; modules or they want to know about it anyway.
180 (logand mode sb-posix::s-iwoth))
184 (let* ((now (get-universal-time))
185 ;; FIXME: (encode-universal-time 00 00 00 01 01 1970)
186 (unix-now (- now 2208988800))
187 (stat (sb-posix:stat *test-directory*))
188 (atime (sb-posix::stat-atime stat)))
189 ;; FIXME: breaks if mounted noatime :-(
190 (< (- atime unix-now) 10))
193 ;;; FIXME: add tests for carrying a stat structure around in the
194 ;;; optional argument to SB-POSIX:STAT
196 (deftest stat.error.1
197 (handler-case (sb-posix:stat "")
198 (sb-posix:syscall-error (c)
199 (sb-posix:syscall-errno c)))
202 (deftest stat.error.2
203 (let* ((dir (merge-pathnames
204 (make-pathname :directory '(:relative "stat.error.2"))
206 (file (merge-pathnames
207 (make-pathname :name "unstatable")
209 (sb-posix:mkdir dir +mode-rwx-all+)
210 (with-open-file (s file :direction :output)
211 (write "" :stream s))
212 (sb-posix:chmod dir 0)
215 (sb-posix:syscall-error (c)
216 (sb-posix:chmod dir (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
217 (sb-posix:unlink file)
219 (sb-posix:syscall-errno c))))
223 (defmacro with-stat-mode ((mode pathname) &body body)
224 (let ((stat (gensym)))
225 `(let* ((,stat (sb-posix:stat ,pathname))
226 (,mode (sb-posix::stat-mode ,stat)))
229 (defmacro with-lstat-mode ((mode pathname) &body body)
230 (let ((stat (gensym)))
231 `(let* ((,stat (sb-posix:lstat ,pathname))
232 (,mode (sb-posix::stat-mode ,stat)))
236 (with-stat-mode (mode *test-directory*)
237 (sb-posix:s-isreg mode))
241 (with-stat-mode (mode *test-directory*)
242 (sb-posix:s-isdir mode))
246 (with-stat-mode (mode *test-directory*)
247 (sb-posix:s-ischr mode))
251 (with-stat-mode (mode *test-directory*)
252 (sb-posix:s-isblk mode))
256 (with-stat-mode (mode *test-directory*)
257 (sb-posix:s-isfifo mode))
261 (with-stat-mode (mode *test-directory*)
262 (sb-posix:s-issock mode))
266 (let ((link-pathname (make-pathname :name "stat-mode.7"
267 :defaults *test-directory*)))
270 (sb-posix:symlink *test-directory* link-pathname)
271 (with-lstat-mode (mode link-pathname)
272 (sb-posix:s-islnk mode)))
273 (ignore-errors (sb-posix:unlink link-pathname))))
277 (let ((pathname (make-pathname :name "stat-mode.8"
278 :defaults *test-directory*)))
281 (with-open-file (out pathname :direction :output)
282 (write-line "test" out))
283 (with-stat-mode (mode pathname)
284 (sb-posix:s-isreg mode)))
285 (ignore-errors (delete-file pathname))))
288 ;;; see comment in filename's designator definition, in macros.lisp
289 (deftest filename-designator.1
290 (let ((file (format nil "~A/[foo].txt" (namestring *test-directory*))))
291 ;; creat() with a string as argument
292 (sb-posix:creat file 0)
293 ;; if this test fails, it will probably be with
294 ;; "System call error 2 (No such file or directory)"
295 (let ((*default-pathname-defaults* *test-directory*))
296 (sb-posix:unlink (car (directory "*.txt")))))