Merge branch 'MDL-70125_39-3' of git://github.com/mdjnelson/moodle into MOODLE_39_STABLE
[moodle.git] / lib / tests / session_manager_test.php
bloba71d1acee6af0a9d4944aadaf35e722ebfbbf919
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
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.
8 //
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/>.
17 /**
18 * Unit tests for session manager class.
20 * @package core
21 * @category phpunit
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();
28 /**
29 * Unit tests for session manager class.
31 * @package core
32 * @category phpunit
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();
94 $USER->test2 = true;
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() {
105 global $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() {
126 global $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() {
163 global $USER;
164 $this->resetAfterTest();
166 // Just make sure no errors and $USER->id is kept
167 $this->setAdminUser();
168 $userid = $USER->id;
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() {
177 global $CFG, $DB;
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.
186 $sid = md5('hokus');
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();
193 $record->userid = 0;
194 $record->sid = $sid;
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() {
223 global $DB;
224 $this->resetAfterTest();
226 $sid = md5('hokus');
227 $record = new \stdClass();
228 $record->state = 0;
229 $record->sid = $sid;
230 $record->sessdata = null;
231 $record->userid = 2;
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);
237 $now = time();
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() {
246 global $DB, $USER;
247 $this->resetAfterTest();
249 $this->setAdminUser();
250 $userid = $USER->id;
252 $sid = md5('hokus');
253 $record = new \stdClass();
254 $record->state = 0;
255 $record->sid = $sid;
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);
263 $record->userid = 0;
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() {
278 global $DB, $USER;
279 $this->resetAfterTest();
281 $this->setAdminUser();
282 $userid = $USER->id;
284 $sid = md5('hokus');
285 $record = new \stdClass();
286 $record->state = 0;
287 $record->sid = $sid;
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);
298 $record->userid = 0;
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() {
330 global $DB;
331 $this->resetAfterTest();
333 $user1 = $this->getDataGenerator()->create_user();
334 $user2 = $this->getDataGenerator()->create_user();
335 $guest = guest_user();
337 $record = new \stdClass();
338 $record->state = 0;
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);
374 $record->userid = 0;
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() {
453 global $DB, $USER;
454 $this->resetAfterTest();
456 $this->setAdminUser();
457 $userid = $USER->id;
459 $sid = md5('hokus');
460 $record = new \stdClass();
461 $record->state = 0;
462 $record->sid = $sid;
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);
473 $record->userid = 0;
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;
493 $this->setUser(0);
495 $CFG->sessiontimeout = 60*10;
497 $record = new \stdClass();
498 $record->state = 0;
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');
526 $record->userid = 0;
527 $record->timecreated = time() - 60*5;
528 $record->timemodified = time() - 60*5;
529 $r5 = $DB->insert_record('sessions', $record);
531 $record->sid = md5('hokus6');
532 $record->userid = 0;
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');
538 $record->userid = 0;
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)));
555 * Test loginas.
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();
564 $adminuser = $USER;
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();
599 $sink->close();
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&amp;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.
660 * @return array
662 public function pages_sessionlocks() {
663 return [
665 'url' => '/good.php',
666 'start' => 1500000001.000,
667 'gained' => 1500000002.000,
668 'released' => 1500000003.000,
669 'wait' => 1.0,
670 'held' => 1.0
673 'url' => '/bad.php?wait=5',
674 'start' => 1500000003.000,
675 'gained' => 1500000005.000,
676 'released' => 1500000007.000,
677 'held' => 2.0,
678 'wait' => 2.0
684 * Test to get recent session locks.
686 public function test_get_recent_session_locks() {
687 global $CFG;
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() {
717 global $CFG;
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() {
737 global $PERF;
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.
750 * @return array
752 public function sessionlock_history() {
753 return [
755 'url' => '/good.php',
756 'start' => 1500000001.000,
757 'gained' => 1500000001.100,
758 'released' => 1500000001.500,
759 'wait' => 0.1
762 // This bad request doesn't release the session for 10 seconds.
763 'url' => '/bad.php',
764 'start' => 1500000012.000,
765 'gained' => 1500000012.200,
766 'released' => 1500000020.200,
767 'wait' => 0.2
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,
775 'wait' => 7.29
778 'url' => '/good.php?id=2',
779 'start' => 1500000014.000,
780 'gained' => 1500000022.000,
781 'released' => 1500000025.000,
782 'wait' => 8.0
785 'url' => '/good.php?id=3',
786 'start' => 1500000015.000,
787 'gained' => 1500000025.000,
788 'released' => 1500000026.000,
789 'wait' => 10.0
792 'url' => '/good.php?id=4',
793 'start' => 1500000016.000,
794 'gained' => 1500000026.000,
795 'released' => 1500000027.000,
796 'wait' => 10.0
802 * Data provider for test_get_locked_page_at function.
804 * @return array
806 public function sessionlocks_info_provider() : array {
807 return [
809 'url' => null,
810 'time' => 1500000001.000
813 'url' => '/bad.php',
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() {
859 $a = [];
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() {
875 $a = [];
876 $a['stdClass'] = new stdClass();
877 $a['stdClass']->attribute = 'This is an attribute';
878 $a['array'] = ['array', 'contents'];
880 $b = [];
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]);
889 $expected = [];
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() {
896 $a = [];
897 $a['array'] = ['array', 'contents'];
899 $b = [];
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.
911 $expected = [];
912 $this->assertEquals($expected, $result);