Passed
Pull Request — master (#17)
by Mihail
15:10
created

StreamTest::test_stream_metadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 11
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 15
rs 9.9
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