Merge "Follow-up cdc93a62bf: add serialize/unserialize tests for RedisBagOStuff"
[lhc/web/wiklou.git] / tests / phpunit / includes / session / SessionProviderTest.php
1 <?php
2
3 namespace MediaWiki\Session;
4
5 use MediaWikiTestCase;
6
7 /**
8 * @group Session
9 * @group Database
10 * @covers MediaWiki\Session\SessionProvider
11 */
12 class SessionProviderTest extends MediaWikiTestCase {
13
14 public function testBasics() {
15 $manager = new SessionManager();
16 $logger = new \TestLogger();
17 $config = new \HashConfig();
18
19 $provider = $this->getMockForAbstractClass( SessionProvider::class );
20 $priv = \TestingAccessWrapper::newFromObject( $provider );
21
22 $provider->setConfig( $config );
23 $this->assertSame( $config, $priv->config );
24 $provider->setLogger( $logger );
25 $this->assertSame( $logger, $priv->logger );
26 $provider->setManager( $manager );
27 $this->assertSame( $manager, $priv->manager );
28 $this->assertSame( $manager, $provider->getManager() );
29
30 $provider->invalidateSessionsForUser( new \User );
31
32 $this->assertSame( [], $provider->getVaryHeaders() );
33 $this->assertSame( [], $provider->getVaryCookies() );
34 $this->assertSame( null, $provider->suggestLoginUsername( new \FauxRequest ) );
35
36 $this->assertSame( get_class( $provider ), (string)$provider );
37
38 $this->assertNull( $provider->whyNoSession() );
39
40 $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [
41 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
42 'provider' => $provider,
43 ] );
44 $metadata = [ 'foo' ];
45 $this->assertTrue( $provider->refreshSessionInfo( $info, new \FauxRequest, $metadata ) );
46 $this->assertSame( [ 'foo' ], $metadata );
47 }
48
49 /**
50 * @dataProvider provideNewSessionInfo
51 * @param bool $persistId Return value for ->persistsSessionId()
52 * @param bool $persistUser Return value for ->persistsSessionUser()
53 * @param bool $ok Whether a SessionInfo is provided
54 */
55 public function testNewSessionInfo( $persistId, $persistUser, $ok ) {
56 $manager = new SessionManager();
57
58 $provider = $this->getMockBuilder( SessionProvider::class )
59 ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
60 ->getMockForAbstractClass();
61 $provider->expects( $this->any() )->method( 'persistsSessionId' )
62 ->will( $this->returnValue( $persistId ) );
63 $provider->expects( $this->any() )->method( 'canChangeUser' )
64 ->will( $this->returnValue( $persistUser ) );
65 $provider->setManager( $manager );
66
67 if ( $ok ) {
68 $info = $provider->newSessionInfo();
69 $this->assertNotNull( $info );
70 $this->assertFalse( $info->wasPersisted() );
71 $this->assertTrue( $info->isIdSafe() );
72
73 $id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
74 $info = $provider->newSessionInfo( $id );
75 $this->assertNotNull( $info );
76 $this->assertSame( $id, $info->getId() );
77 $this->assertFalse( $info->wasPersisted() );
78 $this->assertTrue( $info->isIdSafe() );
79 } else {
80 $this->assertNull( $provider->newSessionInfo() );
81 }
82 }
83
84 public function testMergeMetadata() {
85 $provider = $this->getMockBuilder( SessionProvider::class )
86 ->getMockForAbstractClass();
87
88 try {
89 $provider->mergeMetadata(
90 [ 'foo' => 1, 'baz' => 3 ],
91 [ 'bar' => 2, 'baz' => '3' ]
92 );
93 $this->fail( 'Expected exception not thrown' );
94 } catch ( MetadataMergeException $ex ) {
95 $this->assertSame( 'Key "baz" changed', $ex->getMessage() );
96 $this->assertSame(
97 [ 'old_value' => 3, 'new_value' => '3' ], $ex->getContext() );
98 }
99
100 $res = $provider->mergeMetadata(
101 [ 'foo' => 1, 'baz' => 3 ],
102 [ 'bar' => 2, 'baz' => 3 ]
103 );
104 $this->assertSame( [ 'bar' => 2, 'baz' => 3 ], $res );
105 }
106
107 public static function provideNewSessionInfo() {
108 return [
109 [ false, false, false ],
110 [ true, false, false ],
111 [ false, true, false ],
112 [ true, true, true ],
113 ];
114 }
115
116 public function testImmutableSessions() {
117 $provider = $this->getMockBuilder( SessionProvider::class )
118 ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
119 ->getMockForAbstractClass();
120 $provider->expects( $this->any() )->method( 'canChangeUser' )
121 ->will( $this->returnValue( true ) );
122 $provider->preventSessionsForUser( 'Foo' );
123
124 $provider = $this->getMockBuilder( SessionProvider::class )
125 ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
126 ->getMockForAbstractClass();
127 $provider->expects( $this->any() )->method( 'canChangeUser' )
128 ->will( $this->returnValue( false ) );
129 try {
130 $provider->preventSessionsForUser( 'Foo' );
131 $this->fail( 'Expected exception not thrown' );
132 } catch ( \BadMethodCallException $ex ) {
133 $this->assertSame(
134 'MediaWiki\\Session\\SessionProvider::preventSessionsForUser must be implmented ' .
135 'when canChangeUser() is false',
136 $ex->getMessage()
137 );
138 }
139
140 }
141
142 public function testHashToSessionId() {
143 $config = new \HashConfig( [
144 'SecretKey' => 'Shhh!',
145 ] );
146
147 $provider = $this->getMockForAbstractClass( SessionProvider::class,
148 [], 'MockSessionProvider' );
149 $provider->setConfig( $config );
150 $priv = \TestingAccessWrapper::newFromObject( $provider );
151
152 $this->assertSame( 'eoq8cb1mg7j30ui5qolafps4hg29k5bb', $priv->hashToSessionId( 'foobar' ) );
153 $this->assertSame( '4do8j7tfld1g8tte9jqp3csfgmulaun9',
154 $priv->hashToSessionId( 'foobar', 'secret' ) );
155
156 try {
157 $priv->hashToSessionId( [] );
158 $this->fail( 'Expected exception not thrown' );
159 } catch ( \InvalidArgumentException $ex ) {
160 $this->assertSame(
161 '$data must be a string, array was passed',
162 $ex->getMessage()
163 );
164 }
165 try {
166 $priv->hashToSessionId( '', false );
167 $this->fail( 'Expected exception not thrown' );
168 } catch ( \InvalidArgumentException $ex ) {
169 $this->assertSame(
170 '$key must be a string or null, boolean was passed',
171 $ex->getMessage()
172 );
173 }
174 }
175
176 public function testDescribe() {
177 $provider = $this->getMockForAbstractClass( SessionProvider::class,
178 [], 'MockSessionProvider' );
179
180 $this->assertSame(
181 'MockSessionProvider sessions',
182 $provider->describe( \Language::factory( 'en' ) )
183 );
184 }
185
186 public function testGetAllowedUserRights() {
187 $provider = $this->getMockForAbstractClass( SessionProvider::class );
188 $backend = TestUtils::getDummySessionBackend();
189
190 try {
191 $provider->getAllowedUserRights( $backend );
192 $this->fail( 'Expected exception not thrown' );
193 } catch ( \InvalidArgumentException $ex ) {
194 $this->assertSame(
195 'Backend\'s provider isn\'t $this',
196 $ex->getMessage()
197 );
198 }
199
200 \TestingAccessWrapper::newFromObject( $backend )->provider = $provider;
201 $this->assertNull( $provider->getAllowedUserRights( $backend ) );
202 }
203
204 }