0.8.6.7:
[sbcl.git] / contrib / sb-posix / posix-tests.lisp
1 (defpackage "SB-POSIX-TESTS"
2   (:use "COMMON-LISP" "SB-RT"))
3
4 (in-package "SB-POSIX-TESTS")
5
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*)))))
11
12 (defvar *current-directory* *default-pathname-defaults*)
13
14 (defvar *this-file* *load-truename*)
15
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)))
20 \f
21 (deftest chdir.1
22   (sb-posix:chdir *test-directory*)
23   0)
24
25 (deftest chdir.2
26   (sb-posix:chdir (namestring *test-directory*))
27   0)
28
29 (deftest chdir.3
30   (sb-posix:chdir "/")
31   0)
32
33 (deftest chdir.4
34   (sb-posix:chdir #p"/")
35   0)
36
37 (deftest chdir.5
38   (sb-posix:chdir *current-directory*)
39   0)
40
41 (deftest chdir.error.1
42   (let ((dne (make-pathname :directory '(:relative "chdir.does-not-exist"))))
43     (handler-case
44         (sb-posix:chdir (merge-pathnames dne *test-directory*))
45       (sb-posix:syscall-error (c)
46         (sb-posix:syscall-errno c))))
47   #.sb-posix::enoent)
48
49 (deftest chdir.error.2
50   (handler-case
51       (sb-posix:chdir *this-file*)
52     (sb-posix:syscall-error (c)
53       (sb-posix:syscall-errno c)))
54   #.sb-posix::enotdir)
55 \f
56 (deftest mkdir.1
57   (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.1"))))
58     (unwind-protect
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*)))))
63   0)
64
65 (deftest mkdir.2
66   (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.2"))))
67     (unwind-protect
68          (sb-posix:mkdir (namestring (merge-pathnames dne *test-directory*)) 0)
69       (ignore-errors (sb-posix:rmdir (merge-pathnames dne *test-directory*)))))
70   0)
71
72 (deftest mkdir.error.1
73   (handler-case
74       (sb-posix:mkdir *test-directory* 0)
75     (sb-posix:syscall-error (c)
76       (sb-posix:syscall-errno c)))
77   #.sb-posix::eexist)
78
79 (deftest mkdir.error.2
80   (handler-case
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)
86
87 (deftest mkdir.error.3
88   (handler-case
89       (sb-posix:mkdir "/almost-certainly-does-not-exist" 0)
90     (sb-posix:syscall-error (c)
91       (sb-posix:syscall-errno c)))
92   #.sb-posix::eacces)
93 \f
94 (deftest rmdir.1
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*)))
98   0)
99
100 (deftest rmdir.2
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*))))
104   0)
105
106 (deftest rmdir.error.1
107   (let ((dne (make-pathname :directory '(:relative "rmdir.dne.error.1"))))
108     (handler-case 
109         (sb-posix:rmdir (merge-pathnames dne *test-directory*))
110       (sb-posix:syscall-error (c)
111         (sb-posix:syscall-errno c))))
112   #.sb-posix::enoent)
113
114 (deftest rmdir.error.2
115   (handler-case
116       (sb-posix:rmdir *this-file*)
117     (sb-posix:syscall-error (c)
118       (sb-posix:syscall-errno c)))
119   #.sb-posix::enotdir)
120
121 #-sunos ; Apparently gives EINVAL on SunOS 8, which doesn't make sense
122 (deftest rmdir.error.3
123   (handler-case
124       (sb-posix:rmdir "/")
125     (sb-posix:syscall-error (c)
126       (sb-posix:syscall-errno c)))
127   #-bsd #.sb-posix::ebusy
128   #+bsd #.sb-posix::eisdir)
129
130 (deftest rmdir.error.4
131   (let* ((dir (ensure-directories-exist
132                (merge-pathnames
133                 (make-pathname :directory '(:relative "rmdir.error.4"))
134                 *test-directory*)))
135          (file (make-pathname :name "foo" :defaults dir)))
136     (with-open-file (s file :direction :output)
137       (write "" :stream s))
138     (handler-case
139         (sb-posix:rmdir dir)
140       (sb-posix:syscall-error (c)
141         (delete-file file)
142         (sb-posix:rmdir dir)
143         (let ((errno (sb-posix:syscall-errno c)))
144           ;; documented by POSIX
145           (or (= errno sb-posix::eexist) (= errno sb-posix::enotempty))))))
146   t)
147
148 (deftest rmdir.error.5
149   (let* ((dir (merge-pathnames
150                (make-pathname :directory '(:relative "rmdir.error.5"))
151                *test-directory*))
152          (dir2 (merge-pathnames
153                 (make-pathname :directory '(:relative "unremovable"))
154                 dir)))
155     (sb-posix:mkdir dir +mode-rwx-all+)
156     (sb-posix:mkdir dir2 +mode-rwx-all+)
157     (sb-posix:chmod dir 0)
158     (handler-case
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)
163         (sb-posix:rmdir dir)
164         (sb-posix:syscall-errno c))))
165   #.sb-posix::eacces)
166 \f
167 (deftest stat.1
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))
173
174 (deftest stat.2
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))
181   0)
182     
183 (deftest stat.3
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))
191   t)
192
193 ;;; FIXME: add tests for carrying a stat structure around in the
194 ;;; optional argument to SB-POSIX:STAT
195
196 (deftest stat.error.1
197   (handler-case (sb-posix:stat "")
198     (sb-posix:syscall-error (c)
199       (sb-posix:syscall-errno c)))
200   #.sb-posix::enoent)
201
202 (deftest stat.error.2
203   (let* ((dir (merge-pathnames
204                (make-pathname :directory '(:relative "stat.error.2"))
205                *test-directory*))
206          (file (merge-pathnames
207                 (make-pathname :name "unstatable")
208                 dir)))
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)
213     (handler-case
214         (sb-posix:stat file)
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)
218         (sb-posix:rmdir dir)
219         (sb-posix:syscall-errno c))))
220   #.sb-posix::eacces)
221 \f
222 ;;; stat-mode tests
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)))
227        ,@body)))
228
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)))
233        ,@body)))
234
235 (deftest stat-mode.1
236   (with-stat-mode (mode *test-directory*)
237     (sb-posix:s-isreg mode))
238   nil)
239
240 (deftest stat-mode.2
241   (with-stat-mode (mode *test-directory*)
242     (sb-posix:s-isdir mode))
243   t)
244
245 (deftest stat-mode.3
246   (with-stat-mode (mode *test-directory*)
247     (sb-posix:s-ischr mode))
248   nil)
249
250 (deftest stat-mode.4
251   (with-stat-mode (mode *test-directory*)
252     (sb-posix:s-isblk mode))
253   nil)
254
255 (deftest stat-mode.5
256   (with-stat-mode (mode *test-directory*)
257     (sb-posix:s-isfifo mode))
258   nil)
259
260 (deftest stat-mode.6
261   (with-stat-mode (mode *test-directory*)
262     (sb-posix:s-issock mode))
263   nil)
264
265 (deftest stat-mode.7
266   (let ((link-pathname (make-pathname :name "stat-mode.7"
267                                       :defaults *test-directory*)))
268     (unwind-protect
269          (progn
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))))
274   t)
275
276 (deftest stat-mode.8
277   (let ((pathname (make-pathname :name "stat-mode.8"
278                                  :defaults *test-directory*)))
279     (unwind-protect
280          (progn
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))))
286   t)
287 \f
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")))))
297   0)
298