See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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 /** 18 * Unit tests for the progress classes. 19 * 20 * @package core_progress 21 * @category phpunit 22 * @copyright 2013 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Progress tests. 30 */ 31 class core_progress_testcase extends basic_testcase { 32 33 /** 34 * Tests for basic use with simple numeric progress. 35 */ 36 public function test_basic() { 37 $progress = new core_mock_progress(); 38 39 // Check values of empty progress things. 40 $this->assertFalse($progress->is_in_progress_section()); 41 42 // Start progress counting, check basic values and check that update 43 // gets called. 44 $progress->start_progress('hello', 10); 45 $this->assertTrue($progress->was_update_called()); 46 $this->assertTrue($progress->is_in_progress_section()); 47 $this->assertEquals('hello', $progress->get_current_description()); 48 49 // Check numeric position and indeterminate count. 50 $this->assert_min_max(0.0, 0.0, $progress); 51 $this->assertEquals(0, $progress->get_progress_count()); 52 53 // Make some progress and check that the time limit gets added. 54 $progress->step_time(); 55 core_php_time_limit::get_and_clear_unit_test_data(); 56 $progress->progress(2); 57 $this->assertTrue($progress->was_update_called()); 58 $this->assertEquals(array(\core\progress\base::TIME_LIMIT_WITHOUT_PROGRESS), 59 core_php_time_limit::get_and_clear_unit_test_data()); 60 61 // Check the new value. 62 $this->assert_min_max(0.2, 0.2, $progress); 63 64 // Do another progress run at same time, it should be ignored. 65 $progress->progress(3); 66 $this->assertFalse($progress->was_update_called()); 67 $this->assert_min_max(0.3, 0.3, $progress); 68 69 // End the section. This should cause an update. 70 $progress->end_progress(); 71 $this->assertTrue($progress->was_update_called()); 72 73 // Because there are no sections left open, it thinks we finished. 74 $this->assert_min_max(1.0, 1.0, $progress); 75 76 // There was 1 progress call. 77 $this->assertEquals(1, $progress->get_progress_count()); 78 } 79 80 /** 81 * Tests progress that is nested and/or indeterminate. 82 */ 83 public function test_nested() { 84 // Outer progress goes from 0 to 10. 85 $progress = new core_mock_progress(); 86 $progress->start_progress('hello', 10); 87 88 // Get up to 4, check position. 89 $progress->step_time(); 90 $progress->progress(4); 91 $this->assert_min_max(0.4, 0.4, $progress); 92 $this->assertEquals('hello', $progress->get_current_description()); 93 94 // Now start indeterminate progress. 95 $progress->start_progress('world'); 96 $this->assert_min_max(0.4, 0.5, $progress); 97 $this->assertEquals('world', $progress->get_current_description()); 98 99 // Do some indeterminate progress and count it (once per second). 100 $progress->step_time(); 101 $progress->progress(); 102 $this->assertEquals(2, $progress->get_progress_count()); 103 $progress->progress(); 104 $this->assertEquals(2, $progress->get_progress_count()); 105 $progress->step_time(); 106 $progress->progress(); 107 $this->assertEquals(3, $progress->get_progress_count()); 108 $this->assert_min_max(0.4, 0.5, $progress); 109 110 // Exit the indeterminate section. 111 $progress->end_progress(); 112 $this->assert_min_max(0.5, 0.5, $progress); 113 114 $progress->step_time(); 115 $progress->progress(7); 116 $this->assert_min_max(0.7, 0.7, $progress); 117 118 // Enter a numbered section (this time with a range of 5). 119 $progress->start_progress('frogs', 5); 120 $this->assert_min_max(0.7, 0.7, $progress); 121 $progress->step_time(); 122 $progress->progress(1); 123 $this->assert_min_max(0.72, 0.72, $progress); 124 $progress->step_time(); 125 $progress->progress(3); 126 $this->assert_min_max(0.76, 0.76, $progress); 127 128 // Now enter another indeterminate section. 129 $progress->start_progress('and'); 130 $this->assert_min_max(0.76, 0.78, $progress); 131 132 // Make some progress, should increment indeterminate count. 133 $progress->step_time(); 134 $progress->progress(); 135 $this->assertEquals(7, $progress->get_progress_count()); 136 137 // Enter numbered section, won't make any difference to values. 138 $progress->start_progress('zombies', 2); 139 $progress->step_time(); 140 $progress->progress(1); 141 $this->assert_min_max(0.76, 0.78, $progress); 142 $this->assertEquals(8, $progress->get_progress_count()); 143 144 // Leaving it will make no difference too. 145 $progress->end_progress(); 146 147 // Leaving the indeterminate section will though. 148 $progress->end_progress(); 149 $this->assert_min_max(0.78, 0.78, $progress); 150 151 // Leave the two numbered sections. 152 $progress->end_progress(); 153 $this->assert_min_max(0.8, 0.8, $progress); 154 $progress->end_progress(); 155 $this->assertFalse($progress->is_in_progress_section()); 156 } 157 158 /** 159 * Tests the feature for 'weighting' nested progress. 160 */ 161 public function test_nested_weighted() { 162 $progress = new core_mock_progress(); 163 $progress->start_progress('', 10); 164 165 // First nested child has 2 units of its own and is worth 1 unit. 166 $progress->start_progress('', 2); 167 $progress->step_time(); 168 $progress->progress(1); 169 $this->assert_min_max(0.05, 0.05, $progress); 170 $progress->end_progress(); 171 $this->assert_min_max(0.1, 0.1, $progress); 172 173 // Next child has 2 units of its own but is worth 3 units. 174 $progress->start_progress('weighted', 2, 3); 175 $progress->step_time(); 176 $progress->progress(1); 177 $this->assert_min_max(0.25, 0.25, $progress); 178 $progress->end_progress(); 179 $this->assert_min_max(0.4, 0.4, $progress); 180 181 // Next indeterminate child is worth 6 units. 182 $progress->start_progress('', \core\progress\base::INDETERMINATE, 6); 183 $progress->step_time(); 184 $progress->progress(); 185 $this->assert_min_max(0.4, 1.0, $progress); 186 $progress->end_progress(); 187 $this->assert_min_max(1.0, 1.0, $progress); 188 } 189 190 /** 191 * I had some issues with real use in backup/restore, this test is intended 192 * to be similar. 193 */ 194 public function test_realistic() { 195 $progress = new core_mock_progress(); 196 $progress->start_progress('parent', 100); 197 $progress->start_progress('child', 1); 198 $progress->progress(1); 199 $this->assert_min_max(0.01, 0.01, $progress); 200 $progress->end_progress(); 201 $this->assert_min_max(0.01, 0.01, $progress); 202 } 203 204 /** 205 * To avoid causing problems, progress needs to work for sections that have 206 * zero entries. 207 */ 208 public function test_zero() { 209 $progress = new core_mock_progress(); 210 $progress->start_progress('parent', 100); 211 $progress->progress(1); 212 $this->assert_min_max(0.01, 0.01, $progress); 213 $progress->start_progress('child', 0); 214 215 // For 'zero' progress, the progress section as immediately complete 216 // within the parent count, so it moves up to 2%. 217 $this->assert_min_max(0.02, 0.02, $progress); 218 $progress->progress(0); 219 $this->assert_min_max(0.02, 0.02, $progress); 220 $progress->end_progress(); 221 $this->assert_min_max(0.02, 0.02, $progress); 222 } 223 224 /** 225 * Tests for any exceptions due to invalid calls. 226 */ 227 public function test_exceptions() { 228 $progress = new core_mock_progress(); 229 230 // Check errors when empty. 231 try { 232 $progress->progress(); 233 $this->fail(); 234 } catch (coding_exception $e) { 235 $this->assertEquals(1, preg_match('~without start_progress~', $e->getMessage())); 236 } 237 try { 238 $progress->end_progress(); 239 $this->fail(); 240 } catch (coding_exception $e) { 241 $this->assertEquals(1, preg_match('~without start_progress~', $e->getMessage())); 242 } 243 try { 244 $progress->get_current_description(); 245 $this->fail(); 246 } catch (coding_exception $e) { 247 $this->assertEquals(1, preg_match('~Not inside progress~', $e->getMessage())); 248 } 249 try { 250 $progress->start_progress('', 1, 7); 251 $this->fail(); 252 } catch (coding_exception $e) { 253 $this->assertEquals(1, preg_match('~must be 1~', $e->getMessage())); 254 } 255 256 // Check invalid start (-2). 257 try { 258 $progress->start_progress('hello', -2); 259 $this->fail(); 260 } catch (coding_exception $e) { 261 $this->assertEquals(1, preg_match('~cannot be negative~', $e->getMessage())); 262 } 263 264 // Indeterminate when value expected. 265 $progress->start_progress('hello', 10); 266 try { 267 $progress->progress(\core\progress\base::INDETERMINATE); 268 $this->fail(); 269 } catch (coding_exception $e) { 270 $this->assertEquals(1, preg_match('~expecting value~', $e->getMessage())); 271 } 272 273 // Value when indeterminate expected. 274 $progress->start_progress('hello'); 275 try { 276 $progress->progress(4); 277 $this->fail(); 278 } catch (coding_exception $e) { 279 $this->assertEquals(1, preg_match('~expecting INDETERMINATE~', $e->getMessage())); 280 } 281 282 // Illegal values. 283 $progress->start_progress('hello', 10); 284 try { 285 $progress->progress(-2); 286 $this->fail(); 287 } catch (coding_exception $e) { 288 $this->assertEquals(1, preg_match('~out of range~', $e->getMessage())); 289 } 290 try { 291 $progress->progress(11); 292 $this->fail(); 293 } catch (coding_exception $e) { 294 $this->assertEquals(1, preg_match('~out of range~', $e->getMessage())); 295 } 296 297 // You are allowed two with the same value... 298 $progress->progress(4); 299 $progress->step_time(); 300 $progress->progress(4); 301 $progress->step_time(); 302 303 // ...but not to go backwards. 304 try { 305 $progress->progress(3); 306 $this->fail(); 307 } catch (coding_exception $e) { 308 $this->assertEquals(1, preg_match('~backwards~', $e->getMessage())); 309 } 310 311 // When you go forward, you can't go further than there is room. 312 try { 313 $progress->start_progress('', 1, 7); 314 $this->fail(); 315 } catch (coding_exception $e) { 316 $this->assertEquals(1, preg_match('~would exceed max~', $e->getMessage())); 317 } 318 } 319 320 public function test_progress_change() { 321 322 $progress = new core_mock_progress(); 323 324 $progress->start_progress('hello', 50); 325 326 327 for ($n = 1; $n <= 10; $n++) { 328 $progress->increment_progress(); 329 } 330 331 // Check numeric position and indeterminate count. 332 $this->assert_min_max(0.2, 0.2, $progress); 333 $this->assertEquals(1, $progress->get_progress_count()); 334 335 // Make some progress and check that the time limit gets added. 336 $progress->step_time(); 337 338 for ($n = 1; $n <= 20; $n++) { 339 $progress->increment_progress(); 340 } 341 342 $this->assertTrue($progress->was_update_called()); 343 344 // Check the new value. 345 $this->assert_min_max(0.6, 0.6, $progress); 346 $this->assertEquals(2, $progress->get_progress_count()); 347 348 for ($n = 1; $n <= 10; $n++) { 349 $progress->increment_progress(); 350 } 351 $this->assertFalse($progress->was_update_called()); 352 $this->assert_min_max(0.8, 0.8, $progress); 353 $this->assertEquals(2, $progress->get_progress_count()); 354 355 // Do another progress run at same time, it should be ignored. 356 $progress->increment_progress(5); 357 $this->assertFalse($progress->was_update_called()); 358 $this->assert_min_max(0.9, 0.9, $progress); 359 $this->assertEquals(2, $progress->get_progress_count()); 360 361 for ($n = 1; $n <= 3; $n++) { 362 $progress->step_time(); 363 $progress->increment_progress(1); 364 } 365 $this->assertTrue($progress->was_update_called()); 366 $this->assert_min_max(0.96, 0.96, $progress); 367 $this->assertEquals(5, $progress->get_progress_count()); 368 369 370 // End the section. This should cause an update. 371 $progress->end_progress(); 372 $this->assertTrue($progress->was_update_called()); 373 $this->assertEquals(5, $progress->get_progress_count()); 374 375 // Because there are no sections left open, it thinks we finished. 376 $this->assert_min_max(1.0, 1.0, $progress); 377 } 378 379 /** 380 * Checks the current progress values are as expected. 381 * 382 * @param number $min Expected min progress 383 * @param number $max Expected max progress 384 * @param core_mock_progress $progress 385 */ 386 private function assert_min_max($min, $max, core_mock_progress $progress) { 387 $this->assertEquals(array($min, $max), 388 $progress->get_progress_proportion_range()); 389 } 390 } 391 392 /** 393 * Helper class that records when update_progress is called and allows time 394 * stepping. 395 */ 396 class core_mock_progress extends \core\progress\base { 397 private $updatecalled = false; 398 private $time = 1; 399 400 /** 401 * Checks if update was called since the last call to this function. 402 * 403 * @return boolean True if update was called 404 */ 405 public function was_update_called() { 406 if ($this->updatecalled) { 407 $this->updatecalled = false; 408 return true; 409 } 410 return false; 411 } 412 413 /** 414 * Steps the current time by 1 second. 415 */ 416 public function step_time() { 417 $this->time++; 418 } 419 420 protected function update_progress() { 421 $this->updatecalled = true; 422 } 423 424 protected function get_time() { 425 return $this->time; 426 } 427 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body