0.8.5.27:
[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 \f
16 (deftest chdir.1
17   (sb-posix:chdir *test-directory*)
18   0)
19
20 (deftest chdir.2
21   (sb-posix:chdir (namestring *test-directory*))
22   0)
23
24 (deftest chdir.3
25   (sb-posix:chdir "/")
26   0)
27
28 (deftest chdir.4
29   (sb-posix:chdir #p"/")
30   0)
31
32 (deftest chdir.5
33   (sb-posix:chdir *current-directory*)
34   0)
35
36 (deftest chdir.error.1
37   (let ((dne (make-pathname :directory '(:relative "chdir.does-not-exist"))))
38     (handler-case
39         (sb-posix:chdir (merge-pathnames dne *test-directory*))
40       (sb-posix:syscall-error (c)
41         (sb-posix:syscall-errno c))))
42   #.sb-posix::enoent)
43
44 (deftest chdir.error.2
45   (handler-case
46       (sb-posix:chdir *this-file*)
47     (sb-posix:syscall-error (c)
48       (sb-posix:syscall-errno c)))
49   #.sb-posix::enotdir)
50 \f
51 (deftest mkdir.1
52   (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.1"))))
53     (unwind-protect
54          (sb-posix:mkdir (merge-pathnames dne *test-directory*) 0)
55       ;; FIXME: no delete-directory in CL, but using our own operators
56       ;; is probably not ideal
57       (ignore-errors (sb-posix:rmdir (merge-pathnames dne *test-directory*)))))
58   0)
59
60 (deftest mkdir.2
61   (let ((dne (make-pathname :directory '(:relative "mkdir.does-not-exist.2"))))
62     (unwind-protect
63          (sb-posix:mkdir (namestring (merge-pathnames dne *test-directory*)) 0)
64       (ignore-errors (sb-posix:rmdir (merge-pathnames dne *test-directory*)))))
65   0)
66
67 (deftest mkdir.error.1
68   (handler-case
69       (sb-posix:mkdir *test-directory* 0)
70     (sb-posix:syscall-error (c)
71       (sb-posix:syscall-errno c)))
72   #.sb-posix::eexist)
73
74 (deftest mkdir.error.2
75   (handler-case
76       (sb-posix:mkdir "/" 0)
77     (sb-posix:syscall-error (c)
78       (sb-posix:syscall-errno c)))
79   #.sb-posix::eexist)
80
81 (deftest mkdir.error.3
82   (handler-case
83       (sb-posix:mkdir "/almost-certainly-does-not-exist" 0)
84     (sb-posix:syscall-error (c)
85       (sb-posix:syscall-errno c)))
86   #.sb-posix::eacces)
87 \f
88 (deftest rmdir.1
89   (let ((dne (make-pathname :directory '(:relative "rmdir.does-not-exist.1"))))
90     (ensure-directories-exist (merge-pathnames dne *test-directory*))
91     (sb-posix:rmdir (merge-pathnames dne *test-directory*)))
92   0)
93
94 (deftest rmdir.2
95   (let ((dne (make-pathname :directory '(:relative "rmdir.does-not-exist.2"))))
96     (ensure-directories-exist (merge-pathnames dne *test-directory*))
97     (sb-posix:rmdir (namestring (merge-pathnames dne *test-directory*))))
98   0)
99
100 (deftest rmdir.error.1
101   (let ((dne (make-pathname :directory '(:relative "rmdir.dne.error.1"))))
102     (handler-case 
103         (sb-posix:rmdir (merge-pathnames dne *test-directory*))
104       (sb-posix:syscall-error (c)
105         (sb-posix:syscall-errno c))))
106   #.sb-posix::enoent)
107
108 (deftest rmdir.error.2
109   (handler-case
110       (sb-posix:rmdir *this-file*)
111     (sb-posix:syscall-error (c)
112       (sb-posix:syscall-errno c)))
113   #.sb-posix::enotdir)
114
115 #-sunos ; Apparently gives EINVAL on SunOS 8, which doesn't make sense
116 (deftest rmdir.error.3
117   (handler-case
118       (sb-posix:rmdir "/")
119     (sb-posix:syscall-error (c)
120       (sb-posix:syscall-errno c)))
121   #.sb-posix::ebusy)
122
123 (deftest rmdir.error.4
124   (let* ((dir (ensure-directories-exist
125                (merge-pathnames
126                 (make-pathname :directory '(:relative "rmdir.error.4"))
127                 *test-directory*)))
128          (file (make-pathname :name "foo" :defaults dir)))
129     (with-open-file (s file :direction :output)
130       (write "" :stream s))
131     (handler-case
132         (sb-posix:rmdir dir)
133       (sb-posix:syscall-error (c)
134         (delete-file file)
135         (sb-posix:rmdir dir)
136         (let ((errno (sb-posix:syscall-errno c)))
137           ;; documented by POSIX
138           (or (= errno sb-posix::eexist) (= errno sb-posix::enotempty))))))
139   t)
140
141 (deftest rmdir.error.5
142   (let* ((dir (merge-pathnames
143                (make-pathname :directory '(:relative "rmdir.error.5"))
144                *test-directory*))
145          (dir2 (merge-pathnames
146                 (make-pathname :directory '(:relative "unremovable"))
147                 dir)))
148     (sb-posix:mkdir dir #xffffffff)
149     (sb-posix:mkdir dir2 #xffffffff)
150     (sb-posix:chmod dir 0)
151     (handler-case
152         (sb-posix:rmdir dir2)
153       (sb-posix:syscall-error (c)
154         (sb-posix:chmod dir (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
155         (sb-posix:rmdir dir2)
156         (sb-posix:rmdir dir)
157         (sb-posix:syscall-errno c))))
158   #.sb-posix::eacces)
159 \f
160 (deftest stat.1
161   (let* ((stat (sb-posix:stat *test-directory*))
162          (mode (sb-posix::stat-mode stat)))
163     ;; FIXME: Ugly ::s everywhere
164     (logand mode (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec)))
165   #.(logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
166
167 (deftest stat.2
168   (let* ((stat (sb-posix:stat "/"))
169          (mode (sb-posix::stat-mode stat)))
170     ;; it's logically possible for / to be writeable by others... but
171     ;; if it is, either someone is playing with strange security
172     ;; modules or they want to know about it anyway.
173     (logand mode sb-posix::s-iwoth))
174   0)
175     
176 (deftest stat.3
177   (let* ((now (get-universal-time))
178          ;; FIXME: (encode-universal-time 00 00 00 01 01 1970)
179          (unix-now (- now 2208988800))
180          (stat (sb-posix:stat *test-directory*))
181          (atime (sb-posix::stat-atime stat)))
182     ;; FIXME: breaks if mounted noatime :-(
183     (< (- atime unix-now) 10))
184   t)
185
186 ;;; FIXME: add tests for carrying a stat structure around in the
187 ;;; optional argument to SB-POSIX:STAT
188
189 (deftest stat.error.1
190   (handler-case (sb-posix:stat "")
191     (sb-posix:syscall-error (c)
192       (sb-posix:syscall-errno c)))
193   #.sb-posix::enoent)
194
195 (deftest stat.error.2
196   (let* ((dir (merge-pathnames
197                (make-pathname :directory '(:relative "stat.error.2"))
198                *test-directory*))
199          (file (merge-pathnames
200                 (make-pathname :name "unstatable")
201                 dir)))
202     (sb-posix:mkdir dir #xffffffff)
203     (with-open-file (s file :direction :output)
204       (write "" :stream s))
205     (sb-posix:chmod dir 0)
206     (handler-case
207         (sb-posix:stat file)
208       (sb-posix:syscall-error (c)
209         (sb-posix:chmod dir (logior sb-posix::s-iread sb-posix::s-iwrite sb-posix::s-iexec))
210         (sb-posix:unlink file)
211         (sb-posix:rmdir dir)
212         (sb-posix:syscall-errno c))))
213   #.sb-posix::eacces)
214 \f
215 ;;; stat-mode tests
216 (defmacro with-stat-mode ((mode pathname) &body body)
217   (let ((stat (gensym)))
218     `(let* ((,stat (sb-posix:stat ,pathname))
219             (,mode (sb-posix::stat-mode ,stat)))
220        ,@body)))
221
222 (defmacro with-lstat-mode ((mode pathname) &body body)
223   (let ((stat (gensym)))
224     `(let* ((,stat (sb-posix:lstat ,pathname))
225             (,mode (sb-posix::stat-mode ,stat)))
226        ,@body)))
227
228 (deftest stat-mode.1
229   (with-stat-mode (mode *test-directory*)
230     (sb-posix:s-isreg mode))
231   nil)
232
233 (deftest stat-mode.2
234   (with-stat-mode (mode *test-directory*)
235     (sb-posix:s-isdir mode))
236   t)
237
238 (deftest stat-mode.3
239   (with-stat-mode (mode *test-directory*)
240     (sb-posix:s-ischr mode))
241   nil)
242
243 (deftest stat-mode.4
244   (with-stat-mode (mode *test-directory*)
245     (sb-posix:s-isblk mode))
246   nil)
247
248 (deftest stat-mode.5
249   (with-stat-mode (mode *test-directory*)
250     (sb-posix:s-isfifo mode))
251   nil)
252
253 (deftest stat-mode.6
254   (with-stat-mode (mode *test-directory*)
255     (sb-posix:s-issock mode))
256   nil)
257
258 (deftest stat-mode.7
259   (let ((link-pathname (make-pathname :name "stat-mode.7"
260                                       :defaults *test-directory*)))
261     (unwind-protect
262          (progn
263            (sb-posix:symlink *test-directory* link-pathname)
264            (with-lstat-mode (mode link-pathname)
265              (sb-posix:s-islnk mode)))
266       (ignore-errors (sb-posix:unlink link-pathname))))
267   t)
268
269 (deftest stat-mode.8
270   (let ((pathname (make-pathname :name "stat-mode.8"
271                                  :defaults *test-directory*)))
272     (unwind-protect
273          (progn
274            (with-open-file (out pathname :direction :output)
275              (write-line "test" out))
276            (with-stat-mode (mode pathname)
277              (sb-posix:s-isreg mode)))
278       (ignore-errors (delete-file pathname))))
279   t)
280 \f
281 ;;; see comment in filename's designator definition, in macros.lisp
282 (deftest filename-designator.1
283   (let ((file (format nil "~A/[foo].txt" (namestring *test-directory*))))
284     ;; creat() with a string as argument
285     (sb-posix:creat file 0)
286     ;; if this test fails, it will probably be with
287     ;; "System call error 2 (No such file or directory)"
288     (let ((*default-pathname-defaults* *test-directory*))
289       (sb-posix:unlink (car (directory "*.txt")))))
290   0)
291