Differences Between: [Versions 311 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 namespace core\task; 18 19 defined('MOODLE_INTERNAL') || die(); 20 require_once (__DIR__ . '/../fixtures/task_fixtures.php'); 21 22 23 /** 24 * Test class for adhoc tasks. 25 * 26 * @package core 27 * @category test 28 * @copyright 2013 Damyon Wiese 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 * @coversDefaultClass \core\task\manager 31 */ 32 class adhoc_task_test extends \advanced_testcase { 33 34 /** 35 * Test getting name of task that implements it's own get_name method 36 * 37 * @covers \core\task\adhoc_task::get_name 38 */ 39 public function test_get_name(): void { 40 $task = new \core\task\adhoc_test_task(); 41 $this->assertEquals('Test adhoc class', $task->get_name()); 42 } 43 44 /** 45 * Test getting name of task that uses the default implementation of get_name 46 * 47 * @covers \core\task\adhoc_task::get_name 48 */ 49 public function test_get_name_default(): void { 50 $task = new \mod_fake\task\adhoc_component_task(); 51 $this->assertEquals('Adhoc component task', $task->get_name()); 52 } 53 54 /** 55 * Test basic adhoc task execution. 56 * 57 * @covers ::get_next_adhoc_task 58 */ 59 public function test_get_next_adhoc_task_now() { 60 $this->resetAfterTest(true); 61 62 // Create an adhoc task. 63 $task = new adhoc_test_task(); 64 65 // Queue it. 66 manager::queue_adhoc_task($task); 67 68 $now = time(); 69 // Get it from the scheduler. 70 $task = manager::get_next_adhoc_task($now); 71 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 72 $task->execute(); 73 manager::adhoc_task_complete($task); 74 } 75 76 /** 77 * Test basic adhoc task execution. 78 * 79 * @covers ::get_next_adhoc_task 80 */ 81 public function test_get_next_adhoc_task_class() { 82 $this->resetAfterTest(true); 83 84 // Create an adhoc task. 85 $task = new \core\task\adhoc_test_task(); 86 87 // Queue it. 88 manager::queue_adhoc_task($task); 89 90 $now = time(); 91 $classname = get_class($task); 92 93 // The task will not be returned. 94 $this->assertNull(manager::get_next_adhoc_task($now, true, "{$classname}notexists")); 95 96 // Get it from the scheduler. 97 $task = manager::get_next_adhoc_task($now, true, $classname); 98 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 99 $task->execute(); 100 manager::adhoc_task_complete($task); 101 } 102 103 /** 104 * Test adhoc task failure retry backoff. 105 * 106 * @covers ::get_next_adhoc_task 107 * @covers ::get_adhoc_task 108 */ 109 public function test_get_next_adhoc_task_fail_retry() { 110 $this->resetAfterTest(true); 111 112 // Create an adhoc task. 113 $task = new adhoc_test_task(); 114 manager::queue_adhoc_task($task); 115 116 $now = time(); 117 118 // Get it from the scheduler, execute it, and mark it as failed. 119 $task = manager::get_next_adhoc_task($now); 120 $taskid = $task->get_id(); 121 $task->execute(); 122 manager::adhoc_task_failed($task); 123 124 // The task will not be returned immediately. 125 $this->assertNull(manager::get_next_adhoc_task($now)); 126 127 // Should get the adhoc task (retry after delay). Fail it again. 128 $task = manager::get_next_adhoc_task($now + 120); 129 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 130 $this->assertEquals($taskid, $task->get_id()); 131 $task->execute(); 132 manager::adhoc_task_failed($task); 133 134 // Should get the adhoc task immediately. 135 $task = manager::get_adhoc_task($taskid); 136 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 137 $this->assertEquals($taskid, $task->get_id()); 138 $task->execute(); 139 manager::adhoc_task_complete($task); 140 141 // Should not get any task. 142 $this->assertNull(manager::get_next_adhoc_task($now)); 143 } 144 145 /** 146 * Test future adhoc task execution. 147 * @covers ::get_next_adhoc_task 148 */ 149 public function test_get_next_adhoc_task_future() { 150 $this->resetAfterTest(true); 151 152 $now = time(); 153 // Create an adhoc task in future. 154 $task = new adhoc_test_task(); 155 $task->set_next_run_time($now + 1000); 156 manager::queue_adhoc_task($task); 157 158 // Fetching the next task should not return anything. 159 $this->assertNull(manager::get_next_adhoc_task($now)); 160 161 // Fetching in the future should return the task. 162 $task = manager::get_next_adhoc_task($now + 1020); 163 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 164 $task->execute(); 165 manager::adhoc_task_complete($task); 166 } 167 168 /** 169 * Test queueing an adhoc task belonging to a component, where we set the task component accordingly 170 * @covers ::queue_adhoc_task 171 */ 172 public function test_queue_adhoc_task_for_component(): void { 173 $this->resetAfterTest(); 174 175 $task = new \mod_forum\task\send_user_digests(); 176 $task->set_component('mod_test'); 177 178 manager::queue_adhoc_task($task); 179 $this->assertDebuggingNotCalled(); 180 } 181 182 /** 183 * Test queueing an adhoc task belonging to a component, where we do not set the task component 184 * @covers ::queue_adhoc_task 185 */ 186 public function test_queue_task_for_component_without_set_component(): void { 187 $this->resetAfterTest(); 188 189 $task = new \mod_forum\task\send_user_digests(); 190 191 manager::queue_adhoc_task($task); 192 $this->assertDebuggingNotCalled(); 193 194 // Assert the missing component was set. 195 $this->assertEquals('mod_forum', $task->get_component()); 196 } 197 198 /** 199 * Test queueing an adhoc task belonging to an invalid component, where we do not set the task component 200 * @covers ::queue_adhoc_task 201 */ 202 public function test_queue_task_for_invalid_component_without_set_component(): void { 203 $this->resetAfterTest(); 204 205 $task = new \mod_fake\task\adhoc_component_task(); 206 207 manager::queue_adhoc_task($task); 208 $this->assertDebuggingCalled('Component not set and the class namespace does not match a valid component (mod_fake).'); 209 } 210 211 /** 212 * Test empty set of adhoc tasks 213 * @covers ::get_adhoc_tasks 214 */ 215 public function test_get_adhoc_tasks_empty_set() { 216 $this->resetAfterTest(true); 217 218 $this->assertEquals([], manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task')); 219 } 220 221 /** 222 * Test correct set of adhoc tasks is returned for class. 223 * @covers ::get_adhoc_tasks 224 */ 225 public function test_get_adhoc_tasks_result_set() { 226 $this->resetAfterTest(true); 227 228 for ($i = 0; $i < 3; $i++) { 229 $task = new adhoc_test_task(); 230 manager::queue_adhoc_task($task); 231 } 232 233 for ($i = 0; $i < 3; $i++) { 234 $task = new adhoc_test2_task(); 235 manager::queue_adhoc_task($task); 236 } 237 238 $adhoctests = manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task'); 239 $adhoctest2s = manager::get_adhoc_tasks('\\core\\task\\adhoc_test2_task'); 240 241 $this->assertCount(3, $adhoctests); 242 $this->assertCount(3, $adhoctest2s); 243 244 foreach ($adhoctests as $task) { 245 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 246 } 247 248 foreach ($adhoctest2s as $task) { 249 $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task); 250 } 251 } 252 253 /** 254 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if no tasks exist. 255 * @covers ::reschedule_or_queue_adhoc_task 256 */ 257 public function test_reschedule_or_queue_adhoc_task_no_existing() { 258 $this->resetAfterTest(true); 259 260 // Schedule adhoc task. 261 $task = new adhoc_test_task(); 262 $task->set_custom_data(['courseid' => 10]); 263 manager::reschedule_or_queue_adhoc_task($task); 264 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 265 } 266 267 /** 268 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task for the same user does 269 * not exist. 270 * @covers ::reschedule_or_queue_adhoc_task 271 */ 272 public function test_reschedule_or_queue_adhoc_task_different_user() { 273 $this->resetAfterTest(true); 274 $user = \core_user::get_user_by_username('admin'); 275 276 // Schedule adhoc task. 277 $task = new adhoc_test_task(); 278 $task->set_custom_data(['courseid' => 10]); 279 manager::reschedule_or_queue_adhoc_task($task); 280 281 // Schedule adhoc task for a different user. 282 $task = new adhoc_test_task(); 283 $task->set_custom_data(['courseid' => 10]); 284 $task->set_userid($user->id); 285 manager::reschedule_or_queue_adhoc_task($task); 286 287 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 288 } 289 290 /** 291 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task with different custom 292 * data exists. 293 * @covers ::reschedule_or_queue_adhoc_task 294 */ 295 public function test_reschedule_or_queue_adhoc_task_different_data() { 296 $this->resetAfterTest(true); 297 298 // Schedule adhoc task. 299 $task = new adhoc_test_task(); 300 $task->set_custom_data(['courseid' => 10]); 301 manager::reschedule_or_queue_adhoc_task($task); 302 303 // Schedule adhoc task for a different user. 304 $task = new adhoc_test_task(); 305 $task->set_custom_data(['courseid' => 11]); 306 manager::reschedule_or_queue_adhoc_task($task); 307 308 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 309 } 310 311 /** 312 * Ensure that the reschedule_or_queue_adhoc_task function will not make any change for matching data if no time was 313 * specified. 314 * @covers ::reschedule_or_queue_adhoc_task 315 */ 316 public function test_reschedule_or_queue_adhoc_task_match_no_change() { 317 $this->resetAfterTest(true); 318 319 // Schedule adhoc task. 320 $task = new adhoc_test_task(); 321 $task->set_custom_data(['courseid' => 10]); 322 $task->set_next_run_time(time() + DAYSECS); 323 manager::reschedule_or_queue_adhoc_task($task); 324 325 $before = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 326 327 // Schedule the task again but do not specify a time. 328 $task = new adhoc_test_task(); 329 $task->set_custom_data(['courseid' => 10]); 330 manager::reschedule_or_queue_adhoc_task($task); 331 332 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 333 $this->assertEquals($before, manager::get_adhoc_tasks('core\task\adhoc_test_task')); 334 } 335 336 /** 337 * Ensure that the reschedule_or_queue_adhoc_task function will update the run time if there are planned changes. 338 * @covers ::reschedule_or_queue_adhoc_task 339 */ 340 public function test_reschedule_or_queue_adhoc_task_match_update_runtime() { 341 $this->resetAfterTest(true); 342 $initialruntime = time() + DAYSECS; 343 $newruntime = time() + WEEKSECS; 344 345 // Schedule adhoc task. 346 $task = new adhoc_test_task(); 347 $task->set_custom_data(['courseid' => 10]); 348 $task->set_next_run_time($initialruntime); 349 manager::reschedule_or_queue_adhoc_task($task); 350 351 $before = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 352 353 // Schedule the task again. 354 $task = new adhoc_test_task(); 355 $task->set_custom_data(['courseid' => 10]); 356 $task->set_next_run_time($newruntime); 357 manager::reschedule_or_queue_adhoc_task($task); 358 359 $tasks = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 360 $this->assertEquals(1, count($tasks)); 361 $this->assertNotEquals($before, $tasks); 362 $firsttask = reset($tasks); 363 $this->assertEquals($newruntime, $firsttask->get_next_run_time()); 364 } 365 366 /** 367 * Test queue_adhoc_task "if not scheduled". 368 * @covers ::queue_adhoc_task 369 */ 370 public function test_queue_adhoc_task_if_not_scheduled() { 371 $this->resetAfterTest(true); 372 $user = \core_user::get_user_by_username('admin'); 373 374 // Schedule adhoc task. 375 $task = new adhoc_test_task(); 376 $task->set_custom_data(array('courseid' => 10)); 377 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 378 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 379 380 // Schedule adhoc task with a user. 381 $task = new adhoc_test_task(); 382 $task->set_custom_data(array('courseid' => 10)); 383 $task->set_userid($user->id); 384 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 385 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 386 387 // Schedule same adhoc task with different custom data. 388 $task = new adhoc_test_task(); 389 $task->set_custom_data(array('courseid' => 1)); 390 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 391 $this->assertEquals(3, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 392 393 // Schedule same adhoc task with same custom data. 394 $task = new adhoc_test_task(); 395 $task->set_custom_data(array('courseid' => 1)); 396 $this->assertEmpty(manager::queue_adhoc_task($task, true)); 397 $this->assertEquals(3, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 398 399 // Schedule same adhoc task with same custom data and a user. 400 $task = new adhoc_test_task(); 401 $task->set_custom_data(array('courseid' => 1)); 402 $task->set_userid($user->id); 403 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 404 $this->assertEquals(4, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 405 406 // Schedule same adhoc task without custom data. 407 // Note: This task was created earlier. 408 $task = new adhoc_test_task(); 409 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 410 $this->assertEquals(5, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 411 412 // Schedule same adhoc task without custom data (again). 413 $task5 = new adhoc_test_task(); 414 $this->assertEmpty(manager::queue_adhoc_task($task5, true)); 415 $this->assertEquals(5, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 416 417 // Schedule same adhoc task without custom data but with a userid. 418 $task6 = new adhoc_test_task(); 419 $user = \core_user::get_user_by_username('admin'); 420 $task6->set_userid($user->id); 421 $this->assertNotEmpty(manager::queue_adhoc_task($task6, true)); 422 $this->assertEquals(6, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 423 424 // Schedule same adhoc task again without custom data but with a userid. 425 $task6 = new adhoc_test_task(); 426 $user = \core_user::get_user_by_username('admin'); 427 $task6->set_userid($user->id); 428 $this->assertEmpty(manager::queue_adhoc_task($task6, true)); 429 $this->assertEquals(6, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 430 } 431 432 /** 433 * Test that when no userid is specified, it returns empty from the DB 434 * too. 435 * @covers \core\task\adhoc_task::get_userid 436 */ 437 public function test_adhoc_task_user_empty() { 438 $this->resetAfterTest(true); 439 440 // Create an adhoc task in future. 441 $task = new adhoc_test_task(); 442 manager::queue_adhoc_task($task); 443 444 // Get it back from the scheduler. 445 $now = time(); 446 $task = manager::get_next_adhoc_task($now); 447 manager::adhoc_task_complete($task); 448 449 $this->assertEmpty($task->get_userid()); 450 } 451 452 /** 453 * Test that when a userid is specified, that userid is subsequently 454 * returned. 455 * 456 * @covers \core\task\adhoc_task::set_userid 457 * @covers \core\task\adhoc_task::get_userid 458 */ 459 public function test_adhoc_task_user_set() { 460 $this->resetAfterTest(true); 461 462 // Create an adhoc task in future. 463 $task = new adhoc_test_task(); 464 $user = \core_user::get_user_by_username('admin'); 465 $task->set_userid($user->id); 466 manager::queue_adhoc_task($task); 467 468 // Get it back from the scheduler. 469 $now = time(); 470 $task = manager::get_next_adhoc_task($now); 471 manager::adhoc_task_complete($task); 472 473 $this->assertEquals($user->id, $task->get_userid()); 474 } 475 476 /** 477 * Test get_concurrency_limit() method to return 0 by default. 478 * 479 * @covers \core\task\adhoc_task::get_concurrency_limit 480 */ 481 public function test_get_concurrency_limit() { 482 $this->resetAfterTest(true); 483 $task = new adhoc_test_task(); 484 $concurrencylimit = $task->get_concurrency_limit(); 485 $this->assertEquals(0, $concurrencylimit); 486 } 487 488 /** 489 * Test get_concurrency_limit() method to return a default value set in config. 490 * @covers \core\task\adhoc_task::get_concurrency_limit 491 */ 492 public function test_get_concurrency_limit_default() { 493 $this->resetAfterTest(true); 494 set_config('task_concurrency_limit_default', 10); 495 $task = new adhoc_test_task(); 496 $concurrencylimit = $task->get_concurrency_limit(); 497 $this->assertEquals(10, $concurrencylimit); 498 } 499 500 /** 501 * Test get_concurrency_limit() method to return a value for specific task class. 502 * @covers \core\task\adhoc_task::get_concurrency_limit 503 */ 504 public function test_get_concurrency_limit_for_task() { 505 global $CFG; 506 $this->resetAfterTest(true); 507 set_config('task_concurrency_limit_default', 10); 508 $CFG->task_concurrency_limit = array('core\task\adhoc_test_task' => 5); 509 $task = new adhoc_test_task(); 510 $concurrencylimit = $task->get_concurrency_limit(); 511 $this->assertEquals(5, $concurrencylimit); 512 } 513 514 /** 515 * Test adhoc task sorting. 516 * @covers ::get_next_adhoc_task 517 */ 518 public function test_get_next_adhoc_task_sorting() { 519 $this->resetAfterTest(true); 520 521 // Create adhoc tasks. 522 $task1 = new adhoc_test_task(); 523 $task1->set_next_run_time(1510000000); 524 $task1->set_custom_data_as_string('Task 1'); 525 manager::queue_adhoc_task($task1); 526 527 $task2 = new adhoc_test_task(); 528 $task2->set_next_run_time(1520000000); 529 $task2->set_custom_data_as_string('Task 2'); 530 manager::queue_adhoc_task($task2); 531 532 $task3 = new adhoc_test_task(); 533 $task3->set_next_run_time(1520000000); 534 $task3->set_custom_data_as_string('Task 3'); 535 manager::queue_adhoc_task($task3); 536 537 // Shuffle tasks. 538 $task1->set_next_run_time(1540000000); 539 manager::reschedule_or_queue_adhoc_task($task1); 540 541 $task3->set_next_run_time(1530000000); 542 manager::reschedule_or_queue_adhoc_task($task3); 543 544 $task2->set_next_run_time(1530000000); 545 manager::reschedule_or_queue_adhoc_task($task2); 546 547 // Confirm, that tasks are sorted by nextruntime and then by id (ascending). 548 $task = manager::get_next_adhoc_task(time()); 549 $this->assertEquals('Task 2', $task->get_custom_data_as_string()); 550 manager::adhoc_task_complete($task); 551 552 $task = manager::get_next_adhoc_task(time()); 553 $this->assertEquals('Task 3', $task->get_custom_data_as_string()); 554 manager::adhoc_task_complete($task); 555 556 $task = manager::get_next_adhoc_task(time()); 557 $this->assertEquals('Task 1', $task->get_custom_data_as_string()); 558 manager::adhoc_task_complete($task); 559 } 560 561 /** 562 * Test adhoc task run from CLI. 563 * @covers ::run_adhoc_from_cli 564 */ 565 public function test_run_adhoc_from_cli() { 566 $this->resetAfterTest(true); 567 568 $taskid = 1; 569 570 if (!manager::is_runnable()) { 571 $this->markTestSkipped("Cannot run tasks"); 572 } 573 574 ob_start(); 575 manager::run_adhoc_from_cli($taskid); 576 $output = ob_get_contents(); 577 ob_end_clean(); 578 579 $this->assertMatchesRegularExpression( 580 sprintf('!admin/cli/adhoc_task.php\W+--id=%d\W+--force!', $taskid), 581 $output 582 ); 583 } 584 585 /** 586 * Test adhoc class run from CLI. 587 * @covers ::run_all_adhoc_from_cli 588 */ 589 public function test_run_all_adhoc_from_cli() { 590 $this->resetAfterTest(true); 591 592 $classname = 'fake'; 593 594 if (!manager::is_runnable()) { 595 $this->markTestSkipped("Cannot run tasks"); 596 } 597 598 ob_start(); 599 manager::run_all_adhoc_from_cli(false, $classname); 600 $output = ob_get_contents(); 601 ob_end_clean(); 602 603 $this->assertMatchesRegularExpression( 604 sprintf('!admin/cli/adhoc_task.php\W+--classname=%s\W+--force!', $classname), 605 $output 606 ); 607 } 608 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body