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
7 ;;;; This software is part of the SBCL system. See the README file for
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
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.
18 (defmacro do-external-formats
((xf) &body body
)
20 `(loop for
,nxf being the hash-values of sb-impl
::*external-formats
*
21 do
(let ((,xf
(first (sb-impl::ef-names
,nxf
))))
24 (defvar *test-path
* "external-format-test.tmp")
26 (with-test (:name
:end-of-file
)
27 (do-external-formats (xf)
28 (with-open-file (s #-win32
"/dev/null" #+win32
"nul" :direction
:input
:external-format xf
)
29 (assert (eq (read-char s nil s
) s
)))))
31 ;;; Test standard character read-write equivalency over all external formats.
35 (do-external-formats (xf)
36 (pushnew `(with-test (:name
(:standard-character
:read-write-equivalency
,xf
))
37 (let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~"))
38 (with-open-file (s *test-path
* :direction
:output
39 :if-exists
:supersede
:external-format
,xf
)
40 (loop for character across standard-characters
41 do
(write-char character s
)))
42 (with-open-file (s *test-path
* :direction
:input
44 (loop for character across standard-characters
45 do
(let ((got (read-char s
)))
46 (unless (eql character got
)
47 (error "wanted ~S, got ~S" character got
)))))))
48 tests
:key
#'cadr
:test
#'equal
))
52 (delete-file *test-path
*)
55 (test-util:report-test-status
)
56 (sb-ext:exit
:code
104))
58 ;;; Test UTF-8 writing and reading of 1, 2, 3 and 4 octet characters with
59 ;;; all possible offsets. Tests for buffer edge bugs. fd-stream buffers are
62 (let ((character (code-char (elt '(1 #x81
#x801
#x10001
) width-1
))))
63 (dotimes (offset (+ width-1
1))
64 (with-open-file (s *test-path
* :direction
:output
65 :if-exists
:supersede
:external-format
:utf-8
)
68 (dotimes (n (+ 4 sb-impl
::+bytes-per-buffer
+))
69 (write-char character s
)))
70 (with-open-file (s *test-path
* :direction
:input
71 :external-format
:utf-8
)
73 (assert (eql (read-char s
) #\a)))
74 (dotimes (n (+ 4 sb-impl
::+bytes-per-buffer
+))
75 (let ((got (read-char s
)))
76 (unless (eql got character
)
77 (error "wanted ~S, got ~S (~S)" character got n
))))
78 (assert (eql (read-char s nil s
) s
))))))
80 ;;; Test character decode restarts.
81 (with-open-file (s *test-path
* :direction
:output
82 :if-exists
:supersede
:element-type
'(unsigned-byte 8))
87 (with-open-file (s *test-path
* :direction
:input
88 :external-format
:utf-8
)
91 ((sb-int:character-decoding-error
#'(lambda (decoding-error)
92 (declare (ignore decoding-error
))
93 (when (> (incf count
) 1)
94 (error "too many errors"))
96 'sb-int
:attempt-resync
))))
97 (assert (equal (read-line s nil s
) "ABC"))
98 (assert (equal (read-line s nil s
) s
)))))
99 (with-open-file (s *test-path
* :direction
:input
100 :external-format
:utf-8
)
103 ((sb-int:character-decoding-error
#'(lambda (decoding-error)
104 (declare (ignore decoding-error
))
105 (when (> (incf count
) 1)
106 (error "too many errors"))
108 'sb-int
:force-end-of-file
))))
109 (assert (equal (read-line s nil s
) "AB"))
111 (assert (equal (read-line s nil s
) s
)))))
113 ;;; And again with more data to account for buffering (this was briefly)
114 ;;; broken in early 0.9.6.
115 (with-open-file (s *test-path
* :direction
:output
116 :if-exists
:supersede
:element-type
'(unsigned-byte 8))
117 (let ((a (make-array 50
118 :element-type
'(unsigned-byte 64)
119 :initial-contents
(map 'list
#'char-code
120 "1234567890123456789012345678901234567890123456789."))))
121 (setf (aref a
49) (char-code #\Newline
))
123 (write-sequence a s
))
126 (write-sequence a s
))))
127 (with-test (:name
(:character-decode-large
:attempt-resync
))
128 (with-open-file (s *test-path
* :direction
:input
129 :external-format
:utf-8
)
132 ((sb-int:character-decoding-error
(lambda (decoding-error)
133 (declare (ignore decoding-error
))
134 (when (> (incf count
) 1)
135 (error "too many errors"))
137 'sb-int
:attempt-resync
)))
138 ;; The failure mode is an infinite loop, add a timeout to
140 (sb-ext:timeout
(lambda () (error "Timeout"))))
141 (sb-ext:with-timeout
5
143 (assert (equal (read-line s nil s
)
144 "1234567890123456789012345678901234567890123456789"))))))))
146 (with-test (:name
(:character-decode-large
:force-end-of-file
))
147 (with-open-file (s *test-path
* :direction
:input
148 :external-format
:utf-8
)
151 ((sb-int:character-decoding-error
(lambda (decoding-error)
152 (declare (ignore decoding-error
))
153 (when (> (incf count
) 1)
154 (error "too many errors"))
156 'sb-int
:force-end-of-file
)))
157 ;; The failure mode is an infinite loop, add a timeout to detetct it.
158 (sb-ext:timeout
(lambda () (error "Timeout"))))
159 (sb-ext:with-timeout
5
161 (assert (equal (read-line s nil s
)
162 "1234567890123456789012345678901234567890123456789")))
164 (assert (equal (read-line s nil s
) s
)))))))
166 ;;; Test character encode restarts.
167 (with-open-file (s *test-path
* :direction
:output
168 :if-exists
:supersede
:external-format
:latin-1
)
170 ((sb-int:character-encoding-error
#'(lambda (encoding-error)
171 (declare (ignore encoding-error
))
173 'sb-impl
::output-nothing
))))
176 (write-char (code-char 322) s
)
178 (with-open-file (s *test-path
* :direction
:input
179 :external-format
:latin-1
)
180 (assert (equal (read-line s nil s
) "ABC"))
181 (assert (equal (read-line s nil s
) s
)))
183 (with-open-file (s *test-path
* :direction
:output
184 :if-exists
:supersede
:external-format
:latin-1
)
186 ((sb-int:character-encoding-error
#'(lambda (encoding-error)
187 (declare (ignore encoding-error
))
189 'sb-impl
::output-nothing
))))
190 (let ((string (make-array 4 :element-type
'character
191 :initial-contents
`(#\A
#\B
,(code-char 322)
193 (write-string string s
))))
194 (with-open-file (s *test-path
* :direction
:input
195 :external-format
:latin-1
)
196 (assert (equal (read-line s nil s
) "ABC"))
197 (assert (equal (read-line s nil s
) s
)))
199 ;;; Test skipping character-decode-errors in comments.
200 (let ((s (open "external-format-test.lisp" :direction
:output
201 :if-exists
:supersede
:external-format
:latin-1
)))
204 (write-string ";;; ABCD" s
)
205 (write-char (code-char 233) s
)
208 (let ((*error-output
* (make-broadcast-stream)))
209 (compile-file "external-format-test.lisp"
210 :external-format
:utf-8
:verbose nil
)))
212 (let ((p (probe-file (compile-file-pathname "external-format-test.lisp"))))
217 ;;;; KOI8-R external format
218 (with-open-file (s *test-path
* :direction
:output
219 :if-exists
:supersede
:external-format
:koi8-r
)
220 (write-char (code-char #xB0
) s
)
224 (write-char (code-char #xBAAD
) s
)
226 (sb-int:character-encoding-error
()
229 (with-open-file (s *test-path
* :direction
:input
230 :element-type
'(unsigned-byte 8))
231 (let ((byte (read-byte s
)))
232 (assert (= (eval byte
) #x9C
))))
233 (with-open-file (s *test-path
* :direction
:input
234 :external-format
:koi8-r
)
235 (let ((char (read-char s
)))
236 (assert (= (char-code (eval char
)) #xB0
))))
237 (delete-file *test-path
*)
239 (let* ((koi8-r-codes (coerce '(240 210 201 215 197 212 33) '(vector (unsigned-byte 8))))
240 (uni-codes #(1055 1088 1080 1074 1077 1090 33))
242 (string (octets-to-string koi8-r-codes
:external-format
:koi8-r
))
243 (uni-decoded (map 'vector
#'char-code string
)))
244 (declare (ignore uni-decoded
))
245 (assert (equalp (map 'vector
#'char-code
(octets-to-string koi8-r-codes
:external-format
:koi8-r
))
247 (assert (equalp (string-to-octets (map 'string
#'code-char uni-codes
) :external-format
:koi8-r
)
250 ;;; tests of FILE-STRING-LENGTH
251 (let ((standard-characters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!$\"'(),_-./:;?+<=>#%&*@[\\]{|}`^~"))
252 (do-external-formats (xf)
253 (with-open-file (s *test-path
* :direction
:output
255 (loop for x across standard-characters
256 for position
= (file-position s
)
257 for char-length
= (file-string-length s x
)
259 do
(assert (= (file-position s
) (+ position char-length
))))
260 (let ((position (file-position s
))
261 (string-length (file-string-length s standard-characters
)))
262 (write-string standard-characters s
)
263 (assert (= (file-position s
) (+ position string-length
)))))
264 (delete-file *test-path
*)))
266 (let ((char-codes '(0 1 255 256 511 512 1023 1024 2047 2048 4095 4096
267 8191 8192 16383 16384 32767 32768 65535 65536 131071
268 131072 262143 262144)))
269 (with-open-file (s *test-path
* :direction
:output
270 :external-format
:utf-8
)
271 (dolist (code char-codes
)
272 (let* ((char (code-char code
))
273 (position (file-position s
))
274 (char-length (file-string-length s char
)))
276 (assert (= (file-position s
) (+ position char-length
)))))
277 (let* ((string (map 'string
#'code-char char-codes
))
278 (position (file-position s
))
279 (string-length (file-string-length s string
)))
280 (write-string string s
)
281 (assert (= (file-position s
) (+ position string-length
))))))
284 ;;; See sbcl-devel "Subject: Bug in FILE-POSITION on UTF-8-encoded files"
285 ;;; by Lutz Euler on 2006-03-05 for more details.
286 (with-test (:name
(:file-position
:utf-8
))
287 (let ((path *test-path
*))
288 (with-open-file (s path
290 :if-exists
:supersede
291 :element-type
'(unsigned-byte 8))
292 ;; Write #\*, encoded in UTF-8, to the file.
294 ;; Append #\adiaeresis, encoded in UTF-8, to the file.
295 (write-sequence '(195 164) s
))
296 (with-open-file (s path
:external-format
:utf-8
)
298 (let ((pos (file-position s
))
299 (char (read-char s
)))
301 (format t
"read character with code ~a successfully from file position ~a~%"
302 (char-code char
) pos
)
303 (file-position s pos
)
305 (format t
"set file position back to ~a, trying to read-char again~%" pos
)
306 (let ((new-char (read-char s
)))
307 (assert (char= char new-char
)))))
309 (delete-file *test-path
*)
311 ;;; We used to call STREAM-EXTERNAL-FORMAT on the stream in the error
312 ;;; when printing a coding error, but that didn't work if the stream
313 ;;; was closed by the time the error was printed. See sbcl-devel
314 ;;; "Subject: Printing coding errors for closed streams" by Zach Beane
315 ;;; on 2008-10-16 for more info.
316 (with-test (:name
(:character-coding-error-stream-external-format
))
317 (flet ((first-file-character ()
318 (with-open-file (stream *test-path
* :external-format
:utf-8
)
319 (read-char stream
))))
320 (with-open-file (stream *test-path
*
322 :if-exists
:supersede
323 :element-type
'(unsigned-byte 8))
324 (write-byte 192 stream
))
325 (princ-to-string (nth-value 1 (ignore-errors (first-file-character))))))
326 (delete-file *test-path
*)
328 ;;; External format support in SB-ALIEN
330 (with-test (:name
(:sb-alien
:vanilla
))
331 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
334 (assert (equal "foo" (strdup "foo"))))
336 (with-test (:name
(:sb-alien
:utf-8
:utf-8
))
337 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
338 (c-string :external-format
:utf-8
)
339 (str (c-string :external-format
:utf-8
)))
340 (assert (equal "foo" (strdup "foo"))))
342 (with-test (:name
(:sb-alien
:latin-1
:utf-8
))
343 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
344 (c-string :external-format
:latin-1
)
345 (str (c-string :external-format
:utf-8
)))
346 (assert (= (length (strdup (string (code-char 246))))
349 (with-test (:name
(:sb-alien
:utf-8
:latin-1
))
350 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
351 (c-string :external-format
:utf-8
)
352 (str (c-string :external-format
:latin-1
)))
353 (assert (equal (string (code-char 228))
354 (strdup (concatenate 'string
355 (list (code-char 195))
356 (list (code-char 164)))))))
358 (with-test (:name
(:sb-alien
:ebcdic
:ebcdic
))
359 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
360 (c-string :external-format
:ebcdic-us
)
361 (str (c-string :external-format
:ebcdic-us
)))
362 (assert (equal "foo" (strdup "foo"))))
364 (with-test (:name
(:sb-alien
:latin-1
:ebcdic
))
365 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
366 (c-string :external-format
:latin-1
)
367 (str (c-string :external-format
:ebcdic-us
)))
368 (assert (not (equal "foo" (strdup "foo")))))
370 (with-test (:name
(:sb-alien
:simple-base-string
))
371 (define-alien-routine (#-win32
"strdup" #+win32
"_strdup" strdup
)
372 (c-string :external-format
:ebcdic-us
373 :element-type base-char
)
374 (str (c-string :external-format
:ebcdic-us
)))
375 (assert (typep (strdup "foo") 'simple-base-string
)))
377 (with-test (:name
(:input-replacement
:at-end-of-file
))
379 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
381 (handler-bind ((sb-int:character-decoding-error
384 (invoke-restart 'sb-impl
::input-replacement
#\?))))
385 (with-open-file (s *test-path
* :external-format
:utf-8
)
387 ((char= (read-char s
) #\?)
388 (assert (or (= i
(char-code #\?)) (> i
127))))
389 (t (assert (and (not (= i
(char-code #\?))) (< i
128)))))))))
391 (with-test (:name
(:unibyte-invalid-codepoints
:cp857
))
393 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
395 (with-open-file (s *test-path
* :external-format
:cp857
)
396 (handler-case (read-char s
)
397 (error () (assert (member i
'(#xd5
#xe7
#xf2
))))
398 (:no-error
(char) char
(assert (not (member i
'(#xd5
#xe7
#xf2
)))))))))
399 (delete-file *test-path
*)
401 (with-test (:name
(:unibyte-input-replacement
:cp857
))
403 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
405 (with-open-file (s *test-path
* :external-format
'(:cp857
:replacement
#\?))
406 (let ((char (read-char s
)))
409 (assert (member i
`(,(char-code #\?) #xd5
#xe7
#xf2
))))
410 (t (assert (not (member i
`(,(char-code #\?) #xd5
#xe7
#xf2
))))))))))
411 (delete-file *test-path
*)
413 (with-test (:name
(:unibyte-output-replacement
:cp857
))
414 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:cp857
:replacement
#\?))
416 (write-char (code-char i
) s
)))
417 (with-open-file (s *test-path
* :external-format
'(:cp857
))
418 (let ((string (make-string 256)))
419 (read-sequence string s
)
421 (assert (= (char-code (char string i
)) i
)))
422 (assert (= 38 (count #\? string
:start
128))))))
423 (delete-file *test-path
*)
425 (with-test (:name
(:unibyte-input-replacement
:ascii
))
427 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
429 (with-open-file (s *test-path
* :external-format
'(:ascii
:replacement
#\?))
430 (let ((char (read-char s
)))
433 (assert (or (= i
(char-code #\?)) (> i
127))))
434 (t (assert (and (< i
128) (not (= i
(char-code #\?)))))))))))
435 (delete-file *test-path
*)
437 (with-test (:name
(:unibyte-output-replacement
:ascii
))
438 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:ascii
:replacement
#\?))
440 (write-char (code-char i
) s
)))
441 (with-open-file (s *test-path
* :external-format
'(:ascii
))
442 (let ((string (make-string 256)))
443 (read-sequence string s
)
445 (assert (= (char-code (char string i
)) i
)))
446 (assert (= 128 (count #\? string
:start
128))))))
447 (delete-file *test-path
*)
449 (with-test (:name
(:unibyte-input-replacement
:latin-1
))
451 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
453 (with-open-file (s *test-path
* :external-format
'(:latin-1
:replacement
#\?))
454 (let ((char (read-char s
)))
455 (assert (= (char-code char
) i
))))))
456 (delete-file *test-path
*)
458 (with-test (:name
(:unibyte-output-replacement
:latin-1
))
459 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-1
:replacement
#\?))
461 (write-char (code-char i
) s
)))
462 (with-open-file (s *test-path
* :external-format
'(:latin-1
))
463 (let ((string (make-string 257)))
464 (read-sequence string s
)
466 (assert (= (char-code (char string i
)) i
)))
467 (assert (char= #\? (char string
256))))))
468 (delete-file *test-path
*)
471 (with-test (:name
(:unibyte-input-replacement
:latin-2
))
473 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
475 (with-open-file (s *test-path
* :external-format
'(:latin-2
:replacement
#\?))
476 (let ((char (read-char s
)))
478 ((< i
#xa1
) (assert (= (char-code char
) i
)))
481 (delete-file *test-path
*)
483 (with-test (:name
(:unibyte-output-replacement
:latin-2
))
484 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-2
:replacement
#\?))
486 (write-char (code-char i
) s
)))
487 (with-open-file (s *test-path
* :external-format
'(:latin-2
))
488 (let ((string (make-string 256)))
489 (read-sequence string s
)
491 (assert (= (char-code (char string i
)) i
)))
492 (assert (= 57 (count #\? string
:start
#xa1
))))))
493 (delete-file *test-path
*)
496 (with-test (:name
(:unibyte-input-replacement
:latin-3
))
498 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
500 (with-open-file (s *test-path
* :external-format
'(:latin-3
:replacement
#\?))
501 (let ((char (read-char s
)))
504 (assert #1=(or (= i
(char-code #\?))
505 (member i
'(#xa5
#xae
#xbe
#xc3
#xd0
#xe3
#xf0
)))))
506 (t (assert (not #1#))))))))
507 (delete-file *test-path
*)
509 (with-test (:name
(:unibyte-output-replacement
:latin-3
))
510 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-3
:replacement
#\?))
512 (write-char (code-char i
) s
)))
513 (with-open-file (s *test-path
* :external-format
'(:latin-3
))
514 (let ((string (make-string 256)))
515 (read-sequence string s
)
517 (assert (= (char-code (char string i
)) i
)))
518 (assert (= 35 (count #\? string
:start
#xa1
))))))
519 (delete-file *test-path
*)
522 (with-test (:name
(:unibyte-input-replacement
:latin-4
))
524 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
526 (with-open-file (s *test-path
* :external-format
'(:latin-4
:replacement
#\?))
527 (let ((char (read-char s
)))
529 ((< i
#xa1
) (assert (= (char-code char
) i
)))
532 (delete-file *test-path
*)
534 (with-test (:name
(:unibyte-output-replacement
:latin-4
))
535 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-4
:replacement
#\?))
537 (write-char (code-char i
) s
)))
538 (with-open-file (s *test-path
* :external-format
'(:latin-4
))
539 (let ((string (make-string 256)))
540 (read-sequence string s
)
542 (assert (= (char-code (char string i
)) i
)))
543 (assert (= 50 (count #\? string
:start
#xa1
))))))
544 (delete-file *test-path
*)
547 (with-test (:name
(:unibyte-input-replacement
:iso-8859-5
))
549 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
551 (with-open-file (s *test-path
* :external-format
'(:iso-8859-5
:replacement
#\?))
552 (let ((char (read-char s
)))
554 ((= (char-code char
) i
)
555 (assert (or (< i
#xa1
) (= i
#xad
))))
556 (t (assert (and (>= i
#xa1
) (/= i
#xad
)))))))))
557 (delete-file *test-path
*)
559 (with-test (:name
(:unibyte-output-replacement
:iso-8859-5
))
560 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:iso-8859-5
:replacement
#\?))
562 (write-char (code-char i
) s
)))
563 (with-open-file (s *test-path
* :external-format
'(:iso-8859-5
))
564 (let ((string (make-string 256)))
565 (read-sequence string s
)
567 (assert (= (char-code (char string i
)) i
)))
568 (assert (= 93 (count #\? string
:start
#xa1
))))))
569 (delete-file *test-path
*)
572 (with-test (:name
(:unibyte-input-replacement
:iso-8859-6
))
574 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
576 (with-open-file (s *test-path
* :external-format
'(:iso-8859-6
:replacement
#\?))
577 (let ((char (read-char s
)))
580 (assert #1=(or (= i
(char-code #\?))
581 (<= #xa1 i
#xa3
) (<= #xa5 i
#xab
) (<= #xae i
#xba
)
582 (<= #xbc i
#xbe
) (= i
#xc0
) (<= #xdb i
#xdf
)
584 (t (assert (not #1#))))))))
585 (delete-file *test-path
*)
587 (with-test (:name
(:unibyte-output-replacement
:iso-8859-6
))
588 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:iso-8859-6
:replacement
#\?))
590 (write-char (code-char i
) s
)))
591 (with-open-file (s *test-path
* :external-format
'(:iso-8859-6
))
592 (let ((string (make-string 256)))
593 (read-sequence string s
)
595 (assert (= (char-code (char string i
)) i
)))
596 (assert (= 93 (count #\? string
:start
#xa1
))))))
597 (delete-file *test-path
*)
600 (with-test (:name
(:unibyte-input-replacement
:iso-8859-7
))
602 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
604 (with-open-file (s *test-path
* :external-format
'(:iso-8859-7
:replacement
#\?))
605 (let ((char (read-char s
)))
608 (assert #1=(or (= i
(char-code #\?))
609 (member i
'(#xa4
#xa5
#xaa
#xae
#xd2
#xff
)))))
610 (t (assert (not #1#))))))))
611 (delete-file *test-path
*)
613 (with-test (:name
(:unibyte-output-replacement
:iso-8859-7
))
614 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:iso-8859-7
:replacement
#\?))
616 (write-char (code-char i
) s
)))
617 (with-open-file (s *test-path
* :external-format
'(:iso-8859-7
))
618 (let ((string (make-string 256)))
619 (read-sequence string s
)
621 (assert (= (char-code (char string i
)) i
)))
622 (assert (= 80 (count #\? string
:start
#xa1
))))))
623 (delete-file *test-path
*)
626 (with-test (:name
(:unibyte-input-replacement
:iso-8859-8
))
628 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
630 (with-open-file (s *test-path
* :external-format
'(:iso-8859-8
:replacement
#\?))
631 (let ((char (read-char s
)))
634 (assert #1=(or (= i
(char-code #\?))
635 (= i
#xa1
) (<= #xbf i
#xde
) (>= i
#xfb
))))
636 (t (assert (not #1#))))))))
637 (delete-file *test-path
*)
639 (with-test (:name
(:unibyte-output-replacement
:iso-8859-8
))
640 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:iso-8859-8
:replacement
#\?))
642 (write-char (code-char i
) s
)))
643 (with-open-file (s *test-path
* :external-format
'(:iso-8859-8
))
644 (let ((string (make-string 256)))
645 (read-sequence string s
)
647 (assert (= (char-code (char string i
)) i
)))
648 (assert (= 67 (count #\? string
:start
#xa1
))))))
649 (delete-file *test-path
*)
652 (with-test (:name
(:unibyte-input-replacement
:latin-5
))
654 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
656 (with-open-file (s *test-path
* :external-format
'(:latin-5
:replacement
#\?))
657 (let ((char (read-char s
)))
658 (assert (or (and (= (char-code char
) i
)
659 (not (member i
'(#xd0
#xdd
#xde
#xf0
#xfd
#xfe
))))
660 (and (member i
'(#xd0
#xdd
#xde
#xf0
#xfd
#xfe
))
661 (not (char= char
#\?)))))))))
662 (delete-file *test-path
*)
664 (with-test (:name
(:unibyte-output-replacement
:latin-5
))
665 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-5
:replacement
#\?))
667 (write-char (code-char i
) s
)))
668 (with-open-file (s *test-path
* :external-format
'(:latin-5
))
669 (let ((string (make-string 256)))
670 (read-sequence string s
)
672 (assert (= (char-code (char string i
)) i
)))
673 (assert (= 6 (count #\? string
:start
#xd0
))))))
674 (delete-file *test-path
*)
677 (with-test (:name
(:unibyte-input-replacement
:latin-6
))
679 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
681 (with-open-file (s *test-path
* :external-format
'(:latin-6
:replacement
#\?))
682 (let ((char (read-char s
)))
683 (assert (or (= (char-code char
) i
)
684 (and (<= #xa1 i
#xff
)
685 (not (char= char
#\?)))))))))
686 (delete-file *test-path
*)
688 (with-test (:name
(:unibyte-output-replacement
:latin-6
))
689 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-6
:replacement
#\?))
691 (write-char (code-char i
) s
)))
692 (with-open-file (s *test-path
* :external-format
'(:latin-6
))
693 (let ((string (make-string 256)))
694 (read-sequence string s
)
696 (assert (= (char-code (char string i
)) i
)))
697 (assert (= 46 (count #\? string
:start
#xa1
))))))
698 (delete-file *test-path
*)
700 ;;; iso-8859-11 tests
701 (with-test (:name
(:unibyte-input-replacement
:iso-8859-11
))
703 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
705 (with-open-file (s *test-path
* :external-format
'(:iso-8859-11
:replacement
#\?))
706 (let ((char (read-char s
)))
709 (assert (member i
#1=`(,(char-code #\?) #xdb
#xdc
#xdd
#xde
#xfc
#xfd
#xfe
#xff
))))
710 (t (assert (not (member i
#1#)))))))))
711 (delete-file *test-path
*)
713 (with-test (:name
(:unibyte-output-replacement
:iso-8859-11
))
714 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:iso-8859-11
:replacement
#\?))
716 (write-char (code-char i
) s
)))
717 (with-open-file (s *test-path
* :external-format
'(:iso-8859-11
))
718 (let ((string (make-string 256)))
719 (read-sequence string s
)
721 (assert (= (char-code (char string i
)) i
)))
722 (assert (= 95 (count #\? string
:start
#xa1
))))))
723 (delete-file *test-path
*)
726 (with-test (:name
(:unibyte-input-replacement
:latin-7
))
728 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
730 (with-open-file (s *test-path
* :external-format
'(:latin-7
:replacement
#\?))
731 (let ((char (read-char s
)))
732 (assert (or (= (char-code char
) i
)
733 (and (<= #xa1 i
#xff
)
734 (not (char= char
#\?)))))))))
735 (delete-file *test-path
*)
737 (with-test (:name
(:unibyte-output-replacement
:latin-7
))
738 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-7
:replacement
#\?))
740 (write-char (code-char i
) s
)))
741 (with-open-file (s *test-path
* :external-format
'(:latin-7
))
742 (let ((string (make-string 256)))
743 (read-sequence string s
)
745 (assert (= (char-code (char string i
)) i
)))
746 (dolist (i '(#xd8
#xc6
#xf8
#xe6
))
747 (assert (char/= (char string i
) #\?)))
748 (assert (= 52 (count #\? string
:start
#xa1
))))))
749 (delete-file *test-path
*)
752 (with-test (:name
(:unibyte-input-replacement
:latin-8
))
754 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
756 (with-open-file (s *test-path
* :external-format
'(:latin-8
:replacement
#\?))
757 (let ((char (read-char s
)))
758 (assert (or (= (char-code char
) i
)
759 (and (<= #xa1 i
#xfe
)
760 (not (char= char
#\?)))))))))
761 (delete-file *test-path
*)
763 (with-test (:name
(:unibyte-output-replacement
:latin-8
))
764 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-8
:replacement
#\?))
766 (write-char (code-char i
) s
)))
767 (with-open-file (s *test-path
* :external-format
'(:latin-8
))
768 (let ((string (make-string 256)))
769 (read-sequence string s
)
771 (assert (= (char-code (char string i
)) i
)))
772 (assert (= 31 (count #\? string
:start
#xa1
))))))
773 (delete-file *test-path
*)
776 (with-test (:name
(:unibyte-input-replacement
:latin-9
))
778 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
780 (with-open-file (s *test-path
* :external-format
'(:latin-9
:replacement
#\?))
781 (let ((char (read-char s
)))
782 (assert (or (and (= (char-code char
) i
)
783 (not (member i
'(#xa4
#xa6
#xa8
#xb4
#xb8
#xbc
#xbd
#xbe
))))
784 (and (member i
'(#xa4
#xa6
#xa8
#xb4
#xb8
#xbc
#xbd
#xbe
))
785 (not (char= char
#\?)))))))))
786 (delete-file *test-path
*)
788 (with-test (:name
(:unibyte-output-replacement
:latin-9
))
789 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:latin-9
:replacement
#\?))
791 (write-char (code-char i
) s
)))
792 (with-open-file (s *test-path
* :external-format
'(:latin-9
))
793 (let ((string (make-string 256)))
794 (read-sequence string s
)
796 (assert (= (char-code (char string i
)) i
)))
797 (assert (= 8 (count #\? string
:start
#xa4
))))))
798 (delete-file *test-path
*)
801 (with-test (:name
(:unibyte-input-replacement
:koi8-r
))
803 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
805 (with-open-file (s *test-path
* :external-format
'(:koi8-r
:replacement
#\?))
806 (let ((char (read-char s
)))
807 (cond ((= (char-code char
) i
)
809 (t (assert (> i
127))))))))
810 (delete-file *test-path
*)
812 (with-test (:name
(:unibyte-output-replacement
:koi8-r
))
813 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:koi8-r
:replacement
#\?))
815 (write-char (code-char i
) s
)))
816 (with-open-file (s *test-path
* :external-format
'(:koi8-r
))
817 (let ((string (make-string 256)))
818 (read-sequence string s
)
820 (assert (= (char-code (char string i
)) i
)))
821 (assert (= 122 (count #\? string
:start
#x80
))))))
822 (delete-file *test-path
*)
825 (with-test (:name
(:unibyte-input-replacement
:koi8-u
))
827 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
829 (with-open-file (s *test-path
* :external-format
'(:koi8-u
:replacement
#\?))
830 (let ((char (read-char s
)))
831 (cond ((= (char-code char
) i
)
833 (t (assert (> i
127))))))))
834 (delete-file *test-path
*)
836 (with-test (:name
(:unibyte-output-replacement
:koi8-u
))
837 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:koi8-u
:replacement
#\?))
839 (write-char (code-char i
) s
)))
840 (with-open-file (s *test-path
* :external-format
'(:koi8-u
))
841 (let ((string (make-string 256)))
842 (read-sequence string s
)
844 (assert (= (char-code (char string i
)) i
)))
845 (assert (= 122 (count #\? string
:start
#x80
))))))
846 (delete-file *test-path
*)
848 ;;; x-mac-cyrillic tests
849 (with-test (:name
(:unibyte-input-replacement
:x-mac-cyrillic
))
851 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
853 (with-open-file (s *test-path
* :external-format
'(:x-mac-cyrillic
:replacement
#\?))
854 (let ((char (read-char s
)))
855 (cond ((= (char-code char
) i
)
856 (assert (or (< i
128) (member i
'(#xa2
#xa3
#xa9
#xb1
#xb5
)))))
857 (t (assert (and (> i
127)
858 (not (member i
'(#xa2
#xa3
#xa9
#xb1
#xb5
)))))))))))
859 (delete-file *test-path
*)
861 (with-test (:name
(:unibyte-output-replacement
:x-mac-cyrillic
))
862 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:x-mac-cyrillic
:replacement
#\?))
864 (write-char (code-char i
) s
)))
865 (with-open-file (s *test-path
* :external-format
'(:x-mac-cyrillic
))
866 (let ((string (make-string 256)))
867 (read-sequence string s
)
869 (assert (= (char-code (char string i
)) i
)))
870 (assert (= 113 (count #\? string
:start
#x80
))))))
871 (delete-file *test-path
*)
874 (with-test (:name
(:multibyte
:ucs2le
))
876 (array (map-into (make-array size
:element-type
'(unsigned-byte 16))
877 (lambda () (random #x10000
)))))
878 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
880 (write-byte (ldb (byte 8 0) (aref array i
)) s
)
881 (write-byte (ldb (byte 8 8) (aref array i
)) s
)))
882 (with-open-file (s *test-path
* :external-format
:ucs2le
)
883 (let ((string (make-string size
)))
884 (read-sequence string s
)
886 (assert (= (char-code (char string i
)) (aref array i
))))))))
888 (with-test (:name
(:multibyte
:ucs2be
))
890 (array (map-into (make-array size
:element-type
'(unsigned-byte 16))
891 (lambda () (random #x10000
)))))
892 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
894 (write-byte (ldb (byte 8 8) (aref array i
)) s
)
895 (write-byte (ldb (byte 8 0) (aref array i
)) s
)))
896 (with-open-file (s *test-path
* :external-format
:ucs2be
)
897 (let ((string (make-string size
)))
898 (read-sequence string s
)
900 (assert (= (char-code (char string i
)) (aref array i
))))))))
902 (with-test (:name
(:multibyte
:output-replacement
:ucs2le
))
904 (string (map-into (make-string size
)
905 (lambda () (code-char (random #x10000
))))))
906 (setf (char string
0) (code-char #x10001
)
907 (char string
(1- size
)) (code-char #x10002
))
908 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:ucs2le
:replacement
#\replacement_character
))
909 (write-string string s
))
910 (with-open-file (s *test-path
* :external-format
:ucs2le
)
911 (let ((new (make-string size
)))
912 (read-sequence new s
)
913 (assert (char= (char new
0) #\replacement_character
))
914 (assert (char= (char new
(1- size
)) #\replacement_character
))
915 (assert (string= string new
:start1
1 :start2
1 :end1
(1- size
) :end2
(1- size
)))))))
917 (with-test (:name
(:multibyte
:output-replacement
:ucs2be
))
919 (string (map-into (make-string size
)
920 (lambda () (code-char (random #x10000
))))))
921 (setf (char string
0) (code-char #x10001
)
922 (char string
(1- size
)) (code-char #x10002
))
923 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:external-format
'(:ucs2be
:replacement
#\replacement_character
))
924 (write-string string s
))
925 (with-open-file (s *test-path
* :external-format
:ucs2be
)
926 (let ((new (make-string size
)))
927 (read-sequence new s
)
928 (assert (char= (char new
0) #\replacement_character
))
929 (assert (char= (char new
(1- size
)) #\replacement_character
))
930 (assert (string= string new
:start1
1 :start2
1 :end1
(1- size
) :end2
(1- size
)))))))
932 (with-test (:name
(:multibyte
:input-replacement
:ucs4le
))
933 (let ((octets (coerce '(0 1 1 0 1 0 0 1) '(vector (unsigned-byte 8)))))
934 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
935 (write-sequence octets s
))
936 (with-open-file (s *test-path
* :external-format
'(:ucs4le
:replacement
#\replacement_character
))
937 (let ((string (read-line s
)))
938 (assert (char= (char string
0) (code-char #x10100
)))
939 (assert (char= (char string
1) #\replacement_character
))))))
941 (with-test (:name
(:multibyte
:input-replacement
:ucs4le
))
942 (let ((octets (coerce '(0 1 1 0 1 0 0 1) '(vector (unsigned-byte 8)))))
943 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
:element-type
'(unsigned-byte 8))
944 (write-sequence octets s
))
945 (with-open-file (s *test-path
* :external-format
'(:ucs4be
:replacement
#\replacement_character
))
946 (let ((string (read-line s
)))
947 (assert (char= (char string
0) (code-char #x10100
)))
948 (assert (char= (char string
1) #\replacement_character
))))))
951 (with-test (:name
(:utf-16le
:roundtrip
))
952 (let ((string (map 'string
'code-char
'(#x20
#x200
#x2000
#xfffd
#x10fffd
))))
953 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
954 :external-format
:utf-16le
)
955 (write-string string s
))
956 (with-open-file (s *test-path
* :external-format
:utf-16le
)
957 (assert (string= string
(read-line s
))))))
958 (with-test (:name
(:utf-16be
:roundtrip
))
959 (let ((string (map 'string
'code-char
'(#x20
#x200
#x2000
#xfffd
#x10fffd
))))
960 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
961 :external-format
:utf-16be
)
962 (write-string string s
))
963 (with-open-file (s *test-path
* :external-format
:utf-16be
)
964 (assert (string= string
(read-line s
))))))
965 (with-test (:name
(:utf-16le
:encoding-error
))
966 (let ((string (map 'string
'code-char
'(#x20
#xfffe
#xdc00
#xd800
#x1fffe
#x20
))))
967 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
968 :external-format
'(:utf-16le
:replacement
#\?))
969 (write-string string s
))
970 (with-open-file (s *test-path
* :external-format
:utf-16le
)
971 (assert (string= " ???? " (read-line s
))))))
972 (with-test (:name
(:utf-16be
:encoding-error
))
973 (let ((string (map 'string
'code-char
'(#x20
#xfffe
#xdc00
#xd800
#x1fffe
#x20
))))
974 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
975 :external-format
'(:utf-16be
:replacement
#\?))
976 (write-string string s
))
977 (with-open-file (s *test-path
* :external-format
:utf-16be
)
978 (assert (string= " ???? " (read-line s
))))))
980 (with-test (:name
(:utf-32le
:roundtrip
))
981 (let ((string (map 'string
'code-char
'(#x20
#x200
#x2000
#xfffd
#x10fffd
))))
982 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
983 :external-format
:utf-32le
)
984 (write-string string s
))
985 (with-open-file (s *test-path
* :external-format
:utf-32le
)
986 (assert (string= string
(read-line s
))))))
987 (with-test (:name
(:utf-32be
:roundtrip
))
988 (let ((string (map 'string
'code-char
'(#x20
#x200
#x2000
#xfffd
#x10fffd
))))
989 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
990 :external-format
:utf-32be
)
991 (write-string string s
))
992 (with-open-file (s *test-path
* :external-format
:utf-32be
)
993 (assert (string= string
(read-line s
))))))
994 (with-test (:name
(:utf-32le
:encoding-error
))
995 (let ((string (map 'string
'code-char
'(#x20
#xfffe
#xdc00
#xd800
#x1fffe
#x20
))))
996 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
997 :external-format
'(:utf-32le
:replacement
#\?))
998 (write-string string s
))
999 (with-open-file (s *test-path
* :external-format
:utf-32le
)
1000 (assert (string= " ???? " (read-line s
))))))
1001 (with-test (:name
(:utf-32be
:encoding-error
))
1002 (let ((string (map 'string
'code-char
'(#x20
#xfffe
#xdc00
#xd800
#x1fffe
#x20
))))
1003 (with-open-file (s *test-path
* :direction
:output
:if-exists
:supersede
1004 :external-format
'(:utf-32be
:replacement
#\?))
1005 (write-string string s
))
1006 (with-open-file (s *test-path
* :external-format
:utf-32be
)
1007 (assert (string= " ???? " (read-line s
))))))
1009 (with-test (:name
:invalid-external-format
:fails-on
:win32
)
1010 (labels ((test-error (e)
1011 (assert (typep e
'error
))
1012 (unless (equal "Undefined external-format: :BAD-FORMAT"
1013 (princ-to-string e
))
1014 (error "Bad error:~% ~A" e
)))
1018 (open "/dev/null" :direction direction
:external-format
:bad-format
1019 :if-exists
:overwrite
)
1026 (run-program "sh" '() :input
:stream
:external-format
:bad-format
)
1030 (string-to-octets "foobar" :external-format
:bad-format
)
1033 (let ((octets (string-to-octets "foobar" :external-format
:latin1
)))
1035 (octets-to-string octets
:external-format
:bad-format
)
1038 (with-test (:name
:lp713063
)
1039 (with-open-file (f *test-path
*
1041 :external-format
'(:euc-jp
:replacement
#\?)
1042 :if-exists
:supersede
)
1043 (write-string (make-string 3 :initial-element
#\horizontal_bar
) f
))
1044 (assert (equal "???"
1045 (with-open-file (f *test-path
*
1047 :external-format
:euc-jp
)
1049 (delete-file *test-path
*))