3 namespace MediaWiki\Session
;
11 * @covers MediaWiki\Session\ImmutableSessionProviderWithCookie
13 class ImmutableSessionProviderWithCookieTest
extends MediaWikiTestCase
{
15 private function getProvider( $name, $prefix = null ) {
16 $config = new \
HashConfig();
17 $config->set( 'CookiePrefix', 'wgCookiePrefix' );
20 'sessionCookieName' => $name,
21 'sessionCookieOptions' => [],
23 if ( $prefix !== null ) {
24 $params['sessionCookieOptions']['prefix'] = $prefix;
27 $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie
::class )
28 ->setConstructorArgs( [ $params ] )
29 ->getMockForAbstractClass();
30 $provider->setLogger( new \
TestLogger() );
31 $provider->setConfig( $config );
32 $provider->setManager( new SessionManager() );
37 public function testConstructor() {
38 $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie
::class )
39 ->getMockForAbstractClass();
40 $priv = \TestingAccessWrapper
::newFromObject( $provider );
41 $this->assertNull( $priv->sessionCookieName
);
42 $this->assertSame( [], $priv->sessionCookieOptions
);
44 $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie
::class )
45 ->setConstructorArgs( [ [
46 'sessionCookieName' => 'Foo',
47 'sessionCookieOptions' => [ 'Bar' ],
49 ->getMockForAbstractClass();
50 $priv = \TestingAccessWrapper
::newFromObject( $provider );
51 $this->assertSame( 'Foo', $priv->sessionCookieName
);
52 $this->assertSame( [ 'Bar' ], $priv->sessionCookieOptions
);
55 $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie
::class )
56 ->setConstructorArgs( [ [
57 'sessionCookieName' => false,
59 ->getMockForAbstractClass();
60 $this->fail( 'Expected exception not thrown' );
61 } catch ( \InvalidArgumentException
$ex ) {
63 'sessionCookieName must be a string',
69 $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie
::class )
70 ->setConstructorArgs( [ [
71 'sessionCookieOptions' => 'x',
73 ->getMockForAbstractClass();
74 $this->fail( 'Expected exception not thrown' );
75 } catch ( \InvalidArgumentException
$ex ) {
77 'sessionCookieOptions must be an array',
83 public function testBasics() {
84 $provider = $this->getProvider( null );
85 $this->assertFalse( $provider->persistsSessionID() );
86 $this->assertFalse( $provider->canChangeUser() );
88 $provider = $this->getProvider( 'Foo' );
89 $this->assertTrue( $provider->persistsSessionID() );
90 $this->assertFalse( $provider->canChangeUser() );
92 $msg = $provider->whyNoSession();
93 $this->assertInstanceOf( 'Message', $msg );
94 $this->assertSame( 'sessionprovider-nocookies', $msg->getKey() );
97 public function testGetVaryCookies() {
98 $provider = $this->getProvider( null );
99 $this->assertSame( [], $provider->getVaryCookies() );
101 $provider = $this->getProvider( 'Foo' );
102 $this->assertSame( [ 'wgCookiePrefixFoo' ], $provider->getVaryCookies() );
104 $provider = $this->getProvider( 'Foo', 'Bar' );
105 $this->assertSame( [ 'BarFoo' ], $provider->getVaryCookies() );
107 $provider = $this->getProvider( 'Foo', '' );
108 $this->assertSame( [ 'Foo' ], $provider->getVaryCookies() );
111 public function testGetSessionIdFromCookie() {
112 $this->setMwGlobals( 'wgCookiePrefix', 'wgCookiePrefix' );
113 $request = new \
FauxRequest();
114 $request->setCookies( [
115 '' => 'empty---------------------------',
116 'Foo' => 'foo-----------------------------',
117 'wgCookiePrefixFoo' => 'wgfoo---------------------------',
118 'BarFoo' => 'foobar--------------------------',
122 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( null ) );
124 $provider->getSessionIdFromCookie( $request );
125 $this->fail( 'Expected exception not thrown' );
126 } catch ( \BadMethodCallException
$ex ) {
128 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie::getSessionIdFromCookie ' .
129 'may not be called when $this->sessionCookieName === null',
134 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( 'Foo' ) );
136 'wgfoo---------------------------',
137 $provider->getSessionIdFromCookie( $request )
140 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( 'Foo', 'Bar' ) );
142 'foobar--------------------------',
143 $provider->getSessionIdFromCookie( $request )
146 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( 'Foo', '' ) );
148 'foo-----------------------------',
149 $provider->getSessionIdFromCookie( $request )
152 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( 'bad', '' ) );
153 $this->assertSame( null, $provider->getSessionIdFromCookie( $request ) );
155 $provider = \TestingAccessWrapper
::newFromObject( $this->getProvider( 'none', '' ) );
156 $this->assertSame( null, $provider->getSessionIdFromCookie( $request ) );
159 protected function getSentRequest() {
160 $sentResponse = $this->getMock( 'FauxResponse', [ 'headersSent', 'setCookie', 'header' ] );
161 $sentResponse->expects( $this->any() )->method( 'headersSent' )
162 ->will( $this->returnValue( true ) );
163 $sentResponse->expects( $this->never() )->method( 'setCookie' );
164 $sentResponse->expects( $this->never() )->method( 'header' );
166 $sentRequest = $this->getMock( 'FauxRequest', [ 'response' ] );
167 $sentRequest->expects( $this->any() )->method( 'response' )
168 ->will( $this->returnValue( $sentResponse ) );
173 * @dataProvider providePersistSession
174 * @param bool $secure
175 * @param bool $remember
177 public function testPersistSession( $secure, $remember ) {
178 $this->setMwGlobals( [
179 'wgCookieExpiration' => 100,
180 'wgSecureLogin' => false,
183 $provider = $this->getProvider( 'session' );
184 $provider->setLogger( new \Psr\Log\
NullLogger() );
185 $priv = \TestingAccessWrapper
::newFromObject( $provider );
186 $priv->sessionCookieOptions
= [
188 'path' => 'CookiePath',
189 'domain' => 'CookieDomain',
194 $sessionId = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
195 $user = User
::newFromName( 'UTSysop' );
196 $this->assertFalse( $user->requiresHTTPS(), 'sanity check' );
198 $backend = new SessionBackend(
199 new SessionId( $sessionId ),
200 new SessionInfo( SessionInfo
::MIN_PRIORITY
, [
201 'provider' => $provider,
204 'userInfo' => UserInfo
::newFromUser( $user, true ),
208 new \Psr\Log\
NullLogger(),
211 \TestingAccessWrapper
::newFromObject( $backend )->usePhpSessionHandling
= false;
212 $backend->setRememberUser( $remember );
213 $backend->setForceHTTPS( $secure );
216 $priv->sessionCookieName
= null;
217 $request = new \
FauxRequest();
218 $provider->persistSession( $backend, $request );
219 $this->assertSame( [], $request->response()->getCookies() );
222 $priv->sessionCookieName
= 'session';
223 $request = new \
FauxRequest();
225 $provider->persistSession( $backend, $request );
227 $cookie = $request->response()->getCookieData( 'xsession' );
228 $this->assertInternalType( 'array', $cookie );
229 if ( isset( $cookie['expire'] ) && $cookie['expire'] > 0 ) {
230 // Round expiry so we don't randomly fail if the seconds ticked during the test.
231 $cookie['expire'] = round( $cookie['expire'] - $time, -2 );
233 $this->assertEquals( [
234 'value' => $sessionId,
236 'path' => 'CookiePath',
237 'domain' => 'CookieDomain',
243 $cookie = $request->response()->getCookieData( 'forceHTTPS' );
245 $this->assertInternalType( 'array', $cookie );
246 if ( isset( $cookie['expire'] ) && $cookie['expire'] > 0 ) {
247 // Round expiry so we don't randomly fail if the seconds ticked during the test.
248 $cookie['expire'] = round( $cookie['expire'] - $time, -2 );
250 $this->assertEquals( [
253 'path' => 'CookiePath',
254 'domain' => 'CookieDomain',
260 $this->assertNull( $cookie );
264 $request = $this->getSentRequest();
265 $provider->persistSession( $backend, $request );
266 $this->assertSame( [], $request->response()->getCookies() );
269 public static function providePersistSession() {
278 public function testUnpersistSession() {
279 $provider = $this->getProvider( 'session', '' );
280 $provider->setLogger( new \Psr\Log\
NullLogger() );
281 $priv = \TestingAccessWrapper
::newFromObject( $provider );
284 $priv->sessionCookieName
= null;
285 $request = new \
FauxRequest();
286 $provider->unpersistSession( $request );
287 $this->assertSame( null, $request->response()->getCookie( 'session', '' ) );
290 $priv->sessionCookieName
= 'session';
291 $request = new \
FauxRequest();
292 $provider->unpersistSession( $request );
293 $this->assertSame( '', $request->response()->getCookie( 'session', '' ) );
296 $request = $this->getSentRequest();
297 $provider->unpersistSession( $request );
298 $this->assertSame( null, $request->response()->getCookie( 'session', '' ) );