0.8.2.7:
[sbcl.git] / contrib / sb-simple-streams / simple-stream-tests.lisp
index 735b154..010d0ab 100644 (file)
@@ -7,7 +7,7 @@
 (in-package #:sb-simple-streams-test)
 
 (defparameter *dumb-string*
-  "This file created by simple-stream-tests.lisp. Nothing to see here, move along.")
+  "This file was created by simple-stream-tests.lisp. Nothing to see here, move along.")
 
 (defparameter *test-path*
   (merge-pathnames (make-pathname :name nil :type nil :version nil)
 
 (eval-when (:load-toplevel) (ensure-directories-exist *test-path*))
 
+(defmacro with-test-file ((stream file &rest open-arguments
+                                  &key (delete-afterwards t)
+                                  initial-content
+                                  &allow-other-keys)
+                          &body body)
+  (remf open-arguments :delete-afterwards)
+  (remf open-arguments :initial-content)
+  (if initial-content
+      (let ((create-file-stream (gensym)))
+        `(progn
+           (with-open-file (,create-file-stream ,file :direction :output
+                                                :if-exists :supersede
+                                                :if-does-not-exist :create)
+             (write-sequence ,initial-content ,create-file-stream))
+           (unwind-protect
+                (with-open-file (,stream ,file ,@open-arguments)
+                  (progn ,@body))
+             ,(when delete-afterwards `(ignore-errors (delete-file ,file))))))
+      `(unwind-protect
+            (with-open-file (,stream ,file ,@open-arguments)
+              (progn ,@body))
+         ,(when delete-afterwards `(ignore-errors (delete-file ,file))))))
 
 
 (deftest create-file-1
@@ -25,7 +47,8 @@
         (with-open-stream (s (make-instance 'file-simple-stream
                                             :filename file
                                             :direction :output
-                                            :if-exists :overwrite))
+                                            :if-exists :overwrite
+                                            :if-does-not-exist :create))
           (string= (write-string *dumb-string* s) *dumb-string*))
       (delete-file file)))
   t)
 (deftest create-file-2
   ;; Create a file-simple-stream via :class argument to open, write data.
   (let ((file (merge-pathnames #p"test-data.txt" *test-path*)))
-    (prog1
-        (with-open-file (s file
-                           :class 'file-simple-stream
-                           :direction :output :if-exists :overwrite)
-           (string= (write-string *dumb-string* s) *dumb-string*))
-      (delete-file file)))
+    (with-test-file (s file :class 'file-simple-stream :direction :output
+                       :if-exists :overwrite :if-does-not-exist :create)
+      (string= (write-string *dumb-string* s) *dumb-string*)))
   t)
 
 (deftest create-read-file-1
   ;; Via file-simple-stream objects, write and then re-read data.
   (let ((result t)
         (file (merge-pathnames #p"test-data.txt" *test-path*)))
-    (with-open-stream (s (make-instance 'file-simple-stream
-                                        :filename file
-                                        :direction :output
-                                        :if-exists :overwrite))
+    (with-test-file (s file :class 'file-simple-stream :direction :output
+                       :if-exists :overwrite :if-does-not-exist :create
+                       :delete-afterwards nil)
       (write-line *dumb-string* s)
       (setf result (and result (string= (write-string *dumb-string* s)
                                         *dumb-string*))))
-    (with-open-stream (s (make-instance 'file-simple-stream
-                                        :filename file
-                                        :direction :input
-                                        :if-does-not-exist :error))
+
+    (with-test-file (s file :class 'file-simple-stream
+                       :direction :input :if-does-not-exist :error)
       ;; Check first line
       (multiple-value-bind (string missing-newline-p)
           (read-line s)
@@ -66,7 +84,6 @@
           (read-line s)
         (setf result (and result (string= string *dumb-string*)
                           missing-newline-p))))
-    (delete-file file)
     result)
   t)
 
   ;; Read data via a mapped-file-simple-stream object.
   (let ((result t)
         (file (merge-pathnames #p"test-data.txt" *test-path*)))
-    (with-open-file (s file
-                       :class 'file-simple-stream
-                       :direction :output :if-exists :overwrite)
-       (setf result (and result (string= (write-string *dumb-string* s)
-                                         *dumb-string*))))
-    (with-open-file (s file
-                       :class 'mapped-file-simple-stream
-                       :direction :input)
-       (setf result (and result (string= (read-line s) *dumb-string*))))
-    (delete-file file)
+    (with-test-file (s file :class 'mapped-file-simple-stream
+                       :direction :input :if-does-not-exist :error
+                       :initial-content *dumb-string*)
+      (setf result (and result (string= (read-line s) *dumb-string*))))
     result)
   t)
 
   ;; (single-channel simple-stream)
   (let* ((file (merge-pathnames #p"test-data.txt" *test-path*))
          (stream (make-instance 'file-simple-stream
-                                :filename file
-                                :direction :output))
+                                :filename file :direction :output
+                                :if-exists :overwrite
+                                :if-does-not-exist :create))
          (content (make-string (1+ (device-buffer-length stream))
                                :initial-element #\x)))
     (with-open-stream (s stream)
       (write-string content s))
-    (with-open-stream (s (make-instance 'file-simple-stream
-                                        :filename file
-                                        :direction :input))
-      (prog1 (string= content (read-line s))
-        (delete-file file))))
+    (with-test-file (s file :class 'file-simple-stream
+                       :direction :input :if-does-not-exist :error)
+      (string= content (read-line s))))
   t)
 
 (deftest write-read-large-dc-1
    (sb-bsd-sockets::connection-refused-error () t))
   t)
 
+
+(deftest file-position-1
+  ;; Test reading of file-position
+  (let* ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+    (with-test-file (s file :class 'file-simple-stream :direction :input
+                       :initial-content *dumb-string*)
+      (file-position s)))
+  0)
+
+;;; file-position-2 fails ONLY when called with
+;;; (asdf:oos 'asdf:test-op :sb-simple-streams)
+;;; TODO: Find out why
+#+nil
+(deftest file-position-2
+  ;; Test reading of file-position
+  (let* ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+    (with-test-file (s file :class 'file-simple-stream :direction :input
+                       :initial-content *dumb-string*)
+      (read-byte s)
+      (file-position s)))
+  1)
+
+(deftest file-position-3
+  ;; Test reading of file-position in the presence of unsaved data
+  (let* ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+    (with-test-file (s file :class 'file-simple-stream :direction :output
+                       :if-exists :supersede :if-does-not-exist :create)
+      (write-byte 50 s)
+      (file-position s)))
+  1)
+
+(deftest file-position-4
+    ;; Test file position when opening with :if-exists :append
+    (let ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+      (with-test-file (s file :class 'file-simple-stream :direction :io
+                         :if-exists :append :if-does-not-exist :create
+                         :initial-content "Foo")
+        (= (file-length s) (file-position s))))
+  T)
+
+(deftest write-read-unflushed-sc-1
+  ;; Write something into a single-channel stream and read it back
+  ;; without explicitly flushing the buffer in-between
+  (let* ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+    (with-test-file (s file :class 'file-simple-stream :direction :io
+                       :if-does-not-exist :create :if-exists :supersede)
+      (write-char #\x s)
+      (file-position s :start)
+      (read-char s)))
+  #\x)
+
+(deftest write-read-unflushed-sc-2
+  ;; Write something into a single-channel stream, try to read back too much
+  (handler-case
+   (let* ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+     (with-test-file (s file :class 'file-simple-stream :direction :io
+                        :if-does-not-exist :create :if-exists :supersede)
+       (write-char #\x s)
+       (file-position s :start)
+       (read-char s)
+       (read-char s))
+     nil)
+    (end-of-file () t))
+  t)
+
+(deftest write-read-unflushed-sc-3
+    (let ((file (merge-pathnames #p"test-data.txt" *test-path*))
+          (result t))
+      (with-test-file (s file :class 'file-simple-stream :direction :io
+                         :if-exists :overwrite :if-does-not-exist :create
+                         :initial-content *dumb-string*)
+        (setq result (and result (char= (read-char s) (char *dumb-string* 0))))
+        (setq result (and result (= (file-position s) 1)))
+        (let ((pos (file-position s)))
+          (write-char #\x s)
+          (file-position s pos)
+          (setq result (and result (char= (read-char s) #\x)))))
+      result)
+  t)
+
+(deftest write-read-unflushed-sc-4
+    ;; Test flushing of buffers
+    (let ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+      (with-test-file (s file :class 'file-simple-stream :direction :io
+                         :if-exists :overwrite :if-does-not-exist :create
+                         :initial-content "Foo"
+                         :delete-afterwards nil)
+        (read-char s)                   ; Fill the buffer.
+        (file-position s :start)        ; Change existing data.
+        (write-char #\X s)
+        (file-position s :end)          ; Extend file.
+        (write-char #\X s))
+      (with-test-file (s file :class 'file-simple-stream :direction :input
+                         :if-does-not-exist :error)
+        (read-line s)))
+  "XooX"
+  T)
+
+(deftest write-read-append-sc-1
+    ;; Test writing in the middle of a stream opened in append mode
+    (let ((file (merge-pathnames #p"test-data.txt" *test-path*)))
+      (with-test-file (s file :class 'file-simple-stream :direction :io
+                         :if-exists :append :if-does-not-exist :create
+                         :initial-content "Foo"
+                         :delete-afterwards nil)
+        (file-position s :start)        ; Jump to beginning.
+        (write-char #\X s)
+        (file-position s :end)          ; Extend file.
+        (write-char #\X s))
+      (with-test-file (s file :class 'file-simple-stream :direction :input
+                         :if-does-not-exist :error)
+        (read-line s)))
+  "XooX"
+  T)
+
+
+
+