Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / http-foundation / Tests / Session / Storage / Handler / MongoDbSessionHandlerTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler;
16
17 /**
18  * @author Markus Bachmann <markus.bachmann@bachi.biz>
19  * @group time-sensitive
20  * @group legacy
21  */
22 class MongoDbSessionHandlerTest extends TestCase
23 {
24     /**
25      * @var \PHPUnit_Framework_MockObject_MockObject
26      */
27     private $mongo;
28     private $storage;
29     public $options;
30
31     protected function setUp()
32     {
33         parent::setUp();
34
35         if (extension_loaded('mongodb')) {
36             if (!class_exists('MongoDB\Client')) {
37                 $this->markTestSkipped('The mongodb/mongodb package is required.');
38             }
39         } elseif (!extension_loaded('mongo')) {
40             $this->markTestSkipped('The Mongo or MongoDB extension is required.');
41         }
42
43         if (phpversion('mongodb')) {
44             $mongoClass = 'MongoDB\Client';
45         } else {
46             $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';
47         }
48
49         $this->mongo = $this->getMockBuilder($mongoClass)
50             ->disableOriginalConstructor()
51             ->getMock();
52
53         $this->options = array(
54             'id_field' => '_id',
55             'data_field' => 'data',
56             'time_field' => 'time',
57             'expiry_field' => 'expires_at',
58             'database' => 'sf2-test',
59             'collection' => 'session-test',
60         );
61
62         $this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
63     }
64
65     /**
66      * @expectedException \InvalidArgumentException
67      */
68     public function testConstructorShouldThrowExceptionForInvalidMongo()
69     {
70         new MongoDbSessionHandler(new \stdClass(), $this->options);
71     }
72
73     /**
74      * @expectedException \InvalidArgumentException
75      */
76     public function testConstructorShouldThrowExceptionForMissingOptions()
77     {
78         new MongoDbSessionHandler($this->mongo, array());
79     }
80
81     public function testOpenMethodAlwaysReturnTrue()
82     {
83         $this->assertTrue($this->storage->open('test', 'test'), 'The "open" method should always return true');
84     }
85
86     public function testCloseMethodAlwaysReturnTrue()
87     {
88         $this->assertTrue($this->storage->close(), 'The "close" method should always return true');
89     }
90
91     public function testRead()
92     {
93         $collection = $this->createMongoCollectionMock();
94
95         $this->mongo->expects($this->once())
96             ->method('selectCollection')
97             ->with($this->options['database'], $this->options['collection'])
98             ->will($this->returnValue($collection));
99
100         // defining the timeout before the actual method call
101         // allows to test for "greater than" values in the $criteria
102         $testTimeout = time() + 1;
103
104         $collection->expects($this->once())
105             ->method('findOne')
106             ->will($this->returnCallback(function ($criteria) use ($testTimeout) {
107                 $this->assertArrayHasKey($this->options['id_field'], $criteria);
108                 $this->assertEquals($criteria[$this->options['id_field']], 'foo');
109
110                 $this->assertArrayHasKey($this->options['expiry_field'], $criteria);
111                 $this->assertArrayHasKey('$gte', $criteria[$this->options['expiry_field']]);
112
113                 if (phpversion('mongodb')) {
114                     $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$gte']);
115                     $this->assertGreaterThanOrEqual(round((string) $criteria[$this->options['expiry_field']]['$gte'] / 1000), $testTimeout);
116                 } else {
117                     $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$gte']);
118                     $this->assertGreaterThanOrEqual($criteria[$this->options['expiry_field']]['$gte']->sec, $testTimeout);
119                 }
120
121                 $fields = array(
122                     $this->options['id_field'] => 'foo',
123                 );
124
125                 if (phpversion('mongodb')) {
126                     $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary('bar', \MongoDB\BSON\Binary::TYPE_OLD_BINARY);
127                     $fields[$this->options['id_field']] = new \MongoDB\BSON\UTCDateTime(time() * 1000);
128                 } else {
129                     $fields[$this->options['data_field']] = new \MongoBinData('bar', \MongoBinData::BYTE_ARRAY);
130                     $fields[$this->options['id_field']] = new \MongoDate();
131                 }
132
133                 return $fields;
134             }));
135
136         $this->assertEquals('bar', $this->storage->read('foo'));
137     }
138
139     public function testWrite()
140     {
141         $collection = $this->createMongoCollectionMock();
142
143         $this->mongo->expects($this->once())
144             ->method('selectCollection')
145             ->with($this->options['database'], $this->options['collection'])
146             ->will($this->returnValue($collection));
147
148         $data = array();
149
150         $methodName = phpversion('mongodb') ? 'updateOne' : 'update';
151
152         $collection->expects($this->once())
153             ->method($methodName)
154             ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) {
155                 $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria);
156
157                 if (phpversion('mongodb')) {
158                     $this->assertEquals(array('upsert' => true), $options);
159                 } else {
160                     $this->assertEquals(array('upsert' => true, 'multiple' => false), $options);
161                 }
162
163                 $data = $updateData['$set'];
164             }));
165
166         $expectedExpiry = time() + (int) ini_get('session.gc_maxlifetime');
167         $this->assertTrue($this->storage->write('foo', 'bar'));
168
169         if (phpversion('mongodb')) {
170             $this->assertEquals('bar', $data[$this->options['data_field']]->getData());
171             $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]);
172             $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]);
173             $this->assertGreaterThanOrEqual($expectedExpiry, round((string) $data[$this->options['expiry_field']] / 1000));
174         } else {
175             $this->assertEquals('bar', $data[$this->options['data_field']]->bin);
176             $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
177             $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]);
178             $this->assertGreaterThanOrEqual($expectedExpiry, $data[$this->options['expiry_field']]->sec);
179         }
180     }
181
182     public function testWriteWhenUsingExpiresField()
183     {
184         $this->options = array(
185             'id_field' => '_id',
186             'data_field' => 'data',
187             'time_field' => 'time',
188             'database' => 'sf2-test',
189             'collection' => 'session-test',
190             'expiry_field' => 'expiresAt',
191         );
192
193         $this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
194
195         $collection = $this->createMongoCollectionMock();
196
197         $this->mongo->expects($this->once())
198             ->method('selectCollection')
199             ->with($this->options['database'], $this->options['collection'])
200             ->will($this->returnValue($collection));
201
202         $data = array();
203
204         $methodName = phpversion('mongodb') ? 'updateOne' : 'update';
205
206         $collection->expects($this->once())
207             ->method($methodName)
208             ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) {
209                 $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria);
210
211                 if (phpversion('mongodb')) {
212                     $this->assertEquals(array('upsert' => true), $options);
213                 } else {
214                     $this->assertEquals(array('upsert' => true, 'multiple' => false), $options);
215                 }
216
217                 $data = $updateData['$set'];
218             }));
219
220         $this->assertTrue($this->storage->write('foo', 'bar'));
221
222         if (phpversion('mongodb')) {
223             $this->assertEquals('bar', $data[$this->options['data_field']]->getData());
224             $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]);
225             $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]);
226         } else {
227             $this->assertEquals('bar', $data[$this->options['data_field']]->bin);
228             $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
229             $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]);
230         }
231     }
232
233     public function testReplaceSessionData()
234     {
235         $collection = $this->createMongoCollectionMock();
236
237         $this->mongo->expects($this->once())
238             ->method('selectCollection')
239             ->with($this->options['database'], $this->options['collection'])
240             ->will($this->returnValue($collection));
241
242         $data = array();
243
244         $methodName = phpversion('mongodb') ? 'updateOne' : 'update';
245
246         $collection->expects($this->exactly(2))
247             ->method($methodName)
248             ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) {
249                 $data = $updateData;
250             }));
251
252         $this->storage->write('foo', 'bar');
253         $this->storage->write('foo', 'foobar');
254
255         if (phpversion('mongodb')) {
256             $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->getData());
257         } else {
258             $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->bin);
259         }
260     }
261
262     public function testDestroy()
263     {
264         $collection = $this->createMongoCollectionMock();
265
266         $this->mongo->expects($this->once())
267             ->method('selectCollection')
268             ->with($this->options['database'], $this->options['collection'])
269             ->will($this->returnValue($collection));
270
271         $methodName = phpversion('mongodb') ? 'deleteOne' : 'remove';
272
273         $collection->expects($this->once())
274             ->method($methodName)
275             ->with(array($this->options['id_field'] => 'foo'));
276
277         $this->assertTrue($this->storage->destroy('foo'));
278     }
279
280     public function testGc()
281     {
282         $collection = $this->createMongoCollectionMock();
283
284         $this->mongo->expects($this->once())
285             ->method('selectCollection')
286             ->with($this->options['database'], $this->options['collection'])
287             ->will($this->returnValue($collection));
288
289         $methodName = phpversion('mongodb') ? 'deleteMany' : 'remove';
290
291         $collection->expects($this->once())
292             ->method($methodName)
293             ->will($this->returnCallback(function ($criteria) {
294                 if (phpversion('mongodb')) {
295                     $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$lt']);
296                     $this->assertGreaterThanOrEqual(time() - 1, round((string) $criteria[$this->options['expiry_field']]['$lt'] / 1000));
297                 } else {
298                     $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$lt']);
299                     $this->assertGreaterThanOrEqual(time() - 1, $criteria[$this->options['expiry_field']]['$lt']->sec);
300                 }
301             }));
302
303         $this->assertTrue($this->storage->gc(1));
304     }
305
306     public function testGetConnection()
307     {
308         $method = new \ReflectionMethod($this->storage, 'getMongo');
309         $method->setAccessible(true);
310
311         if (phpversion('mongodb')) {
312             $mongoClass = 'MongoDB\Client';
313         } else {
314             $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';
315         }
316
317         $this->assertInstanceOf($mongoClass, $method->invoke($this->storage));
318     }
319
320     private function createMongoCollectionMock()
321     {
322         $collectionClass = 'MongoCollection';
323         if (phpversion('mongodb')) {
324             $collectionClass = 'MongoDB\Collection';
325         }
326
327         $collection = $this->getMockBuilder($collectionClass)
328             ->disableOriginalConstructor()
329             ->getMock();
330
331         return $collection;
332     }
333 }