/** * @dataProvider set_table_modified_by_sql_provider */ public function test_set_table_modified_by_sql($sql, $expectations) { phpunit_util::reset_updated_table_list(); phpunit_util::set_table_modified_by_sql($sql); foreach ($expectations as $table => $present) { $this->assertEquals($present, !empty(phpunit_util::$tableupdated[$table])); } }
/** * Runs the bare test sequence and log any changes in global state or database. * @return void */ public final function runBare() { global $DB; try { parent::runBare(); } catch (Exception $e) { // cleanup after failed expectation phpunit_util::reset_all_data(); throw $e; } if ($DB->is_transaction_started()) { phpunit_util::reset_all_data(); throw new coding_exception('basic_testcase ' . $this->getName() . ' is not supposed to use database transactions!'); } phpunit_util::reset_all_data(true); }
/** * Runs the bare test sequence and log any changes in global state or database. * @return void */ public final function runBare() { global $DB; try { parent::runBare(); } catch (Exception $ex) { $e = $ex; } catch (Throwable $ex) { // Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5). $e = $ex; } if (isset($e)) { // cleanup after failed expectation phpunit_util::reset_all_data(); throw $e; } if ($DB->is_transaction_started()) { phpunit_util::reset_all_data(); throw new coding_exception('basic_testcase ' . $this->getName() . ' is not supposed to use database transactions!'); } phpunit_util::reset_all_data(true); }
/** * Tests the get_year_for_tables function. */ public function test_get_year_for_tables() { $this->resetAfterTest(); // Create a couple of courses for testing. $course1 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2013-01-04 10:00'))); $course2 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2020-01-04 10:00'))); $course3 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2021-01-04 10:00'))); // System not turned on. $this->assertFalse(year_tables::get_year_for_tables()); // System turned on, initially transferring. Test with course and no course. set_config(year_tables::CONFIG_ENABLED, year_tables::ENABLED_TRANSFERRING, 'local_ousearch'); $this->assertFalse(year_tables::get_year_for_tables()); $this->assertFalse(year_tables::get_year_for_tables($course1)); // If any course is transferring, the non-course ones will return default. set_config(year_tables::CONFIG_TRANSFERRING_COURSE, $course1->id, 'local_ousearch'); $this->assertEquals(year_tables::NON_COURSE_YEAR, year_tables::get_year_for_tables()); $this->assertFalse(year_tables::get_year_for_tables($course1)); // Once course 1 is finished, course 2 will still return false and course 1 // should return its year. set_config(year_tables::CONFIG_TRANSFERRING_COURSE, $course2->id, 'local_ousearch'); $this->assertEquals(2013, year_tables::get_year_for_tables($course1)); $this->assertFalse(year_tables::get_year_for_tables($course2)); // Now we'll set it to mark that everything was transferred. set_config(year_tables::CONFIG_ENABLED, year_tables::ENABLED_ON, 'local_ousearch'); unset_config(year_tables::CONFIG_TRANSFERRING_COURSE, 'local_ousearch'); // 2020 should show a warning that we're running out of tables. $this->assertEquals(2020, year_tables::get_year_for_tables($course2)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // 2021 should throw exception. try { year_tables::get_year_for_tables($course3); $this->fail(); } catch (moodle_exception $e) { $this->assertContains('start date beyond that supported by the OU search system', $e->getMessage()); } }
protected function PostSend() { // Now ask phpunit if it wants to catch this message. if (PHPUNIT_TEST) { if (!phpunit_util::is_redirecting_phpmailer()) { debugging('Unit tests must not send real emails! Use $this->start_phpmailer_redirection()'); return true; } $mail = new stdClass(); $mail->header = $this->MIMEHeader; $mail->body = $this->MIMEBody; $mail->subject = $this->Subject; $mail->from = $this->From; $mail->to = $this->to[0][0]; phpunit_util::phpmailer_sent($mail); return true; } else { return parent::PostSend(); } }
/** * Test is_user_access_restricted_by_conditional_access() * * The underlying conditional access system is more thoroughly tested in lib/tests/conditionlib_test.php */ public function test_is_user_access_restricted_by_conditional_access() { global $DB, $CFG; $this->resetAfterTest(); // Enable conditional availability before creating modules, otherwise the condition data is not written in DB. $CFG->enableavailability = true; // Create a course. $course = $this->getDataGenerator()->create_course(); // 1. Create an activity that is currently unavailable and hidden entirely (for students). $assign1 = $this->getDataGenerator()->create_module('assign', array('course' => $course->id), array('availability' => '{"op":"|","show":false,"c":[' . '{"type":"date","d":">=","t":' . (time() + 10000) . '}]}')); // 2. Create an activity that is currently available. $assign2 = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); // 3. Create an activity that is currently unavailable and set to be greyed out. $assign3 = $this->getDataGenerator()->create_module('assign', array('course' => $course->id), array('availability' => '{"op":"|","show":true,"c":[' . '{"type":"date","d":">=","t":' . (time() + 10000) . '}]}')); // Set up a teacher. $coursecontext = context_course::instance($course->id); $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST); $teacher = $this->getDataGenerator()->create_user(); role_assign($teacherrole->id, $teacher->id, $coursecontext); // If conditional availability is disabled the activity will always be unrestricted. $CFG->enableavailability = false; $cm = get_fast_modinfo($course)->instances['assign'][$assign1->id]; $this->assertTrue($cm->uservisible); // Test deprecated function. $this->assertFalse($cm->is_user_access_restricted_by_conditional_access()); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // Turn on conditional availability and reset the get_fast_modinfo cache. $CFG->enableavailability = true; get_fast_modinfo($course, 0, true); // The unavailable, hidden entirely activity should now be restricted. $cm = get_fast_modinfo($course)->instances['assign'][$assign1->id]; $this->assertFalse($cm->uservisible); $this->assertFalse($cm->available); $this->assertEquals('', $cm->availableinfo); // Test deprecated function. $this->assertTrue($cm->is_user_access_restricted_by_conditional_access()); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // If the activity is available it should not be restricted. $cm = get_fast_modinfo($course)->instances['assign'][$assign2->id]; $this->assertTrue($cm->uservisible); $this->assertTrue($cm->available); // If the activity is unavailable and set to be greyed out it should not be restricted. $cm = get_fast_modinfo($course)->instances['assign'][$assign3->id]; $this->assertFalse($cm->uservisible); $this->assertFalse($cm->available); $this->assertNotEquals('', (string) $cm->availableinfo); // Test deprecated function (weird case, it actually checks visibility). $this->assertFalse($cm->is_user_access_restricted_by_conditional_access()); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // If the activity is unavailable and set to be hidden entirely its restricted unless user has 'moodle/course:viewhiddenactivities'. // Switch to a teacher and reload the context info. $this->setUser($teacher); $this->assertTrue(has_capability('moodle/course:viewhiddenactivities', $coursecontext)); $cm = get_fast_modinfo($course)->instances['assign'][$assign1->id]; $this->assertTrue($cm->uservisible); $this->assertFalse($cm->available); }
/** * @depends test_message_redirection_noreset */ public function test_message_redirection_reset() { $this->assertFalse(phpunit_util::is_redirecting_messages(), 'Test reset must stop message redirection.'); }
/** * Called when a message provider wants to send a message. * This functions checks the message recipient's message processor configuration then * sends the message to the configured processors * * Required parameters of the $eventdata object: * component string component name. must exist in message_providers * name string message type name. must exist in message_providers * userfrom object|int the user sending the message * userto object|int the message recipient * subject string the message subject * fullmessage string the full message in a given format * fullmessageformat int the format if the full message (FORMAT_MOODLE, FORMAT_HTML, ..) * fullmessagehtml string the full version (the message processor will choose with one to use) * smallmessage string the small version of the message * * Optional parameters of the $eventdata object: * notification bool should the message be considered as a notification rather than a personal message * contexturl string if this is a notification then you can specify a url to view the event. For example the forum post the user is being notified of. * contexturlname string the display text for contexturl * * @category message * @param object $eventdata information about the message (component, userfrom, userto, ...) * @return mixed the integer ID of the new message or false if there was a problem with a processor */ function message_send($eventdata) { global $CFG, $DB; //new message ID to return $messageid = false; //TODO: we need to solve problems with database transactions here somehow, for now we just prevent transactions - sorry $DB->transactions_forbidden(); if (is_number($eventdata->userto)) { $eventdata->userto = $DB->get_record('user', array('id' => $eventdata->userto)); } if (is_int($eventdata->userfrom)) { $eventdata->userfrom = $DB->get_record('user', array('id' => $eventdata->userfrom)); } if (!isset($eventdata->userto->auth) or !isset($eventdata->userto->suspended) or !isset($eventdata->userto->deleted)) { $eventdata->userto = $DB->get_record('user', array('id' => $eventdata->userto->id)); } //after how long inactive should the user be considered logged off? if (isset($CFG->block_online_users_timetosee)) { $timetoshowusers = $CFG->block_online_users_timetosee * 60; } else { $timetoshowusers = 300;//5 minutes } // Work out if the user is logged in or not if (!empty($eventdata->userto->lastaccess) && (time()-$timetoshowusers) < $eventdata->userto->lastaccess) { $userstate = 'loggedin'; } else { $userstate = 'loggedoff'; } // Create the message object $savemessage = new stdClass(); $savemessage->useridfrom = $eventdata->userfrom->id; $savemessage->useridto = $eventdata->userto->id; $savemessage->subject = $eventdata->subject; $savemessage->fullmessage = $eventdata->fullmessage; $savemessage->fullmessageformat = $eventdata->fullmessageformat; $savemessage->fullmessagehtml = $eventdata->fullmessagehtml; $savemessage->smallmessage = $eventdata->smallmessage; if (!empty($eventdata->notification)) { $savemessage->notification = $eventdata->notification; } else { $savemessage->notification = 0; } if (!empty($eventdata->contexturl)) { $savemessage->contexturl = $eventdata->contexturl; } else { $savemessage->contexturl = null; } if (!empty($eventdata->contexturlname)) { $savemessage->contexturlname = $eventdata->contexturlname; } else { $savemessage->contexturlname = null; } $savemessage->timecreated = time(); if (PHPUNIT_TEST and class_exists('phpunit_util')) { // Add some more tests to make sure the normal code can actually work. $componentdir = get_component_directory($eventdata->component); if (!$componentdir or !is_dir($componentdir)) { throw new coding_exception('Invalid component specified in message-send(): '.$eventdata->component); } if (!file_exists("$componentdir/db/messages.php")) { throw new coding_exception("$eventdata->component does not contain db/messages.php necessary for message_send()"); } $messageproviders = null; include("$componentdir/db/messages.php"); if (!isset($messageproviders[$eventdata->name])) { throw new coding_exception("Missing messaging defaults for event '$eventdata->name' in '$eventdata->component' messages.php file"); } unset($componentdir); unset($messageproviders); // Now ask phpunit if it wants to catch this message. if (phpunit_util::is_redirecting_messages()) { $savemessage->timeread = time(); $messageid = $DB->insert_record('message_read', $savemessage); $message = $DB->get_record('message_read', array('id'=>$messageid)); phpunit_util::message_sent($message); return $messageid; } } // Fetch enabled processors $processors = get_message_processors(true); // Fetch default (site) preferences $defaultpreferences = get_message_output_default_preferences(); // Preset variables $processorlist = array(); $preferencebase = $eventdata->component.'_'.$eventdata->name; // Fill in the array of processors to be used based on default and user preferences foreach ($processors as $processor) { // First find out permissions $defaultpreference = $processor->name.'_provider_'.$preferencebase.'_permitted'; if (isset($defaultpreferences->{$defaultpreference})) { $permitted = $defaultpreferences->{$defaultpreference}; } else { //MDL-25114 They supplied an $eventdata->component $eventdata->name combination which doesn't //exist in the message_provider table (thus there is no default settings for them) $preferrormsg = get_string('couldnotfindpreference', 'message', $defaultpreference); throw new coding_exception($preferrormsg,'blah'); } // Find out if user has configured this output // Some processors cannot function without settings from the user $userisconfigured = $processor->object->is_user_configured($eventdata->userto); // DEBUG: notify if we are forcing unconfigured output if ($permitted == 'forced' && !$userisconfigured) { debugging('Attempt to force message delivery to user who has "'.$processor->name.'" output unconfigured', DEBUG_NORMAL); } // Warn developers that necessary data is missing regardless of how the processors are configured if (!isset($eventdata->userto->emailstop)) { debugging('userto->emailstop is not set. Retrieving it from the user table'); $eventdata->userto->emailstop = $DB->get_field('user', 'emailstop', array('id'=>$eventdata->userto->id)); } // Populate the list of processors we will be using if ($permitted == 'forced' && $userisconfigured) { // An admin is forcing users to use this message processor. Use this processor unconditionally. $processorlist[] = $processor->name; } else if ($permitted == 'permitted' && $userisconfigured && !$eventdata->userto->emailstop) { // User has not disabled notifications // See if user set any notification preferences, otherwise use site default ones $userpreferencename = 'message_provider_'.$preferencebase.'_'.$userstate; if ($userpreference = get_user_preferences($userpreferencename, null, $eventdata->userto->id)) { if (in_array($processor->name, explode(',', $userpreference))) { $processorlist[] = $processor->name; } } else if (isset($defaultpreferences->{$userpreferencename})) { if (in_array($processor->name, explode(',', $defaultpreferences->{$userpreferencename}))) { $processorlist[] = $processor->name; } } } } if (empty($processorlist) && $savemessage->notification) { //if they have deselected all processors and its a notification mark it read. The user doesnt want to be bothered $savemessage->timeread = time(); $messageid = $DB->insert_record('message_read', $savemessage); } else { // Process the message // Store unread message just in case we can not send it $messageid = $savemessage->id = $DB->insert_record('message', $savemessage); $eventdata->savedmessageid = $savemessage->id; // Try to deliver the message to each processor if (!empty($processorlist)) { foreach ($processorlist as $procname) { if (!$processors[$procname]->object->send_message($eventdata)) { debugging('Error calling message processor '.$procname); $messageid = false; } } //if messaging is disabled and they previously had forum notifications handled by the popup processor //or any processor that puts a row in message_working then the notification will remain forever //unread. To prevent this mark the message read if messaging is disabled if (empty($CFG->messaging)) { require_once($CFG->dirroot.'/message/lib.php'); $messageid = message_mark_message_read($savemessage, time()); } else if ( $DB->count_records('message_working', array('unreadmessageid' => $savemessage->id)) == 0){ //if there is no more processors that want to process this we can move message to message_read require_once($CFG->dirroot.'/message/lib.php'); $messageid = message_mark_message_read($savemessage, time(), true); } } } return $messageid; }
public function test_message_attachment_send() { global $CFG; $this->preventResetByRollback(); $this->resetAfterTest(); // Set config setting to allow attachments. $CFG->allowattachments = true; unset_config('noemailever'); $user = $this->getDataGenerator()->create_user(); $context = context_user::instance($user->id); // Create a test file. $fs = get_file_storage(); $filerecord = array('contextid' => $context->id, 'component' => 'core', 'filearea' => 'unittest', 'itemid' => 99999, 'filepath' => '/', 'filename' => 'emailtest.txt'); $file = $fs->create_file_from_string($filerecord, 'Test content'); $message = new stdClass(); $message->component = 'moodle'; $message->name = 'instantmessage'; $message->userfrom = get_admin(); $message->userto = $user; $message->subject = 'message subject 1'; $message->fullmessage = 'message body'; $message->fullmessageformat = FORMAT_MARKDOWN; $message->fullmessagehtml = '<p>message body</p>'; $message->smallmessage = 'small message'; $message->attachment = $file; $message->attachname = 'emailtest.txt'; $message->notification = 0; // Make sure we are redirecting emails. $sink = $this->redirectEmails(); $this->assertTrue(phpunit_util::is_redirecting_phpmailer()); message_send($message); // Get the email that we just sent. $emails = $sink->get_messages(); $email = reset($emails); $this->assertTrue(strpos($email->body, 'Content-Disposition: attachment;') !== false); $this->assertTrue(strpos($email->body, 'emailtest.txt') !== false); // Check if the stored file still exists after remove the temporary attachment. $storedfileexists = $fs->file_exists($filerecord['contextid'], $filerecord['component'], $filerecord['filearea'], $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']); $this->assertTrue($storedfileexists); }
/** * Create a new framework. * * @param array|stdClass $record * @return competency_framework */ public function create_framework($record = null) { $generator = phpunit_util::get_data_generator(); $this->frameworkcount++; $i = $this->frameworkcount; $record = (object) $record; if (!isset($record->shortname)) { $record->shortname = "Framework shortname {$i}"; } if (!isset($record->idnumber)) { $record->idnumber = "frm{$i}"; } if (!isset($record->description)) { $record->description = "Framework {$i} description "; } if (!isset($record->descriptionformat)) { $record->descriptionformat = FORMAT_HTML; } if (!isset($record->visible)) { $record->visible = 1; } if (!isset($record->scaleid)) { if (isset($record->scaleconfiguration)) { throw new coding_exception('Scale configuration must be provided with a scale.'); } if (!$this->scale) { $this->scale = $generator->create_scale(array('scale' => 'A,B,C,D')); } $record->scaleid = $this->scale->id; } if (!isset($record->scaleconfiguration)) { $scale = grade_scale::fetch(array('id' => $record->scaleid)); $values = $scale->load_items(); foreach ($values as $key => $value) { // Add a key (make the first value 1). $values[$key] = array('id' => $key + 1, 'name' => $value); } if (count($values) < 2) { throw new coding_exception('Please provide the scale configuration for one-item scales.'); } $scaleconfig = array(); // Last item is proficient. $item = array_pop($values); array_unshift($scaleconfig, array('id' => $item['id'], 'proficient' => 1)); // Second-last item is default and proficient. $item = array_pop($values); array_unshift($scaleconfig, array('id' => $item['id'], 'scaledefault' => 1, 'proficient' => 1)); array_unshift($scaleconfig, array('scaleid' => $record->scaleid)); $record->scaleconfiguration = json_encode($scaleconfig); } if (is_array($record->scaleconfiguration) || is_object($record->scaleconfiguration)) { // Conveniently encode the config. $record->scaleconfiguration = json_encode($record->scaleconfiguration); } if (!isset($record->contextid)) { $record->contextid = context_system::instance()->id; } $framework = new competency_framework(0, $record); $framework->create(); return $framework; }
/** * Calculate unique version hash for all plugins and core. * @static * @return string sha1 hash */ public static function get_version_hash() { global $CFG; if (self::$versionhash) { return self::$versionhash; } $versions = array(); // main version first $version = null; include $CFG->dirroot . '/version.php'; $versions['core'] = $version; // modules $mods = get_plugin_list('mod'); ksort($mods); foreach ($mods as $mod => $fullmod) { $module = new stdClass(); $module->version = null; include $fullmod . '/version.php'; $versions[$mod] = $module->version; } // now the rest of plugins $plugintypes = get_plugin_types(); unset($plugintypes['mod']); ksort($plugintypes); foreach ($plugintypes as $type => $unused) { $plugs = get_plugin_list($type); ksort($plugs); foreach ($plugs as $plug => $fullplug) { $plugin = new stdClass(); $plugin->version = null; @(include $fullplug . '/version.php'); $versions[$plug] = $plugin->version; } } self::$versionhash = sha1(serialize($versions)); return self::$versionhash; }
public function test_async_section_deletion_hook_implemented() { // Async section deletion (provided section contains modules), depends on the 'true' being returned by at least one plugin // implementing the 'course_module_adhoc_deletion_recommended' hook. In core, is implemented by the course recyclebin, // which will only return true if the plugin is enabled. To make sure async deletion occurs, this test enables recyclebin. global $DB, $USER; $this->resetAfterTest(true); $this->setAdminUser(); // Ensure recyclebin is enabled. set_config('coursebinenable', true, 'tool_recyclebin'); // Create course, module and context. $generator = $this->getDataGenerator(); $course = $generator->create_course(['numsections' => 4, 'format' => 'topics'], ['createsections' => true]); $assign0 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign1 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign2 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign3 = $generator->create_module('assign', ['course' => $course, 'section' => 0]); // Delete empty section. No difference from normal, synchronous behaviour. $this->assertTrue(course_delete_section($course, 4, false, true)); $this->assertEquals(3, course_get_format($course)->get_course()->numsections); // Delete a module in section 2 (using async). Need to verify this doesn't generate two tasks when we delete // the section in the next step. course_delete_module($assign2->cmid, true); // Confirm that the module is pending deletion in its current section. $section = $DB->get_record('course_sections', ['course' => $course->id, 'section' => '2']); // For event comparison. $this->assertEquals(true, $DB->record_exists('course_modules', ['id' => $assign2->cmid, 'deletioninprogress' => 1, 'section' => $section->id])); // Now, delete section 2. $this->assertFalse(course_delete_section($course, 2, false, true)); // Non-empty section, no forcedelete, so no change. $sink = $this->redirectEvents(); // To capture the event. $this->assertTrue(course_delete_section($course, 2, true, true)); // Now, confirm that: // a) the section's modules have been flagged for deletion and moved to section 0 and; // b) the section has been deleted and; // c) course_section_deleted event has been fired. The course_module_deleted events will only fire once they have been // removed from section 0 via the adhoc task. // Modules should have been flagged for deletion and moved to section 0. $sectionid = $DB->get_field('course_sections', 'id', ['course' => $course->id, 'section' => 0]); $this->assertEquals(3, $DB->count_records('course_modules', ['section' => $sectionid, 'deletioninprogress' => 1])); // Confirm the section has been deleted. $this->assertEquals(2, course_get_format($course)->get_course()->numsections); // Check event fired. $events = $sink->get_events(); $event = array_pop($events); $sink->close(); $this->assertInstanceOf('\\core\\event\\course_section_deleted', $event); $this->assertEquals($section->id, $event->objectid); $this->assertEquals($USER->id, $event->userid); $this->assertEquals('course_sections', $event->objecttable); $this->assertEquals(null, $event->get_url()); $this->assertEquals($section, $event->get_record_snapshot('course_sections', $section->id)); // Now, run the adhoc task to delete the modules from section 0. $sink = $this->redirectEvents(); // To capture the events. phpunit_util::run_all_adhoc_tasks(); // Confirm the modules have been deleted. list($insql, $assignids) = $DB->get_in_or_equal([$assign0->cmid, $assign1->cmid, $assign2->cmid]); $cmcount = $DB->count_records_select('course_modules', 'id ' . $insql, $assignids); $this->assertEmpty($cmcount); // Confirm other modules in section 0 still remain. $this->assertEquals(1, $DB->count_records('course_modules', ['id' => $assign3->cmid])); // Confirm that events were generated for all 3 of the modules. $events = $sink->get_events(); $sink->close(); $count = 0; while (!empty($events)) { $event = array_pop($events); if ($event instanceof \core\event\course_module_deleted && in_array($event->objectid, [$assign0->cmid, $assign1->cmid, $assign2->cmid])) { $count++; } } $this->assertEquals(3, $count); }
/** * Runs the entire 'make' process. * * @return int Course id */ public function make() { global $DB, $CFG; require_once $CFG->dirroot . '/lib/phpunit/classes/util.php'; raise_memory_limit(MEMORY_EXTRA); if ($this->progress && !CLI_SCRIPT) { echo html_writer::start_tag('ul'); } $entirestart = microtime(true); // Get generator. $this->generator = phpunit_util::get_data_generator(); // Make course. $this->course = $this->create_course(); $this->create_assignments(); $this->create_pages(); $this->create_small_files(); $this->create_big_files(); // Create users as late as possible to reduce regarding in the gradebook. $this->create_users(); $this->create_forum(); // Log total time. $this->log('coursecompleted', round(microtime(true) - $entirestart, 1)); if ($this->progress && !CLI_SCRIPT) { echo html_writer::end_tag('ul'); } return $this->course->id; }
/** * End message redirection. * * Note: Do not call directly from tests, * use $sink->close() instead. */ public static function stop_message_redirection() { self::$messagesink = null; }
/** * Generate the mpr contents (xml files) in the temporal directory. * * @param array $runids list of runids to be generated. * @param string $tmpdir filesystem fullpath of tmp generation. * @return boolean the mpr contents have been generated (true) or no (false). */ function profiling_export_generate(array $runids, $tmpdir) { global $CFG, $DB; // Calculate the header information to be sent to moodle_profiling_runs.xml. $release = $CFG->release; $version = $CFG->version; $dbtype = $CFG->dbtype; $githash = phpunit_util::get_git_hash(); $date = time(); // Create the xml output and writer for the main file. $mainxo = new file_xml_output($tmpdir . '/moodle_profiling_runs.xml'); $mainxw = new xml_writer($mainxo); // Output begins. $mainxw->start(); $mainxw->begin_tag('moodle_profiling_runs'); // Send header information. $mainxw->begin_tag('info'); $mainxw->full_tag('release', $release); $mainxw->full_tag('version', $version); $mainxw->full_tag('dbtype', $dbtype); if ($githash) { $mainxw->full_tag('githash', $githash); } $mainxw->full_tag('date', $date); $mainxw->end_tag('info'); // Send information about runs. $mainxw->begin_tag('runs'); foreach ($runids as $runid) { // Get the run information from DB. $run = $DB->get_record('profiling', array('runid' => $runid), '*', MUST_EXIST); $attributes = array('id' => $run->id, 'ref' => $run->runid . '.xml'); $mainxw->full_tag('run', null, $attributes); // Create the individual run file. $runxo = new file_xml_output($tmpdir . '/' . $attributes['ref']); $runxw = new xml_writer($runxo); $runxw->start(); $runxw->begin_tag('moodle_profiling_run'); $runxw->full_tag('id', $run->id); $runxw->full_tag('runid', $run->runid); $runxw->full_tag('url', $run->url); $runxw->full_tag('runreference', $run->runreference); $runxw->full_tag('runcomment', $run->runcomment); $runxw->full_tag('timecreated', $run->timecreated); $runxw->full_tag('totalexecutiontime', $run->totalexecutiontime); $runxw->full_tag('totalcputime', $run->totalcputime); $runxw->full_tag('totalcalls', $run->totalcalls); $runxw->full_tag('totalmemory', $run->totalmemory); $runxw->full_tag('data', $run->data); $runxw->end_tag('moodle_profiling_run'); $runxw->stop(); } $mainxw->end_tag('runs'); $mainxw->end_tag('moodle_profiling_runs'); $mainxw->stop(); return true; }
/** * Standard Debugging Function * * Returns true if the current site debugging settings are equal or above specified level. * If passed a parameter it will emit a debugging notice similar to trigger_error(). The * routing of notices is controlled by $CFG->debugdisplay * eg use like this: * * 1) debugging('a normal debug notice'); * 2) debugging('something really picky', DEBUG_ALL); * 3) debugging('annoying debug message only for developers', DEBUG_DEVELOPER); * 4) if (debugging()) { perform extra debugging operations (do not use print or echo) } * * In code blocks controlled by debugging() (such as example 4) * any output should be routed via debugging() itself, or the lower-level * trigger_error() or error_log(). Using echo or print will break XHTML * JS and HTTP headers. * * It is also possible to define NO_DEBUG_DISPLAY which redirects the message to error_log. * * @param string $message a message to print * @param int $level the level at which this debugging statement should show * @param array $backtrace use different backtrace * @return bool */ function debugging($message = '', $level = DEBUG_NORMAL, $backtrace = null) { global $CFG, $USER; $forcedebug = false; if (!empty($CFG->debugusers) && $USER) { $debugusers = explode(',', $CFG->debugusers); $forcedebug = in_array($USER->id, $debugusers); } if (!$forcedebug and empty($CFG->debug) || ($CFG->debug != -1 and $CFG->debug < $level)) { return false; } if (!isset($CFG->debugdisplay)) { $CFG->debugdisplay = ini_get_bool('display_errors'); } if ($message) { if (!$backtrace) { $backtrace = debug_backtrace(); } $from = format_backtrace($backtrace, CLI_SCRIPT || NO_DEBUG_DISPLAY); if (PHPUNIT_TEST) { if (phpunit_util::debugging_triggered($message, $level, $from)) { // We are inside test, the debug message was logged. return true; } } if (NO_DEBUG_DISPLAY) { // Script does not want any errors or debugging in output, // we send the info to error log instead. error_log('Debugging: ' . $message . ' in ' . PHP_EOL . $from); } else { if ($forcedebug or $CFG->debugdisplay) { if (!defined('DEBUGGING_PRINTED')) { define('DEBUGGING_PRINTED', 1); // Indicates we have printed something. } if (CLI_SCRIPT) { echo "++ {$message} ++\n{$from}"; } else { echo '<div class="notifytiny debuggingmessage" data-rel="debugging">', $message, $from, '</div>'; } } else { trigger_error($message . $from, E_USER_NOTICE); } } } return true; }
$CFG->debugdisplay = 1; error_reporting($CFG->debug); ini_set('display_errors', '1'); ini_set('log_errors', '1'); $CFG->noemailever = true; // better not mail anybody from tests, override temporarily if necessary $CFG->cachetext = 0; // disable this very nasty setting // some ugly hacks $CFG->themerev = 1; $CFG->jsrev = 1; // load test case stub classes and other stuff require_once "{$CFG->dirroot}/lib/phpunit/lib.php"; // finish moodle init define('ABORT_AFTER_CONFIG_CANCEL', true); require "{$CFG->dirroot}/lib/setup.php"; raise_memory_limit(MEMORY_HUGE); if (PHPUNIT_UTIL) { // we are not going to do testing, this is 'true' in utility scripts that only init database return; } // is database and dataroot ready for testing? list($errorcode, $message) = phpunit_util::testing_ready_problem(); // print some version info phpunit_util::bootstrap_moodle_info(); if ($errorcode) { phpunit_bootstrap_error($errorcode, $message); } // prepare for the first test run - store fresh globals, reset database and dataroot, etc. phpunit_util::bootstrap_init();
* @copyright 2015 Skylar Kelty <*****@*****.**> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('CLI_SCRIPT', true); require __DIR__ . '/../../../../config.php'; require_once $CFG->libdir . '/clilib.php'; require_once $CFG->libdir . '/coursecatlib.php'; require_once $CFG->dirroot . '/lib/phpunit/classes/util.php'; cli_writeln('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); cli_writeln('Welcome to the school generator!'); cli_writeln('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); cli_writeln(''); $category = $DB->get_record('course_categories', array('name' => 'School of Witchcraft and Wizardry')); if (!$category) { cli_writeln('Creating category...'); $category = \coursecat::create(array('name' => 'School of Witchcraft and Wizardry', 'description' => 'A school like no other!', 'descriptionformat' => 1, 'parent' => 0, 'sortorder' => 520000, 'coursecount' => 0, 'visible' => 1, 'visibleold' => 1, 'timemodified' => 0, 'depth' => 1, 'path' => '/2', 'theme' => '')); } else { cli_writeln('Using existing category.'); } $courses = array('Astronomy', 'Charms', 'Dark Arts', 'Defence Against the Dark Arts', 'Flying', 'Herbology', 'History of Magic', 'Muggle Studies', 'Potions', 'Transfiguration', 'Alchemy', 'Apparition', 'Arithmancy', 'Care of Magical Creatures', 'Divination', 'Study of Ancient Runes', 'Extra-curricular subjects', 'Ancient Studies', 'Art', 'Frog Choir', 'Ghoul Studies', 'Magical Theory', 'Muggle Art', 'Music', 'Muggle Music', 'Orchestra', 'Xylomancy'); cli_writeln('Creating courses...'); $generator = \phpunit_util::get_data_generator(); $id = 1000; foreach ($courses as $course) { if ($DB->record_exists('course', array('fullname' => $course))) { continue; } $courserecord = array('shortname' => "WZ{$id}", 'fullname' => $course, 'numsections' => 10, 'startdate' => usergetmidnight(time()), 'category' => $category->id); $generator->create_course($courserecord, array('createsections' => true)); $id += 100; }
/** * Get data generator * @static * @return testing_data_generator */ public static function getDataGenerator() { return phpunit_util::get_data_generator(); }
private function create_marker_module($markerid) { global $CFG, $DB; require_once $CFG->dirroot . '/lib/phpunit/classes/util.php'; // Start transaction. $transaction = $DB->start_delegated_transaction(); try { // Get generator. $generator = phpunit_util::get_data_generator(); /**@var mod_emarking_generator $emarking_generator*/ $emarking_generator = $generator->get_plugin_generator('mod_emarking'); $blueprint = $DB->get_record('emarking', array("id" => $this->cm->instance)); $blueprint->timecreated = time(); $originalname = $blueprint->name; $markers = get_users_by_capability($this->context, 'mod/emarking:grade', 'u.id,u.username'); $marker = $markers[$markerid]; if (!$marker) { throw new Exception("Marker not found"); } $previous = $DB->get_record('emarking_markers', array('masteractivity' => $this->parentcm->instance, 'markerid' => $markerid)); if ($previous) { throw new Exception("Delete previous marker record before assigning a new one"); } $submissions = $DB->get_records('emarking_submission', array("emarking" => $this->cm->instance)); $pages = array(); foreach ($submissions as $sub) { $pages[$sub->id] = $DB->get_records('emarking_page', array("submission" => $sub->id)); } unset($blueprint->id); $blueprint->name = $originalname . " -- " . $marker->username; $inserted = $emarking_generator->create_instance($blueprint, array("visible" => 0)); $markermap = new stdClass(); $markermap->masteractivity = $this->parentcm->instance; $markermap->markerid = $marker->id; $markermap->activityid = $inserted->id; $DB->insert_record('emarking_markers', $markermap); // se agrega el grading method correcto. require_once $CFG->dirroot . '/grade/grading/lib.php'; $gradingman = get_grading_manager(context_module::instance($inserted->cmid), 'mod_emarking'); $gradingman->set_area("attempt"); $gradingman->set_active_method("rubric"); emarking_grade_item_update($inserted); //Now replicate submissions foreach ($submissions as $sub) { $insertable = clone $sub; unset($insertable->id); $insertable->emarking = $inserted->id; $id = $DB->insert_record('emarking_submission', $insertable); foreach ($pages[$sub->id] as $subpage) { $insertablepage = clone $subpage; unset($insertablepage->id); $insertablepage->submission = $id; $DB->insert_record('emarking_page', $insertablepage); } // Update the raw grade of the user $grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'emarking', 'iteminstance' => $inserted->id)); $grade = $grade_item->get_grade($insertable->student, true); $grade_item->update_final_grade($insertable->student, null, 'upload', '', FORMAT_HTML, $marker->id); // grade } $transaction->allow_commit(); } catch (Exception $e) { $transaction->rollback($e); } }
/** * Called when a message provider wants to send a message. * This functions checks the message recipient's message processor configuration then * sends the message to the configured processors * * Required parameters of the $eventdata object: * component string component name. must exist in message_providers * name string message type name. must exist in message_providers * userfrom object|int the user sending the message * userto object|int the message recipient * subject string the message subject * fullmessage string the full message in a given format * fullmessageformat int the format if the full message (FORMAT_MOODLE, FORMAT_HTML, ..) * fullmessagehtml string the full version (the message processor will choose with one to use) * smallmessage string the small version of the message * * Optional parameters of the $eventdata object: * notification bool should the message be considered as a notification rather than a personal message * contexturl string if this is a notification then you can specify a url to view the event. For example the forum post the user is being notified of. * contexturlname string the display text for contexturl * * Note: processor failure is is not reported as false return value, * earlier versions did not do it consistently either. * * @todo MDL-55449 Drop support for stdClass in Moodle 3.6 * @category message * @param \core\message\message $eventdata information about the message (component, userfrom, userto, ...) * @return mixed the integer ID of the new message or false if there was a problem with submitted data */ function message_send($eventdata) { global $CFG, $DB; // TODO MDL-55449 Drop support for stdClass in Moodle 3.6. if ($eventdata instanceof \stdClass) { if (!isset($eventdata->courseid)) { $eventdata->courseid = null; } debugging('eventdata as \stdClass is deprecated. Please use core\message\message instead.', DEBUG_DEVELOPER); } //new message ID to return $messageid = false; // Fetch default (site) preferences $defaultpreferences = get_message_output_default_preferences(); $preferencebase = $eventdata->component.'_'.$eventdata->name; // If message provider is disabled then don't do any processing. if (!empty($defaultpreferences->{$preferencebase.'_disable'})) { return $messageid; } // By default a message is a notification. Only personal/private messages aren't notifications. if (!isset($eventdata->notification)) { $eventdata->notification = 1; } if (!is_object($eventdata->userto)) { $eventdata->userto = core_user::get_user($eventdata->userto); } if (!is_object($eventdata->userfrom)) { $eventdata->userfrom = core_user::get_user($eventdata->userfrom); } if (!$eventdata->userto) { debugging('Attempt to send msg to unknown user', DEBUG_NORMAL); return false; } if (!$eventdata->userfrom) { debugging('Attempt to send msg from unknown user', DEBUG_NORMAL); return false; } // Verify all necessary data fields are present. if (!isset($eventdata->userto->auth) or !isset($eventdata->userto->suspended) or !isset($eventdata->userto->deleted) or !isset($eventdata->userto->emailstop)) { debugging('Necessary properties missing in userto object, fetching full record', DEBUG_DEVELOPER); $eventdata->userto = core_user::get_user($eventdata->userto->id); } $usertoisrealuser = (core_user::is_real_user($eventdata->userto->id) != false); // If recipient is internal user (noreply user), and emailstop is set then don't send any msg. if (!$usertoisrealuser && !empty($eventdata->userto->emailstop)) { debugging('Attempt to send msg to internal (noreply) user', DEBUG_NORMAL); return false; } //after how long inactive should the user be considered logged off? if (isset($CFG->block_online_users_timetosee)) { $timetoshowusers = $CFG->block_online_users_timetosee * 60; } else { $timetoshowusers = 300;//5 minutes } // Work out if the user is logged in or not if (!empty($eventdata->userto->lastaccess) && (time()-$timetoshowusers) < $eventdata->userto->lastaccess) { $userstate = 'loggedin'; } else { $userstate = 'loggedoff'; } // Create the message object $savemessage = new stdClass(); $savemessage->courseid = $eventdata->courseid; $savemessage->useridfrom = $eventdata->userfrom->id; $savemessage->useridto = $eventdata->userto->id; $savemessage->subject = $eventdata->subject; $savemessage->fullmessage = $eventdata->fullmessage; $savemessage->fullmessageformat = $eventdata->fullmessageformat; $savemessage->fullmessagehtml = $eventdata->fullmessagehtml; $savemessage->smallmessage = $eventdata->smallmessage; $savemessage->notification = $eventdata->notification; $savemessage->eventtype = $eventdata->name; $savemessage->component = $eventdata->component; if (!empty($eventdata->contexturl)) { $savemessage->contexturl = (string)$eventdata->contexturl; } else { $savemessage->contexturl = null; } if (!empty($eventdata->contexturlname)) { $savemessage->contexturlname = (string)$eventdata->contexturlname; } else { $savemessage->contexturlname = null; } $savemessage->timecreated = time(); if (PHPUNIT_TEST and class_exists('phpunit_util')) { // Add some more tests to make sure the normal code can actually work. $componentdir = core_component::get_component_directory($eventdata->component); if (!$componentdir or !is_dir($componentdir)) { throw new coding_exception('Invalid component specified in message-send(): '.$eventdata->component); } if (!file_exists("$componentdir/db/messages.php")) { throw new coding_exception("$eventdata->component does not contain db/messages.php necessary for message_send()"); } $messageproviders = null; include("$componentdir/db/messages.php"); if (!isset($messageproviders[$eventdata->name])) { throw new coding_exception("Missing messaging defaults for event '$eventdata->name' in '$eventdata->component' messages.php file"); } unset($componentdir); unset($messageproviders); // Now ask phpunit if it wants to catch this message. if (phpunit_util::is_redirecting_messages()) { $savemessage->timeread = time(); $messageid = $DB->insert_record('message_read', $savemessage); $message = $DB->get_record('message_read', array('id'=>$messageid)); phpunit_util::message_sent($message); return $messageid; } } // Fetch enabled processors $processors = get_message_processors(true); // Preset variables $processorlist = array(); // Fill in the array of processors to be used based on default and user preferences foreach ($processors as $processor) { // Skip adding processors for internal user, if processor doesn't support sending message to internal user. if (!$usertoisrealuser && !$processor->object->can_send_to_any_users()) { continue; } // First find out permissions $defaultpreference = $processor->name.'_provider_'.$preferencebase.'_permitted'; if (isset($defaultpreferences->{$defaultpreference})) { $permitted = $defaultpreferences->{$defaultpreference}; } else { // MDL-25114 They supplied an $eventdata->component $eventdata->name combination which doesn't // exist in the message_provider table (thus there is no default settings for them). $preferrormsg = "Could not load preference $defaultpreference. Make sure the component and name you supplied to message_send() are valid."; throw new coding_exception($preferrormsg); } // Find out if user has configured this output // Some processors cannot function without settings from the user $userisconfigured = $processor->object->is_user_configured($eventdata->userto); // DEBUG: notify if we are forcing unconfigured output if ($permitted == 'forced' && !$userisconfigured) { debugging('Attempt to force message delivery to user who has "'.$processor->name.'" output unconfigured', DEBUG_NORMAL); } // Populate the list of processors we will be using if ($permitted == 'forced' && $userisconfigured) { // An admin is forcing users to use this message processor. Use this processor unconditionally. $processorlist[] = $processor->name; } else if ($permitted == 'permitted' && $userisconfigured && !$eventdata->userto->emailstop) { // User has not disabled notifications // See if user set any notification preferences, otherwise use site default ones $userpreferencename = 'message_provider_'.$preferencebase.'_'.$userstate; if ($userpreference = get_user_preferences($userpreferencename, null, $eventdata->userto)) { if (in_array($processor->name, explode(',', $userpreference))) { $processorlist[] = $processor->name; } } else if (isset($defaultpreferences->{$userpreferencename})) { if (in_array($processor->name, explode(',', $defaultpreferences->{$userpreferencename}))) { $processorlist[] = $processor->name; } } } } // Only cache messages, not notifications. if (empty($savemessage->notification)) { // Cache the timecreated value of the last message between these two users. $cache = cache::make('core', 'message_time_last_message_between_users'); $key = \core_message\helper::get_last_message_time_created_cache_key($savemessage->useridfrom, $savemessage->useridto); $cache->set($key, $savemessage->timecreated); } // Store unread message just in case we get a fatal error any time later. $savemessage->id = $DB->insert_record('message', $savemessage); $eventdata->savedmessageid = $savemessage->id; // Let the manager do the sending or buffering when db transaction in progress. return \core\message\manager::send_message($eventdata, $savemessage, $processorlist); }
/** * Runs the entire 'make' process. * * @return int Course id */ public function make() { global $DB, $CFG; require_once $CFG->dirroot . '/lib/phpunit/classes/util.php'; raise_memory_limit(MEMORY_EXTRA); if ($this->progress && !CLI_SCRIPT) { echo html_writer::start_tag('ul'); } $entirestart = microtime(true); // Start transaction. $transaction = $DB->start_delegated_transaction(); // Get generator. $this->generator = phpunit_util::get_data_generator(); // Make course. $this->course = $this->create_course(); $this->create_users(); $this->create_pages(); $this->create_small_files(); $this->create_big_files(); $this->create_forum(); // Log total time. $this->log('coursecompleted', round(microtime(true) - $entirestart, 1)); if ($this->progress && !CLI_SCRIPT) { echo html_writer::end_tag('ul'); } // Commit transaction and finish. $transaction->allow_commit(); return $this->course->id; }
try { if ($dbhash = $DB->get_field('config', 'value', array('name' => 'phpunittest'))) { // reset DB tables phpunit_util::reset_database(); } } catch (Exception $e) { if ($dbhash) { // we ned to reinit if reset fails $DB->set_field('config', 'value', 'na', array('name' => 'phpunittest')); } } unset($dbhash); } // Load up any configuration from the config table or MUC cache. if (PHPUNIT_TEST) { phpunit_util::initialise_cfg(); } else { initialise_cfg(); } if (isset($CFG->debug)) { $CFG->debug = (int) $CFG->debug; error_reporting($CFG->debug); } else { $CFG->debug = 0; } $CFG->debugdeveloper = ($CFG->debug & DEBUG_DEVELOPER) === DEBUG_DEVELOPER; // Find out if PHP configured to display warnings, // this is a security problem because some moodle scripts may // disclose sensitive information. if (ini_get_bool('display_errors')) { define('WARN_DISPLAY_ERRORS_ENABLED', true);
/** * Trigger event. */ public final function trigger() { global $CFG; if ($this->restored) { throw new \coding_exception('Can not trigger restored event'); } if ($this->triggered or $this->dispatched) { throw new \coding_exception('Can not trigger event twice'); } $this->validate_before_trigger(); $this->triggered = true; if (isset($CFG->loglifetime) and $CFG->loglifetime != -1) { if ($data = $this->get_legacy_logdata()) { call_user_func_array('add_to_log', $data); } } if (PHPUNIT_TEST and \phpunit_util::is_redirecting_events()) { $this->dispatched = true; \phpunit_util::event_triggered($this); return; } \core\event\manager::dispatch($this); $this->dispatched = true; if ($legacyeventname = static::get_legacy_eventname()) { events_trigger_legacy($legacyeventname, $this->get_legacy_eventdata()); } }
/** * Clear all previous debugging messages in current test. */ public function resetDebugging() { phpunit_util::reset_debugging(); }
/** * Trigger event. */ public final function trigger() { global $CFG; if ($this->restored) { throw new \coding_exception('Can not trigger restored event'); } if ($this->triggered or $this->dispatched) { throw new \coding_exception('Can not trigger event twice'); } $this->validate_before_trigger(); $this->triggered = true; if (isset($CFG->loglifetime) and $CFG->loglifetime != -1) { if ($data = $this->get_legacy_logdata()) { $manager = get_log_manager(); if (method_exists($manager, 'legacy_add_to_log')) { if (is_array($data[0])) { // Some events require several entries in 'log' table. foreach ($data as $d) { call_user_func_array(array($manager, 'legacy_add_to_log'), $d); } } else { call_user_func_array(array($manager, 'legacy_add_to_log'), $data); } } } } if (PHPUNIT_TEST and \phpunit_util::is_redirecting_events()) { $this->dispatched = true; \phpunit_util::event_triggered($this); return; } \core\event\manager::dispatch($this); $this->dispatched = true; if ($legacyeventname = static::get_legacy_eventname()) { events_trigger_legacy($legacyeventname, $this->get_legacy_eventdata()); } }
/** * End event redirection. * * @private * Note: Do not call directly from tests, * use $sink->close() instead. */ public static function stop_event_redirection() { self::$eventsink = null; }
/** * Test that the deprecated twf_is_subscribed accepts numeric twf IDs. */ public function test_twf_is_subscribed_numeric() { global $DB; $this->resetAfterTest(true); // Create a course, with a twf. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); $twf = $this->getDataGenerator()->create_module('twf', $options); // Create a user enrolled in the course as a students. list($author) = $this->helper_create_users($course, 1); // Check that the user is currently unsubscribed to the twf. $this->assertFalse(twf_is_subscribed($author->id, $twf->id)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // It should match the result of when it's called with the twf object. $this->assertFalse(twf_is_subscribed($author->id, $twf)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // And when the user is subscribed, we should also get the correct result. \mod_twf\subscriptions::subscribe_user($author->id, $twf); $this->assertTrue(twf_is_subscribed($author->id, $twf->id)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // It should match the result of when it's called with the twf object. $this->assertTrue(twf_is_subscribed($author->id, $twf)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); }
/** * Tests the info_section class (is_available, get_full_information). */ public function test_info_section() { global $DB; // Create a course. $this->setAdminUser(); $this->resetAfterTest(); $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 4), array('createsections' => true)); // Set up the availability option for the sections to mock options. $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[' . '{"type":"mock","a":false,"m":"public"}]}', array('course' => $course->id, 'section' => 1)); $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[' . '{"type":"mock","a":true,"m":"enemy"}]}', array('course' => $course->id, 'section' => 2)); // Third section is invalid. (Fourth has no availability setting.) $DB->set_field('course_sections', 'availability', '{{{', array('course' => $course->id, 'section' => 3)); $modinfo = get_fast_modinfo($course); $sections = $modinfo->get_section_info_all(); // Do availability and full information checks. $info = new info_section($sections[1]); $information = ''; $this->assertFalse($info->is_available($information)); $this->assertEquals('SA: public', $information); $this->assertEquals('SA: [FULL]public', $info->get_full_information()); $info = new info_section($sections[2]); $this->assertTrue($info->is_available($information)); $this->assertEquals('', $information); $this->assertEquals('SA: [FULL]enemy', $info->get_full_information()); // Check invalid one. $info = new info_section($sections[3]); $this->assertFalse($info->is_available($information)); $debugging = phpunit_util::get_debugging_messages(); phpunit_util::reset_debugging(); $this->assertEquals(1, count($debugging)); $this->assertContains('Invalid availability', $debugging[0]->message); // Check empty one. $info = new info_section($sections[4]); $this->assertTrue($info->is_available($information)); $this->assertEquals('', $information); $this->assertEquals('', $info->get_full_information()); }
if ($errorcode) { phpunit_bootstrap_error($errorcode, $message); } exit(0); } else { if ($buildconfig) { if (phpunit_util::build_config_file()) { exit(0); } else { phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGWARNING, 'Can not create main /phpunit.xml configuration file, verify dirroot permissions'); } } else { if ($buildcomponentconfigs) { phpunit_util::build_component_config_files(); exit(0); } else { if ($drop) { // make sure tests do not run in parallel phpunit_util::acquire_test_lock(); phpunit_util::drop_site(true); // note: we must stop here because $CFG is messed up and we can not reinstall, sorry exit(0); } else { if ($install) { phpunit_util::install_site(); exit(0); } } } } }