2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Unit tests for session manager class.
22 * @copyright 2013 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
29 * Unit tests for session manager class.
33 * @copyright 2013 Petr Skoda {@link http://skodak.org}
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 class core_session_manager_testcase
extends advanced_testcase
{
37 public function test_start() {
38 $this->resetAfterTest();
39 // Session must be started only once...
40 \core\session\manager
::start();
41 $this->assertDebuggingCalled('Session was already started!', DEBUG_DEVELOPER
);
44 public function test_init_empty_session() {
45 global $SESSION, $USER;
46 $this->resetAfterTest();
48 $user = $this->getDataGenerator()->create_user();
50 $SESSION->test
= true;
51 $this->assertTrue($GLOBALS['SESSION']->test
);
52 $this->assertTrue($_SESSION['SESSION']->test
);
54 \core\session\manager
::set_user($user);
55 $this->assertSame($user, $USER);
56 $this->assertSame($user, $GLOBALS['USER']);
57 $this->assertSame($user, $_SESSION['USER']);
59 \core\session\manager
::init_empty_session();
61 $this->assertInstanceOf('stdClass', $SESSION);
62 $this->assertEmpty((array)$SESSION);
63 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
64 $this->assertSame($GLOBALS['SESSION'], $SESSION);
66 $this->assertInstanceOf('stdClass', $USER);
67 $this->assertEquals(array('id' => 0, 'mnethostid' => 1), (array)$USER, '', 0, 10, true);
68 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
69 $this->assertSame($GLOBALS['USER'], $USER);
71 // Now test how references work.
73 $GLOBALS['SESSION'] = new \
stdClass();
74 $GLOBALS['SESSION']->test
= true;
75 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
76 $this->assertSame($GLOBALS['SESSION'], $SESSION);
78 $SESSION = new \
stdClass();
79 $SESSION->test2
= true;
80 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
81 $this->assertSame($GLOBALS['SESSION'], $SESSION);
83 $_SESSION['SESSION'] = new stdClass();
84 $_SESSION['SESSION']->test3
= true;
85 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
86 $this->assertSame($GLOBALS['SESSION'], $SESSION);
88 $GLOBALS['USER'] = new \
stdClass();
89 $GLOBALS['USER']->test
= true;
90 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
91 $this->assertSame($GLOBALS['USER'], $USER);
93 $USER = new \
stdClass();
95 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
96 $this->assertSame($GLOBALS['USER'], $USER);
98 $_SESSION['USER'] = new stdClass();
99 $_SESSION['USER']->test3
= true;
100 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
101 $this->assertSame($GLOBALS['USER'], $USER);
104 public function test_set_user() {
106 $this->resetAfterTest();
108 $this->assertEquals(0, $USER->id
);
110 $user = $this->getDataGenerator()->create_user();
111 $this->assertObjectHasAttribute('description', $user);
112 $this->assertObjectHasAttribute('password', $user);
114 \core\session\manager
::set_user($user);
116 $this->assertEquals($user->id
, $USER->id
);
117 $this->assertObjectNotHasAttribute('description', $user);
118 $this->assertObjectNotHasAttribute('password', $user);
119 $this->assertObjectHasAttribute('sesskey', $user);
120 $this->assertSame($user, $GLOBALS['USER']);
121 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
122 $this->assertSame($GLOBALS['USER'], $USER);
125 public function test_login_user() {
127 $this->resetAfterTest();
129 $this->assertEquals(0, $USER->id
);
131 $user = $this->getDataGenerator()->create_user();
133 @\core\session\manager
::login_user($user); // Ignore header error messages.
134 $this->assertEquals($user->id
, $USER->id
);
136 $this->assertObjectNotHasAttribute('description', $user);
137 $this->assertObjectNotHasAttribute('password', $user);
138 $this->assertSame($user, $GLOBALS['USER']);
139 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
140 $this->assertSame($GLOBALS['USER'], $USER);
143 public function test_terminate_current() {
144 global $USER, $SESSION;
145 $this->resetAfterTest();
147 $this->setAdminUser();
148 \core\session\manager
::terminate_current();
149 $this->assertEquals(0, $USER->id
);
151 $this->assertInstanceOf('stdClass', $SESSION);
152 $this->assertEmpty((array)$SESSION);
153 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
154 $this->assertSame($GLOBALS['SESSION'], $SESSION);
156 $this->assertInstanceOf('stdClass', $USER);
157 $this->assertEquals(array('id' => 0, 'mnethostid' => 1), (array)$USER, '', 0, 10, true);
158 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
159 $this->assertSame($GLOBALS['USER'], $USER);
162 public function test_write_close() {
164 $this->resetAfterTest();
166 // Just make sure no errors and $USER->id is kept
167 $this->setAdminUser();
169 \core\session\manager
::write_close();
170 $this->assertSame($userid, $USER->id
);
172 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
173 $this->assertSame($GLOBALS['USER'], $USER);
176 public function test_session_exists() {
178 $this->resetAfterTest();
180 $this->assertFalse(\core\session\manager
::session_exists('abc'));
182 $user = $this->getDataGenerator()->create_user();
183 $guest = guest_user();
185 // The file handler is used by default, so let's fake the data somehow.
187 mkdir("$CFG->dataroot/sessions/", $CFG->directorypermissions
, true);
188 touch("$CFG->dataroot/sessions/sess_$sid");
190 $this->assertFalse(\core\session\manager
::session_exists($sid));
192 $record = new stdClass();
195 $record->timecreated
= time();
196 $record->timemodified
= $record->timecreated
;
197 $record->id
= $DB->insert_record('sessions', $record);
199 $this->assertTrue(\core\session\manager
::session_exists($sid));
201 $record->timecreated
= time() - $CFG->sessiontimeout
- 100;
202 $record->timemodified
= $record->timecreated +
10;
203 $DB->update_record('sessions', $record);
205 $this->assertTrue(\core\session\manager
::session_exists($sid));
207 $record->userid
= $guest->id
;
208 $DB->update_record('sessions', $record);
210 $this->assertTrue(\core\session\manager
::session_exists($sid));
212 $record->userid
= $user->id
;
213 $DB->update_record('sessions', $record);
215 $this->assertFalse(\core\session\manager
::session_exists($sid));
217 $CFG->sessiontimeout
= $CFG->sessiontimeout +
3000;
219 $this->assertTrue(\core\session\manager
::session_exists($sid));
222 public function test_touch_session() {
224 $this->resetAfterTest();
227 $record = new \
stdClass();
230 $record->sessdata
= null;
232 $record->timecreated
= time() - 60*60;
233 $record->timemodified
= time() - 30;
234 $record->firstip
= $record->lastip
= '10.0.0.1';
235 $record->id
= $DB->insert_record('sessions', $record);
238 \core\session\manager
::touch_session($sid);
239 $updated = $DB->get_field('sessions', 'timemodified', array('id'=>$record->id
));
241 $this->assertGreaterThanOrEqual($now, $updated);
242 $this->assertLessThanOrEqual(time(), $updated);
245 public function test_kill_session() {
247 $this->resetAfterTest();
249 $this->setAdminUser();
253 $record = new \
stdClass();
256 $record->sessdata
= null;
257 $record->userid
= $userid;
258 $record->timecreated
= time() - 60*60;
259 $record->timemodified
= time() - 30;
260 $record->firstip
= $record->lastip
= '10.0.0.1';
261 $DB->insert_record('sessions', $record);
264 $record->sid
= md5('pokus');
265 $DB->insert_record('sessions', $record);
267 $this->assertEquals(2, $DB->count_records('sessions'));
269 \core\session\manager
::kill_session($sid);
271 $this->assertEquals(1, $DB->count_records('sessions'));
272 $this->assertFalse($DB->record_exists('sessions', array('sid'=>$sid)));
274 $this->assertSame($userid, $USER->id
);
277 public function test_kill_user_sessions() {
279 $this->resetAfterTest();
281 $this->setAdminUser();
285 $record = new \
stdClass();
288 $record->sessdata
= null;
289 $record->userid
= $userid;
290 $record->timecreated
= time() - 60*60;
291 $record->timemodified
= time() - 30;
292 $record->firstip
= $record->lastip
= '10.0.0.1';
293 $DB->insert_record('sessions', $record);
295 $record->sid
= md5('hokus2');
296 $DB->insert_record('sessions', $record);
299 $record->sid
= md5('pokus');
300 $DB->insert_record('sessions', $record);
302 $this->assertEquals(3, $DB->count_records('sessions'));
304 \core\session\manager
::kill_user_sessions($userid);
306 $this->assertEquals(1, $DB->count_records('sessions'));
307 $this->assertFalse($DB->record_exists('sessions', array('userid' => $userid)));
309 $record->userid
= $userid;
310 $record->sid
= md5('pokus3');
311 $DB->insert_record('sessions', $record);
313 $record->userid
= $userid;
314 $record->sid
= md5('pokus4');
315 $DB->insert_record('sessions', $record);
317 $record->userid
= $userid;
318 $record->sid
= md5('pokus5');
319 $DB->insert_record('sessions', $record);
321 $this->assertEquals(3, $DB->count_records('sessions', array('userid' => $userid)));
323 \core\session\manager
::kill_user_sessions($userid, md5('pokus5'));
325 $this->assertEquals(1, $DB->count_records('sessions', array('userid' => $userid)));
326 $this->assertEquals(1, $DB->count_records('sessions', array('userid' => $userid, 'sid' => md5('pokus5'))));
329 public function test_apply_concurrent_login_limit() {
331 $this->resetAfterTest();
333 $user1 = $this->getDataGenerator()->create_user();
334 $user2 = $this->getDataGenerator()->create_user();
335 $guest = guest_user();
337 $record = new \
stdClass();
339 $record->sessdata
= null;
340 $record->userid
= $user1->id
;
341 $record->timemodified
= time();
342 $record->firstip
= $record->lastip
= '10.0.0.1';
344 $record->sid
= md5('hokus1');
345 $record->timecreated
= 20;
346 $DB->insert_record('sessions', $record);
347 $record->sid
= md5('hokus2');
348 $record->timecreated
= 10;
349 $DB->insert_record('sessions', $record);
350 $record->sid
= md5('hokus3');
351 $record->timecreated
= 30;
352 $DB->insert_record('sessions', $record);
354 $record->userid
= $user2->id
;
355 $record->sid
= md5('pokus1');
356 $record->timecreated
= 20;
357 $DB->insert_record('sessions', $record);
358 $record->sid
= md5('pokus2');
359 $record->timecreated
= 10;
360 $DB->insert_record('sessions', $record);
361 $record->sid
= md5('pokus3');
362 $record->timecreated
= 30;
363 $DB->insert_record('sessions', $record);
365 $record->timecreated
= 10;
366 $record->userid
= $guest->id
;
367 $record->sid
= md5('g1');
368 $DB->insert_record('sessions', $record);
369 $record->sid
= md5('g2');
370 $DB->insert_record('sessions', $record);
371 $record->sid
= md5('g3');
372 $DB->insert_record('sessions', $record);
375 $record->sid
= md5('nl1');
376 $DB->insert_record('sessions', $record);
377 $record->sid
= md5('nl2');
378 $DB->insert_record('sessions', $record);
379 $record->sid
= md5('nl3');
380 $DB->insert_record('sessions', $record);
382 set_config('limitconcurrentlogins', 0);
383 $this->assertCount(12, $DB->get_records('sessions'));
385 \core\session\manager
::apply_concurrent_login_limit($user1->id
);
386 \core\session\manager
::apply_concurrent_login_limit($user2->id
);
387 \core\session\manager
::apply_concurrent_login_limit($guest->id
);
388 \core\session\manager
::apply_concurrent_login_limit(0);
389 $this->assertCount(12, $DB->get_records('sessions'));
391 set_config('limitconcurrentlogins', -1);
393 \core\session\manager
::apply_concurrent_login_limit($user1->id
);
394 \core\session\manager
::apply_concurrent_login_limit($user2->id
);
395 \core\session\manager
::apply_concurrent_login_limit($guest->id
);
396 \core\session\manager
::apply_concurrent_login_limit(0);
397 $this->assertCount(12, $DB->get_records('sessions'));
399 set_config('limitconcurrentlogins', 2);
401 \core\session\manager
::apply_concurrent_login_limit($user1->id
);
402 $this->assertCount(11, $DB->get_records('sessions'));
403 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 20)));
404 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 30)));
405 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 10)));
407 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 20)));
408 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 30)));
409 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 10)));
410 set_config('limitconcurrentlogins', 2);
411 \core\session\manager
::apply_concurrent_login_limit($user2->id
, md5('pokus2'));
412 $this->assertCount(10, $DB->get_records('sessions'));
413 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 20)));
414 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 30)));
415 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 10)));
417 \core\session\manager
::apply_concurrent_login_limit($guest->id
);
418 \core\session\manager
::apply_concurrent_login_limit(0);
419 $this->assertCount(10, $DB->get_records('sessions'));
421 set_config('limitconcurrentlogins', 1);
423 \core\session\manager
::apply_concurrent_login_limit($user1->id
, md5('grrr'));
424 $this->assertCount(9, $DB->get_records('sessions'));
425 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 20)));
426 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 30)));
427 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 10)));
429 \core\session\manager
::apply_concurrent_login_limit($user1->id
);
430 $this->assertCount(9, $DB->get_records('sessions'));
431 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 20)));
432 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 30)));
433 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id
, 'timecreated' => 10)));
435 \core\session\manager
::apply_concurrent_login_limit($user2->id
, md5('pokus2'));
436 $this->assertCount(8, $DB->get_records('sessions'));
437 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 20)));
438 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 30)));
439 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 10)));
441 \core\session\manager
::apply_concurrent_login_limit($user2->id
);
442 $this->assertCount(8, $DB->get_records('sessions'));
443 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 20)));
444 $this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 30)));
445 $this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id
, 'timecreated' => 10)));
447 \core\session\manager
::apply_concurrent_login_limit($guest->id
);
448 \core\session\manager
::apply_concurrent_login_limit(0);
449 $this->assertCount(8, $DB->get_records('sessions'));
452 public function test_kill_all_sessions() {
454 $this->resetAfterTest();
456 $this->setAdminUser();
460 $record = new \
stdClass();
463 $record->sessdata
= null;
464 $record->userid
= $userid;
465 $record->timecreated
= time() - 60*60;
466 $record->timemodified
= time() - 30;
467 $record->firstip
= $record->lastip
= '10.0.0.1';
468 $DB->insert_record('sessions', $record);
470 $record->sid
= md5('hokus2');
471 $DB->insert_record('sessions', $record);
474 $record->sid
= md5('pokus');
475 $DB->insert_record('sessions', $record);
477 $this->assertEquals(3, $DB->count_records('sessions'));
479 \core\session\manager
::kill_all_sessions();
481 $this->assertEquals(0, $DB->count_records('sessions'));
482 $this->assertSame(0, $USER->id
);
485 public function test_gc() {
486 global $CFG, $DB, $USER;
487 $this->resetAfterTest();
489 $this->setAdminUser();
490 $adminid = $USER->id
;
491 $this->setGuestUser();
492 $guestid = $USER->id
;
495 $CFG->sessiontimeout
= 60*10;
497 $record = new \
stdClass();
499 $record->sid
= md5('hokus1');
500 $record->sessdata
= null;
501 $record->userid
= $adminid;
502 $record->timecreated
= time() - 60*60;
503 $record->timemodified
= time() - 30;
504 $record->firstip
= $record->lastip
= '10.0.0.1';
505 $r1 = $DB->insert_record('sessions', $record);
507 $record->sid
= md5('hokus2');
508 $record->userid
= $adminid;
509 $record->timecreated
= time() - 60*60;
510 $record->timemodified
= time() - 60*20;
511 $r2 = $DB->insert_record('sessions', $record);
513 $record->sid
= md5('hokus3');
514 $record->userid
= $guestid;
515 $record->timecreated
= time() - 60*60*60;
516 $record->timemodified
= time() - 60*20;
517 $r3 = $DB->insert_record('sessions', $record);
519 $record->sid
= md5('hokus4');
520 $record->userid
= $guestid;
521 $record->timecreated
= time() - 60*60*60;
522 $record->timemodified
= time() - 60*10*5 - 60;
523 $r4 = $DB->insert_record('sessions', $record);
525 $record->sid
= md5('hokus5');
527 $record->timecreated
= time() - 60*5;
528 $record->timemodified
= time() - 60*5;
529 $r5 = $DB->insert_record('sessions', $record);
531 $record->sid
= md5('hokus6');
533 $record->timecreated
= time() - 60*60;
534 $record->timemodified
= time() - 60*10 -10;
535 $r6 = $DB->insert_record('sessions', $record);
537 $record->sid
= md5('hokus7');
539 $record->timecreated
= time() - 60*60;
540 $record->timemodified
= time() - 60*9;
541 $r7 = $DB->insert_record('sessions', $record);
543 \core\session\manager
::gc();
545 $this->assertTrue($DB->record_exists('sessions', array('id'=>$r1)));
546 $this->assertFalse($DB->record_exists('sessions', array('id'=>$r2)));
547 $this->assertTrue($DB->record_exists('sessions', array('id'=>$r3)));
548 $this->assertFalse($DB->record_exists('sessions', array('id'=>$r4)));
549 $this->assertFalse($DB->record_exists('sessions', array('id'=>$r5)));
550 $this->assertFalse($DB->record_exists('sessions', array('id'=>$r6)));
551 $this->assertTrue($DB->record_exists('sessions', array('id'=>$r7)));
556 * @copyright 2103 Rajesh Taneja <rajesh@moodle.com>
558 public function test_loginas() {
559 global $USER, $SESSION;
560 $this->resetAfterTest();
562 // Set current user as Admin user and save it for later use.
563 $this->setAdminUser();
565 $adminsession = $SESSION;
566 $user = $this->getDataGenerator()->create_user();
567 $_SESSION['extra'] = true;
569 // Try admin loginas this user in system context.
570 $this->assertObjectNotHasAttribute('realuser', $USER);
571 \core\session\manager
::loginas($user->id
, context_system
::instance());
573 $this->assertSame($user->id
, $USER->id
);
574 $this->assertEquals(context_system
::instance(), $USER->loginascontext
);
575 $this->assertSame($adminuser->id
, $USER->realuser
);
576 $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
577 $this->assertSame($GLOBALS['USER'], $USER);
578 $this->assertNotSame($adminuser, $_SESSION['REALUSER']);
579 $this->assertEquals($adminuser, $_SESSION['REALUSER']);
581 $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
582 $this->assertSame($GLOBALS['SESSION'], $SESSION);
583 $this->assertNotSame($adminsession, $_SESSION['REALSESSION']);
584 $this->assertEquals($adminsession, $_SESSION['REALSESSION']);
586 $this->assertArrayNotHasKey('extra', $_SESSION);
588 // Set user as current user and login as admin user in course context.
589 \core\session\manager
::init_empty_session();
590 $this->setUser($user);
591 $this->assertNotEquals($adminuser->id
, $USER->id
);
592 $course = $this->getDataGenerator()->create_course();
593 $coursecontext = context_course
::instance($course->id
);
595 // Catch event triggered.
596 $sink = $this->redirectEvents();
597 \core\session\manager
::loginas($adminuser->id
, $coursecontext);
598 $events = $sink->get_events();
600 $event = array_pop($events);
602 $this->assertSame($adminuser->id
, $USER->id
);
603 $this->assertSame($coursecontext, $USER->loginascontext
);
604 $this->assertSame($user->id
, $USER->realuser
);
606 // Test event captured has proper information.
607 $this->assertInstanceOf('\core\event\user_loggedinas', $event);
608 $this->assertSame($user->id
, $event->objectid
);
609 $this->assertSame($adminuser->id
, $event->relateduserid
);
610 $this->assertSame($course->id
, $event->courseid
);
611 $this->assertEquals($coursecontext, $event->get_context());
612 $oldfullname = fullname($user, true);
613 $newfullname = fullname($adminuser, true);
614 $expectedlogdata = array($course->id
, "course", "loginas", "../user/view.php?id=$course->id&user=$user->id", "$oldfullname -> $newfullname");
615 $this->assertEventLegacyLogData($expectedlogdata, $event);
618 public function test_is_loggedinas() {
619 $this->resetAfterTest();
621 $user1 = $this->getDataGenerator()->create_user();
622 $user2 = $this->getDataGenerator()->create_user();
624 $this->assertFalse(\core\session\manager
::is_loggedinas());
626 $this->setUser($user1);
627 \core\session\manager
::loginas($user2->id
, context_system
::instance());
629 $this->assertTrue(\core\session\manager
::is_loggedinas());
632 public function test_get_realuser() {
633 $this->resetAfterTest();
635 $user1 = $this->getDataGenerator()->create_user();
636 $user2 = $this->getDataGenerator()->create_user();
638 $this->setUser($user1);
639 $normal = \core\session\manager
::get_realuser();
640 $this->assertSame($GLOBALS['USER'], $normal);
642 \core\session\manager
::loginas($user2->id
, context_system
::instance());
644 $real = \core\session\manager
::get_realuser();
646 unset($real->password
);
647 unset($real->description
);
648 unset($real->sesskey
);
649 unset($user1->password
);
650 unset($user1->description
);
651 unset($user1->sesskey
);
653 $this->assertEquals($real, $user1);
654 $this->assertSame($_SESSION['REALUSER'], $real);
658 * Session lock info on pages.
662 public function pages_sessionlocks() {
665 'url' => '/good.php',
666 'start' => 1500000001.000,
667 'gained' => 1500000002.000,
668 'released' => 1500000003.000,
673 'url' => '/bad.php?wait=5',
674 'start' => 1500000003.000,
675 'gained' => 1500000005.000,
676 'released' => 1500000007.000,
684 * Test to get recent session locks.
686 public function test_get_recent_session_locks() {
689 $this->resetAfterTest();
690 $CFG->debugsessionlock
= 5;
691 $pages = $this->pages_sessionlocks();
692 // Recent session locks must be empty at first.
693 $recentsessionlocks = \core\session\manager
::get_recent_session_locks();
694 $this->assertEmpty($recentsessionlocks);
696 // Add page to the recentsessionlocks array.
697 \core\session\manager
::update_recent_session_locks($pages[0]);
698 $recentsessionlocks = \core\session\manager
::get_recent_session_locks();
699 // Make sure we are getting the first page we added.
700 $this->assertEquals($pages[0], $recentsessionlocks[0]);
701 // There should be 1 page in the array.
702 $this->assertCount(1, $recentsessionlocks);
704 // Add second page to the recentsessionlocks array.
705 \core\session\manager
::update_recent_session_locks($pages[1]);
706 $recentsessionlocks = \core\session\manager
::get_recent_session_locks();
707 // Make sure we are getting the second page we added.
708 $this->assertEquals($pages[1], $recentsessionlocks[1]);
709 // There should be 2 pages in the array.
710 $this->assertCount(2, $recentsessionlocks);
714 * Test to update recent session locks.
716 public function test_update_recent_session_locks() {
719 $this->resetAfterTest();
720 $CFG->debugsessionlock
= 5;
721 $pages = $this->pages_sessionlocks();
723 \core\session\manager
::update_recent_session_locks($pages[0]);
724 \core\session\manager
::update_recent_session_locks($pages[1]);
725 $recentsessionlocks = \core\session\manager
::get_recent_session_locks();
726 // There should be 2 pages in the array.
727 $this->assertCount(2, $recentsessionlocks);
728 // Make sure the last page is added at the end of the array.
729 $this->assertEquals($pages[1], end($recentsessionlocks));
734 * Test to get session lock info.
736 public function test_get_session_lock_info() {
739 $this->resetAfterTest();
741 $pages = $this->pages_sessionlocks();
742 $PERF->sessionlock
= $pages[0];
743 $sessionlock = \core\session\manager
::get_session_lock_info();
744 $this->assertEquals($pages[0], $sessionlock);
748 * Session lock info on some pages to serve as history.
752 public function sessionlock_history() {
755 'url' => '/good.php',
756 'start' => 1500000001.000,
757 'gained' => 1500000001.100,
758 'released' => 1500000001.500,
762 // This bad request doesn't release the session for 10 seconds.
764 'start' => 1500000012.000,
765 'gained' => 1500000012.200,
766 'released' => 1500000020.200,
770 // All subsequent requests are blocked and need to wait.
771 'url' => '/good.php?id=1',
772 'start' => 1500000012.900,
773 'gained' => 1500000020.200,
774 'released' => 1500000022.000,
778 'url' => '/good.php?id=2',
779 'start' => 1500000014.000,
780 'gained' => 1500000022.000,
781 'released' => 1500000025.000,
785 'url' => '/good.php?id=3',
786 'start' => 1500000015.000,
787 'gained' => 1500000025.000,
788 'released' => 1500000026.000,
792 'url' => '/good.php?id=4',
793 'start' => 1500000016.000,
794 'gained' => 1500000026.000,
795 'released' => 1500000027.000,
802 * Data provider for test_get_locked_page_at function.
806 public function sessionlocks_info_provider() : array {
810 'time' => 1500000001.000
814 'time' => 1500000014.000
817 'url' => '/good.php?id=2',
818 'time' => 1500000022.500
824 * Test to get locked page at a speficic timestamp.
826 * @dataProvider sessionlocks_info_provider
827 * @param array $url Session lock page url.
828 * @param array $time Session lock time.
830 public function test_get_locked_page_at($url, $time) {
831 global $CFG, $SESSION;
833 $this->resetAfterTest();
834 $CFG->debugsessionlock
= 5;
835 $SESSION->recentsessionlocks
= $this->sessionlock_history();
837 $page = \core\session\manager
::get_locked_page_at($time);
838 $this->assertEquals($url, is_array($page) ?
$page['url'] : null);
842 * Test cleanup recent session locks.
844 public function test_cleanup_recent_session_locks() {
845 global $CFG, $SESSION;
847 $this->resetAfterTest();
848 $CFG->debugsessionlock
= 5;
850 $SESSION->recentsessionlocks
= $this->sessionlock_history();
851 $this->assertCount(6, $SESSION->recentsessionlocks
);
852 \core\session\manager
::cleanup_recent_session_locks();
853 // Make sure the session history has been cleaned up and only has the latest page.
854 $this->assertCount(1, $SESSION->recentsessionlocks
);
855 $this->assertEquals('/good.php?id=4', $SESSION->recentsessionlocks
[0]['url']);
858 public function test_array_session_diff_same_array() {
860 $a['c'] = new stdClass();
861 $a['c']->o
= new stdClass();
862 $a['c']->o
->o
= new stdClass();
863 $a['c']->o
->o
->l
= 'cool';
865 $class = new ReflectionClass('\core\session\manager');
866 $method = $class->getMethod('array_session_diff');
867 $method->setAccessible(true);
869 $result = $method->invokeArgs(null, [$a, $a]);
871 $this->assertEmpty($result);
874 public function test_array_session_diff_first_array_larger() {
876 $a['stdClass'] = new stdClass();
877 $a['stdClass']->attribute
= 'This is an attribute';
878 $a['array'] = ['array', 'contents'];
881 $b['array'] = ['array', 'contents'];
883 $class = new ReflectionClass('\core\session\manager');
884 $method = $class->getMethod('array_session_diff');
885 $method->setAccessible(true);
887 $result = $method->invokeArgs(null, [$a, $b]);
890 $expected['stdClass'] = new stdClass();
891 $expected['stdClass']->attribute
= 'This is an attribute';
892 $this->assertEquals($expected, $result);
895 public function test_array_session_diff_second_array_larger() {
897 $a['array'] = ['array', 'contents'];
900 $b['stdClass'] = new stdClass();
901 $b['stdClass']->attribute
= 'This is an attribute';
902 $b['array'] = ['array', 'contents'];
904 $class = new ReflectionClass('\core\session\manager');
905 $method = $class->getMethod('array_session_diff');
906 $method->setAccessible(true);
908 $result = $method->invokeArgs(null, [$a, $b]);
910 // It's empty because the first array contains all the contents of the second.
912 $this->assertEquals($expected, $result);