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