See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 * Automated backup tests. 19 * 20 * @package core_backup 21 * @copyright 2019 John Yao <johnyao@catalyst-au.net> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_backup; 26 27 use backup_cron_automated_helper; 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 global $CFG; 32 require_once($CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php'); 33 require_once($CFG->libdir.'/cronlib.php'); 34 require_once($CFG->libdir . '/completionlib.php'); 35 36 /** 37 * Automated backup tests. 38 * 39 * @package core_backup 40 * @copyright 2019 John Yao <johnyao@catalyst-au.net> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class automated_backup_test extends \advanced_testcase { 44 /** 45 * @var \backup_cron_automated_helper 46 */ 47 protected $backupcronautomatedhelper; 48 49 /** 50 * @var \stdClass $course 51 */ 52 protected $course; 53 54 protected function setUp(): void { 55 global $DB, $CFG; 56 57 $this->resetAfterTest(true); 58 $this->setAdminUser(); 59 $CFG->enableavailability = true; 60 $CFG->enablecompletion = true; 61 62 // Getting a testable backup_cron_automated_helper class. 63 $this->backupcronautomatedhelper = new test_backup_cron_automated_helper(); 64 65 $generator = $this->getDataGenerator(); 66 $this->course = $generator->create_course( 67 array('format' => 'topics', 'numsections' => 3, 68 'enablecompletion' => COMPLETION_ENABLED), 69 array('createsections' => true)); 70 $forum = $generator->create_module('forum', array( 71 'course' => $this->course->id)); 72 $forum2 = $generator->create_module('forum', array( 73 'course' => $this->course->id, 'completion' => COMPLETION_TRACKING_MANUAL)); 74 75 // We need a grade, easiest is to add an assignment. 76 $assignrow = $generator->create_module('assign', array( 77 'course' => $this->course->id)); 78 $assign = new \assign(\context_module::instance($assignrow->cmid), false, false); 79 $item = $assign->get_grade_item(); 80 81 // Make a test grouping as well. 82 $grouping = $generator->create_grouping(array('courseid' => $this->course->id, 83 'name' => 'Grouping!')); 84 85 $availability = '{"op":"|","show":false,"c":[' . 86 '{"type":"completion","cm":' . $forum2->cmid .',"e":1},' . 87 '{"type":"grade","id":' . $item->id . ',"min":4,"max":94},' . 88 '{"type":"grouping","id":' . $grouping->id . '}' . 89 ']}'; 90 $DB->set_field('course_modules', 'availability', $availability, array( 91 'id' => $forum->cmid)); 92 $DB->set_field('course_sections', 'availability', $availability, array( 93 'course' => $this->course->id, 'section' => 1)); 94 } 95 96 /** 97 * Tests the automated backup run when the there is course backup should be skipped. 98 */ 99 public function test_automated_backup_skipped_run() { 100 global $DB; 101 102 // Enable automated back up. 103 set_config('backup_auto_active', true, 'backup'); 104 set_config('backup_auto_weekdays', '1111111', 'backup'); 105 106 // Start backup process. 107 $admin = get_admin(); 108 109 // Backup entry should not exist. 110 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 111 $this->assertFalse($backupcourse); 112 $this->assertInstanceOf( 113 backup_cron_automated_helper::class, 114 $this->backupcronautomatedhelper->return_this() 115 ); 116 117 $classobject = $this->backupcronautomatedhelper->return_this(); 118 119 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'get_courses'); 120 $method->setAccessible(true); // Allow accessing of private method. 121 $courses = $method->invoke($classobject); 122 123 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'check_and_push_automated_backups'); 124 $method->setAccessible(true); // Allow accessing of private method. 125 $emailpending = $method->invokeArgs($classobject, [$courses, $admin]); 126 127 $this->expectOutputRegex('/Skipping course id ' . $this->course->id . ': Not scheduled for backup until/'); 128 $this->assertFalse($emailpending); 129 130 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 131 $this->assertNotNull($backupcourse->laststatus); 132 } 133 134 /** 135 * Tests the automated backup run when the there is course backup can be pushed to adhoc task. 136 */ 137 public function test_automated_backup_push_run() { 138 global $DB; 139 140 // Enable automated back up. 141 set_config('backup_auto_active', true, 'backup'); 142 set_config('backup_auto_weekdays', '1111111', 'backup'); 143 144 $admin = get_admin(); 145 146 $classobject = $this->backupcronautomatedhelper->return_this(); 147 148 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'get_courses'); 149 $method->setAccessible(true); // Allow accessing of private method. 150 $courses = $method->invoke($classobject); 151 152 // Create this backup course. 153 $backupcourse = new \stdClass; 154 $backupcourse->courseid = $this->course->id; 155 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_NOTYETRUN; 156 $DB->insert_record('backup_courses', $backupcourse); 157 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 158 159 // We now manually trigger a backup pushed to adhoc task. 160 // Make sure is in the past, which means should run now. 161 $backupcourse->nextstarttime = time() - 10; 162 $DB->update_record('backup_courses', $backupcourse); 163 164 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'check_and_push_automated_backups'); 165 $method->setAccessible(true); // Allow accessing of private method. 166 $emailpending = $method->invokeArgs($classobject, [$courses, $admin]); 167 $this->assertTrue($emailpending); 168 169 $this->expectOutputRegex('/Putting backup of course id ' . $this->course->id. ' in adhoc task queue/'); 170 171 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 172 // Now this backup course status should be queued. 173 $this->assertEquals(backup_cron_automated_helper::BACKUP_STATUS_QUEUED, $backupcourse->laststatus); 174 } 175 176 /** 177 * Tests the automated backup inactive run. 178 */ 179 public function test_inactive_run() { 180 backup_cron_automated_helper::run_automated_backup(); 181 $this->expectOutputString("Checking automated backup status...INACTIVE\n"); 182 } 183 184 /** 185 * Tests the invisible course being skipped. 186 */ 187 public function test_should_skip_invisible_course() { 188 global $DB; 189 190 set_config('backup_auto_active', true, 'backup'); 191 set_config('backup_auto_skip_hidden', true, 'backup'); 192 set_config('backup_auto_weekdays', '1111111', 'backup'); 193 // Create this backup course. 194 $backupcourse = new \stdClass; 195 $backupcourse->courseid = $this->course->id; 196 // This is the status we believe last run was OK. 197 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_SKIPPED; 198 $DB->insert_record('backup_courses', $backupcourse); 199 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 200 201 $this->assertTrue(course_change_visibility($this->course->id, false)); 202 $course = $DB->get_record('course', array('id' => $this->course->id)); 203 $this->assertEquals('0', $course->visible); 204 $classobject = $this->backupcronautomatedhelper->return_this(); 205 $nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time()); 206 207 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup'); 208 $method->setAccessible(true); // Allow accessing of private method. 209 $skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]); 210 211 $this->assertTrue($skipped); 212 $this->expectOutputRegex('/Skipping course id ' . $this->course->id. ': Not visible/'); 213 } 214 215 /** 216 * Tests the not modified course being skipped. 217 */ 218 public function test_should_skip_not_modified_course_in_days() { 219 global $DB; 220 221 set_config('backup_auto_active', true, 'backup'); 222 // Skip if not modified in two days. 223 set_config('backup_auto_skip_modif_days', 2, 'backup'); 224 set_config('backup_auto_weekdays', '1111111', 'backup'); 225 226 // Create this backup course. 227 $backupcourse = new \stdClass; 228 $backupcourse->courseid = $this->course->id; 229 // This is the status we believe last run was OK. 230 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_SKIPPED; 231 $backupcourse->laststarttime = time() - 2 * DAYSECS; 232 $backupcourse->lastendtime = time() - 1 * DAYSECS; 233 $DB->insert_record('backup_courses', $backupcourse); 234 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 235 $course = $DB->get_record('course', array('id' => $this->course->id)); 236 237 $course->timemodified = time() - 2 * DAYSECS - 1; 238 239 $classobject = $this->backupcronautomatedhelper->return_this(); 240 $nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time()); 241 242 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup'); 243 $method->setAccessible(true); // Allow accessing of private method. 244 $skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]); 245 246 $this->assertTrue($skipped); 247 $this->expectOutputRegex('/Skipping course id ' . $this->course->id . ': Not modified in the past 2 days/'); 248 } 249 250 /** 251 * Tests the backup not modified course being skipped. 252 */ 253 public function test_should_skip_not_modified_course_since_prev() { 254 global $DB; 255 256 set_config('backup_auto_active', true, 'backup'); 257 // Skip if not modified in two days. 258 set_config('backup_auto_skip_modif_prev', 2, 'backup'); 259 set_config('backup_auto_weekdays', '1111111', 'backup'); 260 261 // Create this backup course. 262 $backupcourse = new \stdClass; 263 $backupcourse->courseid = $this->course->id; 264 // This is the status we believe last run was OK. 265 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_SKIPPED; 266 $backupcourse->laststarttime = time() - 2 * DAYSECS; 267 $backupcourse->lastendtime = time() - 1 * DAYSECS; 268 $DB->insert_record('backup_courses', $backupcourse); 269 $backupcourse = $DB->get_record('backup_courses', array('courseid' => $this->course->id)); 270 $course = $DB->get_record('course', array('id' => $this->course->id)); 271 272 $course->timemodified = time() - 2 * DAYSECS - 1; 273 274 $classobject = $this->backupcronautomatedhelper->return_this(); 275 $nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time()); 276 277 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup'); 278 $method->setAccessible(true); // Allow accessing of private method. 279 $skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]); 280 281 $this->assertTrue($skipped); 282 $this->expectOutputRegex('/Skipping course id ' . $this->course->id . ': Not modified since previous backup/'); 283 } 284 285 /** 286 * Test the task completes when coureid is missing. 287 */ 288 public function test_task_complete_when_courseid_is_missing() { 289 global $DB; 290 $admin = get_admin(); 291 $classobject = $this->backupcronautomatedhelper->return_this(); 292 293 // Create this backup course. 294 $backupcourse = new \stdClass; 295 $backupcourse->courseid = $this->course->id; 296 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_NOTYETRUN; 297 $DB->insert_record('backup_courses', $backupcourse); 298 $backupcourse = $DB->get_record('backup_courses', ['courseid' => $this->course->id]); 299 300 // Create a backup task. 301 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'push_course_backup_adhoc_task'); 302 $method->setAccessible(true); // Allow accessing of private method. 303 $method->invokeArgs($classobject, [$backupcourse, $admin]); 304 305 // Delete course for this test. 306 delete_course($this->course->id, false); 307 308 $task = \core\task\manager::get_next_adhoc_task(time()); 309 310 ob_start(); 311 $task->execute(); 312 $output = ob_get_clean(); 313 314 $this->assertStringContainsString('Invalid course id: ' . $this->course->id . ', task aborted.', $output); 315 \core\task\manager::adhoc_task_complete($task); 316 } 317 318 /** 319 * Test the task completes when backup course is missing. 320 */ 321 public function test_task_complete_when_backup_course_is_missing() { 322 global $DB; 323 $admin = get_admin(); 324 $classobject = $this->backupcronautomatedhelper->return_this(); 325 326 // Create this backup course. 327 $backupcourse = new \stdClass; 328 $backupcourse->courseid = $this->course->id; 329 $backupcourse->laststatus = backup_cron_automated_helper::BACKUP_STATUS_NOTYETRUN; 330 $DB->insert_record('backup_courses', $backupcourse); 331 $backupcourse = $DB->get_record('backup_courses', ['courseid' => $this->course->id]); 332 333 // Create a backup task. 334 $method = new \ReflectionMethod('\backup_cron_automated_helper', 'push_course_backup_adhoc_task'); 335 $method->setAccessible(true); // Allow accessing of private method. 336 $method->invokeArgs($classobject, [$backupcourse, $admin]); 337 338 // Delete backup course for this test. 339 $DB->delete_records('backup_courses', ['courseid' => $this->course->id]); 340 341 $task = \core\task\manager::get_next_adhoc_task(time()); 342 343 ob_start(); 344 $task->execute(); 345 $output = ob_get_clean(); 346 347 $this->assertStringContainsString('Automated backup for course: ' . $this->course->fullname . ' encounters an error.', 348 $output); 349 \core\task\manager::adhoc_task_complete($task); 350 } 351 } 352 353 /** 354 * New backup_cron_automated_helper class for testing. 355 * 356 * This class extends the helper backup_cron_automated_helper class 357 * in order to utilise abstract class for testing. 358 * 359 * @package core 360 * @copyright 2019 John Yao <johnyao@catalyst-au.net> 361 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 362 */ 363 class test_backup_cron_automated_helper extends backup_cron_automated_helper { 364 /** 365 * Returning this for testing. 366 */ 367 public function return_this() { 368 return $this; 369 } 370 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body