Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4125273
ThumbnailEntryPointTest.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
ThumbnailEntryPointTest.php
View Options
<?php
use
MediaWiki\Context\RequestContext
;
use
MediaWiki\FileRepo\ThumbnailEntryPoint
;
use
MediaWiki\MainConfigNames
;
use
MediaWiki\Permissions\SimpleAuthority
;
use
MediaWiki\Request\FauxRequest
;
use
MediaWiki\Tests\FileRepo\TestRepoTrait
;
use
MediaWiki\Tests\MockEnvironment
;
use
MediaWiki\Title\Title
;
use
MediaWiki\User\UserIdentityValue
;
/**
* @covers \MediaWiki\FileRepo\ThumbnailEntryPoint
* @group Database
*/
class
ThumbnailEntryPointTest
extends
MediaWikiIntegrationTestCase
{
use
TestRepoTrait
;
use
MockHttpTrait
;
private
const
PNG_MAGIC
=
"
\x
89
\x
50
\x
4e
\x
47"
;
private
const
JPEG_MAGIC
=
"
\x
ff
\x
d8
\x
ff
\x
e0"
;
private
const
IMAGES_DIR
=
__DIR__
.
'/../../data/media'
;
/** @var int Counter for getting unique width values */
private
static
$uniqueWidth
=
20
;
private
?
MockEnvironment
$environment
=
null
;
/**
* will be called only once per test class
*/
public
function
addDBDataOnce
()
{
// Set a named user account for the request context as the default,
// so that these tests do not fail with temp accounts enabled
RequestContext
::
getMain
()->
setUser
(
$this
->
getTestUser
()->
getUser
()
);
// Create mock repo with test files
$this
->
initTestRepoGroup
();
$this
->
importFileToTestRepo
(
self
::
IMAGES_DIR
.
'/greyscale-png.png'
,
'Test.png'
);
$this
->
importFileToTestRepo
(
self
::
IMAGES_DIR
.
'/test.jpg'
,
'Icon.jpg'
);
// Create a second version of Test.png and Icon.jpg
$this
->
importFileToTestRepo
(
self
::
IMAGES_DIR
.
'/greyscale-na-png.png'
,
'Test.png'
);
$this
->
importFileToTestRepo
(
self
::
IMAGES_DIR
.
'/portrait-rotated.jpg'
,
'Icon.jpg'
);
// Create a redirect
$title
=
Title
::
makeTitle
(
NS_FILE
,
'Redirect_to_Test.png'
);
$this
->
editPage
(
$title
,
'#REDIRECT [[File:Test.png]]'
);
// Suppress the old version of Icon
$file
=
$this
->
getTestRepo
()->
newFile
(
'Icon.jpg'
);
$history
=
$file
->
getHistory
();
$oldFile
=
$history
[
0
];
$this
->
getDb
()->
newUpdateQueryBuilder
()
->
table
(
'oldimage'
)
->
set
(
[
'oi_deleted'
=>
1
]
)
->
where
(
[
'oi_archive_name'
=>
$oldFile
->
getArchiveName
()
]
)
->
caller
(
__METHOD__
)
->
execute
();
}
public
static
function
tearDownAfterClass
():
void
{
self
::
destroyTestRepo
();
parent
::
tearDownAfterClass
();
}
public
function
setUp
():
void
{
parent
::
setUp
();
$this
->
overrideConfigValue
(
MainConfigNames
::
ThumbLimits
,
[
16
,
24
]
);
$this
->
installTestRepoGroup
();
}
private
function
recordHeader
(
string
$header
)
{
$this
->
environment
->
getFauxResponse
()->
header
(
$header
);
}
/**
* @param FauxRequest|string|array|null $request
*
* @return MockEnvironment
*/
private
function
makeEnvironment
(
$request
):
MockEnvironment
{
if
(
!
$request
)
{
$request
=
new
FauxRequest
();
}
if
(
is_string
(
$request
)
)
{
$request
=
[
'f'
=>
$request
,
'width'
=>
self
::
$uniqueWidth
++
];
}
if
(
is_array
(
$request
)
)
{
$request
=
new
FauxRequest
(
$request
);
$request
->
setRequestURL
(
'/w/img.php'
);
}
$this
->
environment
=
new
MockEnvironment
(
$request
);
return
$this
->
environment
;
}
/**
* @param MockEnvironment|null $environment
* @param FauxRequest|RequestContext|string|array|null $request
*
* @return ThumbnailEntryPoint
*/
private
function
getEntryPoint
(
?
MockEnvironment
$environment
=
null
,
$request
=
null
)
{
if
(
!
$request
&&
$environment
)
{
$request
=
$environment
->
getFauxRequest
();
}
if
(
$request
instanceof
RequestContext
)
{
$context
=
$request
;
$request
=
$context
->
getRequest
();
}
else
{
$context
=
new
RequestContext
();
$context
->
setRequest
(
$request
);
$context
->
setUser
(
$this
->
getTestUser
()->
getUser
()
);
}
if
(
!
$environment
)
{
$environment
=
$this
->
makeEnvironment
(
$request
);
}
$context
->
setLanguage
(
'qqx'
);
$entryPoint
=
new
ThumbnailEntryPoint
(
$context
,
$environment
,
$this
->
getServiceContainer
()
);
$entryPoint
->
enableOutputCapture
();
return
$entryPoint
;
}
public
function
testNotFound
()
{
$env
=
$this
->
makeEnvironment
(
'Missing_puppy.jpeg'
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$env
->
assertStatusCode
(
404
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$output
=
$entryPoint
->
getCapturedOutput
();
$this
->
assertStringContainsString
(
'<title>Error generating thumbnail</title>'
,
$output
);
}
public
function
testGenerateAndStreamThumbnail
()
{
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
12
// Must match the width in testStreamExistingThumbnail
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$response
=
$env
->
getFauxResponse
();
$this
->
assertSame
(
'image/png'
,
$response
->
getHeader
(
'Content-Type'
)
);
$this
->
assertGreaterThan
(
500
,
(
int
)
$response
->
getHeader
(
'Content-Length'
)
);
$env
->
assertStatusCode
(
200
,
$output
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
PNG_MAGIC
,
'width'
=>
12
,
],
$output
);
return
[
'data'
=>
$output
,
'width'
=>
12
];
}
/**
* @depends testGenerateAndStreamThumbnail
*/
public
function
testStreamExistingThumbnail
()
{
// Sabotage transformations, so this test will fail if we do not
// use the existing thumbnail generated by testGenerateAndStreamThumbnail.
$handler
=
$this
->
getMockBuilder
(
BitmapHandler
::
class
)
->
onlyMethods
(
[
'doTransform'
]
)
->
getMock
();
$handler
->
expects
(
$this
->
never
()
)->
method
(
'doTransform'
);
$factory
=
$this
->
createNoOpMock
(
MediaHandlerFactory
::
class
,
[
'getHandler'
]
);
$factory
->
method
(
'getHandler'
)->
willReturn
(
$handler
);
$this
->
setService
(
'MediaHandlerFactory'
,
$factory
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
12
// Must match the width in testGenerateAndStreamThumbnail
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
PNG_MAGIC
,
'width'
=>
12
,
],
$output
);
}
public
function
testNoThumbName
()
{
// Make sure no handler is set, so that File::generateThumbName() returns null
$factory
=
$this
->
createNoOpMock
(
MediaHandlerFactory
::
class
,
[
'getHandler'
]
);
$factory
->
method
(
'getHandler'
)->
willReturn
(
false
);
$this
->
setService
(
'MediaHandlerFactory'
,
$factory
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
self
::
$uniqueWidth
++
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
400
,
$output
);
}
public
static
function
provideTransformError
()
{
yield
'MediaTransformError'
=>
[
new
MediaTransformError
(
'testing'
,
200
,
100
),
500
];
yield
'thumbnail_image-failure-limit'
=>
[
new
MediaTransformError
(
'thumbnail_image-failure-limit'
,
200
,
100
),
429
];
yield
'no thumb'
=>
[
false
,
500
];
yield
'no file path'
=>
[
new
ThumbnailImage
(
new
UnregisteredLocalFile
(
false
,
false
,
'dummy'
),
''
,
false
,
[
'width'
=>
1
,
'height'
=>
1
]
),
500
];
}
/**
* @dataProvider provideTransformError
*/
public
function
testTransformError
(
$transformOutput
,
$expectedCode
)
{
// Mock transformations to return an error
$handler
=
$this
->
getMockBuilder
(
BitmapHandler
::
class
)
->
onlyMethods
(
[
'doTransform'
]
)
->
getMock
();
$handler
->
method
(
'doTransform'
)->
willReturn
(
$transformOutput
);
$factory
=
$this
->
createNoOpMock
(
MediaHandlerFactory
::
class
,
[
'getHandler'
]
);
$factory
->
method
(
'getHandler'
)->
willReturn
(
$handler
);
$this
->
setService
(
'MediaHandlerFactory'
,
$factory
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
self
::
$uniqueWidth
++
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
$expectedCode
,
$output
);
}
public
function
testContentDisposition
()
{
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
12
,
'download'
=>
1
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
PNG_MAGIC
,
],
$output
);
$env
->
assertHeaderValue
(
'attachment;filename*=UTF-8
\'\'
Test.png'
,
'Content-Disposition'
);
}
public
static
function
provideThumbNameParam
()
{
yield
[
'12px-Test.png'
];
yield
[
'page123456-12px-xyz'
];
yield
[
'12px-xyz'
];
yield
[
'xyzzy'
,
400
];
}
/**
* @dataProvider provideThumbNameParam
*/
public
function
testThumbNameParam
(
$thumbName
,
$expected
=
200
)
{
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'thumbName'
=>
$thumbName
,
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
$expected
,
$output
);
if
(
$expected
<
300
)
{
$expectedProps
=
[
'magic'
=>
self
::
PNG_MAGIC
];
// get expected width
if
(
preg_match
(
'/
\b
(
\d
+)px/'
,
$thumbName
,
$matches
)
)
{
$expectedProps
[
'width'
]
=
(
int
)
$matches
[
1
];
}
$this
->
assertThumbnail
(
$expectedProps
,
$output
);
}
}
public
function
testAccessDenied
()
{
// Make the wiki non-public
$this
->
setGroupPermissions
(
'*'
,
'read'
,
false
);
// Make the user have no rights
$authority
=
new
SimpleAuthority
(
new
UserIdentityValue
(
7
,
'Heather'
),
[]
);
$env
=
$this
->
makeEnvironment
(
'Test.png'
);
$context
=
$env
->
makeFauxContext
();
$context
->
setAuthority
(
$authority
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
,
$context
);
$entryPoint
->
run
();
$env
->
assertStatusCode
(
403
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$output
=
$entryPoint
->
getCapturedOutput
();
$this
->
assertStringContainsString
(
'<title>Error generating thumbnail</title>'
,
$output
);
}
public
function
testAccessOnPrivateWiki
()
{
// Make the wiki non-public, so we don't use the short-circuit code
$this
->
setGroupPermissions
(
'*'
,
'read'
,
false
);
// Make a user who is allowed to read
$authority
=
new
SimpleAuthority
(
new
UserIdentityValue
(
7
,
'Heather'
),
[
'read'
,
'renderfile'
,
'renderfile-nonstandard'
]
);
$env
=
$this
->
makeEnvironment
(
'Test.png'
);
$context
=
$env
->
makeFauxContext
();
$context
->
setAuthority
(
$authority
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
,
$context
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
PNG_MAGIC
,
],
$output
);
}
public
static
function
provideRateLimit
()
{
// NOTE: The 12px thumbnail will have been generated at this point.
// We force 16 and 24 to be standard sizes during setup.
// Once the thumbnail is generated, the rate limit is no longer
// triggered.
yield
[
'16'
,
'24'
,
'renderfile'
];
yield
[
self
::
$uniqueWidth
++,
self
::
$uniqueWidth
++,
'renderfile-nonstandard'
];
}
/**
* @dataProvider provideRateLimit
*/
public
function
testRateLimited
(
$width1
,
$width2
,
$limit
)
{
// Set up rate limit config
$rateLimits
=
$this
->
getConfVar
(
MainConfigNames
::
RateLimits
);
$rateLimits
[
$limit
]
=
[
'ip'
=>
[
1
,
60
],
'newbie'
=>
[
1
,
60
],
'user'
=>
[
1
,
60
],
];
$this
->
overrideConfigValue
(
MainConfigNames
::
RateLimits
,
$rateLimits
);
// First run should pass
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
$width1
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
// Second run should fail
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
$width2
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
429
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
}
/**
* @depends testGenerateAndStreamThumbnail
*/
public
function
testStreamOldFile
(
array
$latestThumbnailInfo
)
{
$file
=
$this
->
getTestRepo
()->
newFile
(
'Test.png'
);
$history
=
$file
->
getHistory
();
$oldFile
=
$history
[
0
];
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
$oldFile
->
getArchiveName
(),
'width'
=>
'12px'
,
// use "px" suffix, just so we also cover that code path
'archived'
=>
1
,
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
$this
->
assertNotSame
(
$latestThumbnailInfo
[
'data'
],
$output
,
'Thumbnail for the old version should not be the same as the '
.
'thumbnail for the latest version'
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
PNG_MAGIC
,
'width'
=>
12
,
],
$output
);
}
public
function
testOldDeletedFile
()
{
// Note that we manually set oi_deleted for this revision
// in addDBDataOnce().
$file
=
$this
->
getTestRepo
()->
newFile
(
'Icon.jpg'
);
$history
=
$file
->
getHistory
();
$oldFile
=
$history
[
0
];
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
$oldFile
->
getArchiveName
(),
'width'
=>
'12px'
,
// use "px" suffix, just so we also cover that code path
'archived'
=>
1
,
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
404
,
$output
);
}
/**
* @depends testGenerateAndStreamThumbnail
*/
public
function
testStreamOldFileRedirect
(
array
$latestThumbnailInfo
)
{
$file
=
$this
->
getTestRepo
()->
newFile
(
'Test.png'
);
$history
=
$file
->
getHistory
();
$oldFile
=
$history
[
0
];
// Try accessing the old revision using a redirected title
$archiveName
=
str_replace
(
'Test.png'
,
'Redirect_to_Test.png'
,
$oldFile
->
getArchiveName
()
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
$archiveName
,
'width'
=>
12
,
'archived'
=>
1
,
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$response
=
$env
->
getFauxResponse
();
$this
->
assertSame
(
302
,
$response
->
getStatusCode
()
);
$expected
=
'/'
.
urlencode
(
$oldFile
->
getArchiveName
()
)
.
'/12px-Test.png'
;
$this
->
assertStringEndsWith
(
$expected
,
$response
->
getHeader
(
'Location'
)
);
$this
->
assertSame
(
''
,
$output
);
}
public
function
testStreamTempFile
()
{
$user
=
$this
->
getTestUser
()->
getUser
();
$stash
=
new
UploadStash
(
$this
->
getTestRepo
(),
$user
);
$file
=
$stash
->
stashFile
(
self
::
IMAGES_DIR
.
'/adobergb.jpg'
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
$file
->
getName
(),
'width'
=>
12
,
'temp'
=>
'yes'
,
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
200
);
$this
->
assertThumbnail
(
[
'magic'
=>
self
::
JPEG_MAGIC
,
'width'
=>
12
,
],
$output
);
}
public
function
testRedirect
()
{
$this
->
overrideConfigValue
(
MainConfigNames
::
VaryOnXFP
,
true
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Redirect_to_Test.png'
,
'w'
=>
12
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$response
=
$env
->
getFauxResponse
();
$this
->
assertSame
(
302
,
$response
->
getStatusCode
()
);
$this
->
assertStringEndsWith
(
'/Test.png/12px-Test.png'
,
$response
->
getHeader
(
'Location'
)
);
$this
->
assertSame
(
''
,
$output
);
$env
->
assertHeaderValue
(
'X-Forwarded-Proto'
,
'Vary'
);
}
public
function
testBadTitle
()
{
$env
=
$this
->
makeEnvironment
(
'_/_'
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
404
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$this
->
assertStringContainsString
(
'(badtitletext)'
,
$output
);
}
public
static
function
provideOldFileWithBadTitle
()
{
yield
'invalid title'
=>
[
'_/_'
];
yield
'valid title without timestamp'
=>
[
'Test.png'
];
yield
'invalid title with timestamp'
=>
[
'20200101002233!_/_'
];
}
/**
* @dataProvider provideOldFileWithBadTitle
*/
public
function
testOldFileWithBadTitle
(
$badTitle
)
{
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
$badTitle
,
'width'
=>
12
,
'archived'
=>
1
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
404
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$this
->
assertStringContainsString
(
'(badtitletext)'
,
$output
);
}
public
function
testTooMuchWidth
()
{
// Set the width larger than the size of the image
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
1200
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
400
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$this
->
assertStringContainsString
(
'(thumbnail_error: '
,
$output
);
$this
->
assertStringContainsString
(
'bigger than the source'
,
$output
);
}
public
function
testDeletedFile
()
{
// Delete Icon.jpg
$icon
=
$this
->
getTestRepo
()->
newFile
(
'Icon.jpg'
);
$this
->
assertTrue
(
$icon
->
exists
()
);
// sanity
$icon
->
deleteFile
(
'testing'
,
new
UserIdentityValue
(
0
,
'Test'
)
);
$env
=
$this
->
makeEnvironment
(
'Icon.jpg'
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
404
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$this
->
assertStringContainsString
(
'<title>Error generating thumbnail</title>'
,
$output
);
}
public
function
testNotModified
()
{
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
12
]
);
$env
->
setServerInfo
(
'HTTP_IF_MODIFIED_SINCE'
,
'25250101001122'
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$response
=
$env
->
getFauxResponse
();
$this
->
assertSame
(
304
,
$response
->
getStatusCode
()
);
$this
->
assertSame
(
''
,
$output
);
}
public
function
testProxy
()
{
$this
->
installTestRepoGroup
(
[
'thumbProxyUrl'
=>
'https://images.acme.test/thumbnails/'
]
);
$this
->
installMockHttp
(
'PROXY RESPONSE'
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
self
::
$uniqueWidth
++
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$this
->
assertSame
(
'PROXY RESPONSE'
,
$output
);
}
public
static
function
provideRepoCouldNotStreamFile
()
{
// TODO: figure out how to provoke an error in
// MediaTransformOutput::streamFileWithStatus.
// The below causes an error to be triggered too early.
// Since MediaTransformOutput uses StreamFile directly, we have to also
// sabotage transformations in the handler to return a ThumbnailImage
// with no path. This is unfortunately brittle to implementation changes.
// The width must match the one generated by testGenerateAndStreamThumbnail
/*yield 'existing thumbnail' => [
12,
'Could not stream the file',
];*/
// The specific error message may change as the code evolves
yield
'non-existing thumbnail'
=>
[
self
::
$uniqueWidth
++,
'No path supplied in thumbnail object'
,
];
}
/**
* @dataProvider provideRepoCouldNotStreamFile
* @depends testGenerateAndStreamThumbnail
*/
public
function
testRepoCouldNotStreamFile
(
int
$width
,
string
$expectedError
)
{
$handler
=
$this
->
getMockBuilder
(
BitmapHandler
::
class
)
->
onlyMethods
(
[
'doTransform'
]
)
->
getMock
();
$file
=
$this
->
getTestRepo
()->
newFile
(
'Test.png'
);
$params
=
[
'width'
=>
$width
,
'height'
=>
$width
];
$handler
->
method
(
'doTransform'
)->
willReturn
(
new
ThumbnailImage
(
$file
,
''
,
false
,
$params
)
);
$factory
=
$this
->
createNoOpMock
(
MediaHandlerFactory
::
class
,
[
'getHandler'
]
);
$factory
->
method
(
'getHandler'
)->
willReturn
(
$handler
);
$this
->
setService
(
'MediaHandlerFactory'
,
$factory
);
$env
=
$this
->
makeEnvironment
(
[
'f'
=>
'Test.png'
,
'width'
=>
$width
]
);
$entryPoint
=
$this
->
getEntryPoint
(
$env
);
$entryPoint
->
run
();
$output
=
$entryPoint
->
getCapturedOutput
();
$env
->
assertStatusCode
(
500
,
$output
);
$env
->
assertHeaderValue
(
'text/html; charset=utf-8'
,
'Content-Type'
);
$this
->
assertStringContainsString
(
$expectedError
,
$output
);
}
/**
* @param array $props
* @param string $output binary data
*/
private
function
assertThumbnail
(
array
$props
,
string
$output
):
void
{
if
(
isset
(
$props
[
'magic'
]
)
)
{
$this
->
assertStringStartsWith
(
$props
[
'magic'
],
$output
,
'Magic number should match'
);
}
if
(
isset
(
$props
[
'width'
]
)
&&
function_exists
(
'getimagesizefromstring'
)
)
{
[
$width
,
]
=
getimagesizefromstring
(
$output
);
$this
->
assertSame
(
$props
[
'width'
],
$width
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Wed, Aug 19, 07:23 (2 w, 2 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ab/6a/cd4e26d20ca28a0abfc616ff103b
Default Alt Text
ThumbnailEntryPointTest.php (20 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment