Merge "Selenium: replace UserLoginPage with BlankPage where possible"
[lhc/web/wiklou.git] / tests / phpunit / includes / libs / ParamValidator / Util / UploadedFileStreamTest.php
1 <?php
2
3 namespace Wikimedia\ParamValidator\Util;
4
5 require_once __DIR__ . '/UploadedFileTestBase.php';
6
7 use RuntimeException;
8 use Wikimedia\AtEase\AtEase;
9 use Wikimedia\TestingAccessWrapper;
10
11 /**
12 * @covers Wikimedia\ParamValidator\Util\UploadedFileStream
13 */
14 class UploadedFileStreamTest extends UploadedFileTestBase {
15
16 /**
17 * @expectedException RuntimeException
18 * @expectedExceptionMessage Failed to open file:
19 */
20 public function testConstruct_doesNotExist() {
21 $filename = $this->makeTemp( __FUNCTION__ );
22 unlink( $filename );
23
24 $this->assertFileNotExists( $filename, 'sanity check' );
25 $stream = new UploadedFileStream( $filename );
26 }
27
28 /**
29 * @expectedException RuntimeException
30 * @expectedExceptionMessage Failed to open file:
31 */
32 public function testConstruct_notReadable() {
33 $filename = $this->makeTemp( __FUNCTION__ );
34
35 chmod( $filename, 0000 );
36 $stream = new UploadedFileStream( $filename );
37 }
38
39 public function testCloseOnDestruct() {
40 $filename = $this->makeTemp( __FUNCTION__ );
41 $stream = new UploadedFileStream( $filename );
42 $fp = TestingAccessWrapper::newFromObject( $stream )->fp;
43 $this->assertSame( 'f', fread( $fp, 1 ), 'sanity check' );
44 unset( $stream );
45 $this->assertFalse( AtEase::quietCall( 'fread', $fp, 1 ) );
46 }
47
48 public function testToString() {
49 $filename = $this->makeTemp( __FUNCTION__ );
50 $stream = new UploadedFileStream( $filename );
51
52 // Always starts at the start of the stream
53 $stream->seek( 3 );
54 $this->assertSame( 'foobar', (string)$stream );
55
56 // No exception when closed
57 $stream->close();
58 $this->assertSame( '', (string)$stream );
59 }
60
61 public function testToString_Error() {
62 if ( !class_exists( \Error::class ) ) {
63 $this->markTestSkipped( 'No PHP Error class' );
64 }
65
66 // ... Yeah
67 $filename = $this->makeTemp( __FUNCTION__ );
68 $stream = $this->getMockBuilder( UploadedFileStream::class )
69 ->setConstructorArgs( [ $filename ] )
70 ->setMethods( [ 'getContents' ] )
71 ->getMock();
72 $stream->method( 'getContents' )->willReturnCallback( function () {
73 throw new \Error( 'Bogus' );
74 } );
75 $this->assertSame( '', (string)$stream );
76 }
77
78 public function testClose() {
79 $filename = $this->makeTemp( __FUNCTION__ );
80 $stream = new UploadedFileStream( $filename );
81
82 $stream->close();
83
84 // Second call doesn't error
85 $stream->close();
86 }
87
88 public function testDetach() {
89 $filename = $this->makeTemp( __FUNCTION__ );
90 $stream = new UploadedFileStream( $filename );
91
92 // We got the file descriptor
93 $fp = $stream->detach();
94 $this->assertNotNull( $fp );
95 $this->assertSame( 'f', fread( $fp, 1 ) );
96
97 // Stream operations now fail.
98 try {
99 $stream->seek( 0 );
100 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
101 throw $ex;
102 } catch ( RuntimeException $ex ) {
103 }
104
105 // Stream close doesn't affect the file descriptor
106 $stream->close();
107 $this->assertSame( 'o', fread( $fp, 1 ) );
108
109 // Stream destruction doesn't affect the file descriptor
110 unset( $stream );
111 $this->assertSame( 'o', fread( $fp, 1 ) );
112
113 // On a closed stream, we don't get a file descriptor
114 $stream = new UploadedFileStream( $filename );
115 $stream->close();
116 $this->assertNull( $stream->detach() );
117 }
118
119 public function testGetSize() {
120 $filename = $this->makeTemp( __FUNCTION__ );
121 $stream = new UploadedFileStream( $filename );
122 file_put_contents( $filename, 'foobarbaz' );
123 $this->assertSame( 9, $stream->getSize() );
124
125 // Cached
126 file_put_contents( $filename, 'baz' );
127 clearstatcache();
128 $this->assertSame( 3, stat( $filename )['size'], 'sanity check' );
129 $this->assertSame( 9, $stream->getSize() );
130
131 // No error if closed
132 $stream = new UploadedFileStream( $filename );
133 $stream->close();
134 $this->assertSame( null, $stream->getSize() );
135
136 // No error even if the fd goes bad
137 $stream = new UploadedFileStream( $filename );
138 fclose( TestingAccessWrapper::newFromObject( $stream )->fp );
139 $this->assertSame( null, $stream->getSize() );
140 }
141
142 public function testSeekTell() {
143 $filename = $this->makeTemp( __FUNCTION__ );
144 $stream = new UploadedFileStream( $filename );
145
146 $stream->seek( 2 );
147 $this->assertSame( 2, $stream->tell() );
148 $stream->seek( 2, SEEK_CUR );
149 $this->assertSame( 4, $stream->tell() );
150 $stream->seek( -5, SEEK_END );
151 $this->assertSame( 1, $stream->tell() );
152 $stream->read( 2 );
153 $this->assertSame( 3, $stream->tell() );
154
155 $stream->close();
156 try {
157 $stream->seek( 0 );
158 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
159 throw $ex;
160 } catch ( RuntimeException $ex ) {
161 }
162 try {
163 $stream->tell();
164 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
165 throw $ex;
166 } catch ( RuntimeException $ex ) {
167 }
168 }
169
170 public function testEof() {
171 $filename = $this->makeTemp( __FUNCTION__ );
172 $stream = new UploadedFileStream( $filename );
173
174 $this->assertFalse( $stream->eof() );
175 $stream->getContents();
176 $this->assertTrue( $stream->eof() );
177 $stream->seek( -1, SEEK_END );
178 $this->assertFalse( $stream->eof() );
179
180 // No error if closed
181 $stream = new UploadedFileStream( $filename );
182 $stream->close();
183 $this->assertTrue( $stream->eof() );
184
185 // No error even if the fd goes bad
186 $stream = new UploadedFileStream( $filename );
187 fclose( TestingAccessWrapper::newFromObject( $stream )->fp );
188 $this->assertInternalType( 'boolean', $stream->eof() );
189 }
190
191 public function testIsFuncs() {
192 $filename = $this->makeTemp( __FUNCTION__ );
193 $stream = new UploadedFileStream( $filename );
194 $this->assertTrue( $stream->isSeekable() );
195 $this->assertTrue( $stream->isReadable() );
196 $this->assertFalse( $stream->isWritable() );
197
198 $stream->close();
199 $this->assertFalse( $stream->isSeekable() );
200 $this->assertFalse( $stream->isReadable() );
201 $this->assertFalse( $stream->isWritable() );
202 }
203
204 public function testRewind() {
205 $filename = $this->makeTemp( __FUNCTION__ );
206 $stream = new UploadedFileStream( $filename );
207
208 $stream->seek( 2 );
209 $this->assertSame( 2, $stream->tell() );
210 $stream->rewind();
211 $this->assertSame( 0, $stream->tell() );
212
213 $stream->close();
214 try {
215 $stream->rewind();
216 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
217 throw $ex;
218 } catch ( RuntimeException $ex ) {
219 }
220 }
221
222 public function testWrite() {
223 $filename = $this->makeTemp( __FUNCTION__ );
224 $stream = new UploadedFileStream( $filename );
225
226 try {
227 $stream->write( 'foo' );
228 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
229 throw $ex;
230 } catch ( RuntimeException $ex ) {
231 }
232 }
233
234 public function testRead() {
235 $filename = $this->makeTemp( __FUNCTION__ );
236 $stream = new UploadedFileStream( $filename );
237
238 $this->assertSame( 'foo', $stream->read( 3 ) );
239 $this->assertSame( 'bar', $stream->read( 10 ) );
240 $this->assertSame( '', $stream->read( 10 ) );
241 $stream->rewind();
242 $this->assertSame( 'foobar', $stream->read( 10 ) );
243
244 $stream->close();
245 try {
246 $stream->read( 1 );
247 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
248 throw $ex;
249 } catch ( RuntimeException $ex ) {
250 }
251 }
252
253 public function testGetContents() {
254 $filename = $this->makeTemp( __FUNCTION__ );
255 $stream = new UploadedFileStream( $filename );
256
257 $this->assertSame( 'foobar', $stream->getContents() );
258 $this->assertSame( '', $stream->getContents() );
259 $stream->seek( 3 );
260 $this->assertSame( 'bar', $stream->getContents() );
261
262 $stream->close();
263 try {
264 $stream->getContents();
265 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
266 throw $ex;
267 } catch ( RuntimeException $ex ) {
268 }
269 }
270
271 public function testGetMetadata() {
272 // Whatever
273 $filename = $this->makeTemp( __FUNCTION__ );
274 $fp = fopen( $filename, 'r' );
275 $expect = stream_get_meta_data( $fp );
276 fclose( $fp );
277
278 $stream = new UploadedFileStream( $filename );
279 $this->assertSame( $expect, $stream->getMetadata() );
280 foreach ( $expect as $k => $v ) {
281 $this->assertSame( $v, $stream->getMetadata( $k ) );
282 }
283 $this->assertNull( $stream->getMetadata( 'bogus' ) );
284
285 $stream->close();
286 try {
287 $stream->getMetadata();
288 } catch ( \PHPUnit\Framework\AssertionFailedError $ex ) {
289 throw $ex;
290 } catch ( RuntimeException $ex ) {
291 }
292 }
293
294 }