0.9.12.10:
[sbcl.git] / tests / external-format.impure.lisp
index d4e9cbd..ec676c8 100644 (file)
@@ -15,9 +15,6 @@
 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
 ;;;; more information.
 
-#-sb-unicode
-(sb-ext:quit :unix-status 104)
-
 (defmacro do-external-formats ((xf &optional result) &body body)
   (let ((nxf (gensym)))
     `(dolist (,nxf sb-impl::*external-formats* ,result)
       (loop for character across standard-characters
             do (assert (eql (read-char s) character))))))
 
+(delete-file "external-format-test.txt")
+#-sb-unicode
+(progn
+  (test-util:report-test-status)
+  (sb-ext:quit :unix-status 104))
+
 ;;; Test UTF-8 writing and reading of 1, 2, 3 and 4 octet characters with
 ;;; all possible offsets. Tests for buffer edge bugs. fd-stream buffers are
 ;;; 4096 wide.
     (assert (equal (read-line s nil s) "AB"))
     (assert (equal (read-line s nil s) s))))
 
+;;; And again with more data to account for buffering (this was briefly)
+;;; broken in early 0.9.6.
+(with-open-file (s "external-format-test.txt" :direction :output
+                 :if-exists :supersede :element-type '(unsigned-byte 8))
+  (let ((a (make-array 50
+                       :element-type '(unsigned-byte 64)
+                       :initial-contents (map 'list #'char-code
+                                              "1234567890123456789012345678901234567890123456789."))))
+    (setf (aref a 49) (char-code #\Newline))
+    (dotimes (i 40)
+      (write-sequence a s))
+    (write-byte #xe0 s)
+    (dotimes (i 40)
+      (write-sequence a s))))
+(with-test (:name (:character-decode-large :attempt-resync))
+  (with-open-file (s "external-format-test.txt" :direction :input
+                     :external-format :utf-8)
+    (handler-bind
+        ((sb-int:character-decoding-error #'(lambda (decoding-error)
+                                              (declare (ignore decoding-error))
+                                              (invoke-restart
+                                               'sb-int:attempt-resync)))
+         ;; The failure mode is an infinite loop, add a timeout to detetct it.
+         (sb-ext:timeout (lambda () (error "Timeout"))))
+      (sb-ext:with-timeout 5
+        (dotimes (i 80)
+          (assert (equal (read-line s nil s)
+                         "1234567890123456789012345678901234567890123456789")))))))
+
+(with-test (:name (:character-decode-large :force-end-of-file)
+            :fails-on :sbcl)
+  (error "We can't reliably test this due to WITH-TIMEOUT race condition")
+  ;; This test will currently fail. But sometimes it will fail in
+  ;; ungracefully due to the WITH-TIMEOUT race mentioned above. This
+  ;; rightfully confuses some people, so we'll skip running the code
+  ;; for now. -- JES, 2006-01-27
+  #+nil
+  (with-open-file (s "external-format-test.txt" :direction :input
+                     :external-format :utf-8)
+    (handler-bind
+        ((sb-int:character-decoding-error #'(lambda (decoding-error)
+                                              (declare (ignore decoding-error))
+                                              (invoke-restart
+                                               'sb-int:force-end-of-file)))
+         ;; The failure mode is an infinite loop, add a timeout to detetct it.
+         (sb-ext:timeout (lambda () (error "Timeout"))))
+      (sb-ext:with-timeout 5
+        (dotimes (i 80)
+          (assert (equal (read-line s nil s)
+                         "1234567890123456789012345678901234567890123456789")))
+        (assert (equal (read-line s nil s) s))))))
+
 ;;; Test character encode restarts.
 (with-open-file (s "external-format-test.txt" :direction :output
                  :if-exists :supersede :external-format :latin-1)
       (when p
         (delete-file p)))))
 
+\f
+;;;; KOI8-R external format
+(with-open-file (s "external-format-test.txt" :direction :output
+                 :if-exists :supersede :external-format :koi8-r)
+  (write-char (code-char #xB0) s)
+  (assert (eq
+           (handler-case
+               (progn
+                 (write-char (code-char #xBAAD) s)
+                 :bad)
+             (sb-int:character-encoding-error ()
+               :good))
+           :good)))
+(with-open-file (s "external-format-test.txt" :direction :input
+                 :element-type '(unsigned-byte 8))
+  (let ((byte (read-byte s)))
+    (assert (= (eval byte) #x9C))))
+(with-open-file (s "external-format-test.txt" :direction :input
+                 :external-format :koi8-r)
+  (let ((char (read-char s)))
+    (assert (= (char-code (eval char)) #xB0))))
 (delete-file "external-format-test.txt")
 
-(sb-ext:quit :unix-status 104)
+(let* ((koi8-r-codes (coerce '(240 210 201 215 197 212 33) '(vector (unsigned-byte 8))))
+       (uni-codes #(1055 1088 1080 1074 1077 1090 33))
+
+       (string (octets-to-string koi8-r-codes :external-format :koi8-r))
+       (uni-decoded (map 'vector #'char-code string)))
+  (assert (equalp (map 'vector #'char-code (octets-to-string koi8-r-codes :external-format :koi8-r))
+                  uni-codes))
+  (assert (equalp (string-to-octets (map 'string #'code-char uni-codes) :external-format :koi8-r)
+                  koi8-r-codes)))
+\f
+;;; tests of FILE-STRING-LENGTH
+(let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~"))
+  (do-external-formats (xf)
+    (with-open-file (s "external-format-test.txt" :direction :output
+                       :external-format xf)
+      (loop for x across standard-characters
+            for position = (file-position s)
+            for char-length = (file-string-length s x)
+            do (write-char x s)
+            do (assert (= (file-position s) (+ position char-length))))
+      (let ((position (file-position s))
+            (string-length (file-string-length s standard-characters)))
+        (write-string standard-characters s)
+        (assert (= (file-position s) (+ position string-length)))))
+    (delete-file "external-format-test.txt")))
+
+(let ((char-codes '(0 1 255 256 511 512 1023 1024 2047 2048 4095 4096
+                    8191 8192 16383 16384 32767 32768 65535 65536 131071
+                    131072 262143 262144)))
+  (with-open-file (s "external-format-test.txt" :direction :output
+                     :external-format :utf-8)
+    (dolist (code char-codes)
+      (let* ((char (code-char code))
+             (position (file-position s))
+             (char-length (file-string-length s char)))
+        (write-char char s)
+        (assert (= (file-position s) (+ position char-length)))))
+    (let* ((string (map 'string #'code-char char-codes))
+           (position (file-position s))
+           (string-length (file-string-length s string)))
+      (write-string string s)
+      (assert (= (file-position s) (+ position string-length))))))
+\f
+
+;;; See sbcl-devel "Subject: Bug in FILE-POSITION on UTF-8-encoded files"
+;;; by Lutz Euler on 2006-03-05 for more details.
+(with-test (:name (:file-position :utf-8)
+                  :fails-on :sbcl)
+  (let ((path "external-format-test.txt"))
+    (with-open-file (s path
+                       :direction :output
+                       :if-exists :supersede
+                       :element-type '(unsigned-byte 8))
+      ;; Write #\*, encoded in UTF-8, to the file.
+      (write-byte 42 s)
+      ;; Append #\adiaeresis, encoded in UTF-8, to the file.
+      (write-sequence '(195 164) s))
+    (with-open-file (s path :external-format :utf-8)
+      (read-char s)
+      (let ((pos (file-position s))
+            (char (read-char s)))
+        (format t "read character with code ~a successfully from file position ~a~%"
+                (char-code char) pos)
+        (file-position s pos)
+        (format t "set file position back to ~a, trying to read-char again~%" pos)
+        (let ((new-char (read-char s)))
+          (assert (char= char new-char)))))
+    (values)))
+
+;;;; success
\ No newline at end of file