3 namespace MediaWiki\Session
;
10 * @covers MediaWiki\Session\Session
12 class SessionTest
extends MediaWikiTestCase
{
14 public function testConstructor() {
15 $backend = TestUtils
::getDummySessionBackend();
16 \TestingAccessWrapper
::newFromObject( $backend )->requests
= array( -1 => 'dummy' );
17 \TestingAccessWrapper
::newFromObject( $backend )->id
= new SessionId( 'abc' );
19 $session = new Session( $backend, 42 );
20 $priv = \TestingAccessWrapper
::newFromObject( $session );
21 $this->assertSame( $backend, $priv->backend
);
22 $this->assertSame( 42, $priv->index
);
24 $request = new \
FauxRequest();
25 $priv2 = \TestingAccessWrapper
::newFromObject( $session->sessionWithRequest( $request ) );
26 $this->assertSame( $backend, $priv2->backend
);
27 $this->assertNotSame( $priv->index
, $priv2->index
);
28 $this->assertSame( $request, $priv2->getRequest() );
32 * @dataProvider provideMethods
33 * @param string $m Method to test
34 * @param array $args Arguments to pass to the method
35 * @param bool $index Whether the backend method gets passed the index
36 * @param bool $ret Whether the method returns a value
38 public function testMethods( $m, $args, $index, $ret ) {
39 $mock = $this->getMock( 'MediaWiki\\Session\\DummySessionBackend',
40 array( $m, 'deregisterSession' ) );
41 $mock->expects( $this->once() )->method( 'deregisterSession' )
42 ->with( $this->identicalTo( 42 ) );
44 $tmp = $mock->expects( $this->once() )->method( $m );
45 $expectArgs = array();
47 $expectArgs[] = $this->identicalTo( 42 );
49 foreach ( $args as $arg ) {
50 $expectArgs[] = $this->identicalTo( $arg );
52 $tmp = call_user_func_array( array( $tmp, 'with' ), $expectArgs );
54 $retval = new \stdClass
;
55 $tmp->will( $this->returnValue( $retval ) );
57 $session = TestUtils
::getDummySession( $mock, 42 );
60 $this->assertSame( $retval, call_user_func_array( array( $session, $m ), $args ) );
62 $this->assertNull( call_user_func_array( array( $session, $m ), $args ) );
65 // Trigger Session destructor
69 public static function provideMethods() {
71 array( 'getId', array(), false, true ),
72 array( 'getSessionId', array(), false, true ),
73 array( 'resetId', array(), false, true ),
74 array( 'getProvider', array(), false, true ),
75 array( 'isPersistent', array(), false, true ),
76 array( 'persist', array(), false, false ),
77 array( 'shouldRememberUser', array(), false, true ),
78 array( 'setRememberUser', array( true ), false, false ),
79 array( 'getRequest', array(), true, true ),
80 array( 'getUser', array(), false, true ),
81 array( 'getAllowedUserRights', array(), false, true ),
82 array( 'canSetUser', array(), false, true ),
83 array( 'setUser', array( new \stdClass
), false, false ),
84 array( 'suggestLoginUsername', array(), true, true ),
85 array( 'shouldForceHTTPS', array(), false, true ),
86 array( 'setForceHTTPS', array( true ), false, false ),
87 array( 'getLoggedOutTimestamp', array(), false, true ),
88 array( 'setLoggedOutTimestamp', array( 123 ), false, false ),
89 array( 'getProviderMetadata', array(), false, true ),
90 array( 'save', array(), false, false ),
91 array( 'delaySave', array(), false, true ),
92 array( 'renew', array(), false, false ),
96 public function testDataAccess() {
97 $session = TestUtils
::getDummySession();
98 $backend = \TestingAccessWrapper
::newFromObject( $session )->backend
;
100 $this->assertEquals( 1, $session->get( 'foo' ) );
101 $this->assertEquals( 'zero', $session->get( 0 ) );
102 $this->assertFalse( $backend->dirty
);
104 $this->assertEquals( null, $session->get( 'null' ) );
105 $this->assertEquals( 'default', $session->get( 'null', 'default' ) );
106 $this->assertFalse( $backend->dirty
);
108 $session->set( 'foo', 55 );
109 $this->assertEquals( 55, $backend->data
['foo'] );
110 $this->assertTrue( $backend->dirty
);
111 $backend->dirty
= false;
113 $session->set( 1, 'one' );
114 $this->assertEquals( 'one', $backend->data
[1] );
115 $this->assertTrue( $backend->dirty
);
116 $backend->dirty
= false;
118 $session->set( 1, 'one' );
119 $this->assertFalse( $backend->dirty
);
121 $this->assertTrue( $session->exists( 'foo' ) );
122 $this->assertTrue( $session->exists( 1 ) );
123 $this->assertFalse( $session->exists( 'null' ) );
124 $this->assertFalse( $session->exists( 100 ) );
125 $this->assertFalse( $backend->dirty
);
127 $session->remove( 'foo' );
128 $this->assertArrayNotHasKey( 'foo', $backend->data
);
129 $this->assertTrue( $backend->dirty
);
130 $backend->dirty
= false;
131 $session->remove( 1 );
132 $this->assertArrayNotHasKey( 1, $backend->data
);
133 $this->assertTrue( $backend->dirty
);
134 $backend->dirty
= false;
136 $session->remove( 101 );
137 $this->assertFalse( $backend->dirty
);
139 $backend->data
= array( 'a', 'b', '?' => 'c' );
140 $this->assertSame( 3, $session->count() );
141 $this->assertSame( 3, count( $session ) );
142 $this->assertFalse( $backend->dirty
);
145 foreach ( $session as $key => $value ) {
146 $data[$key] = $value;
148 $this->assertEquals( $backend->data
, $data );
149 $this->assertFalse( $backend->dirty
);
151 $this->assertEquals( $backend->data
, iterator_to_array( $session ) );
152 $this->assertFalse( $backend->dirty
);
155 public function testClear() {
156 $session = TestUtils
::getDummySession();
157 $priv = \TestingAccessWrapper
::newFromObject( $session );
159 $backend = $this->getMock(
160 'MediaWiki\\Session\\DummySessionBackend', array( 'canSetUser', 'setUser', 'save' )
162 $backend->expects( $this->once() )->method( 'canSetUser' )
163 ->will( $this->returnValue( true ) );
164 $backend->expects( $this->once() )->method( 'setUser' )
165 ->with( $this->callback( function ( $user ) {
166 return $user instanceof User
&& $user->isAnon();
168 $backend->expects( $this->once() )->method( 'save' );
169 $priv->backend
= $backend;
171 $this->assertSame( array(), $backend->data
);
172 $this->assertTrue( $backend->dirty
);
174 $backend = $this->getMock(
175 'MediaWiki\\Session\\DummySessionBackend', array( 'canSetUser', 'setUser', 'save' )
177 $backend->data
= array();
178 $backend->expects( $this->once() )->method( 'canSetUser' )
179 ->will( $this->returnValue( true ) );
180 $backend->expects( $this->once() )->method( 'setUser' )
181 ->with( $this->callback( function ( $user ) {
182 return $user instanceof User
&& $user->isAnon();
184 $backend->expects( $this->once() )->method( 'save' );
185 $priv->backend
= $backend;
187 $this->assertFalse( $backend->dirty
);
189 $backend = $this->getMock(
190 'MediaWiki\\Session\\DummySessionBackend', array( 'canSetUser', 'setUser', 'save' )
192 $backend->expects( $this->once() )->method( 'canSetUser' )
193 ->will( $this->returnValue( false ) );
194 $backend->expects( $this->never() )->method( 'setUser' );
195 $backend->expects( $this->once() )->method( 'save' );
196 $priv->backend
= $backend;
198 $this->assertSame( array(), $backend->data
);
199 $this->assertTrue( $backend->dirty
);
202 public function testTokens() {
203 $rc = new \
ReflectionClass( 'MediaWiki\\Session\\Session' );
204 if ( !method_exists( $rc, 'newInstanceWithoutConstructor' ) ) {
205 $this->markTestSkipped(
206 'ReflectionClass::newInstanceWithoutConstructor isn\'t available'
210 // Instead of actually constructing the Session, we use reflection to
211 // bypass the constructor and plug a mock SessionBackend into the
212 // private fields to avoid having to actually create a SessionBackend.
213 $backend = new DummySessionBackend
;
214 $session = $rc->newInstanceWithoutConstructor();
215 $priv = \TestingAccessWrapper
::newFromObject( $session );
216 $priv->backend
= $backend;
219 $token = \TestingAccessWrapper
::newFromObject( $session->getToken() );
220 $this->assertArrayHasKey( 'wsTokenSecrets', $backend->data
);
221 $this->assertArrayHasKey( 'default', $backend->data
['wsTokenSecrets'] );
222 $secret = $backend->data
['wsTokenSecrets']['default'];
223 $this->assertSame( $secret, $token->secret
);
224 $this->assertSame( '', $token->salt
);
225 $this->assertTrue( $token->wasNew() );
227 $token = \TestingAccessWrapper
::newFromObject( $session->getToken( 'foo' ) );
228 $this->assertSame( $secret, $token->secret
);
229 $this->assertSame( 'foo', $token->salt
);
230 $this->assertFalse( $token->wasNew() );
232 $backend->data
['wsTokenSecrets']['secret'] = 'sekret';
233 $token = \TestingAccessWrapper
::newFromObject(
234 $session->getToken( array( 'bar', 'baz' ), 'secret' )
236 $this->assertSame( 'sekret', $token->secret
);
237 $this->assertSame( 'bar|baz', $token->salt
);
238 $this->assertFalse( $token->wasNew() );
240 $session->resetToken( 'secret' );
241 $this->assertArrayHasKey( 'wsTokenSecrets', $backend->data
);
242 $this->assertArrayHasKey( 'default', $backend->data
['wsTokenSecrets'] );
243 $this->assertArrayNotHasKey( 'secret', $backend->data
['wsTokenSecrets'] );
245 $session->resetAllTokens();
246 $this->assertArrayNotHasKey( 'wsTokenSecrets', $backend->data
);