0.9.4.6:
[sbcl.git] / tests / external-format.impure.lisp
1 ;;;; This file is for testing external-format functionality, using
2 ;;;; test machinery which might have side effects (e.g.  executing
3 ;;;; DEFUN, writing files).  Note that the tests here reach into
4 ;;;; unexported functionality, and should not be used as a guide for
5 ;;;; users.
6
7 ;;;; This software is part of the SBCL system. See the README file for
8 ;;;; more information.
9 ;;;;
10 ;;;; While most of SBCL is derived from the CMU CL system, the test
11 ;;;; files (like this one) were written from scratch after the fork
12 ;;;; from CMU CL.
13 ;;;;
14 ;;;; This software is in the public domain and is provided with
15 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
16 ;;;; more information.
17
18 (defmacro do-external-formats ((xf &optional result) &body body)
19   (let ((nxf (gensym)))
20     `(dolist (,nxf sb-impl::*external-formats* ,result)
21        (let ((,xf (first (first ,nxf))))
22          ,@body))))
23
24 (do-external-formats (xf)
25   (with-open-file (s "/dev/null" :direction :input :external-format xf)
26     (assert (eq (read-char s nil s) s))))
27
28 ;;; Test standard character read-write equivalency over all external formats.
29 (let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~"))
30   (do-external-formats (xf)
31     (with-open-file (s "external-format-test.txt" :direction :output
32                      :if-exists :supersede :external-format xf)
33       (loop for character across standard-characters
34             do (write-char character s)))
35     (with-open-file (s "external-format-test.txt" :direction :input
36                      :external-format xf)
37       (loop for character across standard-characters
38             do (assert (eql (read-char s) character))))))
39
40 (delete-file "external-format-test.txt")
41 #-sb-unicode
42 (progn
43   (test-util:report-test-status)
44   (sb-ext:quit :unix-status 104))
45
46 ;;; Test UTF-8 writing and reading of 1, 2, 3 and 4 octet characters with
47 ;;; all possible offsets. Tests for buffer edge bugs. fd-stream buffers are
48 ;;; 4096 wide.
49 (dotimes (width-1 4)
50   (let ((character (code-char (elt '(1 #x81 #x801 #x10001) width-1))))
51     (dotimes (offset (+ width-1 1))
52       (with-open-file (s "external-format-test.txt" :direction :output
53                        :if-exists :supersede :external-format :utf-8)
54         (dotimes (n offset)
55           (write-char #\a s))
56         (dotimes (n 4097)
57           (write-char character s)))
58       (with-open-file (s "external-format-test.txt" :direction :input
59                        :external-format :utf-8)
60         (dotimes (n offset)
61           (assert (eql (read-char s) #\a)))
62         (dotimes (n 4097)
63           (assert (eql (read-char s) character)))
64         (assert (eql (read-char s nil s) s))))))
65
66 ;;; Test character decode restarts.
67 (with-open-file (s "external-format-test.txt" :direction :output
68                  :if-exists :supersede :element-type '(unsigned-byte 8))
69   (write-byte 65 s)
70   (write-byte 66 s)
71   (write-byte #xe0 s)
72   (write-byte 67 s))
73 (with-open-file (s "external-format-test.txt" :direction :input
74                  :external-format :utf-8)
75   (handler-bind
76       ((sb-int:character-decoding-error #'(lambda (decoding-error)
77                                             (declare (ignore decoding-error))
78                                             (invoke-restart
79                                              'sb-int:attempt-resync))))
80     (assert (equal (read-line s nil s) "ABC"))
81     (assert (equal (read-line s nil s) s))))
82 (with-open-file (s "external-format-test.txt" :direction :input
83                  :external-format :utf-8)
84   (handler-bind
85       ((sb-int:character-decoding-error #'(lambda (decoding-error)
86                                             (declare (ignore decoding-error))
87                                             (invoke-restart
88                                              'sb-int:force-end-of-file))))
89     (assert (equal (read-line s nil s) "AB"))
90     (assert (equal (read-line s nil s) s))))
91
92 ;;; Test character encode restarts.
93 (with-open-file (s "external-format-test.txt" :direction :output
94                  :if-exists :supersede :external-format :latin-1)
95   (handler-bind
96       ((sb-int:character-encoding-error #'(lambda (encoding-error)
97                                             (declare (ignore encoding-error))
98                                             (invoke-restart
99                                              'sb-impl::output-nothing))))
100     (write-char #\A s)
101     (write-char #\B s)
102     (write-char (code-char 322) s)
103     (write-char #\C s)))
104 (with-open-file (s "external-format-test.txt" :direction :input
105                  :external-format :latin-1)
106   (assert (equal (read-line s nil s) "ABC"))
107   (assert (equal (read-line s nil s) s)))
108
109 (with-open-file (s "external-format-test.txt" :direction :output
110                  :if-exists :supersede :external-format :latin-1)
111   (handler-bind
112       ((sb-int:character-encoding-error #'(lambda (encoding-error)
113                                             (declare (ignore encoding-error))
114                                             (invoke-restart
115                                              'sb-impl::output-nothing))))
116     (let ((string (make-array 4 :element-type 'character
117                               :initial-contents `(#\A #\B ,(code-char 322)
118                                                       #\C))))
119       (write-string string s))))
120 (with-open-file (s "external-format-test.txt" :direction :input
121                  :external-format :latin-1)
122   (assert (equal (read-line s nil s) "ABC"))
123   (assert (equal (read-line s nil s) s)))
124
125 ;;; Test skipping character-decode-errors in comments.
126 (let ((s (open "external-format-test.lisp" :direction :output
127                :if-exists :supersede :external-format :latin-1)))
128   (unwind-protect
129        (progn
130          (write-string ";;; ABCD" s)
131          (write-char (code-char 233) s)
132          (terpri s)
133          (close s)
134          (compile-file "external-format-test.lisp" :external-format :utf-8))
135     (delete-file s)
136     (let ((p (probe-file (compile-file-pathname "external-format-test.lisp"))))
137       (when p
138         (delete-file p)))))
139
140 \f
141 ;;;; KOI8-R external format
142 (with-open-file (s "external-format-test.txt" :direction :output
143                  :if-exists :supersede :external-format :koi8-r)
144   (write-char (code-char #xB0) s)
145   (assert (eq
146            (handler-case
147                (progn
148                  (write-char (code-char #xBAAD) s)
149                  :bad)
150              (sb-int:character-encoding-error ()
151                :good))
152            :good)))
153 (with-open-file (s "external-format-test.txt" :direction :input
154                  :element-type '(unsigned-byte 8))
155   (let ((byte (read-byte s)))
156     (assert (= (eval byte) #x9C))))
157 (with-open-file (s "external-format-test.txt" :direction :input
158                  :external-format :koi8-r)
159   (let ((char (read-char s)))
160     (assert (= (char-code (eval char)) #xB0))))
161
162 \f
163 (delete-file "external-format-test.txt")