X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Fexternal-format.impure.lisp;h=99e2bdafe3983af7e594ca8cd0014acc2084a1f3;hb=e7ef1082bd3e7f3851de9d90c5dbddf226a71382;hp=5a2b4cd04d75d94c5a6f690a1c9a97cbe753f42a;hpb=c1b609d072224eddf850a0e3f85e578c6919117f;p=sbcl.git diff --git a/tests/external-format.impure.lisp b/tests/external-format.impure.lisp index 5a2b4cd..99e2bda 100644 --- a/tests/external-format.impure.lisp +++ b/tests/external-format.impure.lisp @@ -21,23 +21,27 @@ (let ((,xf (first (first ,nxf)))) ,@body)))) +(defvar *test-path* "external-format-test.tmp") + (do-external-formats (xf) - (with-open-file (s "/dev/null" :direction :input :external-format xf) + (with-open-file (s #-win32 "/dev/null" #+win32 "nul" :direction :input :external-format xf) (assert (eq (read-char s nil s) s)))) ;;; Test standard character read-write equivalency over all external formats. (let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~")) (do-external-formats (xf) - (with-open-file (s "external-format-test.txt" :direction :output + (with-open-file (s *test-path* :direction :output :if-exists :supersede :external-format xf) (loop for character across standard-characters do (write-char character s))) - (with-open-file (s "external-format-test.txt" :direction :input + (with-open-file (s *test-path* :direction :input :external-format xf) (loop for character across standard-characters - do (assert (eql (read-char s) character)))))) + do (let ((got (read-char s))) + (unless (eql character got) + (error "wanted ~S, got ~S" character got))))))) -(delete-file "external-format-test.txt") +(delete-file *test-path*) #-sb-unicode (progn (test-util:report-test-status) @@ -49,28 +53,30 @@ (dotimes (width-1 4) (let ((character (code-char (elt '(1 #x81 #x801 #x10001) width-1)))) (dotimes (offset (+ width-1 1)) - (with-open-file (s "external-format-test.txt" :direction :output + (with-open-file (s *test-path* :direction :output :if-exists :supersede :external-format :utf-8) (dotimes (n offset) (write-char #\a s)) - (dotimes (n 4097) + (dotimes (n (+ 4 sb-impl::+bytes-per-buffer+)) (write-char character s))) - (with-open-file (s "external-format-test.txt" :direction :input + (with-open-file (s *test-path* :direction :input :external-format :utf-8) (dotimes (n offset) (assert (eql (read-char s) #\a))) - (dotimes (n 4097) - (assert (eql (read-char s) character))) + (dotimes (n (+ 4 sb-impl::+bytes-per-buffer+)) + (let ((got (read-char s))) + (unless (eql got character) + (error "wanted ~S, got ~S (~S)" character got n)))) (assert (eql (read-char s nil s) s)))))) ;;; Test character decode restarts. -(with-open-file (s "external-format-test.txt" :direction :output +(with-open-file (s *test-path* :direction :output :if-exists :supersede :element-type '(unsigned-byte 8)) (write-byte 65 s) (write-byte 66 s) (write-byte #xe0 s) (write-byte 67 s)) -(with-open-file (s "external-format-test.txt" :direction :input +(with-open-file (s *test-path* :direction :input :external-format :utf-8) (handler-bind ((sb-int:character-decoding-error #'(lambda (decoding-error) @@ -79,7 +85,7 @@ 'sb-int:attempt-resync)))) (assert (equal (read-line s nil s) "ABC")) (assert (equal (read-line s nil s) s)))) -(with-open-file (s "external-format-test.txt" :direction :input +(with-open-file (s *test-path* :direction :input :external-format :utf-8) (handler-bind ((sb-int:character-decoding-error #'(lambda (decoding-error) @@ -91,7 +97,7 @@ ;;; 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 +(with-open-file (s *test-path* :direction :output :if-exists :supersede :element-type '(unsigned-byte 8)) (let ((a (make-array 50 :element-type '(unsigned-byte 64) @@ -104,7 +110,7 @@ (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 + (with-open-file (s *test-path* :direction :input :external-format :utf-8) (handler-bind ((sb-int:character-decoding-error #'(lambda (decoding-error) @@ -117,9 +123,16 @@ (dotimes (i 80) (assert (equal (read-line s nil s) "1234567890123456789012345678901234567890123456789"))))))) + (with-test (:name (:character-decode-large :force-end-of-file) :fails-on :sbcl) - (with-open-file (s "external-format-test.txt" :direction :input + (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 *test-path* :direction :input :external-format :utf-8) (handler-bind ((sb-int:character-decoding-error #'(lambda (decoding-error) @@ -135,7 +148,7 @@ (assert (equal (read-line s nil s) s)))))) ;;; Test character encode restarts. -(with-open-file (s "external-format-test.txt" :direction :output +(with-open-file (s *test-path* :direction :output :if-exists :supersede :external-format :latin-1) (handler-bind ((sb-int:character-encoding-error #'(lambda (encoding-error) @@ -146,12 +159,12 @@ (write-char #\B s) (write-char (code-char 322) s) (write-char #\C s))) -(with-open-file (s "external-format-test.txt" :direction :input +(with-open-file (s *test-path* :direction :input :external-format :latin-1) (assert (equal (read-line s nil s) "ABC")) (assert (equal (read-line s nil s) s))) -(with-open-file (s "external-format-test.txt" :direction :output +(with-open-file (s *test-path* :direction :output :if-exists :supersede :external-format :latin-1) (handler-bind ((sb-int:character-encoding-error #'(lambda (encoding-error) @@ -162,7 +175,7 @@ :initial-contents `(#\A #\B ,(code-char 322) #\C)))) (write-string string s)))) -(with-open-file (s "external-format-test.txt" :direction :input +(with-open-file (s *test-path* :direction :input :external-format :latin-1) (assert (equal (read-line s nil s) "ABC")) (assert (equal (read-line s nil s) s))) @@ -184,7 +197,7 @@ ;;;; KOI8-R external format -(with-open-file (s "external-format-test.txt" :direction :output +(with-open-file (s *test-path* :direction :output :if-exists :supersede :external-format :koi8-r) (write-char (code-char #xB0) s) (assert (eq @@ -195,14 +208,141 @@ (sb-int:character-encoding-error () :good)) :good))) -(with-open-file (s "external-format-test.txt" :direction :input +(with-open-file (s *test-path* :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 +(with-open-file (s *test-path* :direction :input :external-format :koi8-r) (let ((char (read-char s))) (assert (= (char-code (eval char)) #xB0)))) +(delete-file *test-path*) + +(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))) + +;;; tests of FILE-STRING-LENGTH +(let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~")) + (do-external-formats (xf) + (with-open-file (s *test-path* :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 *test-path*))) +(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 *test-path* :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)))))) -(delete-file "external-format-test.txt") + +;;; 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)) + (let ((path *test-path*)) + (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))) +(delete-file *test-path*) + +;;; We used to call STREAM-EXTERNAL-FORMAT on the stream in the error +;;; when printing a coding error, but that didn't work if the stream +;;; was closed by the time the error was printed. See sbcl-devel +;;; "Subject: Printing coding errors for closed streams" by Zach Beane +;;; on 2008-10-16 for more info. +(with-test (:name (:character-coding-error-stream-external-format)) + (flet ((first-file-character () + (with-open-file (stream *test-file* :external-format :utf-8) + (read-char stream)))) + (with-open-file (stream *test-file* + :direction :output + :if-exists :supersede + :element-type '(unsigned-byte 8)) + (write-byte 192 stream)) + (princ-to-string (nth-value 1 (ignore-errors (first-file-character)))))) +(delete-file *test-path*) + +;;; External format support in SB-ALIEN + +(with-test (:name (:sb-alien :vanilla)) + (define-alien-routine strdup c-string (str c-string)) + (assert (equal "foo" (strdup "foo")))) + +(with-test (:name (:sb-alien :utf-8 :utf-8)) + (define-alien-routine strdup (c-string :external-format :utf-8) + (str (c-string :external-format :utf-8))) + (assert (equal "foo" (strdup "foo")))) + +(with-test (:name (:sb-alien :latin-1 :utf-8)) + (define-alien-routine strdup (c-string :external-format :latin-1) + (str (c-string :external-format :utf-8))) + (assert (= (length (strdup (string (code-char 246)))) + 2))) + +(with-test (:name (:sb-alien :utf-8 :latin-1)) + (define-alien-routine strdup (c-string :external-format :utf-8) + (str (c-string :external-format :latin-1))) + (assert (equal (string (code-char 228)) + (strdup (concatenate 'string + (list (code-char 195)) + (list (code-char 164))))))) + +(with-test (:name (:sb-alien :ebcdic :ebcdic)) + (define-alien-routine strdup (c-string :external-format :ebcdic-us) + (str (c-string :external-format :ebcdic-us))) + (assert (equal "foo" (strdup "foo")))) + +(with-test (:name (:sb-alien :latin-1 :ebcdic)) + (define-alien-routine strdup (c-string :external-format :latin-1) + (str (c-string :external-format :ebcdic-us))) + (assert (not (equal "foo" (strdup "foo"))))) + +(with-test (:name (:sb-alien :simple-base-string)) + (define-alien-routine strdup (c-string :external-format :ebcdic-us + :element-type base-char) + (str (c-string :external-format :ebcdic-us))) + (assert (typep (strdup "foo") 'simple-base-string))) + +;;;; success