1+ <?php namespace io \unittest ;
2+
3+ use io \streams \{SpooledInputStream , MemoryInputStream , Streams };
4+ use io \{TempFile , Folder , Path , IOException };
5+ use lang \Environment ;
6+ use test \{Assert , Expect , Test , Values };
7+
8+ class SpooledInputStreamTest {
9+ const BYTES = 'Test success ' ;
10+
11+ /** @param ?string|io.Path|io.Folder|io.File $temp */
12+ private function newFixture ($ temp = null ): SpooledInputStream {
13+ return new SpooledInputStream (new MemoryInputStream (self ::BYTES ), $ temp );
14+ }
15+
16+ #[Test]
17+ public function can_create () {
18+ $ this ->newFixture ();
19+ }
20+
21+ #[Test]
22+ public function reading () {
23+ $ stream = $ this ->newFixture ();
24+
25+ Assert::equals (0 , $ stream ->tell ());
26+ Assert::equals (strlen (self ::BYTES ), $ stream ->available ());
27+ Assert::equals (self ::BYTES , Streams::readAll ($ stream ));
28+ }
29+
30+ #[Test]
31+ public function reading_after_seeking () {
32+ $ stream = $ this ->newFixture ();
33+ $ stream ->seek (5 );
34+ $ stream ->seek (0 );
35+
36+ Assert::equals (0 , $ stream ->tell ());
37+ Assert::equals (strlen (self ::BYTES ), $ stream ->available ());
38+ Assert::equals (self ::BYTES , Streams::readAll ($ stream ));
39+ }
40+
41+ #[Test, Values([0 , 1 , 5 ])]
42+ public function seeking_forward ($ offset ) {
43+ $ stream = $ this ->newFixture ();
44+ $ stream ->seek ($ offset , SEEK_SET );
45+
46+ Assert::equals ($ offset , $ stream ->tell ());
47+ Assert::equals (strlen (self ::BYTES ) - $ offset , $ stream ->available ());
48+ Assert::equals (substr (self ::BYTES , $ offset ), Streams::readAll ($ stream ));
49+ }
50+
51+ #[Test, Values([0 , -1 , -5 ])]
52+ public function seeking_to_end ($ offset ) {
53+ $ stream = $ this ->newFixture ();
54+ $ stream ->seek ($ offset , SEEK_END );
55+
56+ Assert::equals (strlen (self ::BYTES ) + $ offset , $ stream ->tell ());
57+ Assert::equals (-$ offset , $ stream ->available ());
58+ Assert::equals (substr (self ::BYTES , strlen (self ::BYTES ) + $ offset ), Streams::readAll ($ stream ));
59+ }
60+
61+ #[Test, Values([0 , 1 , -1 ])]
62+ public function seeking_relative ($ offset ) {
63+ $ stream = $ this ->newFixture ();
64+ $ stream ->seek (5 , SEEK_SET );
65+ $ stream ->seek ($ offset , SEEK_CUR );
66+
67+ Assert::equals (5 + $ offset , $ stream ->tell ());
68+ Assert::equals (strlen (self ::BYTES ) - 5 - $ offset , $ stream ->available ());
69+ Assert::equals (substr (self ::BYTES , 5 + $ offset ), Streams::readAll ($ stream ));
70+ }
71+
72+ #[Test, Values([0 , 1 , 5 ])]
73+ public function seeking_forward_set ($ offset ) {
74+ $ stream = $ this ->newFixture ();
75+ $ stream ->seek ($ offset , SEEK_SET );
76+
77+ Assert::equals ($ offset , $ stream ->tell ());
78+ Assert::equals (strlen (self ::BYTES ) - $ offset , $ stream ->available ());
79+ Assert::equals (substr (self ::BYTES , $ offset ), Streams::readAll ($ stream ));
80+ }
81+
82+ #[Test, Values([0 , 1 , 5 ])]
83+ public function seeking_forward_cur ($ offset ) {
84+ $ stream = $ this ->newFixture ();
85+ $ stream ->seek (strlen (self ::BYTES ), SEEK_SET );
86+ $ stream ->seek (-$ offset , SEEK_CUR );
87+
88+ Assert::equals (strlen (self ::BYTES ) - $ offset , $ stream ->tell ());
89+ Assert::equals ($ offset , $ stream ->available ());
90+ Assert::equals (substr (self ::BYTES , strlen (self ::BYTES ) - $ offset ), Streams::readAll ($ stream ));
91+ }
92+
93+ #[Test, Values([0 , 1 , 5 ])]
94+ public function seeking_forward_triggers_read ($ offset ) {
95+ $ stream = $ this ->newFixture ();
96+ $ stream ->seek (5 , SEEK_SET );
97+ $ stream ->seek (strlen (self ::BYTES ) - $ offset , SEEK_SET );
98+
99+ Assert::equals (strlen (self ::BYTES ) - $ offset , $ stream ->tell ());
100+ Assert::equals ($ offset , $ stream ->available ());
101+ Assert::equals (substr (self ::BYTES , strlen (self ::BYTES ) - $ offset ), Streams::readAll ($ stream ));
102+ }
103+
104+ #[Test, Values([0 , 1 , 5 ])]
105+ public function seeking_back_to_offset_after_reading_until_end ($ offset ) {
106+ $ stream = $ this ->newFixture ();
107+ while ($ stream ->available ()) {
108+ $ stream ->read ();
109+ }
110+ $ stream ->seek ($ offset , SEEK_SET );
111+
112+ Assert::equals ($ offset , $ stream ->tell ());
113+ Assert::equals (strlen (self ::BYTES ) - $ offset , $ stream ->available ());
114+ Assert::equals (substr (self ::BYTES , $ offset ), Streams::readAll ($ stream ));
115+ }
116+
117+ #[Test, Values([0 , -1 , -5 ])]
118+ public function seeking_to_end_after_reading_until_end ($ offset ) {
119+ $ stream = $ this ->newFixture ();
120+ while ($ stream ->available ()) {
121+ $ stream ->read ();
122+ }
123+ $ stream ->seek ($ offset , SEEK_END );
124+
125+ Assert::equals (strlen (self ::BYTES ) + $ offset , $ stream ->tell ());
126+ Assert::equals (-$ offset , $ stream ->available ());
127+ Assert::equals (substr (self ::BYTES , strlen (self ::BYTES ) + $ offset ), Streams::readAll ($ stream ));
128+ }
129+
130+ #[Test, Values([0 , -1 , -5 ])]
131+ public function seeking_to_end_after_seeking_relative ($ offset ) {
132+ $ stream = $ this ->newFixture ();
133+ $ stream ->seek (5 , SEEK_SET );
134+ $ stream ->seek ($ offset , SEEK_END );
135+
136+ Assert::equals (strlen (self ::BYTES ) + $ offset , $ stream ->tell ());
137+ Assert::equals (-$ offset , $ stream ->available ());
138+ Assert::equals (substr (self ::BYTES , strlen (self ::BYTES ) + $ offset ), Streams::readAll ($ stream ));
139+ }
140+
141+ #[Test]
142+ public function close_can_be_called_twice () {
143+ $ stream = $ this ->newFixture ();
144+
145+ $ stream ->close ();
146+ $ stream ->close ();
147+ }
148+
149+ #[Test, Expect(IOException::class), Values([SEEK_SET , SEEK_CUR ])]
150+ public function cannot_seek_before_beginning_of_file ($ whence ) {
151+ $ this ->newFixture ()->seek (-1 , $ whence );
152+ }
153+
154+ #[Test, Expect(IOException::class)]
155+ public function cannot_seek_with_invalid_whence () {
156+ $ this ->newFixture ()->seek (0 , 6100 );
157+ }
158+
159+ #[Test]
160+ public function position_after_seek_error () {
161+ $ stream = $ this ->newFixture ();
162+ $ stream ->read (4 );
163+
164+ Assert::throws (IOException::class, fn () => $ stream ->seek (-1 ));
165+ Assert::equals (4 , $ stream ->tell ());
166+ }
167+
168+ #[Test]
169+ public function position_after_seek_set_past_end () {
170+ $ stream = $ this ->newFixture ();
171+ $ stream ->seek (strlen (self ::BYTES ) + 1 , SEEK_SET );
172+
173+ Assert::equals (strlen (self ::BYTES ), $ stream ->tell ());
174+ }
175+
176+ #[Test]
177+ public function position_after_seek_end_past_end () {
178+ $ stream = $ this ->newFixture ();
179+ $ stream ->seek (1 , SEEK_END );
180+
181+ Assert::equals (strlen (self ::BYTES ), $ stream ->tell ());
182+ }
183+ }
0 commit comments