3 namespace Wikimedia\ParamValidator\Util
;
5 require_once __DIR__
. '/UploadedFileTestBase.php';
8 use Wikimedia\AtEase\AtEase
;
9 use Wikimedia\TestingAccessWrapper
;
12 * @covers Wikimedia\ParamValidator\Util\UploadedFileStream
14 class UploadedFileStreamTest
extends UploadedFileTestBase
{
17 * @expectedException RuntimeException
18 * @expectedExceptionMessage Failed to open file:
20 public function testConstruct_doesNotExist() {
21 $filename = $this->makeTemp( __FUNCTION__
);
24 $this->assertFileNotExists( $filename, 'sanity check' );
25 $stream = new UploadedFileStream( $filename );
29 * @expectedException RuntimeException
30 * @expectedExceptionMessage Failed to open file:
32 public function testConstruct_notReadable() {
33 $filename = $this->makeTemp( __FUNCTION__
);
35 chmod( $filename, 0000 );
36 $stream = new UploadedFileStream( $filename );
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' );
45 $this->assertFalse( AtEase
::quietCall( 'fread', $fp, 1 ) );
48 public function testToString() {
49 $filename = $this->makeTemp( __FUNCTION__
);
50 $stream = new UploadedFileStream( $filename );
52 // Always starts at the start of the stream
54 $this->assertSame( 'foobar', (string)$stream );
56 // No exception when closed
58 $this->assertSame( '', (string)$stream );
61 public function testToString_Error() {
62 if ( !class_exists( \Error
::class ) ) {
63 $this->markTestSkipped( 'No PHP Error class' );
67 $filename = $this->makeTemp( __FUNCTION__
);
68 $stream = $this->getMockBuilder( UploadedFileStream
::class )
69 ->setConstructorArgs( [ $filename ] )
70 ->setMethods( [ 'getContents' ] )
72 $stream->method( 'getContents' )->willReturnCallback( function () {
73 throw new \
Error( 'Bogus' );
75 $this->assertSame( '', (string)$stream );
78 public function testClose() {
79 $filename = $this->makeTemp( __FUNCTION__
);
80 $stream = new UploadedFileStream( $filename );
84 // Second call doesn't error
88 public function testDetach() {
89 $filename = $this->makeTemp( __FUNCTION__
);
90 $stream = new UploadedFileStream( $filename );
92 // We got the file descriptor
93 $fp = $stream->detach();
94 $this->assertNotNull( $fp );
95 $this->assertSame( 'f', fread( $fp, 1 ) );
97 // Stream operations now fail.
100 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
102 } catch ( RuntimeException
$ex ) {
105 // Stream close doesn't affect the file descriptor
107 $this->assertSame( 'o', fread( $fp, 1 ) );
109 // Stream destruction doesn't affect the file descriptor
111 $this->assertSame( 'o', fread( $fp, 1 ) );
113 // On a closed stream, we don't get a file descriptor
114 $stream = new UploadedFileStream( $filename );
116 $this->assertNull( $stream->detach() );
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() );
126 file_put_contents( $filename, 'baz' );
128 $this->assertSame( 3, stat( $filename )['size'], 'sanity check' );
129 $this->assertSame( 9, $stream->getSize() );
131 // No error if closed
132 $stream = new UploadedFileStream( $filename );
134 $this->assertSame( null, $stream->getSize() );
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() );
142 public function testSeekTell() {
143 $filename = $this->makeTemp( __FUNCTION__
);
144 $stream = new UploadedFileStream( $filename );
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() );
153 $this->assertSame( 3, $stream->tell() );
158 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
160 } catch ( RuntimeException
$ex ) {
164 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
166 } catch ( RuntimeException
$ex ) {
170 public function testEof() {
171 $filename = $this->makeTemp( __FUNCTION__
);
172 $stream = new UploadedFileStream( $filename );
174 $this->assertFalse( $stream->eof() );
175 $stream->getContents();
176 $this->assertTrue( $stream->eof() );
177 $stream->seek( -1, SEEK_END
);
178 $this->assertFalse( $stream->eof() );
180 // No error if closed
181 $stream = new UploadedFileStream( $filename );
183 $this->assertTrue( $stream->eof() );
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() );
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() );
199 $this->assertFalse( $stream->isSeekable() );
200 $this->assertFalse( $stream->isReadable() );
201 $this->assertFalse( $stream->isWritable() );
204 public function testRewind() {
205 $filename = $this->makeTemp( __FUNCTION__
);
206 $stream = new UploadedFileStream( $filename );
209 $this->assertSame( 2, $stream->tell() );
211 $this->assertSame( 0, $stream->tell() );
216 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
218 } catch ( RuntimeException
$ex ) {
222 public function testWrite() {
223 $filename = $this->makeTemp( __FUNCTION__
);
224 $stream = new UploadedFileStream( $filename );
227 $stream->write( 'foo' );
228 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
230 } catch ( RuntimeException
$ex ) {
234 public function testRead() {
235 $filename = $this->makeTemp( __FUNCTION__
);
236 $stream = new UploadedFileStream( $filename );
238 $this->assertSame( 'foo', $stream->read( 3 ) );
239 $this->assertSame( 'bar', $stream->read( 10 ) );
240 $this->assertSame( '', $stream->read( 10 ) );
242 $this->assertSame( 'foobar', $stream->read( 10 ) );
247 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
249 } catch ( RuntimeException
$ex ) {
253 public function testGetContents() {
254 $filename = $this->makeTemp( __FUNCTION__
);
255 $stream = new UploadedFileStream( $filename );
257 $this->assertSame( 'foobar', $stream->getContents() );
258 $this->assertSame( '', $stream->getContents() );
260 $this->assertSame( 'bar', $stream->getContents() );
264 $stream->getContents();
265 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
267 } catch ( RuntimeException
$ex ) {
271 public function testGetMetadata() {
273 $filename = $this->makeTemp( __FUNCTION__
);
274 $fp = fopen( $filename, 'r' );
275 $expect = stream_get_meta_data( $fp );
278 $stream = new UploadedFileStream( $filename );
279 $this->assertSame( $expect, $stream->getMetadata() );
280 foreach ( $expect as $k => $v ) {
281 $this->assertSame( $v, $stream->getMetadata( $k ) );
283 $this->assertNull( $stream->getMetadata( 'bogus' ) );
287 $stream->getMetadata();
288 } catch ( \PHPUnit\Framework\AssertionFailedError
$ex ) {
290 } catch ( RuntimeException
$ex ) {