1+ <?php namespace io \unittest ;
2+
3+ use ArrayIterator ;
4+ use io \streams \{InputStream , MemoryInputStream , SequenceInputStream };
5+ use lang \IllegalArgumentException ;
6+ use test \{Assert , Expect , Test };
7+
8+ class SequenceInputStreamTest {
9+
10+ /** Drains a stream */
11+ private function drain (InputStream $ stream ): array {
12+ $ r = [];
13+ while ($ available = $ stream ->available ()) {
14+ $ r []= [$ available , $ stream ->read ()];
15+ }
16+ $ r []= [$ stream ->available (), $ stream ->read ()];
17+ return $ r ;
18+ }
19+
20+ /** Creates a memory input stream with a `closed` property */
21+ private function closeable (string $ input ): MemoryInputStream {
22+ return new class ($ input ) extends MemoryInputStream {
23+ public $ closed = false ;
24+ public function close () { $ this ->closed = true ; }
25+ };
26+ }
27+
28+ #[Test, Expect(IllegalArgumentException::class)]
29+ public function without_arguments () {
30+ new SequenceInputStream ();
31+ }
32+
33+ #[Test, Expect(IllegalArgumentException::class)]
34+ public function with_empty_array () {
35+ new SequenceInputStream ([]);
36+ }
37+
38+ #[Test]
39+ public function drain_one () {
40+ $ fixture = new SequenceInputStream (new MemoryInputStream ('Test ' ));
41+ Assert::equals ([[4 , 'Test ' ], [0 , '' ]], $ this ->drain ($ fixture ));
42+ }
43+
44+ #[Test]
45+ public function drain_multiple () {
46+ $ fixture = new SequenceInputStream (
47+ new MemoryInputStream ('One ' ),
48+ new MemoryInputStream ('Two ' )
49+ );
50+ Assert::equals ([[3 , 'One ' ], [3 , 'Two ' ], [0 , '' ]], $ this ->drain ($ fixture ));
51+ }
52+
53+ #[Test]
54+ public function drain_array () {
55+ $ fixture = new SequenceInputStream ([
56+ new MemoryInputStream ('One ' ),
57+ new MemoryInputStream ('Two ' )
58+ ]);
59+ Assert::equals ([[3 , 'One ' ], [3 , 'Two ' ], [0 , '' ]], $ this ->drain ($ fixture ));
60+ }
61+
62+ #[Test]
63+ public function drain_iterator () {
64+ $ fixture = new SequenceInputStream (new ArrayIterator ([
65+ yield new MemoryInputStream ('One ' ),
66+ yield new MemoryInputStream ('Two ' )
67+ ]));
68+ Assert::equals ([[3 , 'One ' ], [3 , 'Two ' ], [0 , '' ]], $ this ->drain ($ fixture ));
69+ }
70+
71+ #[Test]
72+ public function drain_generator () {
73+ $ streams = function () {
74+ yield new MemoryInputStream ('One ' );
75+ yield new MemoryInputStream ('Two ' );
76+ };
77+ $ fixture = new SequenceInputStream ($ streams ());
78+ Assert::equals ([[3 , 'One ' ], [3 , 'Two ' ], [0 , '' ]], $ this ->drain ($ fixture ));
79+ }
80+
81+ #[Test]
82+ public function using_only_read () {
83+ $ fixture = new SequenceInputStream (
84+ new MemoryInputStream ('One ' ),
85+ new MemoryInputStream ('Two ' )
86+ );
87+
88+ Assert::equals ('One ' , $ fixture ->read ());
89+ Assert::equals ('Two ' , $ fixture ->read ());
90+ Assert::equals ('' , $ fixture ->read ());
91+ }
92+
93+ #[Test]
94+ public function close_closes_all_streams () {
95+ $ one = $ this ->closeable ('One ' );
96+ $ two = $ this ->closeable ('Two ' );
97+ $ fixture = new SequenceInputStream ($ one , $ two );
98+ $ fixture ->close ();
99+
100+ Assert::equals ([true , true ], [$ one ->closed , $ two ->closed ]);
101+ }
102+
103+ #[Test]
104+ public function streams_closed_when_drained () {
105+ $ one = $ this ->closeable ('One ' );
106+ $ two = $ this ->closeable ('Two ' );
107+ $ fixture = new SequenceInputStream ($ one , $ two );
108+ $ this ->drain ($ fixture );
109+ $ fixture ->close ();
110+
111+ Assert::equals ([true , true ], [$ one ->closed , $ two ->closed ]);
112+ }
113+ }
0 commit comments