Differences Between: [Versions 39 and 310]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * This file contains the unittests for adhock tasks. 19 * 20 * @package core 21 * @category phpunit 22 * @copyright 2013 Damyon Wiese 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 require_once (__DIR__ . '/fixtures/task_fixtures.php'); 28 29 30 /** 31 * Test class for adhoc tasks. 32 * 33 * @package core 34 * @category task 35 * @copyright 2013 Damyon Wiese 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class core_adhoc_task_testcase extends advanced_testcase { 39 40 /** 41 * Test basic adhoc task execution. 42 */ 43 public function test_get_next_adhoc_task_now() { 44 $this->resetAfterTest(true); 45 46 // Create an adhoc task. 47 $task = new \core\task\adhoc_test_task(); 48 49 // Queue it. 50 \core\task\manager::queue_adhoc_task($task); 51 52 $now = time(); 53 // Get it from the scheduler. 54 $task = \core\task\manager::get_next_adhoc_task($now); 55 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 56 $task->execute(); 57 \core\task\manager::adhoc_task_complete($task); 58 } 59 60 /** 61 * Test adhoc task failure retry backoff. 62 */ 63 public function test_get_next_adhoc_task_fail_retry() { 64 $this->resetAfterTest(true); 65 66 // Create an adhoc task. 67 $task = new \core\task\adhoc_test_task(); 68 \core\task\manager::queue_adhoc_task($task); 69 70 $now = time(); 71 72 // Get it from the scheduler, execute it, and mark it as failed. 73 $task = \core\task\manager::get_next_adhoc_task($now); 74 $task->execute(); 75 \core\task\manager::adhoc_task_failed($task); 76 77 // The task will not be returned immediately. 78 $this->assertNull(\core\task\manager::get_next_adhoc_task($now)); 79 80 // Should get the adhoc task (retry after delay). 81 $task = \core\task\manager::get_next_adhoc_task($now + 120); 82 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 83 $task->execute(); 84 85 \core\task\manager::adhoc_task_complete($task); 86 87 // Should not get any task. 88 $this->assertNull(\core\task\manager::get_next_adhoc_task($now)); 89 } 90 91 /** 92 * Test future adhoc task execution. 93 */ 94 public function test_get_next_adhoc_task_future() { 95 $this->resetAfterTest(true); 96 97 $now = time(); 98 // Create an adhoc task in future. 99 $task = new \core\task\adhoc_test_task(); 100 $task->set_next_run_time($now + 1000); 101 \core\task\manager::queue_adhoc_task($task); 102 103 // Fetching the next task should not return anything. 104 $this->assertNull(\core\task\manager::get_next_adhoc_task($now)); 105 106 // Fetching in the future should return the task. 107 $task = \core\task\manager::get_next_adhoc_task($now + 1020); 108 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 109 $task->execute(); 110 \core\task\manager::adhoc_task_complete($task); 111 } 112 113 /** 114 * Test queueing an adhoc task belonging to a component, where we set the task component accordingly 115 */ 116 public function test_queue_adhoc_task_for_component(): void { 117 $this->resetAfterTest(); 118 119 $task = new \mod_forum\task\refresh_forum_post_counts(); 120 $task->set_component('mod_test'); 121 122 \core\task\manager::queue_adhoc_task($task); 123 $this->assertDebuggingNotCalled(); 124 } 125 126 /** 127 * Test queueing an adhoc task belonging to a component, where we do not set the task component 128 */ 129 public function test_queue_task_for_component_without_set_component(): void { 130 $this->resetAfterTest(); 131 132 $task = new \mod_forum\task\refresh_forum_post_counts(); 133 134 \core\task\manager::queue_adhoc_task($task); 135 $this->assertDebuggingNotCalled(); 136 137 // Assert the missing component was set. 138 $this->assertEquals('mod_forum', $task->get_component()); 139 } 140 141 /** 142 * Test queueing an adhoc task belonging to an invalid component, where we do not set the task component 143 */ 144 public function test_queue_task_for_invalid_component_without_set_component(): void { 145 $this->resetAfterTest(); 146 147 $task = new \mod_fake\task\adhoc_component_task(); 148 149 \core\task\manager::queue_adhoc_task($task); 150 $this->assertDebuggingCalled('Component not set and the class namespace does not match a valid component (mod_fake).'); 151 } 152 153 /** 154 * Test empty set of adhoc tasks 155 */ 156 public function test_get_adhoc_tasks_empty_set() { 157 $this->resetAfterTest(true); 158 159 $this->assertEquals([], \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task')); 160 } 161 162 /** 163 * Test correct set of adhoc tasks is returned for class. 164 */ 165 public function test_get_adhoc_tasks_result_set() { 166 $this->resetAfterTest(true); 167 168 for ($i = 0; $i < 3; $i++) { 169 $task = new \core\task\adhoc_test_task(); 170 \core\task\manager::queue_adhoc_task($task); 171 } 172 173 for ($i = 0; $i < 3; $i++) { 174 $task = new \core\task\adhoc_test2_task(); 175 \core\task\manager::queue_adhoc_task($task); 176 } 177 178 $adhoctests = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task'); 179 $adhoctest2s = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test2_task'); 180 181 $this->assertCount(3, $adhoctests); 182 $this->assertCount(3, $adhoctest2s); 183 184 foreach ($adhoctests as $task) { 185 $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); 186 } 187 188 foreach ($adhoctest2s as $task) { 189 $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task); 190 } 191 } 192 193 /** 194 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if no tasks exist. 195 */ 196 public function test_reschedule_or_queue_adhoc_task_no_existing() { 197 $this->resetAfterTest(true); 198 199 // Schedule adhoc task. 200 $task = new \core\task\adhoc_test_task(); 201 $task->set_custom_data(['courseid' => 10]); 202 \core\task\manager::reschedule_or_queue_adhoc_task($task); 203 $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 204 } 205 206 /** 207 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task for the same user does 208 * not exist. 209 */ 210 public function test_reschedule_or_queue_adhoc_task_different_user() { 211 $this->resetAfterTest(true); 212 $user = \core_user::get_user_by_username('admin'); 213 214 // Schedule adhoc task. 215 $task = new \core\task\adhoc_test_task(); 216 $task->set_custom_data(['courseid' => 10]); 217 \core\task\manager::reschedule_or_queue_adhoc_task($task); 218 219 // Schedule adhoc task for a different user. 220 $task = new \core\task\adhoc_test_task(); 221 $task->set_custom_data(['courseid' => 10]); 222 $task->set_userid($user->id); 223 \core\task\manager::reschedule_or_queue_adhoc_task($task); 224 225 $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 226 } 227 228 /** 229 * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task with different custom 230 * data exists. 231 */ 232 public function test_reschedule_or_queue_adhoc_task_different_data() { 233 $this->resetAfterTest(true); 234 235 // Schedule adhoc task. 236 $task = new \core\task\adhoc_test_task(); 237 $task->set_custom_data(['courseid' => 10]); 238 \core\task\manager::reschedule_or_queue_adhoc_task($task); 239 240 // Schedule adhoc task for a different user. 241 $task = new \core\task\adhoc_test_task(); 242 $task->set_custom_data(['courseid' => 11]); 243 \core\task\manager::reschedule_or_queue_adhoc_task($task); 244 245 $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 246 } 247 248 /** 249 * Ensure that the reschedule_or_queue_adhoc_task function will not make any change for matching data if no time was 250 * specified. 251 */ 252 public function test_reschedule_or_queue_adhoc_task_match_no_change() { 253 $this->resetAfterTest(true); 254 255 // Schedule adhoc task. 256 $task = new \core\task\adhoc_test_task(); 257 $task->set_custom_data(['courseid' => 10]); 258 $task->set_next_run_time(time() + DAYSECS); 259 \core\task\manager::reschedule_or_queue_adhoc_task($task); 260 261 $before = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'); 262 263 // Schedule the task again but do not specify a time. 264 $task = new \core\task\adhoc_test_task(); 265 $task->set_custom_data(['courseid' => 10]); 266 \core\task\manager::reschedule_or_queue_adhoc_task($task); 267 268 $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 269 $this->assertEquals($before, \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')); 270 } 271 272 /** 273 * Ensure that the reschedule_or_queue_adhoc_task function will update the run time if there are planned changes. 274 */ 275 public function test_reschedule_or_queue_adhoc_task_match_update_runtime() { 276 $this->resetAfterTest(true); 277 $initialruntime = time() + DAYSECS; 278 $newruntime = time() + WEEKSECS; 279 280 // Schedule adhoc task. 281 $task = new \core\task\adhoc_test_task(); 282 $task->set_custom_data(['courseid' => 10]); 283 $task->set_next_run_time($initialruntime); 284 \core\task\manager::reschedule_or_queue_adhoc_task($task); 285 286 $before = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'); 287 288 // Schedule the task again. 289 $task = new \core\task\adhoc_test_task(); 290 $task->set_custom_data(['courseid' => 10]); 291 $task->set_next_run_time($newruntime); 292 \core\task\manager::reschedule_or_queue_adhoc_task($task); 293 294 $tasks = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'); 295 $this->assertEquals(1, count($tasks)); 296 $this->assertNotEquals($before, $tasks); 297 $firsttask = reset($tasks); 298 $this->assertEquals($newruntime, $firsttask->get_next_run_time()); 299 } 300 301 /** 302 * Test queue_adhoc_task "if not scheduled". 303 */ 304 public function test_queue_adhoc_task_if_not_scheduled() { 305 $this->resetAfterTest(true); 306 $user = \core_user::get_user_by_username('admin'); 307 308 // Schedule adhoc task. 309 $task = new \core\task\adhoc_test_task(); 310 $task->set_custom_data(array('courseid' => 10)); 311 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true)); 312 $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 313 314 // Schedule adhoc task with a user. 315 $task = new \core\task\adhoc_test_task(); 316 $task->set_custom_data(array('courseid' => 10)); 317 $task->set_userid($user->id); 318 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true)); 319 $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 320 321 // Schedule same adhoc task with different custom data. 322 $task = new \core\task\adhoc_test_task(); 323 $task->set_custom_data(array('courseid' => 1)); 324 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true)); 325 $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 326 327 // Schedule same adhoc task with same custom data. 328 $task = new \core\task\adhoc_test_task(); 329 $task->set_custom_data(array('courseid' => 1)); 330 $this->assertEmpty(\core\task\manager::queue_adhoc_task($task, true)); 331 $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 332 333 // Schedule same adhoc task with same custom data and a user. 334 $task = new \core\task\adhoc_test_task(); 335 $task->set_custom_data(array('courseid' => 1)); 336 $task->set_userid($user->id); 337 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true)); 338 $this->assertEquals(4, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 339 340 // Schedule same adhoc task without custom data. 341 // Note: This task was created earlier. 342 $task = new \core\task\adhoc_test_task(); 343 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true)); 344 $this->assertEquals(5, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 345 346 // Schedule same adhoc task without custom data (again). 347 $task5 = new \core\task\adhoc_test_task(); 348 $this->assertEmpty(\core\task\manager::queue_adhoc_task($task5, true)); 349 $this->assertEquals(5, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 350 351 // Schedule same adhoc task without custom data but with a userid. 352 $task6 = new \core\task\adhoc_test_task(); 353 $user = \core_user::get_user_by_username('admin'); 354 $task6->set_userid($user->id); 355 $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task6, true)); 356 $this->assertEquals(6, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 357 358 // Schedule same adhoc task again without custom data but with a userid. 359 $task6 = new \core\task\adhoc_test_task(); 360 $user = \core_user::get_user_by_username('admin'); 361 $task6->set_userid($user->id); 362 $this->assertEmpty(\core\task\manager::queue_adhoc_task($task6, true)); 363 $this->assertEquals(6, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); 364 } 365 366 /** 367 * Test that when no userid is specified, it returns empty from the DB 368 * too. 369 */ 370 public function test_adhoc_task_user_empty() { 371 $this->resetAfterTest(true); 372 373 // Create an adhoc task in future. 374 $task = new \core\task\adhoc_test_task(); 375 \core\task\manager::queue_adhoc_task($task); 376 377 // Get it back from the scheduler. 378 $now = time(); 379 $task = \core\task\manager::get_next_adhoc_task($now); 380 \core\task\manager::adhoc_task_complete($task); 381 382 $this->assertEmpty($task->get_userid()); 383 } 384 385 /** 386 * Test that when a userid is specified, that userid is subsequently 387 * returned. 388 */ 389 public function test_adhoc_task_user_set() { 390 $this->resetAfterTest(true); 391 392 // Create an adhoc task in future. 393 $task = new \core\task\adhoc_test_task(); 394 $user = \core_user::get_user_by_username('admin'); 395 $task->set_userid($user->id); 396 \core\task\manager::queue_adhoc_task($task); 397 398 // Get it back from the scheduler. 399 $now = time(); 400 $task = \core\task\manager::get_next_adhoc_task($now); 401 \core\task\manager::adhoc_task_complete($task); 402 403 $this->assertEquals($user->id, $task->get_userid()); 404 } 405 406 /** 407 * Test get_concurrency_limit() method to return 0 by default. 408 */ 409 public function test_get_concurrency_limit() { 410 $this->resetAfterTest(true); 411 $task = new \core\task\adhoc_test_task(); 412 $concurrencylimit = $task->get_concurrency_limit(); 413 $this->assertEquals(0, $concurrencylimit); 414 } 415 416 /** 417 * Test get_concurrency_limit() method to return a default value set in config. 418 */ 419 public function test_get_concurrency_limit_default() { 420 $this->resetAfterTest(true); 421 set_config('task_concurrency_limit_default', 10); 422 $task = new \core\task\adhoc_test_task(); 423 $concurrencylimit = $task->get_concurrency_limit(); 424 $this->assertEquals(10, $concurrencylimit); 425 } 426 427 /** 428 * Test get_concurrency_limit() method to return a value for specific task class. 429 */ 430 public function test_get_concurrency_limit_for_task() { 431 global $CFG; 432 $this->resetAfterTest(true); 433 set_config('task_concurrency_limit_default', 10); 434 $CFG->task_concurrency_limit = array('core\task\adhoc_test_task' => 5); 435 $task = new \core\task\adhoc_test_task(); 436 $concurrencylimit = $task->get_concurrency_limit(); 437 $this->assertEquals(5, $concurrencylimit); 438 } 439 440 /** 441 * Test adhoc task sorting. 442 */ 443 public function test_get_next_adhoc_task_sorting() { 444 $this->resetAfterTest(true); 445 446 // Create adhoc tasks. 447 $task1 = new \core\task\adhoc_test_task(); 448 $task1->set_next_run_time(1510000000); 449 $task1->set_custom_data_as_string('Task 1'); 450 \core\task\manager::queue_adhoc_task($task1); 451 452 $task2 = new \core\task\adhoc_test_task(); 453 $task2->set_next_run_time(1520000000); 454 $task2->set_custom_data_as_string('Task 2'); 455 \core\task\manager::queue_adhoc_task($task2); 456 457 $task3 = new \core\task\adhoc_test_task(); 458 $task3->set_next_run_time(1520000000); 459 $task3->set_custom_data_as_string('Task 3'); 460 \core\task\manager::queue_adhoc_task($task3); 461 462 // Shuffle tasks. 463 $task1->set_next_run_time(1540000000); 464 \core\task\manager::reschedule_or_queue_adhoc_task($task1); 465 466 $task3->set_next_run_time(1530000000); 467 \core\task\manager::reschedule_or_queue_adhoc_task($task3); 468 469 $task2->set_next_run_time(1530000000); 470 \core\task\manager::reschedule_or_queue_adhoc_task($task2); 471 472 // Confirm, that tasks are sorted by nextruntime and then by id (ascending). 473 $task = \core\task\manager::get_next_adhoc_task(time()); 474 $this->assertEquals('Task 2', $task->get_custom_data_as_string()); 475 \core\task\manager::adhoc_task_complete($task); 476 477 $task = \core\task\manager::get_next_adhoc_task(time()); 478 $this->assertEquals('Task 3', $task->get_custom_data_as_string()); 479 \core\task\manager::adhoc_task_complete($task); 480 481 $task = \core\task\manager::get_next_adhoc_task(time()); 482 $this->assertEquals('Task 1', $task->get_custom_data_as_string()); 483 \core\task\manager::adhoc_task_complete($task); 484 } 485 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body