See Release Notes
Long Term Support Release
Differences Between: [Versions 311 and 401] [Versions 400 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 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 public function test_get_next_adhoc_task_now() { 58 $this->resetAfterTest(true); 59 60 // Create an adhoc task. 61 $task = new adhoc_test_task(); 62 63 // Queue it. 64 manager::queue_adhoc_task($task); 65 66 $now = time(); 67 // Get it from the scheduler. 68 $task = manager::get_next_adhoc_task($now); 69 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 70 $task->execute(); 71 manager::adhoc_task_complete($task); 72 } 73 74 /** 75 * Test adhoc task failure retry backoff. 76 * 77 * @covers ::get_next_adhoc_task 78 */ 79 public function test_get_next_adhoc_task_fail_retry() { 80 $this->resetAfterTest(true); 81 82 // Create an adhoc task. 83 $task = new adhoc_test_task(); 84 manager::queue_adhoc_task($task); 85 86 $now = time(); 87 88 // Get it from the scheduler, execute it, and mark it as failed. 89 $task = manager::get_next_adhoc_task($now); 90 $task->execute(); 91 manager::adhoc_task_failed($task); 92 93 // The task will not be returned immediately. 94 $this->assertNull(manager::get_next_adhoc_task($now)); 95 96 // Should get the adhoc task (retry after delay). 97 $task = manager::get_next_adhoc_task($now + 120); 98 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 99 $task->execute(); 100 101 manager::adhoc_task_complete($task); 102 103 // Should not get any task. 104 $this->assertNull(manager::get_next_adhoc_task($now)); 105 } 106 107 /** 108 * Test future adhoc task execution. 109 * @covers ::get_next_adhoc_task 110 */ 111 public function test_get_next_adhoc_task_future() { 112 $this->resetAfterTest(true); 113 114 $now = time(); 115 // Create an adhoc task in future. 116 $task = new adhoc_test_task(); 117 $task->set_next_run_time($now + 1000); 118 manager::queue_adhoc_task($task); 119 120 // Fetching the next task should not return anything. 121 $this->assertNull(manager::get_next_adhoc_task($now)); 122 123 // Fetching in the future should return the task. 124 $task = manager::get_next_adhoc_task($now + 1020); 125 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 126 $task->execute(); 127 manager::adhoc_task_complete($task); 128 } 129 130 /** 131 * Test queueing an adhoc task belonging to a component, where we set the task component accordingly 132 * @covers ::queue_adhoc_task 133 */ 134 public function test_queue_adhoc_task_for_component(): void { 135 $this->resetAfterTest(); 136 137 $task = new \mod_forum\task\send_user_digests(); 138 $task->set_component('mod_test'); 139 140 manager::queue_adhoc_task($task); 141 $this->assertDebuggingNotCalled(); 142 } 143 144 /** 145 * Test queueing an adhoc task belonging to a component, where we do not set the task component 146 * @covers ::queue_adhoc_task 147 */ 148 public function test_queue_task_for_component_without_set_component(): void { 149 $this->resetAfterTest(); 150 151 $task = new \mod_forum\task\send_user_digests(); 152 153 manager::queue_adhoc_task($task); 154 $this->assertDebuggingNotCalled(); 155 156 // Assert the missing component was set. 157 $this->assertEquals('mod_forum', $task->get_component()); 158 } 159 160 /** 161 * Test queueing an adhoc task belonging to an invalid component, where we do not set the task component 162 * @covers ::queue_adhoc_task 163 */ 164 public function test_queue_task_for_invalid_component_without_set_component(): void { 165 $this->resetAfterTest(); 166 167 $task = new \mod_fake\task\adhoc_component_task(); 168 169 manager::queue_adhoc_task($task); 170 $this->assertDebuggingCalled('Component not set and the class namespace does not match a valid component (mod_fake).'); 171 } 172 173 /** 174 * Test empty set of adhoc tasks 175 * @covers ::get_adhoc_tasks 176 */ 177 public function test_get_adhoc_tasks_empty_set() { 178 $this->resetAfterTest(true); 179 180 $this->assertEquals([], manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task')); 181 } 182 183 /** 184 * Test correct set of adhoc tasks is returned for class. 185 * @covers ::get_adhoc_tasks 186 */ 187 public function test_get_adhoc_tasks_result_set() { 188 $this->resetAfterTest(true); 189 190 for ($i = 0; $i < 3; $i++) { 191 $task = new adhoc_test_task(); 192 manager::queue_adhoc_task($task); 193 } 194 195 for ($i = 0; $i < 3; $i++) { 196 $task = new adhoc_test2_task(); 197 manager::queue_adhoc_task($task); 198 } 199 200 $adhoctests = manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task'); 201 $adhoctest2s = manager::get_adhoc_tasks('\\core\\task\\adhoc_test2_task'); 202 203 $this->assertCount(3, $adhoctests); 204 $this->assertCount(3, $adhoctest2s); 205 206 foreach ($adhoctests as $task) { 207 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 208 } 209 210 foreach ($adhoctest2s as $task) { 211 $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task); 212 } 213 } 214 215 /** 216 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if no tasks exist. 217 * @covers ::reschedule_or_queue_adhoc_task 218 */ 219 public function test_reschedule_or_queue_adhoc_task_no_existing() { 220 $this->resetAfterTest(true); 221 222 // Schedule adhoc task. 223 $task = new adhoc_test_task(); 224 $task->set_custom_data(['courseid' => 10]); 225 manager::reschedule_or_queue_adhoc_task($task); 226 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 227 } 228 229 /** 230 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task for the same user does 231 * not exist. 232 * @covers ::reschedule_or_queue_adhoc_task 233 */ 234 public function test_reschedule_or_queue_adhoc_task_different_user() { 235 $this->resetAfterTest(true); 236 $user = \core_user::get_user_by_username('admin'); 237 238 // Schedule adhoc task. 239 $task = new adhoc_test_task(); 240 $task->set_custom_data(['courseid' => 10]); 241 manager::reschedule_or_queue_adhoc_task($task); 242 243 // Schedule adhoc task for a different user. 244 $task = new adhoc_test_task(); 245 $task->set_custom_data(['courseid' => 10]); 246 $task->set_userid($user->id); 247 manager::reschedule_or_queue_adhoc_task($task); 248 249 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 250 } 251 252 /** 253 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task with different custom 254 * data exists. 255 * @covers ::reschedule_or_queue_adhoc_task 256 */ 257 public function test_reschedule_or_queue_adhoc_task_different_data() { 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 265 // Schedule adhoc task for a different user. 266 $task = new adhoc_test_task(); 267 $task->set_custom_data(['courseid' => 11]); 268 manager::reschedule_or_queue_adhoc_task($task); 269 270 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 271 } 272 273 /** 274 * Ensure that the reschedule_or_queue_adhoc_task function will not make any change for matching data if no time was 275 * specified. 276 * @covers ::reschedule_or_queue_adhoc_task 277 */ 278 public function test_reschedule_or_queue_adhoc_task_match_no_change() { 279 $this->resetAfterTest(true); 280 281 // Schedule adhoc task. 282 $task = new adhoc_test_task(); 283 $task->set_custom_data(['courseid' => 10]); 284 $task->set_next_run_time(time() + DAYSECS); 285 manager::reschedule_or_queue_adhoc_task($task); 286 287 $before = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 288 289 // Schedule the task again but do not specify a time. 290 $task = new adhoc_test_task(); 291 $task->set_custom_data(['courseid' => 10]); 292 manager::reschedule_or_queue_adhoc_task($task); 293 294 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 295 $this->assertEquals($before, manager::get_adhoc_tasks('core\task\adhoc_test_task')); 296 } 297 298 /** 299 * Ensure that the reschedule_or_queue_adhoc_task function will update the run time if there are planned changes. 300 * @covers ::reschedule_or_queue_adhoc_task 301 */ 302 public function test_reschedule_or_queue_adhoc_task_match_update_runtime() { 303 $this->resetAfterTest(true); 304 $initialruntime = time() + DAYSECS; 305 $newruntime = time() + WEEKSECS; 306 307 // Schedule adhoc task. 308 $task = new adhoc_test_task(); 309 $task->set_custom_data(['courseid' => 10]); 310 $task->set_next_run_time($initialruntime); 311 manager::reschedule_or_queue_adhoc_task($task); 312 313 $before = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 314 315 // Schedule the task again. 316 $task = new adhoc_test_task(); 317 $task->set_custom_data(['courseid' => 10]); 318 $task->set_next_run_time($newruntime); 319 manager::reschedule_or_queue_adhoc_task($task); 320 321 $tasks = manager::get_adhoc_tasks('core\task\adhoc_test_task'); 322 $this->assertEquals(1, count($tasks)); 323 $this->assertNotEquals($before, $tasks); 324 $firsttask = reset($tasks); 325 $this->assertEquals($newruntime, $firsttask->get_next_run_time()); 326 } 327 328 /** 329 * Test queue_adhoc_task "if not scheduled". 330 * @covers ::queue_adhoc_task 331 */ 332 public function test_queue_adhoc_task_if_not_scheduled() { 333 $this->resetAfterTest(true); 334 $user = \core_user::get_user_by_username('admin'); 335 336 // Schedule adhoc task. 337 $task = new adhoc_test_task(); 338 $task->set_custom_data(array('courseid' => 10)); 339 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 340 $this->assertEquals(1, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 341 342 // Schedule adhoc task with a user. 343 $task = new adhoc_test_task(); 344 $task->set_custom_data(array('courseid' => 10)); 345 $task->set_userid($user->id); 346 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 347 $this->assertEquals(2, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 348 349 // Schedule same adhoc task with different custom data. 350 $task = new adhoc_test_task(); 351 $task->set_custom_data(array('courseid' => 1)); 352 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 353 $this->assertEquals(3, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 354 355 // Schedule same adhoc task with same custom data. 356 $task = new adhoc_test_task(); 357 $task->set_custom_data(array('courseid' => 1)); 358 $this->assertEmpty(manager::queue_adhoc_task($task, true)); 359 $this->assertEquals(3, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 360 361 // Schedule same adhoc task with same custom data and a user. 362 $task = new adhoc_test_task(); 363 $task->set_custom_data(array('courseid' => 1)); 364 $task->set_userid($user->id); 365 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 366 $this->assertEquals(4, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 367 368 // Schedule same adhoc task without custom data. 369 // Note: This task was created earlier. 370 $task = new adhoc_test_task(); 371 $this->assertNotEmpty(manager::queue_adhoc_task($task, true)); 372 $this->assertEquals(5, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 373 374 // Schedule same adhoc task without custom data (again). 375 $task5 = new adhoc_test_task(); 376 $this->assertEmpty(manager::queue_adhoc_task($task5, true)); 377 $this->assertEquals(5, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 378 379 // Schedule same adhoc task without custom data but with a userid. 380 $task6 = new adhoc_test_task(); 381 $user = \core_user::get_user_by_username('admin'); 382 $task6->set_userid($user->id); 383 $this->assertNotEmpty(manager::queue_adhoc_task($task6, true)); 384 $this->assertEquals(6, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 385 386 // Schedule same adhoc task again without custom data but with a userid. 387 $task6 = new adhoc_test_task(); 388 $user = \core_user::get_user_by_username('admin'); 389 $task6->set_userid($user->id); 390 $this->assertEmpty(manager::queue_adhoc_task($task6, true)); 391 $this->assertEquals(6, count(manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 392 } 393 394 /** 395 * Test that when no userid is specified, it returns empty from the DB 396 * too. 397 * @covers \core\task\adhoc_task::get_userid 398 */ 399 public function test_adhoc_task_user_empty() { 400 $this->resetAfterTest(true); 401 402 // Create an adhoc task in future. 403 $task = new adhoc_test_task(); 404 manager::queue_adhoc_task($task); 405 406 // Get it back from the scheduler. 407 $now = time(); 408 $task = manager::get_next_adhoc_task($now); 409 manager::adhoc_task_complete($task); 410 411 $this->assertEmpty($task->get_userid()); 412 } 413 414 /** 415 * Test that when a userid is specified, that userid is subsequently 416 * returned. 417 * 418 * @covers \core\task\adhoc_task::set_userid 419 * @covers \core\task\adhoc_task::get_userid 420 */ 421 public function test_adhoc_task_user_set() { 422 $this->resetAfterTest(true); 423 424 // Create an adhoc task in future. 425 $task = new adhoc_test_task(); 426 $user = \core_user::get_user_by_username('admin'); 427 $task->set_userid($user->id); 428 manager::queue_adhoc_task($task); 429 430 // Get it back from the scheduler. 431 $now = time(); 432 $task = manager::get_next_adhoc_task($now); 433 manager::adhoc_task_complete($task); 434 435 $this->assertEquals($user->id, $task->get_userid()); 436 } 437 438 /** 439 * Test get_concurrency_limit() method to return 0 by default. 440 * 441 * @covers \core\task\adhoc_task::get_concurrency_limit 442 */ 443 public function test_get_concurrency_limit() { 444 $this->resetAfterTest(true); 445 $task = new adhoc_test_task(); 446 $concurrencylimit = $task->get_concurrency_limit(); 447 $this->assertEquals(0, $concurrencylimit); 448 } 449 450 /** 451 * Test get_concurrency_limit() method to return a default value set in config. 452 * @covers \core\task\adhoc_task::get_concurrency_limit 453 */ 454 public function test_get_concurrency_limit_default() { 455 $this->resetAfterTest(true); 456 set_config('task_concurrency_limit_default', 10); 457 $task = new adhoc_test_task(); 458 $concurrencylimit = $task->get_concurrency_limit(); 459 $this->assertEquals(10, $concurrencylimit); 460 } 461 462 /** 463 * Test get_concurrency_limit() method to return a value for specific task class. 464 * @covers \core\task\adhoc_task::get_concurrency_limit 465 */ 466 public function test_get_concurrency_limit_for_task() { 467 global $CFG; 468 $this->resetAfterTest(true); 469 set_config('task_concurrency_limit_default', 10); 470 $CFG->task_concurrency_limit = array('core\task\adhoc_test_task' => 5); 471 $task = new adhoc_test_task(); 472 $concurrencylimit = $task->get_concurrency_limit(); 473 $this->assertEquals(5, $concurrencylimit); 474 } 475 476 /** 477 * Test adhoc task sorting. 478 * @covers ::get_next_adhoc_task 479 */ 480 public function test_get_next_adhoc_task_sorting() { 481 $this->resetAfterTest(true); 482 483 // Create adhoc tasks. 484 $task1 = new adhoc_test_task(); 485 $task1->set_next_run_time(1510000000); 486 $task1->set_custom_data_as_string('Task 1'); 487 manager::queue_adhoc_task($task1); 488 489 $task2 = new adhoc_test_task(); 490 $task2->set_next_run_time(1520000000); 491 $task2->set_custom_data_as_string('Task 2'); 492 manager::queue_adhoc_task($task2); 493 494 $task3 = new adhoc_test_task(); 495 $task3->set_next_run_time(1520000000); 496 $task3->set_custom_data_as_string('Task 3'); 497 manager::queue_adhoc_task($task3); 498 499 // Shuffle tasks. 500 $task1->set_next_run_time(1540000000); 501 manager::reschedule_or_queue_adhoc_task($task1); 502 503 $task3->set_next_run_time(1530000000); 504 manager::reschedule_or_queue_adhoc_task($task3); 505 506 $task2->set_next_run_time(1530000000); 507 manager::reschedule_or_queue_adhoc_task($task2); 508 509 // Confirm, that tasks are sorted by nextruntime and then by id (ascending). 510 $task = manager::get_next_adhoc_task(time()); 511 $this->assertEquals('Task 2', $task->get_custom_data_as_string()); 512 manager::adhoc_task_complete($task); 513 514 $task = manager::get_next_adhoc_task(time()); 515 $this->assertEquals('Task 3', $task->get_custom_data_as_string()); 516 manager::adhoc_task_complete($task); 517 518 $task = manager::get_next_adhoc_task(time()); 519 $this->assertEquals('Task 1', $task->get_custom_data_as_string()); 520 manager::adhoc_task_complete($task); 521 } 522 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body