From 897f31a5d0828fbf50145925a5f28cf8a67a6733 Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Thu, 21 Apr 2016 16:38:57 +0800 Subject: [PATCH] MDL-51369 course: Adding tests to cover restoring course info --- course/tests/restore_test.php | 324 ++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 course/tests/restore_test.php diff --git a/course/tests/restore_test.php b/course/tests/restore_test.php new file mode 100644 index 00000000000..f794e66520c --- /dev/null +++ b/course/tests/restore_test.php @@ -0,0 +1,324 @@ +. + +/** + * Course restore tests. + * + * @package core_course + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); +global $CFG; + +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); + +/** + * Course restore testcase. + * + * @package core_course + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_restore_backup_testcase extends advanced_testcase { + + /** + * Backup a course and return its backup ID. + * + * @param int $courseid The course ID. + * @param int $userid The user doing the backup. + * @return string + */ + protected function backup_course($courseid, $userid = 2) { + globaL $CFG; + $packer = get_file_packer('application/vnd.moodle.backup'); + + $bc = new backup_controller(backup::TYPE_1COURSE, $courseid, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, + backup::MODE_GENERAL, $userid); + $bc->execute_plan(); + + $results = $bc->get_results(); + $results['backup_destination']->extract_to_pathname($packer, "$CFG->tempdir/backup/core_course_testcase"); + + $bc->destroy(); + unset($bc); + return 'core_course_testcase'; + } + + /** + * Create a role with capabilities and permissions. + * + * @param string|array $caps Capability names. + * @param int $perm Constant CAP_* to apply to the capabilities. + * @return int The new role ID. + */ + protected function create_role_with_caps($caps, $perm) { + $caps = (array) $caps; + $dg = $this->getDataGenerator(); + $roleid = $dg->create_role(); + foreach ($caps as $cap) { + assign_capability($cap, $perm, $roleid, context_system::instance()->id, true); + } + accesslib_clear_all_caches_for_unit_testing(); + return $roleid; + } + + /** + * Restore a course. + * + * @param int $backupid The backup ID. + * @param int $courseid The course ID to restore in, or 0. + * @param int $userid The ID of the user performing the restore. + * @return stdClass The updated course object. + */ + protected function restore_course($backupid, $courseid, $userid) { + global $DB; + + $target = backup::TARGET_CURRENT_ADDING; + if (!$courseid) { + $target = backup::TARGET_NEW_COURSE; + $categoryid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); + $courseid = restore_dbops::create_new_course('Tmp', 'tmp', $categoryid); + } + + $rc = new restore_controller($backupid, $courseid, backup::INTERACTIVE_NO, backup::MODE_GENERAL, $userid, $target); + $target == backup::TARGET_NEW_COURSE ?: $rc->get_plan()->get_setting('overwrite_conf')->set_value(true); + $rc->execute_precheck(); + $rc->execute_plan(); + + $course = $DB->get_record('course', array('id' => $rc->get_courseid())); + + $rc->destroy(); + unset($rc); + return $course; + } + + /** + * Restore a course to an existing course. + * + * @param int $backupid The backup ID. + * @param int $courseid The course ID to restore in. + * @param int $userid The ID of the user performing the restore. + * @return stdClass The updated course object. + */ + protected function restore_to_existing_course($backupid, $courseid, $userid = 2) { + return $this->restore_course($backupid, $courseid, $userid); + } + + /** + * Restore a course to a new course. + * + * @param int $backupid The backup ID. + * @param int $userid The ID of the user performing the restore. + * @return stdClass The new course object. + */ + protected function restore_to_new_course($backupid, $userid = 2) { + return $this->restore_course($backupid, 0, $userid); + } + + public function test_restore_existing_idnumber_in_new_course() { + $this->resetAfterTest(); + + $dg = $this->getDataGenerator(); + $c1 = $dg->create_course(['idnumber' => 'ABC']); + $backupid = $this->backup_course($c1->id); + $c2 = $this->restore_to_new_course($backupid); + + // The ID number is set empty. + $this->assertEquals('', $c2->idnumber); + } + + public function test_restore_non_existing_idnumber_in_new_course() { + global $DB; + $this->resetAfterTest(); + + $dg = $this->getDataGenerator(); + $c1 = $dg->create_course(['idnumber' => 'ABC']); + $backupid = $this->backup_course($c1->id); + + $c1->idnumber = 'BCD'; + $DB->update_record('course', $c1); + + // The ID number changed. + $c2 = $this->restore_to_new_course($backupid); + $this->assertEquals('ABC', $c2->idnumber); + } + + public function test_restore_existing_idnumber_in_existing_course() { + global $DB; + $this->resetAfterTest(); + + $dg = $this->getDataGenerator(); + $c1 = $dg->create_course(['idnumber' => 'ABC']); + $c2 = $dg->create_course(['idnumber' => 'DEF']); + $backupid = $this->backup_course($c1->id); + + // The ID number does not change. + $c2 = $this->restore_to_existing_course($backupid, $c2->id); + $this->assertEquals('DEF', $c2->idnumber); + + $c1 = $DB->get_record('course', array('id' => $c1->id)); + $this->assertEquals('ABC', $c1->idnumber); + } + + public function test_restore_non_existing_idnumber_in_existing_course() { + global $DB; + $this->resetAfterTest(); + + $dg = $this->getDataGenerator(); + $c1 = $dg->create_course(['idnumber' => 'ABC']); + $c2 = $dg->create_course(['idnumber' => 'DEF']); + $backupid = $this->backup_course($c1->id); + + $c1->idnumber = 'XXX'; + $DB->update_record('course', $c1); + + // The ID number has changed. + $c2 = $this->restore_to_existing_course($backupid, $c2->id); + $this->assertEquals('ABC', $c2->idnumber); + } + + public function test_restore_idnumber_in_existing_course_without_permissions() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $u1 = $dg->create_user(); + + $managers = get_archetype_roles('manager'); + $manager = array_shift($managers); + $roleid = $this->create_role_with_caps('moodle/course:changeidnumber', CAP_PROHIBIT); + $dg->role_assign($manager->id, $u1->id); + $dg->role_assign($roleid, $u1->id); + + $c1 = $dg->create_course(['idnumber' => 'ABC']); + $c2 = $dg->create_course(['idnumber' => 'DEF']); + $backupid = $this->backup_course($c1->id); + + $c1->idnumber = 'XXX'; + $DB->update_record('course', $c1); + + // The ID number does not change. + $c2 = $this->restore_to_existing_course($backupid, $c2->id, $u1->id); + $this->assertEquals('DEF', $c2->idnumber); + } + + public function test_restore_course_info_in_new_course() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + + $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]); + $backupid = $this->backup_course($c1->id); + + // The information is restored but adapted because names are already taken. + $c2 = $this->restore_to_new_course($backupid); + $this->assertEquals('SN_1', $c2->shortname); + $this->assertEquals('FN copy 1', $c2->fullname); + $this->assertEquals('DESC', $c2->summary); + $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat); + } + + public function test_restore_course_info_in_existing_course() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + + $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]); + $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN]); + $backupid = $this->backup_course($c1->id); + + // The information is restored but adapted because names are already taken. + $c2 = $this->restore_to_existing_course($backupid, $c2->id); + $this->assertEquals('SN_1', $c2->shortname); + $this->assertEquals('FN copy 1', $c2->fullname); + $this->assertEquals('DESC', $c2->summary); + $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat); + } + + public function test_restore_course_shortname_in_existing_course_without_permissions() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $u1 = $dg->create_user(); + + $managers = get_archetype_roles('manager'); + $manager = array_shift($managers); + $roleid = $this->create_role_with_caps('moodle/course:changeshortname', CAP_PROHIBIT); + $dg->role_assign($manager->id, $u1->id); + $dg->role_assign($roleid, $u1->id); + + $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]); + $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]); + + // The shortname does not change. + $backupid = $this->backup_course($c1->id); + $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id); + $this->assertEquals($c2->shortname, $restored->shortname); + $this->assertEquals('FN copy 1', $restored->fullname); + $this->assertEquals('DESC', $restored->summary); + $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat); + } + + public function test_restore_course_fullname_in_existing_course_without_permissions() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $u1 = $dg->create_user(); + + $managers = get_archetype_roles('manager'); + $manager = array_shift($managers); + $roleid = $this->create_role_with_caps('moodle/course:changefullname', CAP_PROHIBIT); + $dg->role_assign($manager->id, $u1->id); + $dg->role_assign($roleid, $u1->id); + + $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]); + $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]); + + // The fullname does not change. + $backupid = $this->backup_course($c1->id); + $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id); + $this->assertEquals('SN_1', $restored->shortname); + $this->assertEquals($c2->fullname, $restored->fullname); + $this->assertEquals('DESC', $restored->summary); + $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat); + } + + public function test_restore_course_summary_in_existing_course_without_permissions() { + global $DB; + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $u1 = $dg->create_user(); + + $managers = get_archetype_roles('manager'); + $manager = array_shift($managers); + $roleid = $this->create_role_with_caps('moodle/course:changesummary', CAP_PROHIBIT); + $dg->role_assign($manager->id, $u1->id); + $dg->role_assign($roleid, $u1->id); + + $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]); + $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]); + + // The summary and format do not change. + $backupid = $this->backup_course($c1->id); + $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id); + $this->assertEquals('SN_1', $restored->shortname); + $this->assertEquals('FN copy 1', $restored->fullname); + $this->assertEquals($c2->summary, $restored->summary); + $this->assertEquals($c2->summaryformat, $restored->summaryformat); + } +}