WebRequest: Add more unit tests

* Complete detectServer() coverage,
  test $wgAssumeProxiesUseDefaultProtocolPorts.
* Complete getAcceptLang() coverage.
* Add tests for getGPCVal() normalisation.
* Add tests for other getter methods.

Also:

* Ignore __construct() coverage as it only sets up properties from
  global state. The use of those properties are covered.

* Make normalizeUnicode() visibility explicit.

Change-Id: I6504136e6df47e504bc2e0e91fedddd2625f19d9
This commit is contained in:
Timo Tijhof 2016-09-08 21:58:09 -07:00
parent d18d030d57
commit 1ac5474b7b
2 changed files with 239 additions and 1 deletions

View file

@ -83,6 +83,9 @@ class WebRequest {
/** @var bool Whether this HTTP request is "safe" (even if it is an HTTP post) */
protected $markedAsSafe = false;
/**
* @codeCoverageIgnore
*/
public function __construct() {
$this->requestTime = isset( $_SERVER['REQUEST_TIME_FLOAT'] )
? $_SERVER['REQUEST_TIME_FLOAT'] : microtime( true );
@ -351,7 +354,7 @@ class WebRequest {
* @return array|string Cleaned-up version of the given
* @private
*/
function normalizeUnicode( $data ) {
public function normalizeUnicode( $data ) {
if ( is_array( $data ) ) {
foreach ( $data as $key => $val ) {
$data[$key] = $this->normalizeUnicode( $val );
@ -641,6 +644,7 @@ class WebRequest {
* Get the values passed in the query string.
* No transformation is performed on the values.
*
* @codeCoverageIgnore
* @return array
*/
public function getQueryValues() {
@ -651,6 +655,7 @@ class WebRequest {
* Return the contents of the Query with no decoding. Use when you need to
* know exactly what was sent, e.g. for an OAuth signature over the elements.
*
* @codeCoverageIgnore
* @return string
*/
public function getRawQueryString() {

View file

@ -23,8 +23,11 @@ class WebRequestTest extends MediaWikiTestCase {
/**
* @dataProvider provideDetectServer
* @covers WebRequest::detectServer
* @covers WebRequest::detectProtocol
*/
public function testDetectServer( $expected, $input, $description ) {
$this->setMwGlobals( 'wgAssumeProxiesUseDefaultProtocolPorts', true );
$_SERVER = $input;
$result = WebRequest::detectServer();
$this->assertEquals( $expected, $result, $description );
@ -63,6 +66,24 @@ class WebRequestTest extends MediaWikiTestCase {
],
'Secure off'
],
[
'https://x',
[
'HTTP_HOST' => 'x',
'HTTP_X_FORWARDED_PROTO' => 'https',
],
'Forwarded HTTPS'
],
[
'https://x',
[
'HTTP_HOST' => 'x',
'HTTPS' => 'off',
'SERVER_PORT' => '81',
'HTTP_X_FORWARDED_PROTO' => 'https',
],
'Forwarded HTTPS'
],
[
'http://y',
[
@ -104,6 +125,217 @@ class WebRequestTest extends MediaWikiTestCase {
];
}
protected function mockWebRequest( $data = [] ) {
// Cannot use PHPUnit getMockBuilder() as it does not support
// overriding protected properties afterwards
$reflection = new ReflectionClass( 'WebRequest' );
$req = $reflection->newInstanceWithoutConstructor();
$prop = $reflection->getProperty( 'data' );
$prop->setAccessible( true );
$prop->setValue( $req, $data );
return $req;
}
/**
* @covers WebRequest::getElapsedTime
*/
public function testGetElapsedTime() {
$req = new FauxRequest();
$this->assertGreaterThanOrEqual( 0.0, $req->getElapsedTime() );
$this->assertEquals( 0.0, $req->getElapsedTime(), '', /*delta*/ 0.2 );
}
/**
* @covers WebRequest::getVal
* @covers WebRequest::getGPCVal
* @covers WebRequest::normalizeUnicode
*/
public function testGetValNormal() {
// Assert that WebRequest normalises GPC data using UtfNormal\Validator
$input = "a \x00 null";
$normal = "a \xef\xbf\xbd null";
$req = new FauxRequest( [ 'x' => $input, 'y' => [ $input, $input ] ] );
$this->assertSame( $normal, $req->getVal( 'x' ) );
$this->assertNotSame( $input, $req->getVal( 'x' ) );
$this->assertSame( [ $normal, $normal ], $req->getArray( 'y' ) );
}
/**
* @covers WebRequest::getVal
* @covers WebRequest::getGPCVal
*/
public function testGetVal() {
$req = new FauxRequest( [ 'x' => 'Value', 'y' => [ 'a' ], 'crlf' => "A\r\nb" ] );
$this->assertSame( 'Value', $req->getVal( 'x' ), 'Simple value' );
$this->assertSame( null, $req->getVal( 'z' ), 'Not found' );
$this->assertSame( null, $req->getVal( 'y' ), 'Array is ignored' );
$this->assertSame( "A\r\nb", $req->getVal( 'crlf' ), 'CRLF' );
}
/**
* @covers WebRequest::getRawVal
*/
public function testGetRawVal() {
$req = new FauxRequest( [
'x' => 'Value',
'y' => [ 'a' ],
'crlf' => "A\r\nb"
] );
$this->assertSame( 'Value', $req->getRawVal( 'x' ) );
$this->assertSame( null, $req->getRawVal( 'z' ), 'Not found' );
$this->assertSame( null, $req->getRawVal( 'y' ), 'Array is ignored' );
$this->assertSame( "A\r\nb", $req->getRawVal( 'crlf' ), 'CRLF' );
}
/**
* @covers WebRequest::getArray
*/
public function testGetArray() {
$req = new FauxRequest( [ 'x' => 'Value', 'y' => [ 'a', 'b' ] ] );
$this->assertSame( [ 'Value' ], $req->getArray( 'x' ), 'Value becomes array' );
$this->assertSame( null, $req->getArray( 'z' ), 'Not found' );
$this->assertSame( [ 'a', 'b' ], $req->getArray( 'y' ) );
}
/**
* @covers WebRequest::getIntArray
*/
public function testGetIntArray() {
$req = new FauxRequest( [ 'x' => [ 'Value' ], 'y' => [ '0', '4.2', '-2' ] ] );
$this->assertSame( [ 0 ], $req->getIntArray( 'x' ), 'Text becomes 0' );
$this->assertSame( null, $req->getIntArray( 'z' ), 'Not found' );
$this->assertSame( [ 0, 4, -2 ], $req->getIntArray( 'y' ) );
}
/**
* @covers WebRequest::getInt
*/
public function testGetInt() {
$req = new FauxRequest( [
'x' => 'Value',
'y' => [ 'a' ],
'zero' => '0',
'answer' => '4.2',
'neg' => '-2',
] );
$this->assertSame( 0, $req->getInt( 'x' ), 'Text' );
$this->assertSame( 0, $req->getInt( 'y' ), 'Array' );
$this->assertSame( 0, $req->getInt( 'z' ), 'Not found' );
$this->assertSame( 0, $req->getInt( 'zero' ) );
$this->assertSame( 4, $req->getInt( 'answer' ) );
$this->assertSame( -2, $req->getInt( 'neg' ) );
}
/**
* @covers WebRequest::getIntOrNull
*/
public function testGetIntOrNull() {
$req = new FauxRequest( [
'x' => 'Value',
'y' => [ 'a' ],
'zero' => '0',
'answer' => '4.2',
'neg' => '-2',
] );
$this->assertSame( null, $req->getIntOrNull( 'x' ), 'Text' );
$this->assertSame( null, $req->getIntOrNull( 'y' ), 'Array' );
$this->assertSame( null, $req->getIntOrNull( 'z' ), 'Not found' );
$this->assertSame( 0, $req->getIntOrNull( 'zero' ) );
$this->assertSame( 4, $req->getIntOrNull( 'answer' ) );
$this->assertSame( -2, $req->getIntOrNull( 'neg' ) );
}
/**
* @covers WebRequest::getFloat
*/
public function testGetFloat() {
$req = new FauxRequest( [
'x' => 'Value',
'y' => [ 'a' ],
'zero' => '0',
'answer' => '4.2',
'neg' => '-2',
] );
$this->assertSame( 0.0, $req->getFloat( 'x' ), 'Text' );
$this->assertSame( 0.0, $req->getFloat( 'y' ), 'Array' );
$this->assertSame( 0.0, $req->getFloat( 'z' ), 'Not found' );
$this->assertSame( 0.0, $req->getFloat( 'zero' ) );
$this->assertSame( 4.2, $req->getFloat( 'answer' ) );
$this->assertSame( -2.0, $req->getFloat( 'neg' ) );
}
/**
* @covers WebRequest::getBool
*/
public function testGetBool() {
$req = new FauxRequest( [
'x' => 'Value',
'y' => [ 'a' ],
'zero' => '0',
'f' => 'false',
't' => 'true',
] );
$this->assertSame( true, $req->getBool( 'x' ), 'Text' );
$this->assertSame( false, $req->getBool( 'y' ), 'Array' );
$this->assertSame( false, $req->getBool( 'z' ), 'Not found' );
$this->assertSame( false, $req->getBool( 'zero' ) );
$this->assertSame( true, $req->getBool( 'f' ) );
$this->assertSame( true, $req->getBool( 't' ) );
}
/**
* @covers WebRequest::getFuzzyBool
*/
public function testGetFuzzyBool() {
$req = new FauxRequest( [ 'x' => 'Value', 'f' => 'false', 't' => 'true' ] );
$this->assertSame( true, $req->getFuzzyBool( 'x' ), 'Text' );
$this->assertSame( false, $req->getFuzzyBool( 'z' ), 'Not found' );
$this->assertSame( false, $req->getFuzzyBool( 'f' ) );
$this->assertSame( true, $req->getFuzzyBool( 't' ) );
}
/**
* @covers WebRequest::getCheck
*/
public function testGetCheck() {
$req = new FauxRequest( [ 'x' => 'Value', 'zero' => '0' ] );
$this->assertSame( false, $req->getCheck( 'z' ), 'Not found' );
$this->assertSame( true, $req->getCheck( 'x' ), 'Text' );
$this->assertSame( true, $req->getCheck( 'zero' ) );
}
/**
* @covers WebRequest::getText
*/
public function testGetText() {
// FauxRequest overrides getText
$req = $this->mockWebRequest( [ 'crlf' => "Va\r\nlue" ] );
$this->assertSame( "Va\nlue", $req->getText( 'crlf' ), 'CR stripped' );
}
/**
* @covers WebRequest::getValues
*/
public function testGetValues() {
$values = [ 'x' => 'Value', 'y' => '' ];
// FauxRequest overrides getValues
$req = $this->mockWebRequest( $values );
$this->assertSame( $values, $req->getValues() );
$this->assertSame( [ 'x' => 'Value' ], $req->getValues( 'x' ), 'Specific keys' );
}
/**
* @covers WebRequest::getValueNames
*/
public function testGetValueNames() {
// FauxRequest overrides getValues
$req = new FauxRequest( [ 'x' => 'Value', 'y' => '' ] );
$this->assertSame( [ 'x', 'y' ], $req->getValueNames() );
$this->assertSame( [ 'x' ], $req->getValueNames( [ 'y' ] ), 'Exclude keys' );
}
/**
* @dataProvider provideGetIP
* @covers WebRequest::getIP
@ -343,6 +575,7 @@ class WebRequestTest extends MediaWikiTestCase {
[ 'en-gb' => 1, 'en-us' => '1' ],
'Two equally prefered English variants'
],
[ '_', [], 'Invalid input' ],
];
}