1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Tests\Koded\Http; |
4
|
|
|
|
5
|
|
|
use Koded\Http\Interfaces\HttpStatus; |
6
|
|
|
use Koded\Http\Stream; |
7
|
|
|
use PHPUnit\Framework\TestCase; |
8
|
|
|
use RuntimeException; |
9
|
|
|
use Throwable; |
10
|
|
|
|
11
|
|
|
class StreamTest extends TestCase |
12
|
|
|
{ |
13
|
|
|
use AssertionTestSupportTrait; |
14
|
|
|
|
15
|
|
|
public function test_constructor_with_invalid_argument() |
16
|
|
|
{ |
17
|
|
|
$this->expectException(RuntimeException::class); |
18
|
|
|
$this->expectExceptionCode(HttpStatus::UNPROCESSABLE_ENTITY); |
19
|
|
|
$this->expectExceptionMessage('The provided resource is not a valid stream resource'); |
20
|
|
|
new Stream(''); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
public function test_should_initialize_the_stream_modes() |
24
|
|
|
{ |
25
|
|
|
$stream = new Stream(fopen('php://temp', 'r')); |
26
|
|
|
$this->assertFalse($stream->isWritable()); |
27
|
|
|
$this->assertTrue($stream->isSeekable()); |
28
|
|
|
$this->assertTrue($stream->isReadable()); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
public function test_should_close_the_stream_on_destruct() |
32
|
|
|
{ |
33
|
|
|
$resource = fopen('php://temp', 'r'); |
34
|
|
|
$stream = new Stream($resource); |
35
|
|
|
|
36
|
|
|
$stream->__destruct(); |
37
|
|
|
|
38
|
|
|
$properties = $this->getObjectProperties($stream); |
39
|
|
|
|
40
|
|
|
$this->assertFalse(is_resource($resource)); |
41
|
|
|
$this->assertSame(null, $properties['stream']); |
42
|
|
|
$this->assertSame('w+b', $properties['mode']); |
43
|
|
|
$this->assertFalse($properties['seekable']); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
public function test_stream_should_return_content_when_typecasted_to_string() |
47
|
|
|
{ |
48
|
|
|
$resource = fopen('php://temp', 'w'); |
49
|
|
|
fwrite($resource, 'lorem ipsum'); |
50
|
|
|
|
51
|
|
|
$stream = new Stream($resource); |
52
|
|
|
|
53
|
|
|
// idempotent |
54
|
|
|
$this->assertSame('lorem ipsum', (string)$stream); |
55
|
|
|
$this->assertSame('lorem ipsum', (string)$stream); |
56
|
|
|
$this->assertSame('lorem ipsum', (string)$stream); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
public function test_stream_should_return_empty_string_when_throws_exception_while_typecasted() |
60
|
|
|
{ |
61
|
|
|
$stream = new Stream(fopen('php://stderr', '')); |
62
|
|
|
$this->assertSame('', (string)$stream); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
public function test_stream_should_return_empty_string_with_zero_content_length() |
66
|
|
|
{ |
67
|
|
|
$resource = fopen('php://temp', 'r'); |
68
|
|
|
$stream = new Stream($resource); |
69
|
|
|
$this->assertSame('', $stream->read(0)); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
public function test_stream_should_throw_exception_on_read_when_stream_is_not_readable() |
73
|
|
|
{ |
74
|
|
|
$this->expectException(RuntimeException::class); |
75
|
|
|
$this->expectExceptionMessage('The stream is not readable'); |
76
|
|
|
|
77
|
|
|
$stream = new Stream(fopen('php://stderr', '')); |
78
|
|
|
$stream->read(0); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
public function test_stream_should_return_null_if_stream_is_already_detached() |
82
|
|
|
{ |
83
|
|
|
$stream = new Stream(fopen('php://temp', 'r')); |
84
|
|
|
|
85
|
|
|
$result = $stream->detach(); |
86
|
|
|
$this->assertNotNull($result, 'First detach() returns the underlying stream'); |
87
|
|
|
|
88
|
|
|
$result = $stream->detach(); |
89
|
|
|
$this->assertNull($result, 'Next detach() calls returns NULL for the underlying stream'); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
public function test_stream_should_return_the_stream_size() |
93
|
|
|
{ |
94
|
|
|
$resource = fopen('php://temp', 'w'); |
95
|
|
|
fwrite($resource, 'lorem ipsum'); |
96
|
|
|
$stream = new Stream($resource); |
97
|
|
|
|
98
|
|
|
$this->assertSame(11, $stream->getSize()); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function test_stream_should_return_null_when_getting_size_with_empty_stream() |
102
|
|
|
{ |
103
|
|
|
$stream = new Stream(fopen('php://temp', 'w')); |
104
|
|
|
$stream->detach(); |
105
|
|
|
|
106
|
|
|
$this->assertNull($stream->getSize()); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
public function test_stream_tell_and_eof() |
110
|
|
|
{ |
111
|
|
|
$resource = fopen('php://temp', 'w'); |
112
|
|
|
fwrite($resource, 'lorem ipsum'); |
113
|
|
|
$stream = new Stream($resource); |
114
|
|
|
|
115
|
|
|
$stream->seek(0); |
116
|
|
|
$this->assertSame(0, $stream->tell()); |
117
|
|
|
|
118
|
|
|
$stream->seek(1); |
119
|
|
|
$this->assertSame(1, $stream->tell()); |
120
|
|
|
|
121
|
|
|
$stream->eof(); |
122
|
|
|
$this->assertFalse($stream->eof(), 'eof() do not move the stream pointer'); |
123
|
|
|
$this->assertSame(1, $stream->tell(), 'Still on position 1'); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
public function test_stream_should_throw_exception_when_cannot_tell() |
127
|
|
|
{ |
128
|
|
|
$this->markTestSkipped(); |
129
|
|
|
|
130
|
|
|
$this->expectException(RuntimeException::class); |
131
|
|
|
$this->expectExceptionMessage('Failed to find the position of the file pointer'); |
132
|
|
|
|
133
|
|
|
$stream = new Stream(fopen('php://temp', 'r')); |
134
|
|
|
|
135
|
|
|
try { |
136
|
|
|
$stream->seek(20); |
137
|
|
|
} catch (Throwable $e) { |
138
|
|
|
// NOOP, continue |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
$this->assertSame(29, $stream->tell()); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
public function test_stream_should_throw_exception_when_cannot_seek() |
145
|
|
|
{ |
146
|
|
|
$this->expectException(RuntimeException::class); |
147
|
|
|
$this->expectExceptionMessage('Failed to seek to file pointer'); |
148
|
|
|
|
149
|
|
|
$resource = fopen('php://temp', 'w'); |
150
|
|
|
fwrite($resource, 'lorem ipsum'); |
151
|
|
|
$stream = new Stream($resource); |
152
|
|
|
$stream->seek(-10); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
public function test_stream_rewind() |
156
|
|
|
{ |
157
|
|
|
$resource = fopen('php://temp', 'w'); |
158
|
|
|
fwrite($resource, 'lorem ipsum'); |
159
|
|
|
$stream = new Stream($resource); |
160
|
|
|
|
161
|
|
|
$this->assertSame(11, $stream->tell()); |
162
|
|
|
|
163
|
|
|
$stream->rewind(); |
164
|
|
|
$this->assertSame(0, $stream->tell()); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
public function test_stream_should_throw_exception_when_rewind_but_source_is_not_seekable() |
168
|
|
|
{ |
169
|
|
|
$this->expectException(RuntimeException::class); |
170
|
|
|
$this->expectExceptionMessage('The stream is not seekable'); |
171
|
|
|
|
172
|
|
|
$stream = new Stream(fopen('php://stderr', '')); |
173
|
|
|
$stream->rewind(); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
public function test_stream_write() |
177
|
|
|
{ |
178
|
|
|
$stream = new Stream(fopen('php://temp', 'w')); |
179
|
|
|
$bytes = $stream->write('lorem ipsum'); |
180
|
|
|
|
181
|
|
|
$this->assertSame(11, $bytes); |
182
|
|
|
$this->assertSame('', $stream->getContents(), 'Returns the remaining contents in the string'); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
public function test_stream_should_throw_exception_when_writing_and_stream_is_not_writable() |
186
|
|
|
{ |
187
|
|
|
$this->expectException(RuntimeException::class); |
188
|
|
|
$this->expectExceptionMessage('The stream is not writable'); |
189
|
|
|
|
190
|
|
|
$stream = new Stream(fopen('php://stderr', '')); |
191
|
|
|
$stream->write('lorem ipsum'); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
public function test_stream_read() |
195
|
|
|
{ |
196
|
|
|
$stream = new Stream(fopen('php://temp', 'w')); |
197
|
|
|
$stream->write('lorem ipsum'); |
198
|
|
|
$stream->seek(6); |
199
|
|
|
|
200
|
|
|
$this->assertSame('ipsum', $stream->read(6)); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
public function test_stream_metadata() |
204
|
|
|
{ |
205
|
|
|
$stream = new Stream(fopen('php://temp', 'w')); |
206
|
|
|
$stream->write('lorem ipsum'); |
207
|
|
|
|
208
|
|
|
$metadata = $stream->getMetadata(); |
209
|
|
|
$this->assertSame('PHP', $metadata['wrapper_type']); |
210
|
|
|
$this->assertSame('TEMP', $metadata['stream_type']); |
211
|
|
|
$this->assertSame('w+b', $metadata['mode']); |
212
|
|
|
$this->assertSame(0, $metadata['unread_bytes']); |
213
|
|
|
$this->assertSame(true, $metadata['seekable']); |
214
|
|
|
$this->assertSame('php://temp', $metadata['uri']); |
215
|
|
|
|
216
|
|
|
$this->assertSame('php://temp', $stream->getMetadata('uri')); |
217
|
|
|
$this->assertSame(null, $stream->getMetadata('junk')); |
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
|