Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 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 namespace core\task; 18 19 defined('MOODLE_INTERNAL') || die(); 20 require_once (__DIR__ . '/../fixtures/task_fixtures.php'); 21 22 /** 23 * Test class for scheduled task. 24 * 25 * @package core 26 * @category test 27 * @copyright 2013 Damyon Wiese 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 */ 30 class scheduled_task_test extends \advanced_testcase { 31 32 /** 33 * Test the cron scheduling method 34 */ 35 public function test_eval_cron_field() { 36 $testclass = new scheduled_test_task(); 37 38 $this->assertEquals(20, count($testclass->eval_cron_field('*/3', 0, 59))); 39 $this->assertEquals(31, count($testclass->eval_cron_field('1,*/2', 0, 59))); 40 $this->assertEquals(15, count($testclass->eval_cron_field('1-10,5-15', 0, 59))); 41 $this->assertEquals(13, count($testclass->eval_cron_field('1-10,5-15/2', 0, 59))); 42 $this->assertEquals(3, count($testclass->eval_cron_field('1,2,3,1,2,3', 0, 59))); 43 $this->assertEquals(1, count($testclass->eval_cron_field('-1,10,80', 0, 59))); 44 } 45 46 public function test_get_next_scheduled_time() { 47 global $CFG; 48 $this->resetAfterTest(); 49 50 $this->setTimezone('Europe/London'); 51 52 // Let's specify the hour we are going to use initially for the test. 53 // (note that we pick 01:00 that is tricky for Europe/London, because 54 // it's exactly the Daylight Saving Time Begins hour. 55 $testhour = 1; 56 57 // Test job run at 1 am. 58 $testclass = new scheduled_test_task(); 59 60 // All fields default to '*'. 61 $testclass->set_hour($testhour); 62 $testclass->set_minute('0'); 63 // Next valid time should be 1am of the next day. 64 $nexttime = $testclass->get_next_scheduled_time(); 65 66 $oneamdate = new \DateTime('now', new \DateTimeZone('Europe/London')); 67 $oneamdate->setTime($testhour, 0, 0); 68 69 // Once a year (currently last Sunday of March), when changing to Daylight Saving Time, 70 // Europe/London 01:00 simply doesn't exists because, exactly at 01:00 the clock 71 // is advanced by one hour and becomes 02:00. When that happens, the DateInterval 72 // calculations cannot be to advance by 1 day, but by one less hour. That is exactly when 73 // the next scheduled run will happen (next day 01:00). 74 $isdaylightsaving = false; 75 if ($testhour < (int)$oneamdate->format('H')) { 76 $isdaylightsaving = true; 77 } 78 79 // Make it 1 am tomorrow if the time is after 1am. 80 if ($oneamdate->getTimestamp() < time()) { 81 $oneamdate->add(new \DateInterval('P1D')); 82 if ($isdaylightsaving) { 83 // If today is Europe/London Daylight Saving Time Begins, expectation is 1 less hour. 84 $oneamdate->sub(new \DateInterval('PT1H')); 85 } 86 } 87 $oneam = $oneamdate->getTimestamp(); 88 89 $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); 90 91 // Disabled flag does not affect next time. 92 $testclass->set_disabled(true); 93 $nexttime = $testclass->get_next_scheduled_time(); 94 $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); 95 96 // Now test for job run every 10 minutes. 97 $testclass = new scheduled_test_task(); 98 99 // All fields default to '*'. 100 $testclass->set_minute('*/10'); 101 // Next valid time should be next 10 minute boundary. 102 $nexttime = $testclass->get_next_scheduled_time(); 103 104 $minutes = ((intval(date('i') / 10))+1) * 10; 105 $nexttenminutes = mktime(date('H'), $minutes, 0); 106 107 $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); 108 109 // Disabled flag does not affect next time. 110 $testclass->set_disabled(true); 111 $nexttime = $testclass->get_next_scheduled_time(); 112 $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); 113 114 // Test hourly job executed on Sundays only. 115 $testclass = new scheduled_test_task(); 116 $testclass->set_minute('0'); 117 $testclass->set_day_of_week('7'); 118 119 $nexttime = $testclass->get_next_scheduled_time(); 120 121 $this->assertEquals(7, date('N', $nexttime)); 122 $this->assertEquals(0, date('i', $nexttime)); 123 124 // Test monthly job. 125 $testclass = new scheduled_test_task(); 126 $testclass->set_minute('32'); 127 $testclass->set_hour('0'); 128 $testclass->set_day('1'); 129 130 $nexttime = $testclass->get_next_scheduled_time(); 131 132 $this->assertEquals(32, date('i', $nexttime)); 133 $this->assertEquals(0, date('G', $nexttime)); 134 $this->assertEquals(1, date('j', $nexttime)); 135 } 136 137 public function test_timezones() { 138 global $CFG, $USER; 139 140 // The timezones used in this test are chosen because they do not use DST - that would break the test. 141 $this->resetAfterTest(); 142 143 $this->setTimezone('Asia/Kabul'); 144 145 $testclass = new scheduled_test_task(); 146 147 // Scheduled tasks should always use servertime - so this is 03:30 GMT. 148 $testclass->set_hour('1'); 149 $testclass->set_minute('0'); 150 151 // Next valid time should be 1am of the next day. 152 $nexttime = $testclass->get_next_scheduled_time(); 153 154 // GMT+05:45. 155 $USER->timezone = 'Asia/Kathmandu'; 156 $userdate = userdate($nexttime); 157 158 // Should be displayed in user timezone. 159 // I used http://www.timeanddate.com/worldclock/fixedtime.html?msg=Moodle+Test&iso=20160502T01&p1=113 160 // setting my location to Kathmandu to verify this time. 161 $this->assertStringContainsString('2:15 AM', \core_text::strtoupper($userdate)); 162 } 163 164 public function test_reset_scheduled_tasks_for_component_customised(): void { 165 $this->resetAfterTest(true); 166 167 $tasks = manager::load_scheduled_tasks_for_component('moodle'); 168 169 // Customise a task. 170 $task = reset($tasks); 171 $task->set_minute('1'); 172 $task->set_hour('2'); 173 $task->set_day('3'); 174 $task->set_month('4'); 175 $task->set_day_of_week('5'); 176 $task->set_customised('1'); 177 manager::configure_scheduled_task($task); 178 179 // Now call reset. 180 manager::reset_scheduled_tasks_for_component('moodle'); 181 182 // Fetch the task again. 183 $taskafterreset = manager::get_scheduled_task(get_class($task)); 184 185 // The task should still be the same as the customised. 186 $this->assertTaskEquals($task, $taskafterreset); 187 } 188 189 public function test_reset_scheduled_tasks_for_component_deleted(): void { 190 global $DB; 191 $this->resetAfterTest(true); 192 193 // Delete a task to simulate the fact that its new. 194 $tasklist = manager::load_scheduled_tasks_for_component('moodle'); 195 196 // Note: This test must use a task which does not use any random values. 197 $task = manager::get_scheduled_task(session_cleanup_task::class); 198 199 $DB->delete_records('task_scheduled', array('classname' => '\\' . trim(get_class($task), '\\'))); 200 $this->assertFalse(manager::get_scheduled_task(session_cleanup_task::class)); 201 202 // Now call reset on all the tasks. 203 manager::reset_scheduled_tasks_for_component('moodle'); 204 205 // Assert that the second task was added back. 206 $taskafterreset = manager::get_scheduled_task(session_cleanup_task::class); 207 $this->assertNotFalse($taskafterreset); 208 209 $this->assertTaskEquals($task, $taskafterreset); 210 $this->assertCount(count($tasklist), manager::load_scheduled_tasks_for_component('moodle')); 211 } 212 213 public function test_reset_scheduled_tasks_for_component_changed_in_source(): void { 214 $this->resetAfterTest(true); 215 216 // Delete a task to simulate the fact that its new. 217 // Note: This test must use a task which does not use any random values. 218 $task = manager::get_scheduled_task(session_cleanup_task::class); 219 220 // Get a copy of the task before maing changes for later comparison. 221 $taskbeforechange = manager::get_scheduled_task(session_cleanup_task::class); 222 223 // Edit a task to simulate a change in its definition (as if it was not customised). 224 $task->set_minute('1'); 225 $task->set_hour('2'); 226 $task->set_day('3'); 227 $task->set_month('4'); 228 $task->set_day_of_week('5'); 229 manager::configure_scheduled_task($task); 230 231 // Fetch the task out for comparison. 232 $taskafterchange = manager::get_scheduled_task(session_cleanup_task::class); 233 234 // The task should now be different to the original. 235 $this->assertTaskNotEquals($taskbeforechange, $taskafterchange); 236 237 // Now call reset. 238 manager::reset_scheduled_tasks_for_component('moodle'); 239 240 // Fetch the task again. 241 $taskafterreset = manager::get_scheduled_task(session_cleanup_task::class); 242 243 // The task should now be the same as the original. 244 $this->assertTaskEquals($taskbeforechange, $taskafterreset); 245 } 246 247 /** 248 * Tests that the reset function deletes old tasks. 249 */ 250 public function test_reset_scheduled_tasks_for_component_delete() { 251 global $DB; 252 $this->resetAfterTest(true); 253 254 $count = $DB->count_records('task_scheduled', array('component' => 'moodle')); 255 $allcount = $DB->count_records('task_scheduled'); 256 257 $task = new scheduled_test_task(); 258 $task->set_component('moodle'); 259 $record = manager::record_from_scheduled_task($task); 260 $DB->insert_record('task_scheduled', $record); 261 $this->assertTrue($DB->record_exists('task_scheduled', array('classname' => '\core\task\scheduled_test_task', 262 'component' => 'moodle'))); 263 264 $task = new scheduled_test2_task(); 265 $task->set_component('moodle'); 266 $record = manager::record_from_scheduled_task($task); 267 $DB->insert_record('task_scheduled', $record); 268 $this->assertTrue($DB->record_exists('task_scheduled', array('classname' => '\core\task\scheduled_test2_task', 269 'component' => 'moodle'))); 270 271 $aftercount = $DB->count_records('task_scheduled', array('component' => 'moodle')); 272 $afterallcount = $DB->count_records('task_scheduled'); 273 274 $this->assertEquals($count + 2, $aftercount); 275 $this->assertEquals($allcount + 2, $afterallcount); 276 277 // Now check that the right things were deleted. 278 manager::reset_scheduled_tasks_for_component('moodle'); 279 280 $this->assertEquals($count, $DB->count_records('task_scheduled', array('component' => 'moodle'))); 281 $this->assertEquals($allcount, $DB->count_records('task_scheduled')); 282 $this->assertFalse($DB->record_exists('task_scheduled', array('classname' => '\core\task\scheduled_test2_task', 283 'component' => 'moodle'))); 284 $this->assertFalse($DB->record_exists('task_scheduled', array('classname' => '\core\task\scheduled_test_task', 285 'component' => 'moodle'))); 286 } 287 288 public function test_get_next_scheduled_task() { 289 global $DB; 290 291 $this->resetAfterTest(true); 292 // Delete all existing scheduled tasks. 293 $DB->delete_records('task_scheduled'); 294 // Add a scheduled task. 295 296 // A task that runs once per hour. 297 $record = new \stdClass(); 298 $record->blocking = true; 299 $record->minute = '0'; 300 $record->hour = '0'; 301 $record->dayofweek = '*'; 302 $record->day = '*'; 303 $record->month = '*'; 304 $record->component = 'test_scheduled_task'; 305 $record->classname = '\core\task\scheduled_test_task'; 306 307 $DB->insert_record('task_scheduled', $record); 308 // And another one to test failures. 309 $record->classname = '\core\task\scheduled_test2_task'; 310 $DB->insert_record('task_scheduled', $record); 311 // And disabled test. 312 $record->classname = '\core\task\scheduled_test3_task'; 313 $record->disabled = 1; 314 $DB->insert_record('task_scheduled', $record); 315 316 $now = time(); 317 318 // Should get handed the first task. 319 $task = manager::get_next_scheduled_task($now); 320 $this->assertInstanceOf('\core\task\scheduled_test_task', $task); 321 $task->execute(); 322 323 manager::scheduled_task_complete($task); 324 // Should get handed the second task. 325 $task = manager::get_next_scheduled_task($now); 326 $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); 327 $task->execute(); 328 329 manager::scheduled_task_failed($task); 330 // Should not get any task. 331 $task = manager::get_next_scheduled_task($now); 332 $this->assertNull($task); 333 334 // Should get the second task (retry after delay). 335 $task = manager::get_next_scheduled_task($now + 120); 336 $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); 337 $task->execute(); 338 339 manager::scheduled_task_complete($task); 340 341 // Should not get any task. 342 $task = manager::get_next_scheduled_task($now); 343 $this->assertNull($task); 344 345 // Check ordering. 346 $DB->delete_records('task_scheduled'); 347 $record->lastruntime = 2; 348 $record->disabled = 0; 349 $record->classname = '\core\task\scheduled_test_task'; 350 $DB->insert_record('task_scheduled', $record); 351 352 $record->lastruntime = 1; 353 $record->classname = '\core\task\scheduled_test2_task'; 354 $DB->insert_record('task_scheduled', $record); 355 356 // Should get handed the second task. 357 $task = manager::get_next_scheduled_task($now); 358 $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); 359 $task->execute(); 360 manager::scheduled_task_complete($task); 361 362 // Should get handed the first task. 363 $task = manager::get_next_scheduled_task($now); 364 $this->assertInstanceOf('\core\task\scheduled_test_task', $task); 365 $task->execute(); 366 manager::scheduled_task_complete($task); 367 368 // Should not get any task. 369 $task = manager::get_next_scheduled_task($now); 370 $this->assertNull($task); 371 } 372 373 public function test_get_broken_scheduled_task() { 374 global $DB; 375 376 $this->resetAfterTest(true); 377 // Delete all existing scheduled tasks. 378 $DB->delete_records('task_scheduled'); 379 // Add a scheduled task. 380 381 // A broken task that runs all the time. 382 $record = new \stdClass(); 383 $record->blocking = true; 384 $record->minute = '*'; 385 $record->hour = '*'; 386 $record->dayofweek = '*'; 387 $record->day = '*'; 388 $record->month = '*'; 389 $record->component = 'test_scheduled_task'; 390 $record->classname = '\core\task\scheduled_test_task_broken'; 391 392 $DB->insert_record('task_scheduled', $record); 393 394 $now = time(); 395 // Should not get any task. 396 $task = manager::get_next_scheduled_task($now); 397 $this->assertDebuggingCalled(); 398 $this->assertNull($task); 399 } 400 401 /** 402 * Tests the use of 'R' syntax in time fields of tasks to get 403 * tasks be configured with a non-uniform time. 404 */ 405 public function test_random_time_specification() { 406 407 // Testing non-deterministic things in a unit test is not really 408 // wise, so we just test the values have changed within allowed bounds. 409 $testclass = new scheduled_test_task(); 410 411 // The test task defaults to '*'. 412 $this->assertIsString($testclass->get_minute()); 413 $this->assertIsString($testclass->get_hour()); 414 415 // Set a random value. 416 $testclass->set_minute('R'); 417 $testclass->set_hour('R'); 418 $testclass->set_day_of_week('R'); 419 420 // Verify the minute has changed within allowed bounds. 421 $minute = $testclass->get_minute(); 422 $this->assertIsInt($minute); 423 $this->assertGreaterThanOrEqual(0, $minute); 424 $this->assertLessThanOrEqual(59, $minute); 425 426 // Verify the hour has changed within allowed bounds. 427 $hour = $testclass->get_hour(); 428 $this->assertIsInt($hour); 429 $this->assertGreaterThanOrEqual(0, $hour); 430 $this->assertLessThanOrEqual(23, $hour); 431 432 // Verify the dayofweek has changed within allowed bounds. 433 $dayofweek = $testclass->get_day_of_week(); 434 $this->assertIsInt($dayofweek); 435 $this->assertGreaterThanOrEqual(0, $dayofweek); 436 $this->assertLessThanOrEqual(6, $dayofweek); 437 } 438 439 /** 440 * Test that the file_temp_cleanup_task removes directories and 441 * files as expected. 442 */ 443 public function test_file_temp_cleanup_task() { 444 global $CFG; 445 $backuptempdir = make_backup_temp_directory(''); 446 447 // Create directories. 448 $dir = $backuptempdir . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . 'courses'; 449 mkdir($dir, 0777, true); 450 451 // Create files to be checked and then deleted. 452 $file01 = $dir . DIRECTORY_SEPARATOR . 'sections.xml'; 453 file_put_contents($file01, 'test data 001'); 454 $file02 = $dir . DIRECTORY_SEPARATOR . 'modules.xml'; 455 file_put_contents($file02, 'test data 002'); 456 // Change the time modified for the first file, to a time that will be deleted by the task (greater than seven days). 457 touch($file01, time() - (8 * 24 * 3600)); 458 459 $task = manager::get_scheduled_task('\\core\\task\\file_temp_cleanup_task'); 460 $this->assertInstanceOf('\core\task\file_temp_cleanup_task', $task); 461 $task->execute(); 462 463 // Scan the directory. Only modules.xml should be left. 464 $filesarray = scandir($dir); 465 $this->assertEquals('modules.xml', $filesarray[2]); 466 $this->assertEquals(3, count($filesarray)); 467 468 // Change the time modified on modules.xml. 469 touch($file02, time() - (8 * 24 * 3600)); 470 // Change the time modified on the courses directory. 471 touch($backuptempdir . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . 472 'courses', time() - (8 * 24 * 3600)); 473 // Run the scheduled task to remove the file and directory. 474 $task->execute(); 475 $filesarray = scandir($backuptempdir . DIRECTORY_SEPARATOR . 'backup01'); 476 // There should only be two items in the array, '.' and '..'. 477 $this->assertEquals(2, count($filesarray)); 478 479 // Change the time modified on all of the files and directories. 480 $dir = new \RecursiveDirectoryIterator($CFG->tempdir); 481 // Show all child nodes prior to their parent. 482 $iter = new \RecursiveIteratorIterator($dir, \RecursiveIteratorIterator::CHILD_FIRST); 483 484 for ($iter->rewind(); $iter->valid(); $iter->next()) { 485 if ($iter->isDir() && !$iter->isDot()) { 486 $node = $iter->getRealPath(); 487 touch($node, time() - (8 * 24 * 3600)); 488 } 489 } 490 491 // Run the scheduled task again to remove all of the files and directories. 492 $task->execute(); 493 $filesarray = scandir($CFG->tempdir); 494 // All of the files and directories should be deleted. 495 // There should only be three items in the array, '.', '..' and '.htaccess'. 496 $this->assertEquals([ '.', '..', '.htaccess' ], $filesarray); 497 } 498 499 /** 500 * Test that the function to clear the fail delay from a task works correctly. 501 */ 502 public function test_clear_fail_delay() { 503 504 $this->resetAfterTest(); 505 506 // Get an example task to use for testing. Task is set to run every minute by default. 507 $taskname = '\core\task\send_new_user_passwords_task'; 508 509 // Pretend task started running and then failed 3 times. 510 $before = time(); 511 $cronlockfactory = \core\lock\lock_config::get_lock_factory('cron'); 512 for ($i = 0; $i < 3; $i ++) { 513 $task = manager::get_scheduled_task($taskname); 514 $lock = $cronlockfactory->get_lock('\\' . get_class($task), 10); 515 $task->set_lock($lock); 516 manager::scheduled_task_failed($task); 517 } 518 519 // Confirm task is now delayed by several minutes. 520 $task = manager::get_scheduled_task($taskname); 521 $this->assertEquals(240, $task->get_fail_delay()); 522 $this->assertGreaterThan($before + 230, $task->get_next_run_time()); 523 524 // Clear the fail delay and re-get the task. 525 manager::clear_fail_delay($task); 526 $task = manager::get_scheduled_task($taskname); 527 528 // There should be no delay and it should run within the next minute. 529 $this->assertEquals(0, $task->get_fail_delay()); 530 $this->assertLessThan($before + 70, $task->get_next_run_time()); 531 } 532 533 /** 534 * Data provider for test_tool_health_category_find_missing_parents. 535 */ 536 public static function provider_schedule_overrides(): array { 537 return array( 538 array( 539 'scheduled_tasks' => array( 540 '\core\task\scheduled_test_task' => array( 541 'schedule' => '10 13 1 2 4', 542 'disabled' => 0, 543 ), 544 '\core\task\scheduled_test2_task' => array( 545 'schedule' => '* * * * *', 546 'disabled' => 1, 547 ), 548 ), 549 'task_full_classnames' => array( 550 '\core\task\scheduled_test_task', 551 '\core\task\scheduled_test2_task', 552 ), 553 'expected' => array( 554 '\core\task\scheduled_test_task' => array( 555 'min' => '10', 556 'hour' => '13', 557 'day' => '1', 558 'month' => '2', 559 'week' => '4', 560 'disabled' => 0, 561 ), 562 '\core\task\scheduled_test2_task' => array( 563 'min' => '*', 564 'hour' => '*', 565 'day' => '*', 566 'month' => '*', 567 'week' => '*', 568 'disabled' => 1, 569 ), 570 ) 571 ), 572 array( 573 'scheduled_tasks' => array( 574 '\core\task\*' => array( 575 'schedule' => '1 2 3 4 5', 576 'disabled' => 0, 577 ) 578 ), 579 'task_full_classnames' => array( 580 '\core\task\scheduled_test_task', 581 '\core\task\scheduled_test2_task', 582 ), 583 'expected' => array( 584 '\core\task\scheduled_test_task' => array( 585 'min' => '1', 586 'hour' => '2', 587 'day' => '3', 588 'month' => '4', 589 'week' => '5', 590 'disabled' => 0, 591 ), 592 '\core\task\scheduled_test2_task' => array( 593 'min' => '1', 594 'hour' => '2', 595 'day' => '3', 596 'month' => '4', 597 'week' => '5', 598 'disabled' => 0, 599 ), 600 ) 601 ) 602 ); 603 } 604 605 606 /** 607 * Test to ensure scheduled tasks are updated by values set in config. 608 * 609 * @param array $overrides 610 * @param array $tasks 611 * @param array $expected 612 * @dataProvider provider_schedule_overrides 613 */ 614 public function test_scheduled_task_override_values(array $overrides, array $tasks, array $expected): void { 615 global $CFG, $DB; 616 617 $this->resetAfterTest(); 618 619 // Add overrides to the config. 620 $CFG->scheduled_tasks = $overrides; 621 622 // Set up test scheduled task record. 623 $record = new \stdClass(); 624 $record->component = 'test_scheduled_task'; 625 626 foreach ($tasks as $task) { 627 $record->classname = $task; 628 $DB->insert_record('task_scheduled', $record); 629 630 $scheduledtask = manager::get_scheduled_task($task); 631 $expectedresults = $expected[$task]; 632 633 // Check that the task is actually overridden. 634 $this->assertTrue($scheduledtask->is_overridden(), 'Is overridden'); 635 636 // Check minute is correct. 637 $this->assertEquals($expectedresults['min'], $scheduledtask->get_minute(), 'Minute check'); 638 639 // Check day is correct. 640 $this->assertEquals($expectedresults['day'], $scheduledtask->get_day(), 'Day check'); 641 642 // Check hour is correct. 643 $this->assertEquals($expectedresults['hour'], $scheduledtask->get_hour(), 'Hour check'); 644 645 // Check week is correct. 646 $this->assertEquals($expectedresults['week'], $scheduledtask->get_day_of_week(), 'Day of week check'); 647 648 // Check week is correct. 649 $this->assertEquals($expectedresults['month'], $scheduledtask->get_month(), 'Month check'); 650 651 // Check to see if the task is disabled. 652 $this->assertEquals($expectedresults['disabled'], $scheduledtask->get_disabled(), 'Disabled check'); 653 } 654 } 655 656 /** 657 * Check that an overridden task is sent to be processed. 658 */ 659 public function test_scheduled_task_overridden_task_can_run(): void { 660 global $CFG, $DB; 661 662 $this->resetAfterTest(); 663 664 // Delete all existing scheduled tasks. 665 $DB->delete_records('task_scheduled'); 666 667 // Add overrides to the config. 668 $CFG->scheduled_tasks = [ 669 '\core\task\scheduled_test_task' => [ 670 'disabled' => 1 671 ], 672 '\core\task\scheduled_test2_task' => [ 673 'disabled' => 0 674 ], 675 ]; 676 677 // A task that runs once per hour. 678 $record = new \stdClass(); 679 $record->component = 'test_scheduled_task'; 680 $record->classname = '\core\task\scheduled_test_task'; 681 $record->disabled = 0; 682 $DB->insert_record('task_scheduled', $record); 683 684 // And disabled test. 685 $record->classname = '\core\task\scheduled_test2_task'; 686 $record->disabled = 1; 687 $DB->insert_record('task_scheduled', $record); 688 689 $now = time(); 690 691 $scheduledtask = manager::get_next_scheduled_task($now); 692 $this->assertInstanceOf('\core\task\scheduled_test2_task', $scheduledtask); 693 $scheduledtask->execute(); 694 manager::scheduled_task_complete($scheduledtask); 695 } 696 697 /** 698 * Assert that the specified tasks are equal. 699 * 700 * @param \core\task\task_base $task 701 * @param \core\task\task_base $comparisontask 702 */ 703 public function assertTaskEquals(task_base $task, task_base $comparisontask): void { 704 // Convert both to an object. 705 $task = manager::record_from_scheduled_task($task); 706 $comparisontask = manager::record_from_scheduled_task($comparisontask); 707 708 // Reset the nextruntime field as it is intentionally dynamic. 709 $task->nextruntime = null; 710 $comparisontask->nextruntime = null; 711 712 $args = array_merge( 713 [ 714 $task, 715 $comparisontask, 716 ], 717 array_slice(func_get_args(), 2) 718 ); 719 720 call_user_func_array([$this, 'assertEquals'], $args); 721 } 722 723 /** 724 * Assert that the specified tasks are not equal. 725 * 726 * @param \core\task\task_base $task 727 * @param \core\task\task_base $comparisontask 728 */ 729 public function assertTaskNotEquals(task_base $task, task_base $comparisontask): void { 730 // Convert both to an object. 731 $task = manager::record_from_scheduled_task($task); 732 $comparisontask = manager::record_from_scheduled_task($comparisontask); 733 734 // Reset the nextruntime field as it is intentionally dynamic. 735 $task->nextruntime = null; 736 $comparisontask->nextruntime = null; 737 738 $args = array_merge( 739 [ 740 $task, 741 $comparisontask, 742 ], 743 array_slice(func_get_args(), 2) 744 ); 745 746 call_user_func_array([$this, 'assertNotEquals'], $args); 747 } 748 749 /** 750 * Assert that the lastruntime column holds an original value after a scheduled task is reset. 751 */ 752 public function test_reset_scheduled_tasks_for_component_keeps_original_lastruntime(): void { 753 global $DB; 754 $this->resetAfterTest(true); 755 756 // Set lastruntime for the scheduled task. 757 $DB->set_field('task_scheduled', 'lastruntime', 123456789, ['classname' => '\core\task\session_cleanup_task']); 758 759 // Reset the task. 760 manager::reset_scheduled_tasks_for_component('moodle'); 761 762 // Fetch the task again. 763 $taskafterreset = manager::get_scheduled_task(session_cleanup_task::class); 764 765 // Confirm, that lastruntime is still in place. 766 $this->assertEquals(123456789, $taskafterreset->get_last_run_time()); 767 } 768 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body