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 * @package core_backup 19 * @category phpunit 20 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24defined('MOODLE_INTERNAL') || die(); 25 26// Include all the needed stuff 27global $CFG; 28require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); 29require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); 30 31/* 32 * controller tests (all) 33 */ 34class core_backup_controller_testcase extends advanced_testcase { 35 36 protected $moduleid; // course_modules id used for testing 37 protected $sectionid; // course_sections id used for testing 38 protected $courseid; // course id used for testing 39 protected $userid; // user used if for testing 40 41 protected function setUp() { 42 global $DB, $CFG; 43 44 $this->resetAfterTest(true); 45 46 $course = $this->getDataGenerator()->create_course(); 47 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3)); 48 $coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid)); 49 50 $this->moduleid = $coursemodule->id; 51 $this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id)); 52 $this->courseid = $coursemodule->course; 53 $this->userid = 2; // admin 54 55 // Disable all loggers 56 $CFG->backup_error_log_logger_level = backup::LOG_NONE; 57 $CFG->backup_output_indented_logger_level = backup::LOG_NONE; 58 $CFG->backup_file_logger_level = backup::LOG_NONE; 59 $CFG->backup_database_logger_level = backup::LOG_NONE; 60 $CFG->backup_file_logger_level_extra = backup::LOG_NONE; 61 } 62 63 /** 64 * Test set copy method. 65 */ 66 public function test_base_controller_set_copy() { 67 $this->expectException(\backup_controller_exception::class); 68 $copy = new \stdClass(); 69 70 // Set up controller as a non-copy operation. 71 $bc = new \backup_controller(backup::TYPE_1COURSE, $this->courseid, backup::FORMAT_MOODLE, 72 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid, backup::RELEASESESSION_YES); 73 74 $bc->set_copy($copy); 75 } 76 77 /* 78 * test base_setting class 79 */ 80 public function test_backup_controller() { 81 // Instantiate non interactive backup_controller 82 $bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 83 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid); 84 $this->assertTrue($bc instanceof backup_controller); 85 $this->assertEquals($bc->get_status(), backup::STATUS_AWAITING); 86 // Instantiate interactive backup_controller 87 $bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 88 backup::INTERACTIVE_YES, backup::MODE_GENERAL, $this->userid); 89 $this->assertTrue($bc instanceof backup_controller); 90 $this->assertEquals($bc->get_status(), backup::STATUS_SETTING_UI); 91 $this->assertEquals(strlen($bc->get_backupid()), 32); // is one md5 92 93 // Save and load one backup controller to check everything is in place 94 $bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 95 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid); 96 $recid = $bc->save_controller(); 97 $newbc = mock_backup_controller::load_controller($bc->get_backupid()); 98 $this->assertTrue($newbc instanceof backup_controller); // This means checksum and load worked ok 99 } 100 101 public function test_backup_controller_include_files() { 102 // A MODE_GENERAL controller - this should include files 103 $bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 104 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid); 105 $this->assertEquals($bc->get_include_files(), 1); 106 107 108 // The MODE_IMPORT and MODE_SAMESITE should not include files in the backup. 109 // A MODE_IMPORT controller 110 $bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 111 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $this->userid); 112 $this->assertEquals($bc->get_include_files(), 0); 113 114 // A MODE_SAMESITE controller 115 $bc = new mock_backup_controller(backup::TYPE_1COURSE, $this->courseid, backup::FORMAT_MOODLE, 116 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $this->userid); 117 $this->assertEquals($bc->get_include_files(), 0); 118 } 119 120 /** 121 * Test set kept roles method. 122 */ 123 public function test_backup_controller_set_kept_roles() { 124 $this->expectException(\backup_controller_exception::class); 125 126 // Set up controller as a non-copy operation. 127 $bc = new \backup_controller(backup::TYPE_1COURSE, $this->courseid, backup::FORMAT_MOODLE, 128 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid, backup::RELEASESESSION_YES); 129 130 $bc->set_kept_roles(array(1, 3, 5)); 131 } 132 133 /** 134 * Tests the restore_controller. 135 */ 136 public function test_restore_controller_is_executing() { 137 global $CFG; 138 139 // Make a backup. 140 make_backup_temp_directory(''); 141 $bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 142 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $this->userid); 143 $backupid = $bc->get_backupid(); 144 $bc->execute_plan(); 145 $bc->destroy(); 146 147 // The progress class will get called during restore, so we can use that 148 // to check the executing flag is true. 149 $progress = new core_backup_progress_restore_is_executing(); 150 151 // Set up restore. 152 $rc = new restore_controller($backupid, $this->courseid, 153 backup::INTERACTIVE_NO, backup::MODE_SAMESITE, $this->userid, 154 backup::TARGET_EXISTING_ADDING); 155 $this->assertTrue($rc->execute_precheck()); 156 157 // Check restore is NOT executing. 158 $this->assertFalse(restore_controller::is_executing()); 159 160 // Execute restore. 161 $rc->set_progress($progress); 162 $rc->execute_plan(); 163 164 // Check restore is NOT executing afterward either. 165 $this->assertFalse(restore_controller::is_executing()); 166 $rc->destroy(); 167 168 // During restore, check that executing was true. 169 $this->assertTrue(count($progress->executing) > 0); 170 $alltrue = true; 171 foreach ($progress->executing as $executing) { 172 if (!$executing) { 173 $alltrue = false; 174 break; 175 } 176 } 177 $this->assertTrue($alltrue); 178 } 179 180 /** 181 * Test prepare copy method. 182 */ 183 public function test_restore_controller_prepare_copy() { 184 $this->expectException(\restore_controller_exception::class); 185 186 global $CFG; 187 188 // Make a backup. 189 make_backup_temp_directory(''); 190 $bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE, 191 backup::INTERACTIVE_NO, backup::MODE_IMPORT, $this->userid); 192 $backupid = $bc->get_backupid(); 193 $bc->execute_plan(); 194 $bc->destroy(); 195 196 // Set up restore. 197 $rc = new restore_controller($backupid, $this->courseid, 198 backup::INTERACTIVE_NO, backup::MODE_SAMESITE, $this->userid, 199 backup::TARGET_EXISTING_ADDING); 200 $rc->prepare_copy(); 201 } 202 203 /** 204 * Test restore of deadlock causing backup. 205 */ 206 public function test_restore_of_deadlock_causing_backup() { 207 global $USER, $CFG; 208 $this->preventResetByRollback(); 209 210 $foldername = 'deadlock'; 211 $fp = get_file_packer('application/vnd.moodle.backup'); 212 $tempdir = make_backup_temp_directory($foldername); 213 $files = $fp->extract_to_pathname($CFG->dirroot . '/backup/controller/tests/fixtures/deadlock.mbz', $tempdir); 214 215 $this->setAdminUser(); 216 $controller = new restore_controller( 217 'deadlock', 218 $this->courseid, 219 backup::INTERACTIVE_NO, 220 backup::MODE_GENERAL, 221 $USER->id, 222 backup::TARGET_NEW_COURSE 223 ); 224 $this->assertTrue($controller->execute_precheck()); 225 $controller->execute_plan(); 226 $controller->destroy(); 227 } 228} 229 230 231/** 232 * Progress class that records the result of restore_controller::is_executing calls. 233 * 234 * @package core_backup 235 * @copyright 2014 The Open University 236 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 237 */ 238class core_backup_progress_restore_is_executing extends \core\progress\base { 239 /** @var array Array of results from calling function */ 240 public $executing = array(); 241 242 public function update_progress() { 243 $this->executing[] = restore_controller::is_executing(); 244 } 245} 246 247 248/* 249 * helper extended @backup_controller class that makes some methods public for testing 250 */ 251class mock_backup_controller extends backup_controller { 252 253 public function save_controller($includeobj = true, $cleanobj = false) { 254 parent::save_controller($includeobj, $cleanobj); 255 } 256} 257