a845bd553d5221fe338113007f8e2e9297594a0b
[sbcl.git] / contrib / sb-simple-streams / simple-stream-tests.lisp
1 ;;;; -*- lisp -*-
2
3 (defpackage sb-simple-streams-test
4   (:use #:common-lisp #:sb-simple-streams #:sb-rt))
5
6
7 (in-package #:sb-simple-streams-test)
8
9 (defparameter *dumb-string*
10   "This file was created by simple-stream-tests.lisp. Nothing to see here, move along.")
11
12 (defparameter *test-path*
13   (merge-pathnames (make-pathname :name :unspecific :type :unspecific
14                                   :version :unspecific)
15                    *load-truename*)
16   "Directory for temporary test files.")
17
18 (defparameter *test-file*
19   (merge-pathnames #p"test-data.tmp" *test-path*))
20
21 (eval-when (:load-toplevel) (ensure-directories-exist *test-path* :verbose t))
22
23 ;;; Non-destructive functional analog of REMF
24 (defun remove-key (key list)
25   (loop for (current-key val . rest) on list by #'cddr
26         until (eql current-key key)
27         collect current-key into result
28         collect val into result
29         finally (return (nconc result rest))))
30
31 (defun create-test-file (&key (filename *test-file*) (content *dumb-string*))
32   (with-open-file (s filename :direction :output
33                      :if-does-not-exist :create
34                      :if-exists :supersede)
35     (write-sequence content s)))
36
37 (defun remove-test-file (&key (filename *test-file*))
38   (delete-file filename))
39
40 (defmacro with-test-file ((stream file &rest open-arguments
41                                   &key (delete-afterwards t)
42                                   initial-content
43                                   &allow-other-keys)
44                           &body body)
45   (setq open-arguments (remove-key :delete-afterwards open-arguments))
46   (setq open-arguments (remove-key :initial-content open-arguments))
47   (if initial-content
48       (let ((create-file-stream (gensym)))
49         `(progn
50            (with-open-file (,create-file-stream ,file :direction :output
51                                                 :if-exists :supersede
52                                                 :if-does-not-exist :create)
53              (write-sequence ,initial-content ,create-file-stream))
54            (unwind-protect
55                 (with-open-file (,stream ,file ,@open-arguments)
56                   (progn ,@body))
57              ,(when delete-afterwards `(ignore-errors (delete-file ,file))))))
58       `(unwind-protect
59             (with-open-file (,stream ,file ,@open-arguments)
60               (progn ,@body))
61          ,(when delete-afterwards `(ignore-errors (delete-file ,file))))))
62
63 (deftest create-file-1
64     ;; Create a file-simple-stream, write data.
65     (prog1
66         (with-open-stream (s (make-instance 'file-simple-stream
67                                             :filename *test-file*
68                                             :direction :output
69                                             :if-exists :overwrite
70                                             :if-does-not-exist :create))
71           (string= (write-string *dumb-string* s) *dumb-string*))
72       (delete-file *test-file*))
73   t)
74
75 (deftest create-file-2
76     ;; Create a file-simple-stream via :class argument to open, write data.
77     (with-test-file (s *test-file* :class 'file-simple-stream
78                        :direction :output :if-exists :overwrite
79                        :if-does-not-exist :create)
80       (string= (write-string *dumb-string* s) *dumb-string*))
81   t)
82
83 (deftest create-read-file-1
84   ;; Via file-simple-stream objects, write and then re-read data.
85   (let ((result t))
86     (with-test-file (s *test-file* :class 'file-simple-stream
87                        :direction :output :if-exists :overwrite
88                        :if-does-not-exist :create :delete-afterwards nil)
89       (write-line *dumb-string* s)
90       (setf result (and result (string= (write-string *dumb-string* s)
91                                         *dumb-string*))))
92
93     (with-test-file (s *test-file* :class 'file-simple-stream
94                        :direction :input :if-does-not-exist :error)
95       ;; Check first line
96       (multiple-value-bind (string missing-newline-p)
97           (read-line s)
98         (setf result (and result (string= string *dumb-string*)
99                           (not missing-newline-p))))
100       ;; Check second line
101       (multiple-value-bind (string missing-newline-p)
102           (read-line s)
103         (setf result (and result (string= string *dumb-string*)
104                           missing-newline-p))))
105     result)
106   t)
107
108 (deftest create-read-mapped-file-1
109   ;; Read data via a mapped-file-simple-stream object.
110   (let ((result t))
111     (with-test-file (s *test-file* :class 'mapped-file-simple-stream
112                        :direction :input :if-does-not-exist :error
113                        :initial-content *dumb-string*)
114       (setf result (and result (string= (read-line s) *dumb-string*))))
115     result)
116   t)
117
118 (deftest write-read-inet
119   (handler-case
120       (with-open-stream (s (make-instance 'socket-simple-stream
121                                           :remote-host #(127 0 0 1)
122                                           :remote-port 7
123                                           :direction :io))
124         (string= (prog1 (write-line "Got it!" s) (finish-output s))
125                  (read-line s)))
126     ;; Fail gracefully if echo isn't activated on the system
127     (sb-bsd-sockets::connection-refused-error () t))
128   t)
129
130 (deftest write-read-large-sc-1
131   ;; Do write and read with more data than the buffer will hold
132   ;; (single-channel simple-stream)
133   (let* ((stream (make-instance 'file-simple-stream
134                                 :filename *test-file* :direction :output
135                                 :if-exists :overwrite
136                                 :if-does-not-exist :create))
137          (content (make-string (1+ (device-buffer-length stream))
138                                :initial-element #\x)))
139     (with-open-stream (s stream)
140       (write-string content s))
141     (with-test-file (s *test-file* :class 'file-simple-stream
142                        :direction :input :if-does-not-exist :error)
143       (string= content (read-line s))))
144   t)
145
146 (deftest write-read-large-sc-2
147   (let* ((stream (make-instance 'file-simple-stream
148                                 :filename *test-file* :direction :output
149                                 :if-exists :overwrite
150                                 :if-does-not-exist :create))
151          (length (1+ (* 3 (device-buffer-length stream))))
152          (content (make-string length)))
153     (dotimes (i (length content))
154       (setf (aref content i) (code-char (random 256))))
155     (with-open-stream (s stream)
156       (write-string content s))
157     (with-test-file (s *test-file* :class 'file-simple-stream
158                        :direction :input :if-does-not-exist :error)
159       (let ((seq (make-string length)))
160         #+nil (read-sequence seq s)
161         #-nil (dotimes (i length)
162                 (setf (char seq i) (read-char s)))
163         (string= content seq))))
164   t)
165
166 (deftest write-read-large-sc-3
167   (let* ((stream (make-instance 'file-simple-stream
168                                 :filename *test-file* :direction :output
169                                 :if-exists :overwrite
170                                 :if-does-not-exist :create))
171          (length (1+ (* 3 (device-buffer-length stream))))
172          (content (make-array length :element-type '(unsigned-byte 8))))
173     (dotimes (i (length content))
174       (setf (aref content i) (random 256)))
175     (with-open-stream (s stream)
176       (write-sequence content s))
177     (with-test-file (s *test-file* :class 'file-simple-stream
178                        :direction :input :if-does-not-exist :error)
179       (let ((seq (make-array length :element-type '(unsigned-byte 8))))
180         #+nil (read-sequence seq s)
181         #-nil (dotimes (i length)
182                 (setf (aref seq i) (read-byte s)))
183         (equalp content seq))))
184   t)
185
186 (deftest write-read-large-dc-1
187   ;; Do write and read with more data than the buffer will hold
188   ;; (dual-channel simple-stream; we only have socket streams atm)
189   (handler-case
190    (let* ((stream (make-instance 'socket-simple-stream
191                                  :remote-host #(127 0 0 1)
192                                  :remote-port 7
193                                  :direction :io))
194           (content (make-string (1+ (device-buffer-length stream))
195                                 :initial-element #\x)))
196      (with-open-stream (s stream)
197        (string= (prog1 (write-line content s) (finish-output s))
198                 (read-line s))))
199     ;; Fail gracefully if echo isn't activated on the system
200    (sb-bsd-sockets::connection-refused-error () t))
201   t)
202
203
204 (deftest file-position-1
205     ;; Test reading of file-position
206     (with-test-file (s *test-file* :class 'file-simple-stream :direction :input
207                        :initial-content *dumb-string*)
208       (file-position s))
209   0)
210
211 (deftest file-position-2
212     ;; Test reading of file-position
213     (with-test-file (s *test-file* :class 'file-simple-stream :direction :input
214                        :initial-content *dumb-string*)
215       (read-byte s)
216       (file-position s))
217   1)
218
219 (deftest file-position-3
220     ;; Test reading of file-position in the presence of unsaved data
221     (with-test-file (s *test-file* :class 'file-simple-stream
222                        :direction :output :if-exists :supersede
223                        :if-does-not-exist :create)
224       (write-byte 50 s)
225       (file-position s))
226   1)
227
228 (deftest file-position-4
229     ;; Test reading of file-position in the presence of unsaved data and
230     ;; filled buffer
231     (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
232                        :if-exists :overwrite :if-does-not-exist :create
233                        :initial-content *dumb-string*)
234       (read-byte s)                     ; fill buffer
235       (write-byte 50 s)                 ; advance file-position
236       (file-position s))
237   2)
238
239 (deftest file-position-5
240     ;; Test file position when opening with :if-exists :append
241     (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
242                        :if-exists :append :if-does-not-exist :create
243                        :initial-content *dumb-string*)
244       (= (file-length s) (file-position s)))
245   T)
246
247 (deftest write-read-unflushed-sc-1
248     ;; Write something into a single-channel stream and read it back
249     ;; without explicitly flushing the buffer in-between
250     (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
251                        :if-does-not-exist :create :if-exists :supersede)
252       (write-char #\x s)
253       (file-position s :start)
254       (read-char s))
255   #\x)
256
257 (deftest write-read-unflushed-sc-2
258     ;; Write something into a single-channel stream, try to read back too much
259     (handler-case
260         (with-test-file (s *test-file* :class 'file-simple-stream
261                            :direction :io :if-does-not-exist :create
262                            :if-exists :supersede)
263             (write-char #\x s)
264             (file-position s :start)
265             (read-char s)
266             (read-char s)
267             nil)
268       (end-of-file () t))
269   t)
270
271 (deftest write-read-unflushed-sc-3
272     ;; Test writing in a buffer filled with previous file contents
273     (let ((result t))
274       (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
275                          :if-exists :overwrite :if-does-not-exist :create
276                          :initial-content *dumb-string*)
277         (setq result (and result (char= (read-char s) (schar *dumb-string* 0))))
278         (setq result (and result (= (file-position s) 1)))
279         (let ((pos (file-position s)))
280           (write-char #\x s)
281           (file-position s pos)
282           (setq result (and result (char= (read-char s) #\x)))))
283       result)
284   t)
285
286 (deftest write-read-unflushed-sc-4
287     ;; Test flushing of buffers
288     (progn
289       (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
290                          :if-exists :overwrite :if-does-not-exist :create
291                          :initial-content "Foo"
292                          :delete-afterwards nil)
293         (read-char s)                   ; Fill the buffer.
294         (file-position s :start)        ; Change existing data.
295         (write-char #\X s)
296         (file-position s :end)          ; Extend file.
297         (write-char #\X s))
298       (with-test-file (s *test-file* :class 'file-simple-stream
299                          :direction :input :if-does-not-exist :error)
300         (read-line s)))
301   "XooX"
302   T)
303
304 (deftest write-read-append-sc-1
305     ;; Test writing in the middle of a stream opened in append mode
306     (progn
307       (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
308                          :if-exists :append :if-does-not-exist :create
309                          :initial-content "Foo"
310                          :delete-afterwards nil)
311         (file-position s :start)        ; Jump to beginning.
312         (write-char #\X s)
313         (file-position s :end)          ; Extend file.
314         (write-char #\X s))
315       (with-test-file (s *test-file* :class 'file-simple-stream
316                          :direction :input :if-does-not-exist :error)
317         (read-line s)))
318   "XooX"
319   T)
320
321 (deftest write-read-mixed-sc-1
322     ;; Test read/write-sequence of types string and (unsigned-byte 8)
323     (let ((uvector (make-array '(10) :element-type '(unsigned-byte 8)
324                                :initial-element 64))
325           (svector (make-array '(10) :element-type '(signed-byte 8)
326                                :initial-element -1))
327           (result-uvector (make-array '(10) :element-type '(unsigned-byte 8)
328                               :initial-element 0))
329           (result-svector (make-array '(10) :element-type '(signed-byte 8)
330                               :initial-element 0))
331           (result-string (make-string (length *dumb-string*)
332                                       :initial-element #\Space)))
333       (with-test-file (s *test-file* :class 'file-simple-stream :direction :io
334                          :if-exists :overwrite :if-does-not-exist :create
335                          :delete-afterwards nil)
336         (write-sequence svector s)
337         (write-sequence uvector s)
338         (write-sequence *dumb-string* s))
339       (with-test-file (s *test-file* :class 'file-simple-stream
340                          :direction :input :if-does-not-exist :error
341                          :delete-afterwards nil)
342         (read-sequence result-svector s)
343         (read-sequence result-uvector s)
344         (read-sequence result-string s))
345       (and (string= *dumb-string* result-string)
346            (equalp uvector result-uvector)
347            (equalp svector result-svector)))
348   T)
349
350 (defparameter *multi-line-string*
351   "This file was created by simple-stream-tests.lisp.
352 Nothing to see here, move along.")
353
354 (defmacro with-dc-test-stream ((s &key initial-content) &body body)
355   `(with-test-file
356        (.ansi-stream.
357         *test-file*
358         :direction :io
359         :if-exists :overwrite
360         :initial-content ,(or initial-content '*multi-line-string*))
361      (let ((,s (make-instance 'terminal-simple-stream
362                  :input-handle (sb-kernel::fd-stream-fd .ansi-stream.)
363                  :output-handle (sb-kernel::fd-stream-fd .ansi-stream.))))
364        ,@body)))
365
366 (defmacro with-sc-test-stream ((s &key initial-content) &body body)
367   `(with-test-file
368        (,s
369         *test-file*
370         :class 'file-simple-stream
371         :direction :io
372         :if-exists :overwrite
373         :initial-content ,(or initial-content '*multi-line-string*))
374      ,@body))
375
376 (deftest listen-dc-1
377     ;; LISTEN with filled buffer
378     (with-dc-test-stream (s) (read-char s) (listen s))
379   T)
380
381 (deftest listen-dc-2
382     ;; LISTEN with empty buffer
383     (with-dc-test-stream (s) (listen s))
384   T)
385
386 (deftest listen-dc-3
387     ;; LISTEN at EOF
388     (with-dc-test-stream (s)
389       (read-line s)
390       (read-line s)
391       (listen s))
392   NIL)
393
394 ;;; the following tests are for problems fixed in SBCL 0.8.6.2:
395
396 (deftest charpos-1
397     ;; check for bug involving the -1 vs. 0 oddity in std-dc-newline-in-handler
398     ;;
399     ;; Note: It not not clear to me that input should affect the CHARPOS at
400     ;; all.  (Except for a terminal stream perhaps, which our test stream
401     ;; happens to be.  Hmm.)
402     ;;
403     ;; But CHARPOS must not be -1, so much is sure, hence this test is right
404     ;; in any case.
405     (with-dc-test-stream (s)
406       (read-line s)
407       (sb-simple-streams:charpos s))
408   0)
409
410 (deftest charpos-2
411     ;; FIXME: It not not clear to me that input should affect the CHARPOS at
412     ;; all, and indeed it does not.  That is, except for newlines?! (see above)
413     ;;
414     ;; What this test does is (a) check that the CHARPOS works at all without
415     ;; erroring and (b) force anyone changing the CHARPOS behaviour to read
416     ;; this comment and start thinking things through better than I can.
417     (with-dc-test-stream (s)
418       (read-char s)
419       (and (eql (sb-kernel:charpos s) 0)
420            (eql (sb-simple-streams:charpos s) 0)))
421   T)
422
423 (deftest reader-1
424     ;; does the reader support simple streams?  Note that, say, "123" instead
425     ;; of "(1 2)" does not trigger the bugs present in SBCL 0.8.6.
426     (with-dc-test-stream (s :initial-content "(1 2)")
427       (equal (read s) '(1 2)))
428   T)
429
430 (deftest line-length-dc-1
431     ;; does LINE-LENGTH support simple streams?  
432     (with-dc-test-stream (s)
433       (eql (sb-simple-streams:line-length s)
434            (sb-kernel:line-length s)))
435   T)
436
437 (defvar *synonym*)
438
439 ;; the biggest change in 0.8.6.2:
440 ;; support composite streams writing to simple streams
441
442 ;; first, SYNONYM-STREAM:
443
444 (deftest synonym-stream-1
445     ;; READ-CHAR
446     (with-dc-test-stream (*synonym*)
447       (read-char (make-synonym-stream '*synonym*)))
448   #\T)
449
450 (deftest synonym-stream-2
451     ;; UNREAD-CHAR (via STREAM-MISC-DISPATCH)
452     (with-dc-test-stream (*synonym*)
453       (let ((s (make-synonym-stream '*synonym*)))
454         (unread-char (read-char s) s)
455         (read-char s)))
456   #\T)
457
458 (deftest synonym-stream-3
459     ;; READ-BYTE
460     (with-dc-test-stream (*synonym*)
461       (read-byte (make-synonym-stream '*synonym*)))
462   #.(char-code #\T))
463
464 (deftest synonym-stream-4
465     ;; WRITE-CHAR
466     (with-sc-test-stream (*synonym*)
467       (let ((s (make-synonym-stream '*synonym*)))
468         (write-char #\A s)
469         (file-position s 0)
470         (read-char s)))
471   #\A)
472
473 (deftest synonym-stream-5
474     ;; WRITE-BYTE
475     (with-sc-test-stream (*synonym*)
476       (let ((s (make-synonym-stream '*synonym*)))
477         (write-byte 65 s)
478         (file-position s 0)
479         (read-char s)))
480   #\A)
481
482 (deftest synonym-stream-6
483     ;; WRITE-STRING
484     (with-sc-test-stream (*synonym*)
485       (let ((s (make-synonym-stream '*synonym*)))
486         (write-string "ab" s)
487         (file-position s 0)
488         (and (char= (read-char s) #\a)
489              (char= (read-char s) #\b))))
490   T)
491
492 (deftest synonym-stream-7
493     ;; LISTEN (via STREAM-MISC-DISPATCH)
494     (with-sc-test-stream (*synonym*)
495       (let ((s (make-synonym-stream '*synonym*)))
496         (and (listen s) t)))
497   T)
498
499 (deftest synonym-stream-8
500     ;; CLEAR-INPUT (via STREAM-MISC-DISPATCH)
501     (with-sc-test-stream (*synonym*)
502       (let ((s (make-synonym-stream '*synonym*)))
503         (clear-input s)))
504   NIL)
505
506 (deftest synonym-stream-9
507     ;; FORCE-OUTPUT (via STREAM-MISC-DISPATCH)
508     (with-sc-test-stream (*synonym*)
509       ;; could test more here
510       (force-output (make-synonym-stream '*synonym*)))
511   NIL)
512
513 (deftest synonym-stream-10
514     ;; FINISH-OUTPUT (via STREAM-MISC-DISPATCH)
515     (with-sc-test-stream (*synonym*)
516       ;; could test more here
517       (finish-output (make-synonym-stream '*synonym*)))
518   NIL)
519
520 (deftest synonym-stream-11
521     ;; STREAM-ELEMENT-TYPE (via STREAM-MISC-DISPATCH)
522     (with-sc-test-stream (*synonym*)
523       (eql (stream-element-type (make-synonym-stream '*synonym*))
524            (stream-element-type *synonym*)))
525   T)
526
527 (deftest synonym-stream-12
528     ;; INTERACTIVE-STREAM-P (via STREAM-MISC-DISPATCH)
529     (with-sc-test-stream (*synonym*)
530       (eql (interactive-stream-p (make-synonym-stream '*synonym*))
531            (interactive-stream-p *synonym*)))
532   T)
533
534 (deftest synonym-stream-13
535     ;; LINE-LENGTH (via STREAM-MISC-DISPATCH)
536     (with-sc-test-stream (*synonym*)
537       (eql (sb-kernel:line-length (make-synonym-stream '*synonym*))
538            (sb-kernel:line-length *synonym*)))
539   T)
540
541 (deftest synonym-stream-14
542     ;; CHARPOS (via STREAM-MISC-DISPATCH)
543     (with-sc-test-stream (*synonym*)
544       (eql (sb-kernel:charpos (make-synonym-stream '*synonym*))
545            (sb-kernel:charpos *synonym*)))
546   T)
547
548 (deftest synonym-stream-15
549     ;; FILE-LENGTH (via STREAM-MISC-DISPATCH)
550     (with-sc-test-stream (*synonym*)
551       (eql (file-length (make-synonym-stream '*synonym*))
552            (file-length *synonym*)))
553   T)
554
555 (deftest synonym-stream-16
556     ;; FILE-POSITION (via STREAM-MISC-DISPATCH)
557     (with-sc-test-stream (*synonym*)
558       (eql (file-position (make-synonym-stream '*synonym*))
559            (file-position *synonym*)))
560   T)
561
562 ;; SYNONYM-STREAM tests repeated for BROADCAST-STREAM, where applicable
563
564 (deftest broadcast-stream-4
565     ;; WRITE-CHAR
566     (with-sc-test-stream (synonym)
567       (let ((s (make-broadcast-stream synonym)))
568         (write-char #\A s)
569         (force-output s))
570       (file-position synonym 0)
571       (read-char synonym))
572   #\A)
573
574 (deftest broadcast-stream-5
575     ;; WRITE-BYTE
576     (with-sc-test-stream (synonym)
577       (let ((s (make-broadcast-stream synonym)))
578         (write-byte 65 s)
579         (force-output s))
580       (file-position synonym 0)
581       (read-char synonym))
582   #\A)
583
584 (deftest broadcast-stream-6
585     ;; WRITE-STRING
586     (with-sc-test-stream (synonym)
587       (let ((s (make-broadcast-stream synonym)))
588         (write-string "ab" s)
589         (force-output s))
590       (file-position synonym 0)
591       (and (char= (read-char synonym) #\a)
592            (char= (read-char synonym) #\b)))
593   T)
594
595 (deftest broadcast-stream-9
596     ;; FORCE-OUTPUT (via STREAM-MISC-DISPATCH)
597     (with-sc-test-stream (synonym)
598       ;; could test more here
599       (force-output (make-broadcast-stream synonym)))
600   NIL)
601
602 (deftest broadcast-stream-10
603     ;; FINISH-OUTPUT (via STREAM-MISC-DISPATCH)
604     (with-sc-test-stream (synonym)
605       ;; could test more here
606       (finish-output (make-broadcast-stream synonym)))
607   NIL)
608
609 (deftest broadcast-stream-11
610     ;; STREAM-ELEMENT-TYPE (via STREAM-MISC-DISPATCH)
611     (with-sc-test-stream (synonym)
612       (eql (stream-element-type (make-broadcast-stream synonym))
613            (stream-element-type synonym)))
614   T)
615
616 (deftest broadcast-stream-12
617     ;; INTERACTIVE-STREAM-P (via STREAM-MISC-DISPATCH)
618     (with-sc-test-stream (synonym)
619       (eql (interactive-stream-p (make-broadcast-stream synonym))
620            (interactive-stream-p synonym)))
621   T)
622
623 (deftest broadcast-stream-13
624     ;; LINE-LENGTH (via STREAM-MISC-DISPATCH)
625     (with-sc-test-stream (synonym)
626       (eql (sb-kernel:line-length (make-broadcast-stream synonym))
627            (sb-kernel:line-length synonym)))
628   T)
629
630 (deftest broadcast-stream-14
631     ;; CHARPOS (via STREAM-MISC-DISPATCH)
632     (with-sc-test-stream (synonym)
633       (eql (sb-kernel:charpos (make-broadcast-stream synonym))
634            (sb-kernel:charpos synonym)))
635   T)
636
637 (deftest broadcast-stream-16
638     ;; FILE-POSITION (via STREAM-MISC-DISPATCH)
639     (with-sc-test-stream (synonym)
640       (eql (file-position (make-broadcast-stream synonym))
641            (file-position synonym)))
642   T)
643
644 ;; SYNONYM-STREAM tests repeated for TWO-WAY-STREAM, where applicable
645
646 (deftest two-way-stream-1
647     ;; READ-CHAR
648     (with-dc-test-stream (synonym)
649       (read-char (make-two-way-stream synonym synonym)))
650   #\T)
651
652 (deftest two-way-stream-2
653     ;; UNREAD-CHAR (via STREAM-MISC-DISPATCH)
654     (with-dc-test-stream (synonym)
655       (let ((s (make-two-way-stream synonym synonym)))
656         (unread-char (read-char s) s)
657         (read-char s)))
658   #\T)
659
660 (deftest two-way-stream-3
661     ;; READ-BYTE
662     (with-dc-test-stream (synonym)
663       (read-byte (make-two-way-stream synonym synonym)))
664   #.(char-code #\T))
665
666 (deftest two-way-stream-4
667     ;; WRITE-CHAR
668     (with-sc-test-stream (synonym)
669       (let ((s (make-two-way-stream synonym synonym)))
670         (write-char #\A s)
671         (force-output s))
672       (file-position synonym 0)
673       (read-char synonym))
674   #\A)
675
676 (deftest two-way-stream-5
677     ;; WRITE-BYTE
678     (with-sc-test-stream (synonym)
679       (let ((s (make-two-way-stream synonym synonym)))
680         (write-byte 65 s)
681         (force-output s))
682       (file-position synonym 0)
683       (read-char synonym))
684   #\A)
685
686 (deftest two-way-stream-6
687     ;; WRITE-STRING
688     (with-sc-test-stream (synonym)
689       (let ((s (make-two-way-stream synonym synonym)))
690         (write-string "ab" s)
691         (force-output s))
692       (file-position synonym 0)
693       (and (char= (read-char synonym) #\a)
694            (char= (read-char synonym) #\b)))
695   T)
696
697 (deftest two-way-stream-7
698     ;; LISTEN (via STREAM-MISC-DISPATCH)
699     (with-sc-test-stream (synonym)
700       (let ((s (make-two-way-stream synonym synonym)))
701         (and (listen s) t)))
702   T)
703
704 (deftest two-way-stream-8
705     ;; CLEAR-INPUT (via STREAM-MISC-DISPATCH)
706     (with-sc-test-stream (synonym)
707       (let ((s (make-two-way-stream synonym synonym)))
708         (clear-input s)))
709   NIL)
710
711 (deftest two-way-stream-9
712     ;; FORCE-OUTPUT (via STREAM-MISC-DISPATCH)
713     (with-sc-test-stream (synonym)
714       ;; could test more here
715       (force-output (make-two-way-stream synonym synonym)))
716   NIL)
717
718 (deftest two-way-stream-10
719     ;; FINISH-OUTPUT (via STREAM-MISC-DISPATCH)
720     (with-sc-test-stream (synonym)
721       ;; could test more here
722       (finish-output (make-two-way-stream synonym synonym)))
723   NIL)
724
725 (deftest two-way-stream-11
726     ;; STREAM-ELEMENT-TYPE (via STREAM-MISC-DISPATCH)
727     (with-sc-test-stream (synonym)
728       (eql (stream-element-type (make-two-way-stream synonym synonym))
729            (stream-element-type synonym)))
730   T)
731
732 (deftest two-way-stream-12
733     ;; INTERACTIVE-STREAM-P (via STREAM-MISC-DISPATCH)
734     (with-sc-test-stream (synonym)
735       (eql (interactive-stream-p (make-two-way-stream synonym synonym))
736            (interactive-stream-p synonym)))
737   T)
738
739 (deftest two-way-stream-13
740     ;; LINE-LENGTH (via STREAM-MISC-DISPATCH)
741     (with-sc-test-stream (synonym)
742       (eql (sb-kernel:line-length (make-two-way-stream synonym synonym))
743            (sb-kernel:line-length synonym)))
744   T)
745
746 (deftest two-way-stream-14
747     ;; CHARPOS (via STREAM-MISC-DISPATCH)
748     (with-sc-test-stream (synonym)
749       (eql (sb-kernel:charpos (make-two-way-stream synonym synonym))
750            (sb-kernel:charpos synonym)))
751   T)
752
753 (deftest two-way-stream-16
754     ;; FILE-POSITION (via STREAM-MISC-DISPATCH)
755     (with-sc-test-stream (synonym)
756       (eql (file-position (make-two-way-stream synonym synonym))
757            (file-position synonym)))
758   T)
759
760 ;; SYNONYM-STREAM tests repeated for ECHO-STREAM, where applicable
761
762 (deftest echo-stream-1
763     ;; READ-CHAR
764     (with-dc-test-stream (*synonym*)
765       (read-char (make-echo-stream *synonym* *synonym*)))
766   #\T)
767
768 (deftest echo-stream-2
769     ;; UNREAD-CHAR (via STREAM-MISC-DISPATCH)
770     (with-dc-test-stream (*synonym*)
771       (let ((s (make-echo-stream *synonym* *synonym*)))
772         (unread-char (read-char s) s)
773         (read-char s)))
774   #\T)
775
776 (deftest echo-stream-3
777     ;; READ-BYTE
778     (with-dc-test-stream (*synonym*)
779       (read-byte (make-echo-stream *synonym* *synonym*)))
780   #.(char-code #\T))
781
782 (deftest echo-stream-7
783     ;; LISTEN (via STREAM-MISC-DISPATCH)
784     (with-sc-test-stream (*synonym*)
785       (let ((s (make-echo-stream *synonym* *synonym*)))
786         (and (listen s) t)))
787   T)
788
789 (deftest echo-stream-8
790     ;; CLEAR-INPUT (via STREAM-MISC-DISPATCH)
791     (with-sc-test-stream (*synonym*)
792       (let ((s (make-echo-stream *synonym* *synonym*)))
793         (clear-input s)))
794   NIL)
795
796 (deftest echo-stream-11
797     ;; STREAM-ELEMENT-TYPE (via STREAM-MISC-DISPATCH)
798     (with-sc-test-stream (*synonym*)
799       (eql (stream-element-type (make-echo-stream *synonym* *synonym*))
800            (stream-element-type *synonym*)))
801   T)
802
803 (deftest echo-stream-12
804     ;; INTERACTIVE-STREAM-P (via STREAM-MISC-DISPATCH)
805     (with-sc-test-stream (*synonym*)
806       (eql (interactive-stream-p (make-echo-stream *synonym* *synonym*))
807            (interactive-stream-p *synonym*)))
808   T)
809
810 (deftest echo-stream-13
811     ;; LINE-LENGTH (via STREAM-MISC-DISPATCH)
812     (with-sc-test-stream (*synonym*)
813       (eql (sb-kernel:line-length (make-echo-stream *synonym* *synonym*))
814            (sb-kernel:line-length *synonym*)))
815   T)
816
817 (deftest echo-stream-14
818     ;; CHARPOS (via STREAM-MISC-DISPATCH)
819     (with-sc-test-stream (*synonym*)
820       (eql (sb-kernel:charpos (make-echo-stream *synonym* *synonym*))
821            (sb-kernel:charpos *synonym*)))
822   T)
823
824 (deftest echo-stream-16
825     ;; FILE-POSITION (via STREAM-MISC-DISPATCH)
826     (with-sc-test-stream (*synonym*)
827       (eql (file-position (make-echo-stream *synonym* *synonym*))
828            (file-position *synonym*)))
829   T)
830
831 ;; SYNONYM-STREAM tests repeated for CONCATENATED-STREAM, where applicable
832
833 (deftest concatenated-stream-1
834     ;; READ-CHAR
835     (with-dc-test-stream (*synonym*)
836       (read-char (make-concatenated-stream *synonym*)))
837   #\T)
838
839 (deftest concatenated-stream-2
840     ;; UNREAD-CHAR (via STREAM-MISC-DISPATCH)
841     (with-dc-test-stream (*synonym*)
842       (let ((s (make-concatenated-stream *synonym*)))
843         (unread-char (read-char s) s)
844         (read-char s)))
845   #\T)
846
847 (deftest concatenated-stream-3
848     ;; READ-BYTE
849     (with-dc-test-stream (*synonym*)
850       (read-byte (make-concatenated-stream *synonym*)))
851   #.(char-code #\T))
852
853 (deftest concatenated-stream-7
854     ;; LISTEN (via STREAM-MISC-DISPATCH)
855     (with-sc-test-stream (*synonym*)
856       (let ((s (make-concatenated-stream *synonym*)))
857         (and (listen s) t)))
858   T)
859
860 (deftest concatenated-stream-8
861     ;; CLEAR-INPUT (via STREAM-MISC-DISPATCH)
862     (with-sc-test-stream (*synonym*)
863       (let ((s (make-concatenated-stream *synonym*)))
864         (clear-input s)))
865   NIL)
866
867 (deftest concatenated-stream-11
868     ;; STREAM-ELEMENT-TYPE (via STREAM-MISC-DISPATCH)
869     (with-sc-test-stream (*synonym*)
870       (eql (stream-element-type (make-concatenated-stream *synonym*))
871            (stream-element-type *synonym*)))
872   T)
873
874 (deftest concatenated-stream-12
875     ;; INTERACTIVE-STREAM-P (via STREAM-MISC-DISPATCH)
876     (with-sc-test-stream (*synonym*)
877       (eql (interactive-stream-p (make-concatenated-stream *synonym*))
878            (interactive-stream-p *synonym*)))
879   T)
880
881 (deftest concatenated-stream-13
882     ;; LINE-LENGTH (via STREAM-MISC-DISPATCH)
883     (with-sc-test-stream (*synonym*)
884       (eql (sb-kernel:line-length (make-concatenated-stream *synonym*))
885            (sb-kernel:line-length *synonym*)))
886   T)
887
888 (deftest concatenated-stream-14
889     ;; CHARPOS (via STREAM-MISC-DISPATCH)
890     (with-sc-test-stream (*synonym*)
891       (eql (sb-kernel:charpos (make-concatenated-stream *synonym*))
892            (sb-kernel:charpos *synonym*)))
893   T)
894
895 (deftest concatenated-stream-16
896     ;; FILE-POSITION (via STREAM-MISC-DISPATCH)
897     (with-sc-test-stream (*synonym*)
898       (eql (file-position (make-concatenated-stream *synonym*))
899            (file-position *synonym*)))
900   T)
901
902 ;; uncovered by synonym-stream-15
903
904 (deftest file-simple-stream-1
905     (values (subtypep 'file-simple-stream 'file-stream))
906   T)
907
908 (deftest string-simple-stream-1
909     (values (subtypep 'string-simple-stream 'string-stream))
910   T)