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