Merge "Type hint against LinkTarget in WatchedItemStore"
[lhc/web/wiklou.git] / tests / phpunit / includes / session / SessionTest.php
1 <?php
2
3 namespace MediaWiki\Session;
4
5 use Psr\Log\LogLevel;
6 use MediaWikiTestCase;
7 use User;
8 use Wikimedia\TestingAccessWrapper;
9
10 /**
11 * @group Session
12 * @covers MediaWiki\Session\Session
13 */
14 class SessionTest extends MediaWikiTestCase {
15
16 public function testClear() {
17 $session = TestUtils::getDummySession();
18 $priv = TestingAccessWrapper::newFromObject( $session );
19
20 $backend = $this->getMockBuilder( DummySessionBackend::class )
21 ->setMethods( [ 'canSetUser', 'setUser', 'save' ] )
22 ->getMock();
23 $backend->expects( $this->once() )->method( 'canSetUser' )
24 ->will( $this->returnValue( true ) );
25 $backend->expects( $this->once() )->method( 'setUser' )
26 ->with( $this->callback( function ( $user ) {
27 return $user instanceof User && $user->isAnon();
28 } ) );
29 $backend->expects( $this->once() )->method( 'save' );
30 $priv->backend = $backend;
31 $session->clear();
32 $this->assertSame( [], $backend->data );
33 $this->assertTrue( $backend->dirty );
34
35 $backend = $this->getMockBuilder( DummySessionBackend::class )
36 ->setMethods( [ 'canSetUser', 'setUser', 'save' ] )
37 ->getMock();
38 $backend->data = [];
39 $backend->expects( $this->once() )->method( 'canSetUser' )
40 ->will( $this->returnValue( true ) );
41 $backend->expects( $this->once() )->method( 'setUser' )
42 ->with( $this->callback( function ( $user ) {
43 return $user instanceof User && $user->isAnon();
44 } ) );
45 $backend->expects( $this->once() )->method( 'save' );
46 $priv->backend = $backend;
47 $session->clear();
48 $this->assertFalse( $backend->dirty );
49
50 $backend = $this->getMockBuilder( DummySessionBackend::class )
51 ->setMethods( [ 'canSetUser', 'setUser', 'save' ] )
52 ->getMock();
53 $backend->expects( $this->once() )->method( 'canSetUser' )
54 ->will( $this->returnValue( false ) );
55 $backend->expects( $this->never() )->method( 'setUser' );
56 $backend->expects( $this->once() )->method( 'save' );
57 $priv->backend = $backend;
58 $session->clear();
59 $this->assertSame( [], $backend->data );
60 $this->assertTrue( $backend->dirty );
61 }
62
63 public function testSecrets() {
64 $logger = new \TestLogger;
65 $session = TestUtils::getDummySession( null, -1, $logger );
66
67 // Simple defaulting
68 $this->assertEquals( 'defaulted', $session->getSecret( 'test', 'defaulted' ) );
69
70 // Bad encrypted data
71 $session->set( 'test', 'foobar' );
72 $logger->setCollect( true );
73 $this->assertEquals( 'defaulted', $session->getSecret( 'test', 'defaulted' ) );
74 $logger->setCollect( false );
75 $this->assertSame( [
76 [ LogLevel::WARNING, 'Invalid sealed-secret format' ]
77 ], $logger->getBuffer() );
78 $logger->clearBuffer();
79
80 // Tampered data
81 $session->setSecret( 'test', 'foobar' );
82 $encrypted = $session->get( 'test' );
83 $session->set( 'test', $encrypted . 'x' );
84 $logger->setCollect( true );
85 $this->assertEquals( 'defaulted', $session->getSecret( 'test', 'defaulted' ) );
86 $logger->setCollect( false );
87 $this->assertSame( [
88 [ LogLevel::WARNING, 'Sealed secret has been tampered with, aborting.' ]
89 ], $logger->getBuffer() );
90 $logger->clearBuffer();
91
92 // Unserializable data
93 $iv = random_bytes( 16 );
94 list( $encKey, $hmacKey ) = TestingAccessWrapper::newFromObject( $session )->getSecretKeys();
95 $ciphertext = openssl_encrypt( 'foobar', 'aes-256-ctr', $encKey, OPENSSL_RAW_DATA, $iv );
96 $sealed = base64_encode( $iv ) . '.' . base64_encode( $ciphertext );
97 $hmac = hash_hmac( 'sha256', $sealed, $hmacKey, true );
98 $encrypted = base64_encode( $hmac ) . '.' . $sealed;
99 $session->set( 'test', $encrypted );
100 \Wikimedia\suppressWarnings();
101 $this->assertEquals( 'defaulted', $session->getSecret( 'test', 'defaulted' ) );
102 \Wikimedia\restoreWarnings();
103 }
104
105 /**
106 * @dataProvider provideSecretsRoundTripping
107 * @param mixed $data
108 */
109 public function testSecretsRoundTripping( $data ) {
110 $session = TestUtils::getDummySession();
111
112 // Simple round-trip
113 $session->setSecret( 'secret', $data );
114 $this->assertNotEquals( $data, $session->get( 'secret' ) );
115 $this->assertEquals( $data, $session->getSecret( 'secret', 'defaulted' ) );
116 }
117
118 public static function provideSecretsRoundTripping() {
119 return [
120 [ 'Foobar' ],
121 [ 42 ],
122 [ [ 'foo', 'bar' => 'baz', 'subarray' => [ 1, 2, 3 ] ] ],
123 [ (object)[ 'foo', 'bar' => 'baz', 'subarray' => [ 1, 2, 3 ] ] ],
124 [ true ],
125 [ false ],
126 [ null ],
127 ];
128 }
129
130 }