Merge branch 'w51_MDL-30761_m23_slowmysql' of git://github.com/skodak/moodle
[moodle.git] / lib / simpletest / fulltestaccesslib.php
CommitLineData
e922fe23
PS
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.
13//
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/>.
16
17/**
18 * Full functional accesslib test
19 *
20 * It is implemented as one test case because it would take hours
21 * to prepare the fake test site for each test, at the same time
22 * we have to work around multiple problems in UnitTestCaseUsingDatabase.
23 *
24 * @package core
25 * @copyright 2011 Petr Skoda (http://skodak.org)
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 */
28
29defined('MOODLE_INTERNAL') || die();
30
31
32/**
33 * Context caching fixture
34 */
35class context_inspection extends context_helper {
36 public static function test_context_cache_size() {
37 return self::$cache_count;
38 }
39}
40
41
42/**
43 * Functional test for accesslib.php
44 *
45 * Note: execution may take many minutes especially on slower servers.
46 */
47class accesslib_test extends UnitTestCaseUsingDatabase {
48 // NOTE: The UnitTestCaseUsingDatabase is problematic and VERY dangerous especially for production servers!
49 //
50 // 1. We could create full install without plugins and use the test DB since the very beginning in lib/setup.php.
51 // 2. We should not execute the tests from the web UI because the static caches all over the place collide, instead
52 // we could use CLI
53 // 3. SimpleTest appears to be dead - unfortunately nobody else thinks we should switch to PHPUnit asap
54 // 4. switching of USER->id alone is not acceptable at all, we must switch the complete USER record
55 // and probably deal with _SESSION['USER'] too
56 // 5. we must close session before messing with anything in $USER or $SESSION
57 // 6. $SITE is not switched
58 // 7. tons of other static caches are not reset
59 // 8. etc.
60 //
61 // --
62 // skodak
63
64 //TODO: add more tests for the remaining accesslib parts that were not touched by the refactoring in 2.2dev
65
66 public static $includecoverage = array('lib/accesslib.php');
67
68 protected $accesslibprevuser = null;
69 protected $accesslibprevsite = null;
70
71 /**
72 * A small functional test of accesslib functions and classes.
73 */
74 public function test_everything_in_accesslib() {
75 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
76
77 // First of all finalize the session, we must not carry over any of this mess to the next page via SESSION!!!
78 session_get_instance()->write_close();
79
80 // hack - this is going to take very long time
81 set_time_limit(3600);
82
83 // Get rid of current user that would not work anyway,
84 // do NOT even think about using $this->switch_global_user_id()!
85 if (!isset($this->accesslibprevuser)) {
86 $this->accesslibprevuser = clone($USER);
87 $USER = new stdClass();
88 $USER->id = 0;
89 }
90
91 // Backup $SITE global
92 if (!isset($this->accesslibprevsite)) {
93 $this->accesslibprevsite = $SITE;
94 }
95
96 // Switch DB, if it somehow fails or you specified wrong unittest prefix it will nuke real data, you have been warned!
97 $this->switch_to_test_db();
98
99 // Let's switch the CFG
100 $prevcfg = clone($CFG);
101 $this->switch_to_test_cfg();
102 $CFG->config_php_settings = $prevcfg->config_php_settings;
103 $CFG->noemailever = true;
104 $CFG->admin = $prevcfg->admin;
105 $CFG->lang = 'en';
106 $CFG->tempdir = $prevcfg->tempdir;
107 $CFG->cachedir = $prevcfg->cachedir;
108 $CFG->directorypermissions = $prevcfg->directorypermissions;
109 $CFG->filepermissions = $prevcfg->filepermissions;
110
111 // Reset all caches
112 accesslib_clear_all_caches_for_unit_testing();
113
114 // Add some core tables - this is known to break constantly because we keep adding dependencies...
115 $tablenames = array('config', 'config_plugins', 'modules', 'course', 'course_modules', 'course_sections', 'course_categories', 'mnet_host', 'mnet_application',
116 'capabilities', 'context', 'context_temp', 'role', 'role_capabilities', 'role_allow_switch', 'license', 'my_pages', 'block', 'block_instances', 'block_positions',
117 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels' ,'enrol', 'user_enrolments', 'filter_active', 'filter_config', 'comments',
8a238aee 118 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'rating', 'files', 'role_names', 'user_preferences', 'grading_areas');
e922fe23
PS
119 $this->create_test_tables($tablenames, 'lib');
120
121 // Create all core default records and default settings
122 require_once("$CFG->libdir/db/install.php");
123 xmldb_main_install(); // installs the capabilities too
124
125 // Fake mod_page install
126 $tablenames = array('page');
127 $this->create_test_tables($tablenames, 'mod/page');
128 $module = new stdClass();
129 require($CFG->dirroot .'/mod/page/version.php');
130 $module->name = 'page';
131 $pagemoduleid = $DB->insert_record('modules', $module);
132 update_capabilities('mod_page');
133
134 // Fake block_online_users install
135 $plugin = new stdClass();
136 $plugin->version = NULL;
137 $plugin->cron = 0;
138 include($CFG->dirroot.'/blocks/online_users/version.php');
139 $plugin->name = 'online_users';
140 $onlineusersblockid = $DB->insert_record('block', $plugin);
141 update_capabilities('block_online_users');
142
143 // Finish roles setup
144 set_config('defaultfrontpageroleid', $DB->get_field('role', 'id', array('archetype'=>'frontpage')));
145 set_config('defaultuserroleid', $DB->get_field('role', 'id', array('archetype'=>'user')));
146 set_config('notloggedinroleid', $DB->get_field('role', 'id', array('archetype'=>'guest')));
147 set_config('rolesactive', 1);
148
149 // Init manual enrol
150 set_config('status', ENROL_INSTANCE_ENABLED, 'enrol_manual');
151 set_config('defaultperiod', 0, 'enrol_manual');
152 $manualenrol = enrol_get_plugin('manual');
153
154 // Fill the site with some real data
155 $testcategories = array();
156 $testcourses = array();
157 $testpages = array();
158 $testblocks = array();
159 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
160
161 $systemcontext = context_system::instance();
162 $frontpagecontext = context_course::instance(SITEID);
163
164 // Add block to system context
165 $bi = new stdClass();
166 $bi->blockname = 'online_users';
167 $bi->parentcontextid = $systemcontext->id;
168 $bi->showinsubcontexts = 1;
169 $bi->pagetypepattern = '';
170 $bi->subpagepattern = '';
171 $bi->defaultregion = '';
172 $bi->defaultweight = 0;
173 $bi->configdata = '';
174 $biid = $DB->insert_record('block_instances', $bi);
175 context_block::instance($biid);
176 $testblocks[] = $biid;
177
178 // Some users
179 $testusers = array();
180 for($i=0; $i<20; $i++) {
181 $user = new stdClass();
182 $user->auth = 'manual';
183 $user->firstname = 'user'.$i;
184 $user->lastname = 'user'.$i;
185 $user->username = 'user'.$i;
186 $user->password = 'doesnotexist';
187 $user->email = "user$i@example.com";
188 $user->confirmed = 1;
189 $user->mnethostid = $CFG->mnet_localhost_id;
190 $user->lang = $CFG->lang;
191 $user->maildisplay = 1;
192 $user->timemodified = time();
193 $user->deleted = 0;
194 $user->lastip = '0.0.0.0';
195 $userid = $DB->insert_record('user', $user);
196 $testusers[$i] = $userid;
197 $usercontext = context_user::instance($userid);
198
199 // Add block to user profile
200 $bi->parentcontextid = $usercontext->id;
201 $biid = $DB->insert_record('block_instances', $bi);
202 context_block::instance($biid);
203 $testblocks[] = $biid;
204 }
205 // Deleted user - should be ignored everywhere, can not have context
206 $user = new stdClass();
207 $user->auth = 'manual';
208 $user->firstname = '';
209 $user->lastname = '';
210 $user->username = 'user@example.com121132132';
211 $user->password = '';
212 $user->email = '';
213 $user->confirmed = 1;
214 $user->mnethostid = $CFG->mnet_localhost_id;
215 $user->lang = $CFG->lang;
216 $user->maildisplay = 1;
217 $user->timemodified = time();
218 $user->deleted = 1;
219 $user->lastip = '0.0.0.0';
220 $DB->insert_record('user', $user);
221 unset($user);
222
223 // Add block to frontpage
224 $bi->parentcontextid = $frontpagecontext->id;
225 $biid = $DB->insert_record('block_instances', $bi);
226 $frontpageblockcontext = context_block::instance($biid);
227 $testblocks[] = $biid;
228
229 // Add a resource to frontpage
230 $page = new stdClass();
231 $page->course = $SITE->id;
232 $page->intro = '...';
233 $page->introformat = FORMAT_HTML;
234 $page->content = '...';
235 $page->contentformat = FORMAT_HTML;
236 $pageid = $DB->insert_record('page', $page);
237 $testpages[] = $pageid;
238 $cm = new stdClass();
239 $cm->course = $SITE->id;
240 $cm->module = $pagemoduleid;
241 $cm->section = 1;
242 $cm->instance = $pageid;
243 $cmid = $DB->insert_record('course_modules', $cm);
244 $frontpagepagecontext = context_module::instance($cmid);
245
246 // Add block to frontpage resource
247 $bi->parentcontextid = $frontpagepagecontext->id;
248 $biid = $DB->insert_record('block_instances', $bi);
249 $frontpagepageblockcontext = context_block::instance($biid);
250 $testblocks[] = $biid;
251
252 // Some nested course categories with courses
253 require_once("$CFG->dirroot/course/lib.php");
254 $path = '';
255 $parentcat = 0;
256 for($i=0; $i<5; $i++) {
257 $cat = new stdClass();
258 $cat->name = 'category'.$i;
259 $cat->parent = $parentcat;
260 $cat->depth = $i+1;
261 $cat->sortorder = MAX_COURSES_IN_CATEGORY * ($i+2);
262 $cat->timemodified = time();
263 $catid = $DB->insert_record('course_categories', $cat);
264 $path = $path . '/' . $catid;
265 $DB->set_field('course_categories', 'path', $path, array('id'=>$catid));
266 $parentcat = $catid;
267 $testcategories[] = $catid;
268 $catcontext = context_coursecat::instance($catid);
269
270 if ($i >=4) {
271 continue;
272 }
273
274 // Add resource to each category
275 $bi->parentcontextid = $catcontext->id;
276 $biid = $DB->insert_record('block_instances', $bi);
277 context_block::instance($biid);
278
279 // Add a few courses to each category
280 for($j=0; $j<6; $j++) {
281 $course = new stdClass();
282 $course->fullname = 'course'.$j;
283 $course->shortname = 'c'.$j;
284 $course->summary = 'bah bah bah';
285 $course->newsitems = 0;
286 $course->numsections = 1;
287 $course->category = $catid;
288 $course->format = 'topics';
289 $course->timecreated = time();
290 $course->visible = 1;
291 $course->timemodified = $course->timecreated;
292 $courseid = $DB->insert_record('course', $course);
293 $section = new stdClass();
294 $section->course = $courseid;
295 $section->section = 0;
296 $section->summaryformat = FORMAT_HTML;
297 $DB->insert_record('course_sections', $section);
298 $section->section = 1;
299 $DB->insert_record('course_sections', $section);
300 $testcourses[] = $courseid;
301 $coursecontext = context_course::instance($courseid);
302
303 if ($j >= 5) {
304 continue;
305 }
306 // Add manual enrol instance
307 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$courseid)));
308
309 // Add block to each course
310 $bi->parentcontextid = $coursecontext->id;
311 $biid = $DB->insert_record('block_instances', $bi);
312 context_block::instance($biid);
313 $testblocks[] = $biid;
314
315 // Add a resource to each course
316 $page->course = $courseid;
317 $pageid = $DB->insert_record('page', $page);
318 $testpages[] = $pageid;
319 $cm->course = $courseid;
320 $cm->instance = $pageid;
321 $cm->id = $DB->insert_record('course_modules', $cm);
322 $modcontext = context_module::instance($cm->id);
323
324 // Add block to each module
325 $bi->parentcontextid = $modcontext->id;
326 $biid = $DB->insert_record('block_instances', $bi);
327 context_block::instance($biid);
328 $testblocks[] = $biid;
329 }
330 }
331
332 // Make sure all contexts were created properly
333 $count = 1; //system
334 $count += $DB->count_records('user', array('deleted'=>0));
335 $count += $DB->count_records('course_categories');
336 $count += $DB->count_records('course');
337 $count += $DB->count_records('course_modules');
338 $count += $DB->count_records('block_instances');
339 $this->assertEqual($DB->count_records('context'), $count);
340 $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0);
341 $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0);
342
343
344 // ====== context_helper::get_level_name() ================================
345
346 $levels = context_helper::get_all_levels();
347 foreach ($levels as $level=>$classname) {
348 $name = context_helper::get_level_name($level);
349 $this->assertFalse(empty($name));
350 }
351
352
353 // ======= context::instance_by_id(), context_xxx::instance();
354
355 $context = context::instance_by_id($frontpagecontext->id);
356 $this->assertidentical($context->contextlevel, CONTEXT_COURSE);
357 $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
358 try {
359 context::instance_by_id(-1);
360 $this->fail('exception expected');
361 } catch (Exception $e) {
362 $this->assertTrue(true);
363 }
364 $this->assertTrue(context_system::instance() instanceof context_system);
365 $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
366 $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
367 $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
368 $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
369
370 $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
371 $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
372 $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
373 $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
374 try {
375 context_coursecat::instance(-1);
376 $this->fail('exception expected');
377 } catch (Exception $e) {
378 $this->assertTrue(true);
379 }
380 try {
381 context_course::instance(-1);
382 $this->fail('exception expected');
383 } catch (Exception $e) {
384 $this->assertTrue(true);
385 }
386 try {
387 context_module::instance(-1);
388 $this->fail('exception expected');
389 } catch (Exception $e) {
390 $this->assertTrue(true);
391 }
392 try {
393 context_block::instance(-1);
394 $this->fail('exception expected');
395 } catch (Exception $e) {
396 $this->assertTrue(true);
397 }
398
399
400 // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
401
402 $testcontexts = array();
403 $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
404 $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
405 $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
406 $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
407 $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
408
409 foreach ($testcontexts as $context) {
410 $name = $context->get_context_name(true, true);
411 $this->assertFalse(empty($name));
412
413 $this->assertTrue($context->get_url() instanceof moodle_url);
414
415 $caps = $context->get_capabilities();
416 $this->assertTrue(is_array($caps));
417 foreach ($caps as $cap) {
418 $cap = (array)$cap;
419 $this->assertIdentical(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
420 }
421 }
422 unset($testcontexts);
423
424 // ===== $context->get_course_context() =========================================
425
426 $this->assertFalse($systemcontext->get_course_context(false));
427 try {
428 $systemcontext->get_course_context();
429 $this->fail('exception expected');
430 } catch (Exception $e) {
431 $this->assertTrue(true);
432 }
433 $context = context_coursecat::instance($testcategories[0]);
434 $this->assertFalse($context->get_course_context(false));
435 try {
436 $context->get_course_context();
437 $this->fail('exception expected');
438 } catch (Exception $e) {
439 $this->assertTrue(true);
440 }
441 $this->assertIdentical($frontpagecontext->get_course_context(true), $frontpagecontext);
442 $this->assertIdentical($frontpagepagecontext->get_course_context(true), $frontpagecontext);
443 $this->assertIdentical($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
444
445
446 // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
447
448 $userid = reset($testusers);
449 $usercontext = context_user::instance($userid);
450 $this->assertIdentical($usercontext->get_parent_context(), $systemcontext);
451 $this->assertIdentical($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
452 $this->assertIdentical($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));
453
454 $this->assertIdentical($systemcontext->get_parent_contexts(), array());
455 $this->assertIdentical($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
456 $this->assertIdentical($systemcontext->get_parent_context_ids(), array());
457 $this->assertIdentical($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
458
459 $this->assertIdentical($frontpagecontext->get_parent_context(), $systemcontext);
460 $this->assertIdentical($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
461 $this->assertIdentical($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
462 $this->assertIdentical($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
463 $this->assertEqual($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
464
465 $this->assertIdentical($systemcontext->get_parent_context(), false);
466 $frontpagecontext = context_course::instance($SITE->id);
467 $parent = $systemcontext;
468 foreach ($testcategories as $catid) {
469 $catcontext = context_coursecat::instance($catid);
470 $this->assertIdentical($catcontext->get_parent_context(), $parent);
471 $parent = $catcontext;
472 }
473 $this->assertIdentical($frontpagepagecontext->get_parent_context(), $frontpagecontext);
474 $this->assertIdentical($frontpageblockcontext->get_parent_context(), $frontpagecontext);
475 $this->assertIdentical($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
476
477
478 // ====== $context->get_child_contexts() ================================
479
480 $children = $systemcontext->get_child_contexts();
481 $this->assertEqual(count($children)+1, $DB->count_records('context'));
482
483 $context = context_coursecat::instance($testcategories[3]);
484 $children = $context->get_child_contexts();
485 $countcats = 0;
486 $countcourses = 0;
487 $countblocks = 0;
488 foreach ($children as $child) {
489 if ($child->contextlevel == CONTEXT_COURSECAT) {
490 $countcats++;
491 }
492 if ($child->contextlevel == CONTEXT_COURSE) {
493 $countcourses++;
494 }
495 if ($child->contextlevel == CONTEXT_BLOCK) {
496 $countblocks++;
497 }
498 }
499 $this->assertEqual(count($children), 8);
500 $this->assertEqual($countcats, 1);
501 $this->assertEqual($countcourses, 6);
502 $this->assertEqual($countblocks, 1);
503
504 $context = context_course::instance($testcourses[2]);
505 $children = $context->get_child_contexts();
506 $this->assertEqual(count($children), 3);
507
508 $context = context_module::instance($testpages[3]);
509 $children = $context->get_child_contexts();
510 $this->assertEqual(count($children), 1);
511
512 $context = context_block::instance($testblocks[1]);
513 $children = $context->get_child_contexts();
514 $this->assertEqual(count($children), 0);
515
516 unset($children);
517 unset($countcats);
518 unset($countcourses);
519 unset($countblocks);
520
521
522 // ======= context_helper::reset_caches() ============================
523
524 context_helper::reset_caches();
525 $this->assertEqual(context_inspection::test_context_cache_size(), 0);
526 context_course::instance($SITE->id);
527 $this->assertEqual(context_inspection::test_context_cache_size(), 1);
528
529
530 // ======= context preloading ========================================
531
532 context_helper::reset_caches();
533 $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
534 FROM {context} c
535 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
536 $records = $DB->get_records_sql($sql);
537 $firstrecord = reset($records);
538 $columns = context_helper::get_preload_record_columns('c');
539 $firstrecord = (array)$firstrecord;
540 $this->assertIdentical(array_keys($firstrecord), array_values($columns));
541 context_helper::reset_caches();
542 foreach ($records as $record) {
543 context_helper::preload_from_record($record);
544 $this->assertIdentical($record, new stdClass());
545 }
546 $this->assertEqual(context_inspection::test_context_cache_size(), count($records));
547 unset($records);
548 unset($columns);
549
550 context_helper::reset_caches();
551 context_helper::preload_course($SITE->id);
552 $this->assertEqual(context_inspection::test_context_cache_size(), 4);
553
554 // ====== assign_capability(), unassign_capability() ====================
555
556 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
557 $this->assertFalse($rc);
558 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
559 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
560 $this->assertEqual($rc->permission, CAP_ALLOW);
561 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
562 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
563 $this->assertEqual($rc->permission, CAP_ALLOW);
564 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
565 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
566 $this->assertEqual($rc->permission, CAP_PREVENT);
567
568 assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
569 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
570 $this->assertFalse($rc);
571 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
572 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
573 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
574 $this->assertFalse($rc);
575 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
576 unset($rc);
577
578 accesslib_clear_all_caches(false); // must be done after assign_capability()
579
580
581 // ======= role_assign(), role_unassign(), role_unassign_all() ==============
582
583 $context = context_course::instance($testcourses[1]);
584 $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
585 role_assign($allroles['teacher'], $testusers[1], $context->id);
586 role_assign($allroles['teacher'], $testusers[2], $context->id);
587 role_assign($allroles['manager'], $testusers[1], $context->id);
588 $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
589 role_unassign($allroles['teacher'], $testusers[1], $context->id);
590 $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
591 role_unassign_all(array('contextid'=>$context->id));
592 $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
593 unset($context);
594
595 accesslib_clear_all_caches(false); // just in case
596
597
598 // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
599
600 $adminid = get_admin()->id;
601 $guestid = $CFG->siteguest;
602
603 // Enrol some users into some courses
604 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
605 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
606 $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
607 $cm1 = reset($cms);
608 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
609 $block1 = reset($blocks);
610 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
611 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
612 for($i=0; $i<9; $i++) {
613 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
614 }
615 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
616 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
617
618 for($i=10; $i<15; $i++) {
619 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
620 }
621 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
622
623 // Add tons of role assignments - the more the better
624 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
625 role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
626 role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
627 role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
628 role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
629 role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
630 role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
631 role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
632
633 role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
634 role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
635
636 // Add tons of overrides - the more the better
637 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
638 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
639 assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
640 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
641 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
642
643 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
644 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
645 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
646 assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
647 assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
648
649 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
650 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
651 assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
652 assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
653
654 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
655
656 accesslib_clear_all_caches(false); // must be done after assign_capability()
657
658 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
659 // with get_users_by_capability() where they are ignored
660 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
661 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
662 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
663 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
664
665 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
666 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
667 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
668 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
669
670 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
671 $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
672 $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
673 $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
674
675 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
676 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
677 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
678
679 // Test the list of enrolled users
680 $coursecontext = context_course::instance($course1->id);
681 $enrolled = get_enrolled_users($coursecontext);
682 $this->assertEqual(count($enrolled), 10);
683 for($i=0; $i<10; $i++) {
684 $this->assertTrue(isset($enrolled[$testusers[$i]]));
685 }
686 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
687 $this->assertEqual(count($enrolled), 1);
688 $this->assertTrue(isset($enrolled[$testusers[9]]));
689 unset($enrolled);
690
691 // role switching
692 $userid = $testusers[9];
693 $USER = $DB->get_record('user', array('id'=>$userid));
694 load_all_capabilities();
695 $coursecontext = context_course::instance($course1->id);
696 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
697 $this->assertFalse(is_role_switched($course1->id));
698 role_switch($allroles['student'], $coursecontext);
699 $this->assertTrue(is_role_switched($course1->id));
700 $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']);
701 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
702 reload_all_capabilities();
703 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
704 role_switch(0, $coursecontext);
705 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
706 $userid = $adminid;
707 $USER = $DB->get_record('user', array('id'=>$userid));
708 load_all_capabilities();
709 $coursecontext = context_course::instance($course1->id);
710 $blockcontext = context_block::instance($block1->id);
711 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
712 role_switch($allroles['student'], $coursecontext);
713 $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']);
714 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
715 reload_all_capabilities();
716 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
717 load_all_capabilities();
718 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
719
720 // temp course role for enrol
721 $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
722 $userid = $testusers[5];
723 $roleid = $allroles['editingteacher'];
724 $USER = $DB->get_record('user', array('id'=>$userid));
725 load_all_capabilities();
726 $coursecontext = context_course::instance($course1->id);
727 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
728 $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
729 load_temp_course_role($coursecontext, $roleid);
730 $this->assertEqual($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
731 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
732 remove_temp_course_roles($coursecontext);
733 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
734 load_temp_course_role($coursecontext, $roleid);
735 reload_all_capabilities();
736 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
737 $USER = new stdClass();
738 $USER->id = 0;
739
740 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
741 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
742 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
743 $contexts = $DB->get_records('context', array(), 'id');
744 $contexts = array_values($contexts);
745 $capabilities = $DB->get_records('capabilities', array(), 'id');
746 $capabilities = array_values($capabilities);
747 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
748
749 // Random time!
750 srand(666);
751 foreach($testusers as $userid) { // no guest or deleted
752 // each user gets 0-20 random roles
753 $rcount = rand(0, 10);
754 for($j=0; $j<$rcount; $j++) {
755 $roleid = $roles[rand(0, count($roles)-1)];
756 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
757 role_assign($roleid, $userid, $contextid);
758 }
759 }
760 $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
761 for($j=0; $j<10000; $j++) {
762 $roleid = $roles[rand(0, count($roles)-1)];
763 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
764 $permission = $permissions[rand(0,count($permissions)-1)];
765 $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
766 assign_capability($capname, $permission, $roleid, $contextid, true);
767 }
768 unset($permissions);
769 unset($roles);
770 unset($contexts);
771 unset($users);
772 unset($capabilities);
773
774 accesslib_clear_all_caches(false); // must be done after assign_capability()
775
776 // Test time - let's set up some real user, just in case the logic for USER affects the others...
777 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
778 load_all_capabilities();
779
780 $contexts = $DB->get_records('context', array(), 'id');
781 $users = $DB->get_records('user', array(), 'id', 'id');
782 $capabilities = $DB->get_records('capabilities', array(), 'id');
783 $users[0] = null; // not-logged-in user
784 $users[-1] = null; // non-existent user
785
786 foreach ($contexts as $crecord) {
787 $context = context::instance_by_id($crecord->id);
788 if ($coursecontext = $context->get_course_context(false)) {
789 $enrolled = get_enrolled_users($context);
790 } else {
791 $enrolled = array();
792 }
793 foreach ($capabilities as $cap) {
794 $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
795 if ($enrolled) {
796 $enrolledwithcap = get_enrolled_users($context, $cap->name);
797 } else {
798 $enrolledwithcap = array();
799 }
800 foreach ($users as $userid=>$unused) {
801 if ($userid == 0 or isguestuser($userid)) {
802 if ($userid == 0) {
803 $CFG->forcelogin = true;
804 $this->assertFalse(has_capability($cap->name, $context, $userid));
805 unset($CFG->forcelogin);
806 }
807 if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
808 $this->assertFalse(has_capability($cap->name, $context, $userid));
809 }
810 $this->assertFalse(isset($allowed[$userid]));
811 } else {
812 if (is_siteadmin($userid)) {
813 $this->assertTrue(has_capability($cap->name, $context, $userid, true));
814 }
815 $hascap = has_capability($cap->name, $context, $userid, false);
816 $this->assertIdentical($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
817 if (isset($enrolled[$userid])) {
818 $this->assertIdentical(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
819 }
820 }
821 }
822 }
823 }
824 // Back to nobody
825 $USER = new stdClass();
826 $USER->id = 0;
827 unset($contexts);
828 unset($users);
829 unset($capabilities);
830
831 // Now let's do all the remaining tests that break our carefully prepared fake site
832
833
834
835 // ======= $context->mark_dirty() =======================================
836
837 $DB->delete_records('cache_flags', array());
838 accesslib_clear_all_caches(false);
839 $systemcontext->mark_dirty();
840 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
841 $this->assertTrue(isset($dirty[$systemcontext->path]));
842 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
843
844
845 // ======= $context->reload_if_dirty(); =================================
846
847 $DB->delete_records('cache_flags', array());
848 accesslib_clear_all_caches(false);
849 load_all_capabilities();
850 $context = context_course::instance($testcourses[2]);
851 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
852 $pagecontext = context_module::instance($page->id);
853
854 $context->mark_dirty();
855 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
856 $USER->access['test'] = true;
857 $context->reload_if_dirty();
858 $this->assertFalse(isset($USER->access['test']));
859
860 $context->mark_dirty();
861 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
862 $USER->access['test'] = true;
863 $pagecontext->reload_if_dirty();
864 $this->assertFalse(isset($USER->access['test']));
865
866
867 // ======= context_helper::build_all_paths() ============================
868
869 $oldcontexts = $DB->get_records('context', array(), 'id');
870 $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
871 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
872 context_helper::build_all_paths();
873 $newcontexts = $DB->get_records('context', array(), 'id');
874 $this->assertIdentical($oldcontexts, $newcontexts);
875 unset($oldcontexts);
876 unset($newcontexts);
877
878
879 // ======= $context->reset_paths() ======================================
880
881 $context = context_course::instance($testcourses[2]);
882 $children = $context->get_child_contexts();
883 $context->reset_paths(false);
884 $this->assertIdentical($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
885 $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
886 foreach ($children as $child) {
887 $this->assertIdentical($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
888 $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
889 }
890 $this->assertEqual(count($children)+1, $DB->count_records('context', array('depth'=>0)));
891 $this->assertEqual(count($children)+1, $DB->count_records('context', array('path'=>NULL)));
892
893 $context = context_course::instance($testcourses[2]);
894 $context->reset_paths(true);
895 $context = context_course::instance($testcourses[2]);
896 $this->assertEqual($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
897 $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
898 $this->assertEqual(0, $DB->count_records('context', array('depth'=>0)));
899 $this->assertEqual(0, $DB->count_records('context', array('path'=>NULL)));
900
901
902 // ====== $context->update_moved(); ======================================
903
904 accesslib_clear_all_caches(false);
905 $DB->delete_records('cache_flags', array());
906 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
907 $context = context_course::instance($course->id);
908 $oldpath = $context->path;
909 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
910 $categorycontext = context_coursecat::instance($miscid);
911 $course->category = $miscid;
912 $DB->update_record('course', $course);
913 $context->update_moved($categorycontext);
914
915 $context = context_course::instance($course->id);
916 $this->assertIdentical($context->get_parent_context(), $categorycontext);
917 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
918 $this->assertTrue(isset($dirty[$oldpath]));
919 $this->assertTrue(isset($dirty[$context->path]));
920
921
922 // ====== $context->delete_content() =====================================
923
924 context_helper::reset_caches();
925 $context = context_module::instance($testpages[3]);
926 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
927 $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
928 $context->delete_content();
929 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
930 $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
931
932
933 // ====== $context->delete() =============================
934
935 context_helper::reset_caches();
936 $context = context_module::instance($testpages[4]);
937 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
938 $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
939 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
940 $bicontext = context_block::instance($bi->id);
941 $DB->delete_records('cache_flags', array());
942 $context->delete(); // should delete also linked blocks
943 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
944 $this->assertTrue(isset($dirty[$context->path]));
945 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
946 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
947 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
948 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
949 $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
950 context_module::instance($testpages[4]);
951
952
953 // ====== context_helper::delete_instance() =============================
954
955 context_helper::reset_caches();
956 $lastcourse = array_pop($testcourses);
957 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
958 $coursecontext = context_course::instance($lastcourse);
959 $this->assertEqual(context_inspection::test_context_cache_size(), 1);
960 $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
961 $DB->delete_records('cache_flags', array());
962 context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
963 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
964 $this->assertTrue(isset($dirty[$coursecontext->path]));
965 $this->assertEqual(context_inspection::test_context_cache_size(), 0);
966 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
967 context_course::instance($lastcourse);
968
969
970 // ======= context_helper::create_instances() ==========================
971
972 $prevcount = $DB->count_records('context');
973 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
974 context_helper::create_instances(null, true);
975 $this->assertIdentical($DB->count_records('context'), $prevcount);
976 $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0);
977 $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0);
978
979 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
980 $DB->delete_records('block_instances', array());
981 $prevcount = $DB->count_records('context');
982 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
983 context_helper::create_instances(null, true);
984 $this->assertIdentical($DB->count_records('context'), $prevcount);
985 $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0);
986 $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0);
987
988
989 // ======= context_helper::cleanup_instances() ==========================
990
991 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
992 $DB->delete_records('course', array('id'=>$lastcourse));
993 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
994 $DB->delete_records('course_categories', array('id'=>$lastcategory));
995 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
996 $DB->delete_records('user', array('id'=>$lastuser));
997 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
998 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
999 context_helper::cleanup_instances();
1000 $count = 1; //system
1001 $count += $DB->count_records('user', array('deleted'=>0));
1002 $count += $DB->count_records('course_categories');
1003 $count += $DB->count_records('course');
1004 $count += $DB->count_records('course_modules');
1005 $count += $DB->count_records('block_instances');
1006 $this->assertEqual($DB->count_records('context'), $count);
1007
1008
1009 // ======= context cache size restrictions ==============================
1010
1011 $testusers= array();
1012 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
1013 $user = new stdClass();
1014 $user->auth = 'manual';
1015 $user->firstname = 'xuser'.$i;
1016 $user->lastname = 'xuser'.$i;
1017 $user->username = 'xuser'.$i;
1018 $user->password = 'doesnotexist';
1019 $user->email = "xuser$i@example.com";
1020 $user->confirmed = 1;
1021 $user->mnethostid = $CFG->mnet_localhost_id;
1022 $user->lang = $CFG->lang;
1023 $user->maildisplay = 1;
1024 $user->timemodified = time();
1025 $user->lastip = '0.0.0.0';
1026 $userid = $DB->insert_record('user', $user);
1027 $testusers[$i] = $userid;
1028 }
1029 context_helper::create_instances(null, true);
1030 context_helper::reset_caches();
1031 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
1032 context_user::instance($testusers[$i]);
1033 if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
1034 $this->assertEqual(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
1035 } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
1036 // once the limit is reached roughly 1/3 of records should be removed from cache
1037 $this->assertEqual(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
1038 }
1039 }
1040 // We keep the first 100 cached
1041 $prevsize = context_inspection::test_context_cache_size();
1042 for ($i=0; $i<100; $i++) {
1043 context_user::instance($testusers[$i]);
1044 $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize);
1045 }
1046 context_user::instance($testusers[102]);
1047 $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize+1);
1048 unset($testusers);
1049
1050
1051
1052 // =================================================================
1053 // ======= basic test of legacy functions ==========================
1054 // =================================================================
1055 // note: watch out, the fake site might be pretty borked already
1056
1057 $this->assertIdentical(get_system_context(), context_system::instance());
1058
1059 foreach ($DB->get_records('context') as $contextid=>$record) {
1060 $context = context::instance_by_id($contextid);
1061 $this->assertIdentical(get_context_instance_by_id($contextid), $context);
1062 $this->assertIdentical(get_context_instance($record->contextlevel, $record->instanceid), $context);
1063 $this->assertIdentical(get_parent_contexts($context), $context->get_parent_context_ids());
1064 if ($context->id == SYSCONTEXTID) {
1065 $this->assertIdentical(get_parent_contextid($context), false);
1066 } else {
1067 $this->assertIdentical(get_parent_contextid($context), $context->get_parent_context()->id);
1068 }
1069 }
1070
1071 $children = get_child_contexts($systemcontext);
1072 $this->assertEqual(count($children), $DB->count_records('context')-1);
1073 unset($children);
1074
1075 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
1076 create_contexts();
1077 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));
1078
1079 $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
1080 build_context_path();
1081 $this->assertFalse($DB->record_exists('context', array('depth'=>0)));
1082
1083 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
1084 $DB->delete_records('course', array('id'=>$lastcourse));
1085 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
1086 $DB->delete_records('course_categories', array('id'=>$lastcategory));
1087 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
1088 $DB->delete_records('user', array('id'=>$lastuser));
1089 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
1090 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
1091 cleanup_contexts();
1092 $count = 1; //system
1093 $count += $DB->count_records('user', array('deleted'=>0));
1094 $count += $DB->count_records('course_categories');
1095 $count += $DB->count_records('course');
1096 $count += $DB->count_records('course_modules');
1097 $count += $DB->count_records('block_instances');
1098 $this->assertEqual($DB->count_records('context'), $count);
1099
1100 context_helper::reset_caches();
1101 preload_course_contexts($SITE->id);
1102 $this->assertEqual(context_inspection::test_context_cache_size(), 1);
1103
1104 context_helper::reset_caches();
1105 list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
1106 $sql = "SELECT c.id $select FROM {course_categories} c $join";
1107 $records = $DB->get_records_sql($sql);
1108 foreach ($records as $record) {
1109 context_instance_preload($record);
1110 $record = (array)$record;
1111 $this->assertEqual(1, count($record)); // only id left
1112 }
1113 $this->assertEqual(count($records), context_inspection::test_context_cache_size());
1114
1115 accesslib_clear_all_caches(true);
1116 $DB->delete_records('cache_flags', array());
1117 mark_context_dirty($systemcontext->path);
1118 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
1119 $this->assertTrue(isset($dirty[$systemcontext->path]));
1120
1121 accesslib_clear_all_caches(false);
1122 $DB->delete_records('cache_flags', array());
1123 $course = $DB->get_record('course', array('id'=>$testcourses[2]));
1124 $context = get_context_instance(CONTEXT_COURSE, $course->id);
1125 $oldpath = $context->path;
1126 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
1127 $categorycontext = context_coursecat::instance($miscid);
1128 $course->category = $miscid;
1129 $DB->update_record('course', $course);
1130 context_moved($context, $categorycontext);
1131 $context = get_context_instance(CONTEXT_COURSE, $course->id);
1132 $this->assertIdentical($context->get_parent_context(), $categorycontext);
1133
1134 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
1135 delete_context(CONTEXT_COURSE, $testcourses[2]);
1136 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
1137
1138 $name = get_contextlevel_name(CONTEXT_COURSE);
1139 $this->assertFalse(empty($name));
1140
1141 $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
1142 $name = print_context_name($context);
1143 $this->assertFalse(empty($name));
1144
1145 $url = get_context_url($coursecontext);
1146 $this->assertFalse($url instanceof modole_url);
1147
1148 $page = $DB->get_record('page', array('id'=>$testpages[7]));
1149 $context = get_context_instance(CONTEXT_MODULE, $page->id);
1150 $coursecontext = get_course_context($context);
1151 $this->assertEqual($coursecontext->contextlevel, CONTEXT_COURSE);
1152 $this->assertEqual(get_courseid_from_context($context), $page->course);
1153
1154 $caps = fetch_context_capabilities($systemcontext);
1155 $this->assertTrue(is_array($caps));
1156 unset($caps);
1157 }
1158
1159 public function tearDown() {
1160 global $USER, $SITE;
1161 if (isset($this->accesslibprevuser)) {
1162 $USER = $this->accesslibprevuser;
1163 }
1164 if (isset($this->accesslibprevsite)) {
1165 $SITE = $this->accesslibprevsite;
1166 }
1167
1168
1169 parent::tearDown();
1170 }
1171}
1172