Файловый менеджер - Редактировать - /var/www/html/filebackend.zip
Ðазад
PK ! I�Ya� � FileBackendGroupTest.phpnu �Iw�� <?php use MediaWiki\Config\ServiceOptions; use MediaWiki\FileBackend\FileBackendGroup; use MediaWiki\FileBackend\FSFile\TempFSFileFactory; use MediaWiki\FileBackend\LockManager\LockManagerGroupFactory; use MediaWiki\Tests\Unit\DummyServicesTrait; use Wikimedia\Mime\MimeAnalyzer; use Wikimedia\ObjectCache\BagOStuff; use Wikimedia\ObjectCache\EmptyBagOStuff; use Wikimedia\ObjectCache\WANObjectCache; /** * @coversDefaultClass \MediaWiki\FileBackend\FileBackendGroup */ class FileBackendGroupTest extends MediaWikiUnitTestCase { use DummyServicesTrait; use FileBackendGroupTestTrait; protected function setUp(): void { parent::setUp(); // This config var is not yet dependency-injected. // FileBackendGroup has a default option 'profiler', that holds a closure // that calls Profiler::instance(), which doesn't use service wiring yet. // Without this, the variable would be undefined there. // TODO: Remove this once Profiler uses service wiring and is injected // into FileBackendGroup. $GLOBALS['wgProfiler'] = []; } private static function getWikiID() { return 'mywiki'; } private function getLocalServerCache(): BagOStuff { if ( !$this->srvCache ) { $this->srvCache = new EmptyBagOStuff; } return $this->srvCache; } private function getWANObjectCache(): WANObjectCache { if ( !$this->wanCache ) { $this->wanCache = $this->createNoOpMock( WANObjectCache::class ); } return $this->wanCache; } /** * @param string $domain Expected argument that LockManagerGroupFactory::getLockManagerGroup * will receive * @return LockManagerGroupFactory */ private function getLockManagerGroupFactory( $domain = 'mywiki' ): LockManagerGroupFactory { if ( !$this->lmgFactory ) { $mockLmg = $this->createNoOpMock( LockManagerGroup::class, [ 'get' ] ); $mockLmg->method( 'get' )->with( 'fsLockManager' )->willReturn( 'string lock manager' ); $this->lmgFactory = $this->createNoOpMock( LockManagerGroupFactory::class, [ 'getLockManagerGroup' ] ); $this->lmgFactory->method( 'getLockManagerGroup' )->with( $domain ) ->willReturn( $mockLmg ); } return $this->lmgFactory; } private function getTempFSFileFactory(): TempFSFileFactory { if ( !$this->tmpFileFactory ) { $this->tmpFileFactory = $this->createNoOpMock( TempFSFileFactory::class ); } return $this->tmpFileFactory; } /** * @param array $options Dictionary to use as a source for ServiceOptions before defaults, plus * the following options are available to override other arguments: * * 'readOnlyMode' * * 'lmgFactory' * * 'mimeAnalyzer' * * 'tmpFileFactory' * @return FileBackendGroup */ private function newObj( array $options = [] ): FileBackendGroup { return new FileBackendGroup( new ServiceOptions( FileBackendGroup::CONSTRUCTOR_OPTIONS, $options, self::getDefaultOptions() ), $this->getDummyReadOnlyMode( $options['readOnlyMode'] ?? false ), $this->getLocalServerCache(), $this->getWANObjectCache(), $options['mimeAnalyzer'] ?? $this->createNoOpMock( MimeAnalyzer::class ), $options['lmgFactory'] ?? $this->getLockManagerGroupFactory(), $options['tmpFileFactory'] ?? $this->getTempFSFileFactory(), $this->getDummyObjectFactory() ); } } PK ! 6D�ƶ � + lockmanager/LockManagerGroupFactoryTest.phpnu �Iw�� <?php use MediaWiki\FileBackend\LockManager\LockManagerGroupFactory; use Wikimedia\Rdbms\LBFactory; /** * @covers \MediaWiki\FileBackend\LockManager\LockManagerGroupFactory * @todo Should we somehow test that the LockManagerGroup objects are as we expect? How do we do * that without getting into testing LockManagerGroup itself? */ class LockManagerGroupFactoryTest extends MediaWikiUnitTestCase { public function testGetLockManagerGroup() { $mockLbFactory = $this->createNoOpMock( LBFactory::class ); $factory = new LockManagerGroupFactory( 'defaultDomain', [], $mockLbFactory ); $lbmUnspecified = $factory->getLockManagerGroup(); $lbmFalse = $factory->getLockManagerGroup( false ); $lbmDefault = $factory->getLockManagerGroup( 'defaultDomain' ); $lbmOther = $factory->getLockManagerGroup( 'otherDomain' ); $this->assertSame( $lbmUnspecified, $lbmFalse ); $this->assertSame( $lbmFalse, $lbmDefault ); $this->assertSame( $lbmDefault, $lbmUnspecified ); $this->assertNotEquals( $lbmUnspecified, $lbmOther ); $this->assertNotEquals( $lbmFalse, $lbmOther ); $this->assertNotEquals( $lbmDefault, $lbmOther ); $this->assertSame( $lbmUnspecified, $factory->getLockManagerGroup() ); $this->assertSame( $lbmFalse, $factory->getLockManagerGroup( false ) ); $this->assertSame( $lbmDefault, $factory->getLockManagerGroup( 'defaultDomain' ) ); $this->assertSame( $lbmOther, $factory->getLockManagerGroup( 'otherDomain' ) ); } } PK ! �<� � $ lockmanager/LockManagerGroupTest.phpnu �Iw�� <?php use Wikimedia\Rdbms\LBFactory; /** * Since this is a unit test, we don't test the singleton() or destroySingletons() methods. We also * can't test get() with a valid argument, because that winds up calling static methods of * ObjectCache and LoggerFactory that aren't yet compatible with proper unit tests. Those will be * tested in the integration test for now. * * @covers \LockManagerGroup */ class LockManagerGroupTest extends MediaWikiUnitTestCase { private function getMockLBFactory() { return $this->createNoOpMock( LBFactory::class ); } public function testConstructorNoConfigs() { new LockManagerGroup( 'domain', [], $this->getMockLBFactory() ); $this->assertTrue( true, 'No exception thrown' ); } public function testConstructorConfigWithNoName() { $this->expectException( Exception::class ); $this->expectExceptionMessage( 'Cannot register a lock manager with no name.' ); new LockManagerGroup( 'domain', [ [ 'name' => 'a', 'class' => 'b' ], [ 'class' => 'c' ] ], $this->getMockLBFactory() ); } public function testConstructorConfigWithNoClass() { $this->expectException( Exception::class ); $this->expectExceptionMessage( 'Cannot register lock manager `c` with no class.' ); new LockManagerGroup( 'domain', [ [ 'name' => 'a', 'class' => 'b' ], [ 'name' => 'c' ] ], $this->getMockLBFactory() ); } public function testGetUndefined() { $this->expectException( Exception::class ); $this->expectExceptionMessage( 'No lock manager defined with the name `c`.' ); $lmg = new LockManagerGroup( 'domain', [ [ 'name' => 'a', 'class' => 'b' ] ], $this->getMockLBFactory() ); $lmg->get( 'c' ); } public function testConfigUndefined() { $this->expectException( Exception::class ); $this->expectExceptionMessage( 'No lock manager defined with the name `c`.' ); $lmg = new LockManagerGroup( 'domain', [ [ 'name' => 'a', 'class' => 'b' ] ], $this->getMockLBFactory() ); $lmg->config( 'c' ); } public function testConfig() { $lmg = new LockManagerGroup( 'domain', [ [ 'name' => 'a', 'class' => 'b', 'foo' => 'c' ] ], $this->getMockLBFactory() ); $this->assertSame( [ 'class' => 'b', 'name' => 'a', 'foo' => 'c', 'domain' => 'domain' ], $lmg->config( 'a' ) ); } } PK ! /��) ) HTTPFileStreamerTest.phpnu �Iw�� <?php use MediaWiki\Utils\MWTimestamp; use PHPUnit\Framework\TestCase; use Wikimedia\FileBackend\HTTPFileStreamer; /** * @covers \Wikimedia\FileBackend\HTTPFileStreamer */ class HTTPFileStreamerTest extends TestCase { private const FILE = MW_INSTALL_PATH . '/tests/phpunit/data/media/test.jpg'; /** @var int */ private $obLevel = null; protected function setUp(): void { $this->obLevel = ob_get_level(); ob_start(); parent::setUp(); } protected function tearDown(): void { while ( ob_get_level() > $this->obLevel ) { ob_end_clean(); } parent::tearDown(); } /** * @dataProvider providePreprocessHeaders */ public function testPreprocessHeaders( array $input, array $expectedRaw, array $expectedOpt ) { [ $actualRaw, $actualOpt ] = HTTPFileStreamer::preprocessHeaders( $input ); $this->assertSame( $expectedRaw, $actualRaw ); $this->assertSame( $expectedOpt, $actualOpt ); } public static function providePreprocessHeaders() { return [ [ [ 'Vary' => 'cookie', 'Cache-Control' => 'private' ], [ 'Vary: cookie', 'Cache-Control: private' ], [], ], [ [ 'Range' => 'bytes=(123-456)', 'Content-Type' => 'video/mp4', 'If-Modified-Since' => 'Wed, 21 Oct 2015 07:28:00 GMT', ], [ 'Content-Type: video/mp4' ], [ 'range' => 'bytes=(123-456)', 'if-modified-since' => 'Wed, 21 Oct 2015 07:28:00 GMT' ], ], ]; } private function makeStreamerParams( &$actual ) { $actual = [ 'reset' => 0, 'file' => null, 'range' => null, 'headers' => [], 'status' => 200, ]; return [ 'obResetFunc' => static function () use ( &$actual ) { $actual['reset']++; }, 'streamMimeFunc' => static function () { return 'test/test'; }, 'headerFunc' => static function ( $header ) use ( &$actual ) { if ( preg_match( '/^HTTP.*? (\d+)/', $header, $m ) ) { $actual['status'] = (int)$m[1]; } $actual['headers'][] = $header; }, ]; } public static function provideStream() { $mtime = filemtime( self::FILE ); $size = filesize( self::FILE ); $modified = MWTimestamp::convert( TS_RFC2822, $mtime ); yield 'simple stream' => [ [], [], [ "Last-Modified: $modified", 'Content-type: test/test', "Content-Length: $size" ] ]; yield 'extra header' => [ [ 'Extra: yes' ], [], [ 'Extra: yes', "Last-Modified: $modified", 'Content-type: test/test', "Content-Length: $size" ] ]; yield 'modified' => [ [], [ 'if-modified-since' => MWTimestamp::convert( TS_RFC2822, $mtime - 1 ) ], [ "Last-Modified: $modified", 'Content-type: test/test', "Content-Length: $size" ] ]; yield 'not modified' => [ [], [ 'if-modified-since' => MWTimestamp::convert( TS_RFC2822, $mtime + 1 ) ], [ 'HTTP/1.1 304 Not Modified' ] ]; } /** * @dataProvider provideStream */ public function testStream( $extraHeaders, $reqHeaders, $expectedHeaders ) { $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( self::FILE, $params ); $ok = $streamer->stream( $extraHeaders, true, $reqHeaders ); $this->assertTrue( $ok ); if ( !isset( $actual['status'] ) ) { $this->assertSame( self::FILE, $actual['file'] ); } $this->assertSame( 1, $actual['reset'] ); foreach ( $expectedHeaders as $exp ) { $this->assertContains( $exp, $actual['headers'] ); } } public static function provideStream_range() { $filesize = filesize( self::FILE ); $length = $filesize; $start = 0; $end = $length - 1; yield 'all' => [ 'bytes=-', 206, [ "Content-Length: $length", "Content-Range: bytes $start-$end/$filesize", ], [ $start, $end, $length ] ]; $length = 100; $start = 0; $end = $length - 1; yield 'prefix' => [ 'bytes=0-99', 206, [ "Content-Length: $length", "Content-Range: bytes $start-$end/$filesize", ], [ $start, $end, $length ] ]; $length = 100; $start = 100; $end = $start + $length - 1; yield 'middle' => [ 'bytes=100-199', 206, [ "Content-Length: $length", "Content-Range: bytes $start-$end/$filesize", ], [ $start, $end, $length ] ]; $length = 100; $start = $filesize - $length; $end = $filesize - 1; yield 'suffix' => [ 'bytes=-100', 206, [ "Content-Length: $length", "Content-Range: bytes $start-$end/$filesize", ], [ $start, $end, $length ] ]; $length = $filesize - 100; $start = 100; $end = $start + $length - 1; yield 'remaining' => [ 'bytes=100-', 206, [ "Content-Length: $length", "Content-Range: bytes $start-$end/$filesize", ], [ $start, $end, $length ] ]; yield 'impossible' => [ 'bytes=1000-2000', 416, [ 'Cache-Control: no-cache' ], null ]; yield 'unrecognized' => [ 'foo=1000-2000', 200, [ "Content-Length: $filesize" ], null ]; } /** * Check parsing of the Range header and corresponding response headers. * * @dataProvider provideStream_range */ public function testStream_range( $range, $expectedStatus, $expectedHeaders, $expectedRange ) { $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( self::FILE, $params ); $streamer->stream( [], true, [ 'range' => $range ] ); $this->assertSame( $expectedStatus, $actual['status'] ); foreach ( $expectedHeaders as $exp ) { $this->assertContains( $exp, $actual['headers'] ); } if ( $expectedStatus < 300 ) { [ $start, , $length ] = $expectedRange; $this->assertBufferContainsFile( $start, $length ); } } /** * Check we ar ereaching the correct chunks from the file */ public function testStream_chunks() { $data = file_get_contents( self::FILE ); $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( self::FILE, $params ); // grab a chunk from the middle ob_start(); $streamer->stream( [], true, [ 'range' => 'bytes=100-199' ] ); $chunk1 = ob_get_clean(); // get the start ob_start(); $streamer->stream( [], true, [ 'range' => 'bytes=0-99' ] ); $chunk2 = ob_get_clean(); // fetch the rest ob_start(); $streamer->stream( [], true, [ 'range' => 'bytes=200-' ] ); $chunk3 = ob_get_clean(); $this->assertSame( $data, $chunk2 . $chunk1 . $chunk3 ); } public function testStream_404() { $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( 'Xyzzy.jpg', $params ); ob_start(); $ok = $streamer->stream(); $data = ob_get_clean(); $this->assertFalse( $ok ); $this->assertStringContainsString( '<h1>File not found</h1>', $data ); } public function testStream_allowOB() { $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( self::FILE, $params ); $streamer->stream( [], true, [], HTTPFileStreamer::STREAM_ALLOW_OB ); // Expect no buffer reset, even though the file was sent $this->assertSame( 0, $actual['reset'] ); $this->assertBufferContainsFile(); } public function testStream_headless() { $params = $this->makeStreamerParams( $actual ); $streamer = new HTTPFileStreamer( self::FILE, $params ); $streamer->stream( [ 'Extra: yes' ], true, [], HTTPFileStreamer::STREAM_HEADLESS ); // Expect no headers, not even "extra" $this->assertSame( [], $actual['headers'] ); $this->assertBufferContainsFile(); } private function assertBufferContainsFile( ?int $offset = null, ?int $length = null ) { $actual = ob_get_clean(); $expected = file_get_contents( self::FILE ); if ( $offset !== null || $length !== null ) { $expected = substr( $expected, $offset ?? 0, $length ); } $this->assertSame( $expected, $actual ); } } PK ! �ܶ��>