[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 (some of) ../moodlelib.php. 19 * 20 * @package core 21 * @category phpunit 22 * @copyright © 2006 The Open University 23 * @author [email protected] 24 * @author [email protected] 25 */ 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 class core_moodlelib_testcase extends advanced_testcase { 30 31 public static $includecoverage = array('lib/moodlelib.php'); 32 33 /** 34 * Define a local decimal separator. 35 * 36 * It is not possible to directly change the result of get_string in 37 * a unit test. Instead, we create a language pack for language 'xx' in 38 * dataroot and make langconfig.php with the string we need to change. 39 * The example separator used here is 'X'; on PHP 5.3 and before this 40 * must be a single byte character due to PHP bug/limitation in 41 * number_format, so you can't use UTF-8 characters. 42 */ 43 protected function define_local_decimal_separator() { 44 global $SESSION, $CFG; 45 46 $SESSION->lang = 'xx'; 47 $langconfig = "<?php\n\$string['decsep'] = 'X';"; 48 $langfolder = $CFG->dataroot . '/lang/xx'; 49 check_dir_exists($langfolder); 50 file_put_contents($langfolder . '/langconfig.php', $langconfig); 51 } 52 53 public function test_cleanremoteaddr() { 54 // IPv4. 55 $this->assertNull(cleanremoteaddr('1023.121.234.1')); 56 $this->assertSame('123.121.234.1', cleanremoteaddr('123.121.234.01 ')); 57 58 // IPv6. 59 $this->assertNull(cleanremoteaddr('0:0:0:0:0:0:0:0:0')); 60 $this->assertNull(cleanremoteaddr('0:0:0:0:0:0:0:abh')); 61 $this->assertNull(cleanremoteaddr('0:0:0:::0:0:1')); 62 $this->assertSame('::', cleanremoteaddr('0:0:0:0:0:0:0:0', true)); 63 $this->assertSame('::1:1', cleanremoteaddr('0:0:0:0:0:0:1:1', true)); 64 $this->assertSame('abcd:ef::', cleanremoteaddr('abcd:00ef:0:0:0:0:0:0', true)); 65 $this->assertSame('1::1', cleanremoteaddr('1:0:0:0:0:0:0:1', true)); 66 $this->assertSame('0:0:0:0:0:0:10:1', cleanremoteaddr('::10:1', false)); 67 $this->assertSame('1:1:0:0:0:0:0:0', cleanremoteaddr('01:1::', false)); 68 $this->assertSame('10:0:0:0:0:0:0:10', cleanremoteaddr('10::10', false)); 69 $this->assertSame('::ffff:c0a8:11', cleanremoteaddr('::ffff:192.168.1.1', true)); 70 } 71 72 public function test_address_in_subnet() { 73 // 1: xxx.xxx.xxx.xxx/nn or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/nnn (number of bits in net mask). 74 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.1/32')); 75 $this->assertFalse(address_in_subnet('123.121.23.1', '123.121.23.0/32')); 76 $this->assertTrue(address_in_subnet('10.10.10.100', '123.121.23.45/0')); 77 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/24')); 78 $this->assertFalse(address_in_subnet('123.121.34.1', '123.121.234.0/24')); 79 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/30')); 80 $this->assertFalse(address_in_subnet('123.121.23.8', '123.121.23.0/30')); 81 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128')); 82 $this->assertFalse(address_in_subnet('bab:baba::baba', 'bab:baba::cece/128')); 83 $this->assertTrue(address_in_subnet('baba:baba::baba', 'cece:cece::cece/0')); 84 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128')); 85 $this->assertTrue(address_in_subnet('baba:baba::00ba', 'baba:baba::/120')); 86 $this->assertFalse(address_in_subnet('baba:baba::aba', 'baba:baba::/120')); 87 $this->assertTrue(address_in_subnet('baba::baba:00ba', 'baba::baba:0/112')); 88 $this->assertFalse(address_in_subnet('baba::aba:00ba', 'baba::baba:0/112')); 89 $this->assertFalse(address_in_subnet('aba::baba:0000', 'baba::baba:0/112')); 90 91 // Fixed input. 92 $this->assertTrue(address_in_subnet('123.121.23.1 ', ' 123.121.23.0 / 24')); 93 $this->assertTrue(address_in_subnet('::ffff:10.1.1.1', ' 0:0:0:000:0:ffff:a1:10 / 126')); 94 95 // Incorrect input. 96 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/-2')); 97 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/64')); 98 $this->assertFalse(address_in_subnet('123.121.234.x', '123.121.234.1/24')); 99 $this->assertFalse(address_in_subnet('123.121.234.0', '123.121.234.xx/24')); 100 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/xx0')); 101 $this->assertFalse(address_in_subnet('::1', '::aa:0/xx0')); 102 $this->assertFalse(address_in_subnet('::1', '::aa:0/-5')); 103 $this->assertFalse(address_in_subnet('::1', '::aa:0/130')); 104 $this->assertFalse(address_in_subnet('x:1', '::aa:0/130')); 105 $this->assertFalse(address_in_subnet('::1', '::ax:0/130')); 106 107 // 2: xxx.xxx.xxx.xxx-yyy or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::xxxx-yyyy (a range of IP addresses in the last group). 108 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12-14')); 109 $this->assertTrue(address_in_subnet('123.121.234.13', '123.121.234.12-14')); 110 $this->assertTrue(address_in_subnet('123.121.234.14', '123.121.234.12-14')); 111 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.12-14')); 112 $this->assertFalse(address_in_subnet('123.121.234.20', '123.121.234.12-14')); 113 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.234.12-14')); 114 $this->assertFalse(address_in_subnet('123.12.234.12', '123.121.234.12-14')); 115 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba-babe')); 116 $this->assertTrue(address_in_subnet('baba:baba::babc', 'baba:baba::baba-babe')); 117 $this->assertTrue(address_in_subnet('baba:baba::babe', 'baba:baba::baba-babe')); 118 $this->assertFalse(address_in_subnet('bab:baba::bab0', 'bab:baba::baba-babe')); 119 $this->assertFalse(address_in_subnet('bab:baba::babf', 'bab:baba::baba-babe')); 120 $this->assertFalse(address_in_subnet('bab:baba::bfbe', 'bab:baba::baba-babe')); 121 $this->assertFalse(address_in_subnet('bfb:baba::babe', 'bab:baba::baba-babe')); 122 123 // Fixed input. 124 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12 - 14 ')); 125 $this->assertTrue(address_in_subnet('bab:baba::babe', 'bab:baba::baba - babe ')); 126 127 // Incorrect input. 128 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-234.14')); 129 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-256')); 130 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12--256')); 131 132 // 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx. (incomplete address, a bit non-technical ;-). 133 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12')); 134 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.23.13')); 135 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.')); 136 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234')); 137 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121')); 138 $this->assertTrue(address_in_subnet('123.121.234.12', '123')); 139 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234.')); 140 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234')); 141 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba::bab')); 142 $this->assertFalse(address_in_subnet('baba:baba::ba', 'baba:baba::bc')); 143 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba')); 144 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:')); 145 $this->assertFalse(address_in_subnet('bab:baba::bab', 'baba:')); 146 147 // Multiple subnets. 148 $this->assertTrue(address_in_subnet('123.121.234.12', '::1/64, 124., 123.121.234.10-30')); 149 $this->assertTrue(address_in_subnet('124.121.234.12', '::1/64, 124., 123.121.234.10-30')); 150 $this->assertTrue(address_in_subnet('::2', '::1/64, 124., 123.121.234.10-30')); 151 $this->assertFalse(address_in_subnet('12.121.234.12', '::1/64, 124., 123.121.234.10-30')); 152 153 // Other incorrect input. 154 $this->assertFalse(address_in_subnet('123.123.123.123', '')); 155 } 156 157 public function test_fix_utf8() { 158 // Make sure valid data including other types is not changed. 159 $this->assertSame(null, fix_utf8(null)); 160 $this->assertSame(1, fix_utf8(1)); 161 $this->assertSame(1.1, fix_utf8(1.1)); 162 $this->assertSame(true, fix_utf8(true)); 163 $this->assertSame('', fix_utf8('')); 164 $this->assertSame('abc', fix_utf8('abc')); 165 $array = array('do', 're', 'mi'); 166 $this->assertSame($array, fix_utf8($array)); 167 $object = new stdClass(); 168 $object->a = 'aa'; 169 $object->b = 'bb'; 170 $this->assertEquals($object, fix_utf8($object)); 171 172 // valid utf8 string 173 $this->assertSame("žlutý koníček přeskočil potůček \n\t\r", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0")); 174 175 // Invalid utf8 string. 176 $this->assertSame('aš', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.'); 177 } 178 179 public function test_optional_param() { 180 global $CFG; 181 182 $_POST['username'] = 'post_user'; 183 $_GET['username'] = 'get_user'; 184 $this->assertSame($_POST['username'], optional_param('username', 'default_user', PARAM_RAW)); 185 186 unset($_POST['username']); 187 $this->assertSame($_GET['username'], optional_param('username', 'default_user', PARAM_RAW)); 188 189 unset($_GET['username']); 190 $this->assertSame('default_user', optional_param('username', 'default_user', PARAM_RAW)); 191 192 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 193 $_POST['username'] = 'post_user'; 194 try { 195 optional_param('username', 'default_user', null); 196 $this->fail('coding_exception expected'); 197 } catch (moodle_exception $ex) { 198 $this->assertInstanceOf('coding_exception', $ex); 199 } 200 try { 201 @optional_param('username', 'default_user'); 202 $this->fail('coding_exception expected'); 203 } catch (moodle_exception $ex) { 204 $this->assertInstanceOf('coding_exception', $ex); 205 } 206 try { 207 @optional_param('username'); 208 $this->fail('coding_exception expected'); 209 } catch (moodle_exception $ex) { 210 $this->assertInstanceOf('coding_exception', $ex); 211 } 212 try { 213 optional_param('', 'default_user', PARAM_RAW); 214 $this->fail('coding_exception expected'); 215 } catch (moodle_exception $ex) { 216 $this->assertInstanceOf('coding_exception', $ex); 217 } 218 219 // Make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3. 220 $_POST['username'] = array('a'=>'a'); 221 $this->assertSame($_POST['username'], optional_param('username', 'default_user', PARAM_RAW)); 222 $this->assertDebuggingCalled(); 223 } 224 225 public function test_optional_param_array() { 226 global $CFG; 227 228 $_POST['username'] = array('a'=>'post_user'); 229 $_GET['username'] = array('a'=>'get_user'); 230 $this->assertSame($_POST['username'], optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 231 232 unset($_POST['username']); 233 $this->assertSame($_GET['username'], optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 234 235 unset($_GET['username']); 236 $this->assertSame(array('a'=>'default_user'), optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 237 238 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 239 $_POST['username'] = array('a'=>'post_user'); 240 try { 241 optional_param_array('username', array('a'=>'default_user'), null); 242 $this->fail('coding_exception expected'); 243 } catch (moodle_exception $ex) { 244 $this->assertInstanceOf('coding_exception', $ex); 245 } 246 try { 247 @optional_param_array('username', array('a'=>'default_user')); 248 $this->fail('coding_exception expected'); 249 } catch (moodle_exception $ex) { 250 $this->assertInstanceOf('coding_exception', $ex); 251 } 252 try { 253 @optional_param_array('username'); 254 $this->fail('coding_exception expected'); 255 } catch (moodle_exception $ex) { 256 $this->assertInstanceOf('coding_exception', $ex); 257 } 258 try { 259 optional_param_array('', array('a'=>'default_user'), PARAM_RAW); 260 $this->fail('coding_exception expected'); 261 } catch (moodle_exception $ex) { 262 $this->assertInstanceOf('coding_exception', $ex); 263 } 264 265 // Do not allow nested arrays. 266 try { 267 $_POST['username'] = array('a'=>array('b'=>'post_user')); 268 optional_param_array('username', array('a'=>'default_user'), PARAM_RAW); 269 $this->fail('coding_exception expected'); 270 } catch (coding_exception $ex) { 271 $this->assertTrue(true); 272 } 273 274 // Do not allow non-arrays. 275 $_POST['username'] = 'post_user'; 276 $this->assertSame(array('a'=>'default_user'), optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 277 $this->assertDebuggingCalled(); 278 279 // Make sure array keys are sanitised. 280 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user'); 281 $this->assertSame(array('a1_-'=>'post_user'), optional_param_array('username', array(), PARAM_RAW)); 282 $this->assertDebuggingCalled(); 283 } 284 285 public function test_required_param() { 286 $_POST['username'] = 'post_user'; 287 $_GET['username'] = 'get_user'; 288 $this->assertSame('post_user', required_param('username', PARAM_RAW)); 289 290 unset($_POST['username']); 291 $this->assertSame('get_user', required_param('username', PARAM_RAW)); 292 293 unset($_GET['username']); 294 try { 295 $this->assertSame('default_user', required_param('username', PARAM_RAW)); 296 $this->fail('moodle_exception expected'); 297 } catch (moodle_exception $ex) { 298 $this->assertInstanceOf('moodle_exception', $ex); 299 } 300 301 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 302 $_POST['username'] = 'post_user'; 303 try { 304 @required_param('username'); 305 $this->fail('coding_exception expected'); 306 } catch (moodle_exception $ex) { 307 $this->assertInstanceOf('coding_exception', $ex); 308 } 309 try { 310 required_param('username', ''); 311 $this->fail('coding_exception expected'); 312 } catch (moodle_exception $ex) { 313 $this->assertInstanceOf('coding_exception', $ex); 314 } 315 try { 316 required_param('', PARAM_RAW); 317 $this->fail('coding_exception expected'); 318 } catch (moodle_exception $ex) { 319 $this->assertInstanceOf('coding_exception', $ex); 320 } 321 322 // Make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3. 323 $_POST['username'] = array('a'=>'a'); 324 $this->assertSame($_POST['username'], required_param('username', PARAM_RAW)); 325 $this->assertDebuggingCalled(); 326 } 327 328 public function test_required_param_array() { 329 global $CFG; 330 331 $_POST['username'] = array('a'=>'post_user'); 332 $_GET['username'] = array('a'=>'get_user'); 333 $this->assertSame($_POST['username'], required_param_array('username', PARAM_RAW)); 334 335 unset($_POST['username']); 336 $this->assertSame($_GET['username'], required_param_array('username', PARAM_RAW)); 337 338 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 339 $_POST['username'] = array('a'=>'post_user'); 340 try { 341 required_param_array('username', null); 342 $this->fail('coding_exception expected'); 343 } catch (moodle_exception $ex) { 344 $this->assertInstanceOf('coding_exception', $ex); 345 } 346 try { 347 @required_param_array('username'); 348 $this->fail('coding_exception expected'); 349 } catch (moodle_exception $ex) { 350 $this->assertInstanceOf('coding_exception', $ex); 351 } 352 try { 353 required_param_array('', PARAM_RAW); 354 $this->fail('coding_exception expected'); 355 } catch (moodle_exception $ex) { 356 $this->assertInstanceOf('coding_exception', $ex); 357 } 358 359 // Do not allow nested arrays. 360 try { 361 $_POST['username'] = array('a'=>array('b'=>'post_user')); 362 required_param_array('username', PARAM_RAW); 363 $this->fail('coding_exception expected'); 364 } catch (moodle_exception $ex) { 365 $this->assertInstanceOf('coding_exception', $ex); 366 } 367 368 // Do not allow non-arrays. 369 try { 370 $_POST['username'] = 'post_user'; 371 required_param_array('username', PARAM_RAW); 372 $this->fail('moodle_exception expected'); 373 } catch (moodle_exception $ex) { 374 $this->assertInstanceOf('moodle_exception', $ex); 375 } 376 377 // Make sure array keys are sanitised. 378 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user'); 379 $this->assertSame(array('a1_-'=>'post_user'), required_param_array('username', PARAM_RAW)); 380 $this->assertDebuggingCalled(); 381 } 382 383 public function test_clean_param() { 384 // Forbid objects and arrays. 385 try { 386 clean_param(array('x', 'y'), PARAM_RAW); 387 $this->fail('coding_exception expected'); 388 } catch (moodle_exception $ex) { 389 $this->assertInstanceOf('coding_exception', $ex); 390 } 391 try { 392 $param = new stdClass(); 393 $param->id = 1; 394 clean_param($param, PARAM_RAW); 395 $this->fail('coding_exception expected'); 396 } catch (moodle_exception $ex) { 397 $this->assertInstanceOf('coding_exception', $ex); 398 } 399 400 // Require correct type. 401 try { 402 clean_param('x', 'xxxxxx'); 403 $this->fail('moodle_exception expected'); 404 } catch (moodle_exception $ex) { 405 $this->assertInstanceOf('moodle_exception', $ex); 406 } 407 try { 408 @clean_param('x'); 409 $this->fail('moodle_exception expected'); 410 } catch (moodle_exception $ex) { 411 $this->assertInstanceOf('moodle_exception', $ex); 412 } 413 } 414 415 public function test_clean_param_array() { 416 $this->assertSame(array(), clean_param_array(null, PARAM_RAW)); 417 $this->assertSame(array('a', 'b'), clean_param_array(array('a', 'b'), PARAM_RAW)); 418 $this->assertSame(array('a', array('b')), clean_param_array(array('a', array('b')), PARAM_RAW, true)); 419 420 // Require correct type. 421 try { 422 clean_param_array(array('x'), 'xxxxxx'); 423 $this->fail('moodle_exception expected'); 424 } catch (moodle_exception $ex) { 425 $this->assertInstanceOf('moodle_exception', $ex); 426 } 427 try { 428 @clean_param_array(array('x')); 429 $this->fail('moodle_exception expected'); 430 } catch (moodle_exception $ex) { 431 $this->assertInstanceOf('moodle_exception', $ex); 432 } 433 434 try { 435 clean_param_array(array('x', array('y')), PARAM_RAW); 436 $this->fail('coding_exception expected'); 437 } catch (moodle_exception $ex) { 438 $this->assertInstanceOf('coding_exception', $ex); 439 } 440 441 // Test recursive. 442 } 443 444 public function test_clean_param_raw() { 445 $this->assertSame( 446 '#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', 447 clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_RAW)); 448 } 449 450 public function test_clean_param_trim() { 451 $this->assertSame('Frog toad', clean_param(" Frog toad \r\n ", PARAM_RAW_TRIMMED)); 452 } 453 454 public function test_clean_param_clean() { 455 // PARAM_CLEAN is an ugly hack, do not use in new code (skodak), 456 // instead use more specific type, or submit sothing that can be verified properly. 457 $this->assertSame('xx', clean_param('xx<script>', PARAM_CLEAN)); 458 } 459 460 public function test_clean_param_alpha() { 461 $this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHA)); 462 } 463 464 public function test_clean_param_alphanum() { 465 $this->assertSame('978942897DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHANUM)); 466 } 467 468 public function test_clean_param_alphaext() { 469 $this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHAEXT)); 470 } 471 472 public function test_clean_param_sequence() { 473 $this->assertSame(',9789,42897', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_SEQUENCE)); 474 } 475 476 public function test_clean_param_component() { 477 // Please note the cleaning of component names is very strict, no guessing here. 478 $this->assertSame('mod_forum', clean_param('mod_forum', PARAM_COMPONENT)); 479 $this->assertSame('block_online_users', clean_param('block_online_users', PARAM_COMPONENT)); 480 $this->assertSame('block_blond_online_users', clean_param('block_blond_online_users', PARAM_COMPONENT)); 481 $this->assertSame('mod_something2', clean_param('mod_something2', PARAM_COMPONENT)); 482 $this->assertSame('forum', clean_param('forum', PARAM_COMPONENT)); 483 $this->assertSame('user', clean_param('user', PARAM_COMPONENT)); 484 $this->assertSame('rating', clean_param('rating', PARAM_COMPONENT)); 485 $this->assertSame('feedback360', clean_param('feedback360', PARAM_COMPONENT)); 486 $this->assertSame('mod_feedback360', clean_param('mod_feedback360', PARAM_COMPONENT)); 487 $this->assertSame('', clean_param('mod_2something', PARAM_COMPONENT)); 488 $this->assertSame('', clean_param('2mod_something', PARAM_COMPONENT)); 489 $this->assertSame('', clean_param('mod_something_xx', PARAM_COMPONENT)); 490 $this->assertSame('', clean_param('auth_something__xx', PARAM_COMPONENT)); 491 $this->assertSame('', clean_param('mod_Something', PARAM_COMPONENT)); 492 $this->assertSame('', clean_param('mod_somethíng', PARAM_COMPONENT)); 493 $this->assertSame('', clean_param('mod__something', PARAM_COMPONENT)); 494 $this->assertSame('', clean_param('auth_xx-yy', PARAM_COMPONENT)); 495 $this->assertSame('', clean_param('_auth_xx', PARAM_COMPONENT)); 496 $this->assertSame('', clean_param('a2uth_xx', PARAM_COMPONENT)); 497 $this->assertSame('', clean_param('auth_xx_', PARAM_COMPONENT)); 498 $this->assertSame('', clean_param('auth_xx.old', PARAM_COMPONENT)); 499 $this->assertSame('', clean_param('_user', PARAM_COMPONENT)); 500 $this->assertSame('', clean_param('2rating', PARAM_COMPONENT)); 501 $this->assertSame('', clean_param('user_', PARAM_COMPONENT)); 502 } 503 504 public function test_is_valid_plugin_name() { 505 $this->assertTrue(is_valid_plugin_name('forum')); 506 $this->assertTrue(is_valid_plugin_name('forum2')); 507 $this->assertTrue(is_valid_plugin_name('feedback360')); 508 $this->assertTrue(is_valid_plugin_name('online_users')); 509 $this->assertTrue(is_valid_plugin_name('blond_online_users')); 510 $this->assertFalse(is_valid_plugin_name('online__users')); 511 $this->assertFalse(is_valid_plugin_name('forum ')); 512 $this->assertFalse(is_valid_plugin_name('forum.old')); 513 $this->assertFalse(is_valid_plugin_name('xx-yy')); 514 $this->assertFalse(is_valid_plugin_name('2xx')); 515 $this->assertFalse(is_valid_plugin_name('Xx')); 516 $this->assertFalse(is_valid_plugin_name('_xx')); 517 $this->assertFalse(is_valid_plugin_name('xx_')); 518 } 519 520 public function test_clean_param_plugin() { 521 // Please note the cleaning of plugin names is very strict, no guessing here. 522 $this->assertSame('forum', clean_param('forum', PARAM_PLUGIN)); 523 $this->assertSame('forum2', clean_param('forum2', PARAM_PLUGIN)); 524 $this->assertSame('feedback360', clean_param('feedback360', PARAM_PLUGIN)); 525 $this->assertSame('online_users', clean_param('online_users', PARAM_PLUGIN)); 526 $this->assertSame('blond_online_users', clean_param('blond_online_users', PARAM_PLUGIN)); 527 $this->assertSame('', clean_param('online__users', PARAM_PLUGIN)); 528 $this->assertSame('', clean_param('forum ', PARAM_PLUGIN)); 529 $this->assertSame('', clean_param('forum.old', PARAM_PLUGIN)); 530 $this->assertSame('', clean_param('xx-yy', PARAM_PLUGIN)); 531 $this->assertSame('', clean_param('2xx', PARAM_PLUGIN)); 532 $this->assertSame('', clean_param('Xx', PARAM_PLUGIN)); 533 $this->assertSame('', clean_param('_xx', PARAM_PLUGIN)); 534 $this->assertSame('', clean_param('xx_', PARAM_PLUGIN)); 535 } 536 537 public function test_clean_param_area() { 538 // Please note the cleaning of area names is very strict, no guessing here. 539 $this->assertSame('something', clean_param('something', PARAM_AREA)); 540 $this->assertSame('something2', clean_param('something2', PARAM_AREA)); 541 $this->assertSame('some_thing', clean_param('some_thing', PARAM_AREA)); 542 $this->assertSame('some_thing_xx', clean_param('some_thing_xx', PARAM_AREA)); 543 $this->assertSame('feedback360', clean_param('feedback360', PARAM_AREA)); 544 $this->assertSame('', clean_param('_something', PARAM_AREA)); 545 $this->assertSame('', clean_param('something_', PARAM_AREA)); 546 $this->assertSame('', clean_param('2something', PARAM_AREA)); 547 $this->assertSame('', clean_param('Something', PARAM_AREA)); 548 $this->assertSame('', clean_param('some-thing', PARAM_AREA)); 549 $this->assertSame('', clean_param('somethííng', PARAM_AREA)); 550 $this->assertSame('', clean_param('something.x', PARAM_AREA)); 551 } 552 553 public function test_clean_param_text() { 554 $this->assertSame(PARAM_TEXT, PARAM_MULTILANG); 555 // Standard. 556 $this->assertSame('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', clean_param('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', PARAM_TEXT)); 557 $this->assertSame('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', clean_param('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', PARAM_TEXT)); 558 $this->assertSame('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', clean_param('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', PARAM_TEXT)); 559 // Malformed. 560 $this->assertSame('<span lang="en" class="multilang">aa</span>', clean_param('<span lang="en" class="multilang">aa</span>', PARAM_TEXT)); 561 $this->assertSame('aa', clean_param('<span lang="en" class="nothing" class="multilang">aa</span>', PARAM_TEXT)); 562 $this->assertSame('aa', clean_param('<lang lang="en" class="multilang">aa</lang>', PARAM_TEXT)); 563 $this->assertSame('aa', clean_param('<lang lang="en!!">aa</lang>', PARAM_TEXT)); 564 $this->assertSame('aa', clean_param('<span lang="en==" class="multilang">aa</span>', PARAM_TEXT)); 565 $this->assertSame('abc', clean_param('a<em>b</em>c', PARAM_TEXT)); 566 $this->assertSame('a>c>', clean_param('a><xx >c>', PARAM_TEXT)); // Standard strip_tags() behaviour. 567 $this->assertSame('a', clean_param('a<b', PARAM_TEXT)); 568 $this->assertSame('a>b', clean_param('a>b', PARAM_TEXT)); 569 $this->assertSame('<lang lang="en">a>a</lang>', clean_param('<lang lang="en">a>a</lang>', PARAM_TEXT)); // Standard strip_tags() behaviour. 570 $this->assertSame('a', clean_param('<lang lang="en">a<a</lang>', PARAM_TEXT)); 571 $this->assertSame('<lang lang="en">aa</lang>', clean_param('<lang lang="en">a<br>a</lang>', PARAM_TEXT)); 572 } 573 574 public function test_clean_param_url() { 575 // Test PARAM_URL and PARAM_LOCALURL a bit. 576 $this->assertSame('http://google.com/', clean_param('http://google.com/', PARAM_URL)); 577 $this->assertSame('http://some.very.long.and.silly.domain/with/a/path/', clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_URL)); 578 $this->assertSame('http://localhost/', clean_param('http://localhost/', PARAM_URL)); 579 $this->assertSame('http://0.255.1.1/numericip.php', clean_param('http://0.255.1.1/numericip.php', PARAM_URL)); 580 $this->assertSame('/just/a/path', clean_param('/just/a/path', PARAM_URL)); 581 $this->assertSame('', clean_param('funny:thing', PARAM_URL)); 582 } 583 584 public function test_clean_param_localurl() { 585 global $CFG; 586 $this->assertSame('', clean_param('http://google.com/', PARAM_LOCALURL)); 587 $this->assertSame('', clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_LOCALURL)); 588 $this->assertSame(clean_param($CFG->wwwroot, PARAM_LOCALURL), $CFG->wwwroot); 589 $this->assertSame('/just/a/path', clean_param('/just/a/path', PARAM_LOCALURL)); 590 $this->assertSame('', clean_param('funny:thing', PARAM_LOCALURL)); 591 $this->assertSame('course/view.php?id=3', clean_param('course/view.php?id=3', PARAM_LOCALURL)); 592 } 593 594 public function test_clean_param_file() { 595 $this->assertSame('correctfile.txt', clean_param('correctfile.txt', PARAM_FILE)); 596 $this->assertSame('badfile.txt', clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_FILE)); 597 $this->assertSame('..parentdirfile.txt', clean_param('../parentdirfile.txt', PARAM_FILE)); 598 $this->assertSame('....grandparentdirfile.txt', clean_param('../../grandparentdirfile.txt', PARAM_FILE)); 599 $this->assertSame('..winparentdirfile.txt', clean_param('..\winparentdirfile.txt', PARAM_FILE)); 600 $this->assertSame('....wingrandparentdir.txt', clean_param('..\..\wingrandparentdir.txt', PARAM_FILE)); 601 $this->assertSame('myfile.a.b.txt', clean_param('myfile.a.b.txt', PARAM_FILE)); 602 $this->assertSame('myfile..a..b.txt', clean_param('myfile..a..b.txt', PARAM_FILE)); 603 $this->assertSame('myfile.a..b...txt', clean_param('myfile.a..b...txt', PARAM_FILE)); 604 $this->assertSame('myfile.a.txt', clean_param('myfile.a.txt', PARAM_FILE)); 605 $this->assertSame('myfile...txt', clean_param('myfile...txt', PARAM_FILE)); 606 $this->assertSame('...jpg', clean_param('...jpg', PARAM_FILE)); 607 $this->assertSame('.a.b.', clean_param('.a.b.', PARAM_FILE)); 608 $this->assertSame('', clean_param('.', PARAM_FILE)); 609 $this->assertSame('', clean_param('..', PARAM_FILE)); 610 $this->assertSame('...', clean_param('...', PARAM_FILE)); 611 $this->assertSame('. . . .', clean_param('. . . .', PARAM_FILE)); 612 $this->assertSame('dontrtrim.me. .. .. . ', clean_param('dontrtrim.me. .. .. . ', PARAM_FILE)); 613 $this->assertSame(' . .dontltrim.me', clean_param(' . .dontltrim.me', PARAM_FILE)); 614 $this->assertSame('here is a tab.txt', clean_param("here is a tab\t.txt", PARAM_FILE)); 615 $this->assertSame('here is a linebreak.txt', clean_param("here is a line\r\nbreak.txt", PARAM_FILE)); 616 617 // The following behaviours have been maintained although they seem a little odd. 618 $this->assertSame('funnything', clean_param('funny:thing', PARAM_FILE)); 619 $this->assertSame('.currentdirfile.txt', clean_param('./currentdirfile.txt', PARAM_FILE)); 620 $this->assertSame('ctempwindowsfile.txt', clean_param('c:\temp\windowsfile.txt', PARAM_FILE)); 621 $this->assertSame('homeuserlinuxfile.txt', clean_param('/home/user/linuxfile.txt', PARAM_FILE)); 622 $this->assertSame('~myfile.txt', clean_param('~/myfile.txt', PARAM_FILE)); 623 } 624 625 public function test_clean_param_path() { 626 $this->assertSame('correctfile.txt', clean_param('correctfile.txt', PARAM_PATH)); 627 $this->assertSame('bad/file.txt', clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_PATH)); 628 $this->assertSame('/parentdirfile.txt', clean_param('../parentdirfile.txt', PARAM_PATH)); 629 $this->assertSame('/grandparentdirfile.txt', clean_param('../../grandparentdirfile.txt', PARAM_PATH)); 630 $this->assertSame('/winparentdirfile.txt', clean_param('..\winparentdirfile.txt', PARAM_PATH)); 631 $this->assertSame('/wingrandparentdir.txt', clean_param('..\..\wingrandparentdir.txt', PARAM_PATH)); 632 $this->assertSame('funnything', clean_param('funny:thing', PARAM_PATH)); 633 $this->assertSame('./here', clean_param('./././here', PARAM_PATH)); 634 $this->assertSame('./currentdirfile.txt', clean_param('./currentdirfile.txt', PARAM_PATH)); 635 $this->assertSame('c/temp/windowsfile.txt', clean_param('c:\temp\windowsfile.txt', PARAM_PATH)); 636 $this->assertSame('/home/user/linuxfile.txt', clean_param('/home/user/linuxfile.txt', PARAM_PATH)); 637 $this->assertSame('/home../user ./.linuxfile.txt', clean_param('/home../user ./.linuxfile.txt', PARAM_PATH)); 638 $this->assertSame('~/myfile.txt', clean_param('~/myfile.txt', PARAM_PATH)); 639 $this->assertSame('~/myfile.txt', clean_param('~/../myfile.txt', PARAM_PATH)); 640 $this->assertSame('/..b../.../myfile.txt', clean_param('/..b../.../myfile.txt', PARAM_PATH)); 641 $this->assertSame('..b../.../myfile.txt', clean_param('..b../.../myfile.txt', PARAM_PATH)); 642 $this->assertSame('/super/slashes/', clean_param('/super//slashes///', PARAM_PATH)); 643 } 644 645 public function test_clean_param_username() { 646 global $CFG; 647 $currentstatus = $CFG->extendedusernamechars; 648 649 // Run tests with extended character == false;. 650 $CFG->extendedusernamechars = false; 651 $this->assertSame('johndoe123', clean_param('johndoe123', PARAM_USERNAME) ); 652 $this->assertSame('john.doe', clean_param('john.doe', PARAM_USERNAME)); 653 $this->assertSame('john-doe', clean_param('john-doe', PARAM_USERNAME)); 654 $this->assertSame('john-doe', clean_param('john- doe', PARAM_USERNAME)); 655 $this->assertSame('john_doe', clean_param('john_doe', PARAM_USERNAME)); 656 $this->assertSame('john@doe', clean_param('john@doe', PARAM_USERNAME)); 657 $this->assertSame('johndoe', clean_param('john~doe', PARAM_USERNAME)); 658 $this->assertSame('johndoe', clean_param('john´doe', PARAM_USERNAME)); 659 $this->assertSame(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john_'); 660 $this->assertSame(clean_param(' john# $%&()+_^ ', PARAM_USERNAME), 'john_'); 661 $this->assertSame(clean_param('john#$%&() ', PARAM_USERNAME), 'john'); 662 $this->assertSame('johnd', clean_param('JOHNdóé ', PARAM_USERNAME)); 663 $this->assertSame(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýá?ý??doe ', PARAM_USERNAME), 'john.-_a_x-d@_doe'); 664 665 // Test success condition, if extendedusernamechars == ENABLE;. 666 $CFG->extendedusernamechars = true; 667 $this->assertSame('john_doe', clean_param('john_doe', PARAM_USERNAME)); 668 $this->assertSame('john@doe', clean_param('john@doe', PARAM_USERNAME)); 669 $this->assertSame(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john# $%&()+_^'); 670 $this->assertSame(clean_param(' john# $%&()+_^ ', PARAM_USERNAME), 'john# $%&()+_^'); 671 $this->assertSame('john~doe', clean_param('john~doe', PARAM_USERNAME)); 672 $this->assertSame('john´doe', clean_param('joHN´doe', PARAM_USERNAME)); 673 $this->assertSame('johndoe', clean_param('johnDOE', PARAM_USERNAME)); 674 $this->assertSame('johndóé', clean_param('johndóé ', PARAM_USERNAME)); 675 676 $CFG->extendedusernamechars = $currentstatus; 677 } 678 679 public function test_clean_param_stringid() { 680 // Test string identifiers validation. 681 // Valid strings. 682 $this->assertSame('validstring', clean_param('validstring', PARAM_STRINGID)); 683 $this->assertSame('mod/foobar:valid_capability', clean_param('mod/foobar:valid_capability', PARAM_STRINGID)); 684 $this->assertSame('CZ', clean_param('CZ', PARAM_STRINGID)); 685 $this->assertSame('application/vnd.ms-powerpoint', clean_param('application/vnd.ms-powerpoint', PARAM_STRINGID)); 686 $this->assertSame('grade2', clean_param('grade2', PARAM_STRINGID)); 687 // Invalid strings. 688 $this->assertSame('', clean_param('trailing ', PARAM_STRINGID)); 689 $this->assertSame('', clean_param('space bar', PARAM_STRINGID)); 690 $this->assertSame('', clean_param('0numeric', PARAM_STRINGID)); 691 $this->assertSame('', clean_param('*', PARAM_STRINGID)); 692 $this->assertSame('', clean_param(' ', PARAM_STRINGID)); 693 } 694 695 public function test_clean_param_timezone() { 696 // Test timezone validation. 697 $testvalues = array ( 698 'America/Jamaica' => 'America/Jamaica', 699 'America/Argentina/Cordoba' => 'America/Argentina/Cordoba', 700 'America/Port-au-Prince' => 'America/Port-au-Prince', 701 'America/Argentina/Buenos_Aires' => 'America/Argentina/Buenos_Aires', 702 'PST8PDT' => 'PST8PDT', 703 'Wrong.Value' => '', 704 'Wrong/.Value' => '', 705 'Wrong(Value)' => '', 706 '0' => '0', 707 '0.0' => '0.0', 708 '0.5' => '0.5', 709 '9.0' => '9.0', 710 '-9.0' => '-9.0', 711 '+9.0' => '+9.0', 712 '9.5' => '9.5', 713 '-9.5' => '-9.5', 714 '+9.5' => '+9.5', 715 '12.0' => '12.0', 716 '-12.0' => '-12.0', 717 '+12.0' => '+12.0', 718 '12.5' => '12.5', 719 '-12.5' => '-12.5', 720 '+12.5' => '+12.5', 721 '13.0' => '13.0', 722 '-13.0' => '-13.0', 723 '+13.0' => '+13.0', 724 '13.5' => '', 725 '+13.5' => '', 726 '-13.5' => '', 727 '0.2' => ''); 728 729 foreach ($testvalues as $testvalue => $expectedvalue) { 730 $actualvalue = clean_param($testvalue, PARAM_TIMEZONE); 731 $this->assertEquals($expectedvalue, $actualvalue); 732 } 733 } 734 735 public function test_validate_param() { 736 try { 737 $param = validate_param('11a', PARAM_INT); 738 $this->fail('invalid_parameter_exception expected'); 739 } catch (moodle_exception $ex) { 740 $this->assertInstanceOf('invalid_parameter_exception', $ex); 741 } 742 743 $param = validate_param('11', PARAM_INT); 744 $this->assertSame(11, $param); 745 746 try { 747 $param = validate_param(null, PARAM_INT, false); 748 $this->fail('invalid_parameter_exception expected'); 749 } catch (moodle_exception $ex) { 750 $this->assertInstanceOf('invalid_parameter_exception', $ex); 751 } 752 753 $param = validate_param(null, PARAM_INT, true); 754 $this->assertSame(null, $param); 755 756 try { 757 $param = validate_param(array(), PARAM_INT); 758 $this->fail('invalid_parameter_exception expected'); 759 } catch (moodle_exception $ex) { 760 $this->assertInstanceOf('invalid_parameter_exception', $ex); 761 } 762 try { 763 $param = validate_param(new stdClass, PARAM_INT); 764 $this->fail('invalid_parameter_exception expected'); 765 } catch (moodle_exception $ex) { 766 $this->assertInstanceOf('invalid_parameter_exception', $ex); 767 } 768 769 $param = validate_param('1.0', PARAM_FLOAT); 770 $this->assertSame(1.0, $param); 771 772 // Make sure valid floats do not cause exception. 773 validate_param(1.0, PARAM_FLOAT); 774 validate_param(10, PARAM_FLOAT); 775 validate_param('0', PARAM_FLOAT); 776 validate_param('119813454.545464564564546564545646556564465465456465465465645645465645645645', PARAM_FLOAT); 777 validate_param('011.1', PARAM_FLOAT); 778 validate_param('11', PARAM_FLOAT); 779 validate_param('+.1', PARAM_FLOAT); 780 validate_param('-.1', PARAM_FLOAT); 781 validate_param('1e10', PARAM_FLOAT); 782 validate_param('.1e+10', PARAM_FLOAT); 783 validate_param('1E-1', PARAM_FLOAT); 784 785 try { 786 $param = validate_param('1,2', PARAM_FLOAT); 787 $this->fail('invalid_parameter_exception expected'); 788 } catch (moodle_exception $ex) { 789 $this->assertInstanceOf('invalid_parameter_exception', $ex); 790 } 791 try { 792 $param = validate_param('', PARAM_FLOAT); 793 $this->fail('invalid_parameter_exception expected'); 794 } catch (moodle_exception $ex) { 795 $this->assertInstanceOf('invalid_parameter_exception', $ex); 796 } 797 try { 798 $param = validate_param('.', PARAM_FLOAT); 799 $this->fail('invalid_parameter_exception expected'); 800 } catch (moodle_exception $ex) { 801 $this->assertInstanceOf('invalid_parameter_exception', $ex); 802 } 803 try { 804 $param = validate_param('e10', PARAM_FLOAT); 805 $this->fail('invalid_parameter_exception expected'); 806 } catch (moodle_exception $ex) { 807 $this->assertInstanceOf('invalid_parameter_exception', $ex); 808 } 809 try { 810 $param = validate_param('abc', PARAM_FLOAT); 811 $this->fail('invalid_parameter_exception expected'); 812 } catch (moodle_exception $ex) { 813 $this->assertInstanceOf('invalid_parameter_exception', $ex); 814 } 815 } 816 817 public function test_shorten_text_no_tags_already_short_enough() { 818 // ......12345678901234567890123456. 819 $text = "short text already no tags"; 820 $this->assertSame($text, shorten_text($text)); 821 } 822 823 public function test_shorten_text_with_tags_already_short_enough() { 824 // .........123456...7890....12345678.......901234567. 825 $text = "<p>short <b>text</b> already</p><p>with tags</p>"; 826 $this->assertSame($text, shorten_text($text)); 827 } 828 829 public function test_shorten_text_no_tags_needs_shortening() { 830 // Default truncation is after 30 chars, but allowing 3 for the final '...'. 831 // ......12345678901234567890123456789023456789012345678901234. 832 $text = "long text without any tags blah de blah blah blah what"; 833 $this->assertSame('long text without any tags ...', shorten_text($text)); 834 } 835 836 public function test_shorten_text_with_tags_needs_shortening() { 837 // .......................................123456789012345678901234567890... 838 $text = "<div class='frog'><p><blockquote>Long text with tags that will ". 839 "be chopped off but <b>should be added back again</b></blockquote></p></div>"; 840 $this->assertEquals("<div class='frog'><p><blockquote>Long text with " . 841 "tags that ...</blockquote></p></div>", shorten_text($text)); 842 } 843 844 public function test_shorten_text_with_entities() { 845 // Remember to allow 3 chars for the final '...'. 846 // ......123456789012345678901234567_____890... 847 $text = "some text which shouldn't break there"; 848 $this->assertSame("some text which shouldn't ...", shorten_text($text, 31)); 849 $this->assertSame("some text which shouldn't ...", shorten_text($text, 30)); 850 $this->assertSame("some text which shouldn't ...", shorten_text($text, 29)); 851 } 852 853 public function test_shorten_text_known_tricky_case() { 854 // This case caused a bug up to 1.9.5 855 // ..........123456789012345678901234567890123456789.....0_____1___2___... 856 $text = "<h3>standard 'break-out' sub groups in TGs?</h3> <<There are several"; 857 $this->assertSame("<h3>standard 'break-out' sub groups in ...</h3>", 858 shorten_text($text, 41)); 859 $this->assertSame("<h3>standard 'break-out' sub groups in TGs?...</h3>", 860 shorten_text($text, 42)); 861 $this->assertSame("<h3>standard 'break-out' sub groups in TGs?</h3> ...", 862 shorten_text($text, 43)); 863 } 864 865 public function test_shorten_text_no_spaces() { 866 // ..........123456789. 867 $text = "<h1>123456789</h1>"; // A string with no convenient breaks. 868 $this->assertSame("<h1>12345...</h1>", shorten_text($text, 8)); 869 } 870 871 public function test_shorten_text_utf8_european() { 872 // Text without tags. 873 // ......123456789012345678901234567. 874 $text = "Žluťoučký koníček přeskočil"; 875 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 876 $this->assertSame("Žluťoučký koníče...", shorten_text($text, 19, true)); 877 $this->assertSame("Žluťoučký ...", shorten_text($text, 19, false)); 878 // And try it with 2-less (that are, in bytes, the middle of a sequence). 879 $this->assertSame("Žluťoučký koní...", shorten_text($text, 17, true)); 880 $this->assertSame("Žluťoučký ...", shorten_text($text, 17, false)); 881 882 // .........123456789012345678...901234567....89012345. 883 $text = "<p>Žluťoučký koníček <b>přeskočil</b> potůček</p>"; 884 $this->assertSame($text, shorten_text($text, 60)); 885 $this->assertSame("<p>Žluťoučký koníček ...</p>", shorten_text($text, 21)); 886 $this->assertSame("<p>Žluťoučký koníče...</p>", shorten_text($text, 19, true)); 887 $this->assertSame("<p>Žluťoučký ...</p>", shorten_text($text, 19, false)); 888 // And try it with 2 fewer (that are, in bytes, the middle of a sequence). 889 $this->assertSame("<p>Žluťoučký koní...</p>", shorten_text($text, 17, true)); 890 $this->assertSame("<p>Žluťoučký ...</p>", shorten_text($text, 17, false)); 891 // And try over one tag (start/end), it does proper text len. 892 $this->assertSame("<p>Žluťoučký koníček <b>př...</b></p>", shorten_text($text, 23, true)); 893 $this->assertSame("<p>Žluťoučký koníček <b>přeskočil</b> pot...</p>", shorten_text($text, 34, true)); 894 // And in the middle of one tag. 895 $this->assertSame("<p>Žluťoučký koníček <b>přeskočil...</b></p>", shorten_text($text, 30, true)); 896 } 897 898 public function test_shorten_text_utf8_oriental() { 899 // Japanese 900 // text without tags 901 // ......123456789012345678901234. 902 $text = '言語設定言語設定abcdefghijkl'; 903 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 904 $this->assertSame("言語設定言語...", shorten_text($text, 9, true)); 905 $this->assertSame("言語設定言語...", shorten_text($text, 9, false)); 906 $this->assertSame("言語設定言語設定ab...", shorten_text($text, 13, true)); 907 $this->assertSame("言語設定言語設定...", shorten_text($text, 13, false)); 908 909 // Chinese 910 // text without tags 911 // ......123456789012345678901234. 912 $text = '简体中文简体中文abcdefghijkl'; 913 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 914 $this->assertSame("简体中文简体...", shorten_text($text, 9, true)); 915 $this->assertSame("简体中文简体...", shorten_text($text, 9, false)); 916 $this->assertSame("简体中文简体中文ab...", shorten_text($text, 13, true)); 917 $this->assertSame("简体中文简体中文...", shorten_text($text, 13, false)); 918 } 919 920 public function test_shorten_text_multilang() { 921 // This is not necessaryily specific to multilang. The issue is really 922 // tags with attributes, where before we were generating invalid HTML 923 // output like shorten_text('<span id="x" class="y">A</span> B', 1) 924 // returning '<span id="x" ...</span>'. It is just that multilang 925 // requires the sort of HTML that is quite likely to trigger this. 926 // ........................................1... 927 $text = '<span lang="en" class="multilang">A</span>' . 928 '<span lang="fr" class="multilang">B</span>'; 929 $this->assertSame('<span lang="en" class="multilang">...</span>', 930 shorten_text($text, 1)); 931 } 932 933 public function test_usergetdate() { 934 global $USER, $CFG, $DB; 935 $this->resetAfterTest(); 936 937 // Check if forcetimezone is set then save it and set it to use user timezone. 938 $cfgforcetimezone = null; 939 if (isset($CFG->forcetimezone)) { 940 $cfgforcetimezone = $CFG->forcetimezone; 941 $CFG->forcetimezone = 99; // Get user default timezone. 942 } 943 944 $this->setAdminUser(); 945 946 $userstimezone = $USER->timezone; 947 $USER->timezone = 2;// Set the timezone to a known state. 948 949 // The string version of date comes from server locale setting and does 950 // not respect user language, so it is necessary to reset that. 951 $oldlocale = setlocale(LC_TIME, '0'); 952 setlocale(LC_TIME, 'en_AU.UTF-8'); 953 954 $ts = 1261540267; // The time this function was created. 955 956 $arr = usergetdate($ts, 1); // Specify the timezone as an argument. 957 $arr = array_values($arr); 958 959 list($seconds, $minutes, $hours, $mday, $wday, $mon, $year, $yday, $weekday, $month) = $arr; 960 $this->assertSame(7, $seconds); 961 $this->assertSame(51, $minutes); 962 $this->assertSame(4, $hours); 963 $this->assertSame(23, $mday); 964 $this->assertSame(3, $wday); 965 $this->assertSame(12, $mon); 966 $this->assertSame(2009, $year); 967 $this->assertSame(356, $yday); 968 $this->assertSame('Wednesday', $weekday); 969 $this->assertSame('December', $month); 970 $arr = usergetdate($ts); // Gets the timezone from the $USER object. 971 $arr = array_values($arr); 972 973 list($seconds, $minutes, $hours, $mday, $wday, $mon, $year, $yday, $weekday, $month) = $arr; 974 $this->assertSame(7, $seconds); 975 $this->assertSame(51, $minutes); 976 $this->assertSame(5, $hours); 977 $this->assertSame(23, $mday); 978 $this->assertSame(3, $wday); 979 $this->assertSame(12, $mon); 980 $this->assertSame(2009, $year); 981 $this->assertSame(356, $yday); 982 $this->assertSame('Wednesday', $weekday); 983 $this->assertSame('December', $month); 984 // Set the timezone back to what it was. 985 $USER->timezone = $userstimezone; 986 987 // Restore forcetimezone if changed. 988 if (!is_null($cfgforcetimezone)) { 989 $CFG->forcetimezone = $cfgforcetimezone; 990 } 991 992 setlocale(LC_TIME, $oldlocale); 993 } 994 995 public function test_mark_user_preferences_changed() { 996 $this->resetAfterTest(); 997 $otheruser = $this->getDataGenerator()->create_user(); 998 $otheruserid = $otheruser->id; 999 1000 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1001 mark_user_preferences_changed($otheruserid); 1002 1003 $this->assertEquals(get_cache_flag('userpreferenceschanged', $otheruserid, time()-10), 1); 1004 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1005 } 1006 1007 public function test_check_user_preferences_loaded() { 1008 global $DB; 1009 $this->resetAfterTest(); 1010 1011 $otheruser = $this->getDataGenerator()->create_user(); 1012 $otheruserid = $otheruser->id; 1013 1014 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1015 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1016 1017 $user = new stdClass(); 1018 $user->id = $otheruserid; 1019 1020 // Load. 1021 check_user_preferences_loaded($user); 1022 $this->assertTrue(isset($user->preference)); 1023 $this->assertTrue(is_array($user->preference)); 1024 $this->assertArrayHasKey('_lastloaded', $user->preference); 1025 $this->assertCount(1, $user->preference); 1026 1027 // Add preference via direct call. 1028 $DB->insert_record('user_preferences', array('name'=>'xxx', 'value'=>'yyy', 'userid'=>$user->id)); 1029 1030 // No cache reload yet. 1031 check_user_preferences_loaded($user); 1032 $this->assertCount(1, $user->preference); 1033 1034 // Forced reloading of cache. 1035 unset($user->preference); 1036 check_user_preferences_loaded($user); 1037 $this->assertCount(2, $user->preference); 1038 $this->assertSame('yyy', $user->preference['xxx']); 1039 1040 // Add preference via direct call. 1041 $DB->insert_record('user_preferences', array('name'=>'aaa', 'value'=>'bbb', 'userid'=>$user->id)); 1042 1043 // Test timeouts and modifications from different session. 1044 set_cache_flag('userpreferenceschanged', $user->id, 1, time() + 1000); 1045 $user->preference['_lastloaded'] = $user->preference['_lastloaded'] - 20; 1046 check_user_preferences_loaded($user); 1047 $this->assertCount(2, $user->preference); 1048 check_user_preferences_loaded($user, 10); 1049 $this->assertCount(3, $user->preference); 1050 $this->assertSame('bbb', $user->preference['aaa']); 1051 set_cache_flag('userpreferenceschanged', $user->id, null); 1052 } 1053 1054 public function test_set_user_preference() { 1055 global $DB, $USER; 1056 $this->resetAfterTest(); 1057 1058 $this->setAdminUser(); 1059 1060 $otheruser = $this->getDataGenerator()->create_user(); 1061 $otheruserid = $otheruser->id; 1062 1063 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1064 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1065 1066 $user = new stdClass(); 1067 $user->id = $otheruserid; 1068 1069 set_user_preference('aaa', 'bbb', $otheruserid); 1070 $this->assertSame('bbb', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'aaa'))); 1071 $this->assertSame('bbb', get_user_preferences('aaa', null, $otheruserid)); 1072 1073 set_user_preference('xxx', 'yyy', $user); 1074 $this->assertSame('yyy', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx'))); 1075 $this->assertSame('yyy', get_user_preferences('xxx', null, $otheruserid)); 1076 $this->assertTrue(is_array($user->preference)); 1077 $this->assertSame('bbb', $user->preference['aaa']); 1078 $this->assertSame('yyy', $user->preference['xxx']); 1079 1080 set_user_preference('xxx', null, $user); 1081 $this->assertFalse($DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx'))); 1082 $this->assertNull(get_user_preferences('xxx', null, $otheruserid)); 1083 1084 set_user_preference('ooo', true, $user); 1085 $prefs = get_user_preferences(null, null, $otheruserid); 1086 $this->assertSame($user->preference['aaa'], $prefs['aaa']); 1087 $this->assertSame($user->preference['ooo'], $prefs['ooo']); 1088 $this->assertSame('1', $prefs['ooo']); 1089 1090 set_user_preference('null', 0, $user); 1091 $this->assertSame('0', get_user_preferences('null', null, $otheruserid)); 1092 1093 $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid)); 1094 1095 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1096 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1097 1098 // Test $USER default. 1099 set_user_preference('_test_user_preferences_pref', 'ok'); 1100 $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']); 1101 unset_user_preference('_test_user_preferences_pref'); 1102 $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref'])); 1103 1104 // Test 1333 char values (no need for unicode, there are already tests for that in DB tests). 1105 $longvalue = str_repeat('a', 1333); 1106 set_user_preference('_test_long_user_preference', $longvalue); 1107 $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference')); 1108 $this->assertEquals($longvalue, 1109 $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference'))); 1110 1111 // Test > 1333 char values, coding_exception expected. 1112 $longvalue = str_repeat('a', 1334); 1113 try { 1114 set_user_preference('_test_long_user_preference', $longvalue); 1115 $this->fail('Exception expected - longer than 1333 chars not allowed as preference value'); 1116 } catch (moodle_exception $ex) { 1117 $this->assertInstanceOf('coding_exception', $ex); 1118 } 1119 1120 // Test invalid params. 1121 try { 1122 set_user_preference('_test_user_preferences_pref', array()); 1123 $this->fail('Exception expected - array not valid preference value'); 1124 } catch (moodle_exception $ex) { 1125 $this->assertInstanceOf('coding_exception', $ex); 1126 } 1127 try { 1128 set_user_preference('_test_user_preferences_pref', new stdClass); 1129 $this->fail('Exception expected - class not valid preference value'); 1130 } catch (moodle_exception $ex) { 1131 $this->assertInstanceOf('coding_exception', $ex); 1132 } 1133 try { 1134 set_user_preference('_test_user_preferences_pref', 1, array('xx' => 1)); 1135 $this->fail('Exception expected - user instance expected'); 1136 } catch (moodle_exception $ex) { 1137 $this->assertInstanceOf('coding_exception', $ex); 1138 } 1139 try { 1140 set_user_preference('_test_user_preferences_pref', 1, 'abc'); 1141 $this->fail('Exception expected - user instance expected'); 1142 } catch (moodle_exception $ex) { 1143 $this->assertInstanceOf('coding_exception', $ex); 1144 } 1145 try { 1146 set_user_preference('', 1); 1147 $this->fail('Exception expected - invalid name accepted'); 1148 } catch (moodle_exception $ex) { 1149 $this->assertInstanceOf('coding_exception', $ex); 1150 } 1151 try { 1152 set_user_preference('1', 1); 1153 $this->fail('Exception expected - invalid name accepted'); 1154 } catch (moodle_exception $ex) { 1155 $this->assertInstanceOf('coding_exception', $ex); 1156 } 1157 } 1158 1159 public function test_get_extra_user_fields() { 1160 global $CFG, $USER, $DB; 1161 $this->resetAfterTest(); 1162 1163 $this->setAdminUser(); 1164 1165 // It would be really nice if there were a way to 'mock' has_capability 1166 // checks (either to return true or false) but as there is not, this 1167 // test doesn't test the capability check. Presumably, anyone running 1168 // unit tests will have the capability. 1169 $context = context_system::instance(); 1170 1171 // No fields. 1172 $CFG->showuseridentity = ''; 1173 $this->assertEquals(array(), get_extra_user_fields($context)); 1174 1175 // One field. 1176 $CFG->showuseridentity = 'frog'; 1177 $this->assertEquals(array('frog'), get_extra_user_fields($context)); 1178 1179 // Two fields. 1180 $CFG->showuseridentity = 'frog,zombie'; 1181 $this->assertEquals(array('frog', 'zombie'), get_extra_user_fields($context)); 1182 1183 // No fields, except. 1184 $CFG->showuseridentity = ''; 1185 $this->assertEquals(array(), get_extra_user_fields($context, array('frog'))); 1186 1187 // One field. 1188 $CFG->showuseridentity = 'frog'; 1189 $this->assertEquals(array(), get_extra_user_fields($context, array('frog'))); 1190 1191 // Two fields. 1192 $CFG->showuseridentity = 'frog,zombie'; 1193 $this->assertEquals(array('zombie'), get_extra_user_fields($context, array('frog'))); 1194 } 1195 1196 public function test_get_extra_user_fields_sql() { 1197 global $CFG, $USER, $DB; 1198 $this->resetAfterTest(); 1199 1200 $this->setAdminUser(); 1201 1202 $context = context_system::instance(); 1203 1204 // No fields. 1205 $CFG->showuseridentity = ''; 1206 $this->assertSame('', get_extra_user_fields_sql($context)); 1207 1208 // One field. 1209 $CFG->showuseridentity = 'frog'; 1210 $this->assertSame(', frog', get_extra_user_fields_sql($context)); 1211 1212 // Two fields with table prefix. 1213 $CFG->showuseridentity = 'frog,zombie'; 1214 $this->assertSame(', u1.frog, u1.zombie', get_extra_user_fields_sql($context, 'u1')); 1215 1216 // Two fields with field prefix. 1217 $CFG->showuseridentity = 'frog,zombie'; 1218 $this->assertSame(', frog AS u_frog, zombie AS u_zombie', 1219 get_extra_user_fields_sql($context, '', 'u_')); 1220 1221 // One field excluded. 1222 $CFG->showuseridentity = 'frog'; 1223 $this->assertSame('', get_extra_user_fields_sql($context, '', '', array('frog'))); 1224 1225 // Two fields, one excluded, table+field prefix. 1226 $CFG->showuseridentity = 'frog,zombie'; 1227 $this->assertEquals(', u1.zombie AS u_zombie', 1228 get_extra_user_fields_sql($context, 'u1', 'u_', array('frog'))); 1229 } 1230 1231 /** 1232 * Test some critical TZ/DST. 1233 * 1234 * This method tests some special TZ/DST combinations that were fixed 1235 * by MDL-38999. The tests are done by comparing the results of the 1236 * output using Moodle TZ/DST support and PHP native one. 1237 * 1238 * Note: If you don't trust PHP TZ/DST support, can verify the 1239 * harcoded expectations below with: 1240 * http://www.tools4noobs.com/online_tools/unix_timestamp_to_datetime/ 1241 */ 1242 public function test_some_moodle_special_dst() { 1243 $stamp = 1365386400; // 2013/04/08 02:00:00 GMT/UTC. 1244 1245 // In Europe/Tallinn it was 2013/04/08 05:00:00. 1246 $expectation = '2013/04/08 05:00:00'; 1247 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1248 $phpdt->setTimezone(new DateTimeZone('Europe/Tallinn')); 1249 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1250 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'Europe/Tallinn', false); // Moodle result. 1251 $this->assertSame($expectation, $phpres); 1252 $this->assertSame($expectation, $moodleres); 1253 1254 // In St. Johns it was 2013/04/07 23:30:00. 1255 $expectation = '2013/04/07 23:30:00'; 1256 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1257 $phpdt->setTimezone(new DateTimeZone('America/St_Johns')); 1258 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1259 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'America/St_Johns', false); // Moodle result. 1260 $this->assertSame($expectation, $phpres); 1261 $this->assertSame($expectation, $moodleres); 1262 1263 $stamp = 1383876000; // 2013/11/08 02:00:00 GMT/UTC. 1264 1265 // In Europe/Tallinn it was 2013/11/08 04:00:00. 1266 $expectation = '2013/11/08 04:00:00'; 1267 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1268 $phpdt->setTimezone(new DateTimeZone('Europe/Tallinn')); 1269 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1270 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'Europe/Tallinn', false); // Moodle result. 1271 $this->assertSame($expectation, $phpres); 1272 $this->assertSame($expectation, $moodleres); 1273 1274 // In St. Johns it was 2013/11/07 22:30:00. 1275 $expectation = '2013/11/07 22:30:00'; 1276 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1277 $phpdt->setTimezone(new DateTimeZone('America/St_Johns')); 1278 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1279 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'America/St_Johns', false); // Moodle result. 1280 $this->assertSame($expectation, $phpres); 1281 $this->assertSame($expectation, $moodleres); 1282 } 1283 1284 public function test_userdate() { 1285 global $USER, $CFG, $DB; 1286 $this->resetAfterTest(); 1287 1288 $this->setAdminUser(); 1289 1290 $testvalues = array( 1291 array( 1292 'time' => '1309514400', 1293 'usertimezone' => 'America/Moncton', 1294 'timezone' => '0.0', // No dst offset. 1295 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM' 1296 ), 1297 array( 1298 'time' => '1309514400', 1299 'usertimezone' => 'America/Moncton', 1300 'timezone' => '99', // Dst offset and timezone offset. 1301 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM' 1302 ), 1303 array( 1304 'time' => '1309514400', 1305 'usertimezone' => 'America/Moncton', 1306 'timezone' => 'America/Moncton', // Dst offset and timezone offset. 1307 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM' 1308 ), 1309 array( 1310 'time' => '1293876000 ', 1311 'usertimezone' => 'America/Moncton', 1312 'timezone' => '0.0', // No dst offset. 1313 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM' 1314 ), 1315 array( 1316 'time' => '1293876000 ', 1317 'usertimezone' => 'America/Moncton', 1318 'timezone' => '99', // No dst offset in jan, so just timezone offset. 1319 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM' 1320 ), 1321 array( 1322 'time' => '1293876000 ', 1323 'usertimezone' => 'America/Moncton', 1324 'timezone' => 'America/Moncton', // No dst offset in jan. 1325 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM' 1326 ), 1327 array( 1328 'time' => '1293876000 ', 1329 'usertimezone' => '2', 1330 'timezone' => '99', // Take user timezone. 1331 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM' 1332 ), 1333 array( 1334 'time' => '1293876000 ', 1335 'usertimezone' => '-2', 1336 'timezone' => '99', // Take user timezone. 1337 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM' 1338 ), 1339 array( 1340 'time' => '1293876000 ', 1341 'usertimezone' => '-10', 1342 'timezone' => '2', // Take this timezone. 1343 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM' 1344 ), 1345 array( 1346 'time' => '1293876000 ', 1347 'usertimezone' => '-10', 1348 'timezone' => '-2', // Take this timezone. 1349 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM' 1350 ), 1351 array( 1352 'time' => '1293876000 ', 1353 'usertimezone' => '-10', 1354 'timezone' => 'random/time', // This should show server time. 1355 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM' 1356 ), 1357 array( 1358 'time' => '1293876000 ', 1359 'usertimezone' => '14', // Server time zone. 1360 'timezone' => '99', // This should show user time. 1361 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM' 1362 ), 1363 ); 1364 1365 // Check if forcetimezone is set then save it and set it to use user timezone. 1366 $cfgforcetimezone = null; 1367 if (isset($CFG->forcetimezone)) { 1368 $cfgforcetimezone = $CFG->forcetimezone; 1369 $CFG->forcetimezone = 99; // Get user default timezone. 1370 } 1371 // Store user default timezone to restore later. 1372 $userstimezone = $USER->timezone; 1373 1374 // The string version of date comes from server locale setting and does 1375 // not respect user language, so it is necessary to reset that. 1376 $oldlocale = setlocale(LC_TIME, '0'); 1377 setlocale(LC_TIME, 'en_AU.UTF-8'); 1378 1379 // Set default timezone to Australia/Perth, else time calculated 1380 // will not match expected values. Before that save system defaults. 1381 $systemdefaulttimezone = date_default_timezone_get(); 1382 date_default_timezone_set('Australia/Perth'); 1383 1384 foreach ($testvalues as $vals) { 1385 $USER->timezone = $vals['usertimezone']; 1386 $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']); 1387 1388 // On different systems case of AM PM changes so compare case insensitive. 1389 $vals['expectedoutput'] = core_text::strtolower($vals['expectedoutput']); 1390 $actualoutput = core_text::strtolower($actualoutput); 1391 1392 $this->assertSame($vals['expectedoutput'], $actualoutput, 1393 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput}, 1394 Please check if timezones are updated (Site adminstration -> location -> update timezone)"); 1395 } 1396 1397 // Restore user timezone back to what it was. 1398 $USER->timezone = $userstimezone; 1399 1400 // Restore forcetimezone. 1401 if (!is_null($cfgforcetimezone)) { 1402 $CFG->forcetimezone = $cfgforcetimezone; 1403 } 1404 1405 // Restore system default values. 1406 date_default_timezone_set($systemdefaulttimezone); 1407 setlocale(LC_TIME, $oldlocale); 1408 } 1409 1410 public function test_make_timestamp() { 1411 global $USER, $CFG, $DB; 1412 $this->resetAfterTest(); 1413 1414 $this->setAdminUser(); 1415 1416 $testvalues = array( 1417 array( 1418 'usertimezone' => 'America/Moncton', 1419 'year' => '2011', 1420 'month' => '7', 1421 'day' => '1', 1422 'hour' => '10', 1423 'minutes' => '00', 1424 'seconds' => '00', 1425 'timezone' => '0.0', 1426 'applydst' => false, // No dst offset. 1427 'expectedoutput' => '1309514400' // 6pm at UTC+0. 1428 ), 1429 array( 1430 'usertimezone' => 'America/Moncton', 1431 'year' => '2011', 1432 'month' => '7', 1433 'day' => '1', 1434 'hour' => '10', 1435 'minutes' => '00', 1436 'seconds' => '00', 1437 'timezone' => '99', // User default timezone. 1438 'applydst' => false, // Don't apply dst. 1439 'expectedoutput' => '1309528800' 1440 ), 1441 array( 1442 'usertimezone' => 'America/Moncton', 1443 'year' => '2011', 1444 'month' => '7', 1445 'day' => '1', 1446 'hour' => '10', 1447 'minutes' => '00', 1448 'seconds' => '00', 1449 'timezone' => '99', // User default timezone. 1450 'applydst' => true, // Apply dst. 1451 'expectedoutput' => '1309525200' 1452 ), 1453 array( 1454 'usertimezone' => 'America/Moncton', 1455 'year' => '2011', 1456 'month' => '7', 1457 'day' => '1', 1458 'hour' => '10', 1459 'minutes' => '00', 1460 'seconds' => '00', 1461 'timezone' => 'America/Moncton', // String timezone. 1462 'applydst' => true, // Apply dst. 1463 'expectedoutput' => '1309525200' 1464 ), 1465 array( 1466 'usertimezone' => '2', // No dst applyed. 1467 'year' => '2011', 1468 'month' => '7', 1469 'day' => '1', 1470 'hour' => '10', 1471 'minutes' => '00', 1472 'seconds' => '00', 1473 'timezone' => '99', // Take user timezone. 1474 'applydst' => true, // Apply dst. 1475 'expectedoutput' => '1309507200' 1476 ), 1477 array( 1478 'usertimezone' => '-2', // No dst applyed. 1479 'year' => '2011', 1480 'month' => '7', 1481 'day' => '1', 1482 'hour' => '10', 1483 'minutes' => '00', 1484 'seconds' => '00', 1485 'timezone' => '99', // Take usertimezone. 1486 'applydst' => true, // Apply dst. 1487 'expectedoutput' => '1309521600' 1488 ), 1489 array( 1490 'usertimezone' => '-10', // No dst applyed. 1491 'year' => '2011', 1492 'month' => '7', 1493 'day' => '1', 1494 'hour' => '10', 1495 'minutes' => '00', 1496 'seconds' => '00', 1497 'timezone' => '2', // Take this timezone. 1498 'applydst' => true, // Apply dst. 1499 'expectedoutput' => '1309507200' 1500 ), 1501 array( 1502 'usertimezone' => '-10', // No dst applyed. 1503 'year' => '2011', 1504 'month' => '7', 1505 'day' => '1', 1506 'hour' => '10', 1507 'minutes' => '00', 1508 'seconds' => '00', 1509 'timezone' => '-2', // Take this timezone. 1510 'applydst' => true, // Apply dst. 1511 'expectedoutput' => '1309521600' 1512 ), 1513 array( 1514 'usertimezone' => '-10', // No dst applyed. 1515 'year' => '2011', 1516 'month' => '7', 1517 'day' => '1', 1518 'hour' => '10', 1519 'minutes' => '00', 1520 'seconds' => '00', 1521 'timezone' => 'random/time', // This should show server time. 1522 'applydst' => true, // Apply dst. 1523 'expectedoutput' => '1309485600' 1524 ), 1525 array( 1526 'usertimezone' => '14', // Server time. 1527 'year' => '2011', 1528 'month' => '7', 1529 'day' => '1', 1530 'hour' => '10', 1531 'minutes' => '00', 1532 'seconds' => '00', 1533 'timezone' => '99', // Get user time. 1534 'applydst' => true, // Apply dst. 1535 'expectedoutput' => '1309485600' 1536 ) 1537 ); 1538 1539 // Check if forcetimezone is set then save it and set it to use user timezone. 1540 $cfgforcetimezone = null; 1541 if (isset($CFG->forcetimezone)) { 1542 $cfgforcetimezone = $CFG->forcetimezone; 1543 $CFG->forcetimezone = 99; // Get user default timezone. 1544 } 1545 1546 // Store user default timezone to restore later. 1547 $userstimezone = $USER->timezone; 1548 1549 // The string version of date comes from server locale setting and does 1550 // not respect user language, so it is necessary to reset that. 1551 $oldlocale = setlocale(LC_TIME, '0'); 1552 setlocale(LC_TIME, 'en_AU.UTF-8'); 1553 1554 // Set default timezone to Australia/Perth, else time calculated 1555 // Will not match expected values. Before that save system defaults. 1556 $systemdefaulttimezone = date_default_timezone_get(); 1557 date_default_timezone_set('Australia/Perth'); 1558 1559 // Test make_timestamp with all testvals and assert if anything wrong. 1560 foreach ($testvalues as $vals) { 1561 $USER->timezone = $vals['usertimezone']; 1562 $actualoutput = make_timestamp( 1563 $vals['year'], 1564 $vals['month'], 1565 $vals['day'], 1566 $vals['hour'], 1567 $vals['minutes'], 1568 $vals['seconds'], 1569 $vals['timezone'], 1570 $vals['applydst'] 1571 ); 1572 1573 // On different systems case of AM PM changes so compare case insensitive. 1574 $vals['expectedoutput'] = core_text::strtolower($vals['expectedoutput']); 1575 $actualoutput = core_text::strtolower($actualoutput); 1576 1577 $this->assertSame($vals['expectedoutput'], $actualoutput, 1578 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput}, 1579 Please check if timezones are updated (Site adminstration -> location -> update timezone)"); 1580 } 1581 1582 // Restore user timezone back to what it was. 1583 $USER->timezone = $userstimezone; 1584 1585 // Restore forcetimezone. 1586 if (!is_null($cfgforcetimezone)) { 1587 $CFG->forcetimezone = $cfgforcetimezone; 1588 } 1589 1590 // Restore system default values. 1591 date_default_timezone_set($systemdefaulttimezone); 1592 setlocale(LC_TIME, $oldlocale); 1593 } 1594 1595 /** 1596 * Test get_string and most importantly the implementation of the lang_string 1597 * object. 1598 */ 1599 public function test_get_string() { 1600 global $COURSE; 1601 1602 // Make sure we are using English. 1603 $originallang = $COURSE->lang; 1604 $COURSE->lang = 'en'; 1605 1606 $yes = get_string('yes'); 1607 $yesexpected = 'Yes'; 1608 $this->assertInternalType('string', $yes); 1609 $this->assertSame($yesexpected, $yes); 1610 1611 $yes = get_string('yes', 'moodle'); 1612 $this->assertInternalType('string', $yes); 1613 $this->assertSame($yesexpected, $yes); 1614 1615 $yes = get_string('yes', 'core'); 1616 $this->assertInternalType('string', $yes); 1617 $this->assertSame($yesexpected, $yes); 1618 1619 $yes = get_string('yes', ''); 1620 $this->assertInternalType('string', $yes); 1621 $this->assertSame($yesexpected, $yes); 1622 1623 $yes = get_string('yes', null); 1624 $this->assertInternalType('string', $yes); 1625 $this->assertSame($yesexpected, $yes); 1626 1627 $yes = get_string('yes', null, 1); 1628 $this->assertInternalType('string', $yes); 1629 $this->assertSame($yesexpected, $yes); 1630 1631 $days = 1; 1632 $numdays = get_string('numdays', 'core', '1'); 1633 $numdaysexpected = $days.' days'; 1634 $this->assertInternalType('string', $numdays); 1635 $this->assertSame($numdaysexpected, $numdays); 1636 1637 $yes = get_string('yes', null, null, true); 1638 $this->assertInstanceOf('lang_string', $yes); 1639 $this->assertSame($yesexpected, (string)$yes); 1640 1641 // Test using a lang_string object as the $a argument for a normal 1642 // get_string call (returning string). 1643 $test = new lang_string('yes', null, null, true); 1644 $testexpected = get_string('numdays', 'core', get_string('yes')); 1645 $testresult = get_string('numdays', null, $test); 1646 $this->assertInternalType('string', $testresult); 1647 $this->assertSame($testexpected, $testresult); 1648 1649 // Test using a lang_string object as the $a argument for an object 1650 // get_string call (returning lang_string). 1651 $test = new lang_string('yes', null, null, true); 1652 $testexpected = get_string('numdays', 'core', get_string('yes')); 1653 $testresult = get_string('numdays', null, $test, true); 1654 $this->assertInstanceOf('lang_string', $testresult); 1655 $this->assertSame($testexpected, "$testresult"); 1656 1657 // Make sure that object properties that can't be converted don't cause 1658 // errors. 1659 // Level one: This is as deep as current language processing goes. 1660 $test = new stdClass; 1661 $test->one = 'here'; 1662 $string = get_string('yes', null, $test, true); 1663 $this->assertEquals($yesexpected, $string); 1664 1665 // Make sure that object properties that can't be converted don't cause 1666 // errors. 1667 // Level two: Language processing doesn't currently reach this deep. 1668 // only immediate scalar properties are worked with. 1669 $test = new stdClass; 1670 $test->one = new stdClass; 1671 $test->one->two = 'here'; 1672 $string = get_string('yes', null, $test, true); 1673 $this->assertEquals($yesexpected, $string); 1674 1675 // Make sure that object properties that can't be converted don't cause 1676 // errors. 1677 // Level three: It should never ever go this deep, but we're making sure 1678 // it doesn't cause any probs anyway. 1679 $test = new stdClass; 1680 $test->one = new stdClass; 1681 $test->one->two = new stdClass; 1682 $test->one->two->three = 'here'; 1683 $string = get_string('yes', null, $test, true); 1684 $this->assertEquals($yesexpected, $string); 1685 1686 // Make sure that object properties that can't be converted don't cause 1687 // errors and check lang_string properties. 1688 // Level one: This is as deep as current language processing goes. 1689 $test = new stdClass; 1690 $test->one = new lang_string('yes'); 1691 $string = get_string('yes', null, $test, true); 1692 $this->assertEquals($yesexpected, $string); 1693 1694 // Make sure that object properties that can't be converted don't cause 1695 // errors and check lang_string properties. 1696 // Level two: Language processing doesn't currently reach this deep. 1697 // only immediate scalar properties are worked with. 1698 $test = new stdClass; 1699 $test->one = new stdClass; 1700 $test->one->two = new lang_string('yes'); 1701 $string = get_string('yes', null, $test, true); 1702 $this->assertEquals($yesexpected, $string); 1703 1704 // Make sure that object properties that can't be converted don't cause 1705 // errors and check lang_string properties. 1706 // Level three: It should never ever go this deep, but we're making sure 1707 // it doesn't cause any probs anyway. 1708 $test = new stdClass; 1709 $test->one = new stdClass; 1710 $test->one->two = new stdClass; 1711 $test->one->two->three = new lang_string('yes'); 1712 $string = get_string('yes', null, $test, true); 1713 $this->assertEquals($yesexpected, $string); 1714 1715 // Make sure that array properties that can't be converted don't cause 1716 // errors. 1717 $test = array(); 1718 $test['one'] = new stdClass; 1719 $test['one']->two = 'here'; 1720 $string = get_string('yes', null, $test, true); 1721 $this->assertEquals($yesexpected, $string); 1722 1723 // Same thing but as above except using an object... this is allowed :P. 1724 $string = get_string('yes', null, null, true); 1725 $object = new stdClass; 1726 $object->$string = 'Yes'; 1727 $this->assertEquals($yesexpected, $string); 1728 $this->assertEquals($yesexpected, $object->$string); 1729 1730 // Reset the language. 1731 $COURSE->lang = $originallang; 1732 } 1733 1734 /** 1735 * @expectedException PHPUnit_Framework_Error_Warning 1736 */ 1737 public function test_get_string_limitation() { 1738 // This is one of the limitations to the lang_string class. It can't be 1739 // used as a key. 1740 $array = array(get_string('yes', null, null, true) => 'yes'); 1741 } 1742 1743 /** 1744 * Test localised float formatting. 1745 */ 1746 public function test_format_float() { 1747 1748 // Special case for null. 1749 $this->assertEquals('', format_float(null)); 1750 1751 // Default 1 decimal place. 1752 $this->assertEquals('5.4', format_float(5.43)); 1753 $this->assertEquals('5.0', format_float(5.001)); 1754 1755 // Custom number of decimal places. 1756 $this->assertEquals('5.43000', format_float(5.43, 5)); 1757 1758 // Option to strip ending zeros after rounding. 1759 $this->assertEquals('5.43', format_float(5.43, 5, true, true)); 1760 $this->assertEquals('5', format_float(5.0001, 3, true, true)); 1761 1762 // Tests with a localised decimal separator. 1763 $this->define_local_decimal_separator(); 1764 1765 // Localisation on (default). 1766 $this->assertEquals('5X43000', format_float(5.43, 5)); 1767 $this->assertEquals('5X43', format_float(5.43, 5, true, true)); 1768 1769 // Localisation off. 1770 $this->assertEquals('5.43000', format_float(5.43, 5, false)); 1771 $this->assertEquals('5.43', format_float(5.43, 5, false, true)); 1772 } 1773 1774 /** 1775 * Test localised float unformatting. 1776 */ 1777 public function test_unformat_float() { 1778 1779 // Tests without the localised decimal separator. 1780 1781 // Special case for null, empty or white spaces only strings. 1782 $this->assertEquals(null, unformat_float(null)); 1783 $this->assertEquals(null, unformat_float('')); 1784 $this->assertEquals(null, unformat_float(' ')); 1785 1786 // Regular use. 1787 $this->assertEquals(5.4, unformat_float('5.4')); 1788 $this->assertEquals(5.4, unformat_float('5.4', true)); 1789 1790 // No decimal. 1791 $this->assertEquals(5.0, unformat_float('5')); 1792 1793 // Custom number of decimal. 1794 $this->assertEquals(5.43267, unformat_float('5.43267')); 1795 1796 // Empty decimal. 1797 $this->assertEquals(100.0, unformat_float('100.00')); 1798 1799 // With the thousand separator. 1800 $this->assertEquals(1000.0, unformat_float('1 000')); 1801 $this->assertEquals(1000.32, unformat_float('1 000.32')); 1802 1803 // Negative number. 1804 $this->assertEquals(-100.0, unformat_float('-100')); 1805 1806 // Wrong value. 1807 $this->assertEquals(0.0, unformat_float('Wrong value')); 1808 // Wrong value in strict mode. 1809 $this->assertFalse(unformat_float('Wrong value', true)); 1810 1811 // Combining options. 1812 $this->assertEquals(-1023.862567, unformat_float(' -1 023.862567 ')); 1813 1814 // Bad decimal separator (should crop the decimal). 1815 $this->assertEquals(50.0, unformat_float('50,57')); 1816 // Bad decimal separator in strict mode (should return false). 1817 $this->assertFalse(unformat_float('50,57', true)); 1818 1819 // Tests with a localised decimal separator. 1820 $this->define_local_decimal_separator(); 1821 1822 // We repeat the tests above but with the current decimal separator. 1823 1824 // Regular use without and with the localised separator. 1825 $this->assertEquals (5.4, unformat_float('5.4')); 1826 $this->assertEquals (5.4, unformat_float('5X4')); 1827 1828 // Custom number of decimal. 1829 $this->assertEquals (5.43267, unformat_float('5X43267')); 1830 1831 // Empty decimal. 1832 $this->assertEquals (100.0, unformat_float('100X00')); 1833 1834 // With the thousand separator. 1835 $this->assertEquals (1000.32, unformat_float('1 000X32')); 1836 1837 // Bad different separator (should crop the decimal). 1838 $this->assertEquals (50.0, unformat_float('50Y57')); 1839 // Bad different separator in strict mode (should return false). 1840 $this->assertFalse (unformat_float('50Y57', true)); 1841 1842 // Combining options. 1843 $this->assertEquals (-1023.862567, unformat_float(' -1 023X862567 ')); 1844 // Combining options in strict mode. 1845 $this->assertEquals (-1023.862567, unformat_float(' -1 023X862567 ', true)); 1846 } 1847 1848 /** 1849 * Test deleting of users. 1850 */ 1851 public function test_delete_user() { 1852 global $DB, $CFG; 1853 1854 $this->resetAfterTest(); 1855 1856 $guest = $DB->get_record('user', array('id'=>$CFG->siteguest), '*', MUST_EXIST); 1857 $admin = $DB->get_record('user', array('id'=>$CFG->siteadmins), '*', MUST_EXIST); 1858 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 1859 1860 $user = $this->getDataGenerator()->create_user(array('idnumber'=>'abc')); 1861 $user2 = $this->getDataGenerator()->create_user(array('idnumber'=>'xyz')); 1862 1863 // Delete user and capture event. 1864 $sink = $this->redirectEvents(); 1865 $result = delete_user($user); 1866 $events = $sink->get_events(); 1867 $sink->close(); 1868 $event = array_pop($events); 1869 1870 // Test user is deleted in DB. 1871 $this->assertTrue($result); 1872 $deluser = $DB->get_record('user', array('id'=>$user->id), '*', MUST_EXIST); 1873 $this->assertEquals(1, $deluser->deleted); 1874 $this->assertEquals(0, $deluser->picture); 1875 $this->assertSame('', $deluser->idnumber); 1876 $this->assertSame(md5($user->username), $deluser->email); 1877 $this->assertRegExp('/^'.preg_quote($user->email, '/').'\.\d*$/', $deluser->username); 1878 1879 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 1880 1881 // Test Event. 1882 $this->assertInstanceOf('\core\event\user_deleted', $event); 1883 $this->assertSame($user->id, $event->objectid); 1884 $this->assertSame('user_deleted', $event->get_legacy_eventname()); 1885 $this->assertEventLegacyData($user, $event); 1886 $expectedlogdata = array(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname); 1887 $this->assertEventLegacyLogData($expectedlogdata, $event); 1888 $eventdata = $event->get_data(); 1889 $this->assertSame($eventdata['other']['username'], $user->username); 1890 $this->assertSame($eventdata['other']['email'], $user->email); 1891 $this->assertSame($eventdata['other']['idnumber'], $user->idnumber); 1892 $this->assertSame($eventdata['other']['picture'], $user->picture); 1893 $this->assertSame($eventdata['other']['mnethostid'], $user->mnethostid); 1894 $this->assertEquals($user, $event->get_record_snapshot('user', $event->objectid)); 1895 $this->assertEventContextNotUsed($event); 1896 1897 // Try invalid params. 1898 $record = new stdClass(); 1899 $record->grrr = 1; 1900 try { 1901 delete_user($record); 1902 $this->fail('Expecting exception for invalid delete_user() $user parameter'); 1903 } catch (moodle_exception $ex) { 1904 $this->assertInstanceOf('coding_exception', $ex); 1905 } 1906 $record->id = 1; 1907 try { 1908 delete_user($record); 1909 $this->fail('Expecting exception for invalid delete_user() $user parameter'); 1910 } catch (moodle_exception $ex) { 1911 $this->assertInstanceOf('coding_exception', $ex); 1912 } 1913 1914 $record = new stdClass(); 1915 $record->id = 666; 1916 $record->username = 'xx'; 1917 $this->assertFalse($DB->record_exists('user', array('id'=>666))); // Any non-existent id is ok. 1918 $result = delete_user($record); 1919 $this->assertFalse($result); 1920 1921 $result = delete_user($guest); 1922 $this->assertFalse($result); 1923 1924 $result = delete_user($admin); 1925 $this->assertFalse($result); 1926 1927 $this->resetDebugging(); 1928 } 1929 1930 /** 1931 * Test function convert_to_array() 1932 */ 1933 public function test_convert_to_array() { 1934 // Check that normal classes are converted to arrays the same way as (array) would do. 1935 $obj = new stdClass(); 1936 $obj->prop1 = 'hello'; 1937 $obj->prop2 = array('first', 'second', 13); 1938 $obj->prop3 = 15; 1939 $this->assertEquals(convert_to_array($obj), (array)$obj); 1940 1941 // Check that context object (with iterator) is converted to array properly. 1942 $obj = context_system::instance(); 1943 $ar = array( 1944 'id' => $obj->id, 1945 'contextlevel' => $obj->contextlevel, 1946 'instanceid' => $obj->instanceid, 1947 'path' => $obj->path, 1948 'depth' => $obj->depth 1949 ); 1950 $this->assertEquals(convert_to_array($obj), $ar); 1951 } 1952 1953 /** 1954 * Test the function date_format_string(). 1955 */ 1956 public function test_date_format_string() { 1957 global $CFG; 1958 1959 // Forcing locale and timezone. 1960 $oldlocale = setlocale(LC_TIME, '0'); 1961 if ($CFG->ostype == 'WINDOWS') { 1962 setlocale(LC_TIME, 'English_Australia.1252'); 1963 } else { 1964 setlocale(LC_TIME, 'en_AU.UTF-8'); 1965 } 1966 $systemdefaulttimezone = date_default_timezone_get(); 1967 date_default_timezone_set('Australia/Perth'); 1968 1969 $tests = array( 1970 array( 1971 'tz' => 99, 1972 'str' => '%A, %d %B %Y, %I:%M %p', 1973 'expected' => 'Saturday, 01 January 2011, 06:00 PM' 1974 ), 1975 array( 1976 'tz' => 0, 1977 'str' => '%A, %d %B %Y, %I:%M %p', 1978 'expected' => 'Saturday, 01 January 2011, 10:00 AM' 1979 ), 1980 array( 1981 'tz' => -12, 1982 'str' => '%A, %d %B %Y, %I:%M %p', 1983 'expected' => 'Saturday, 01 January 2011, 10:00 AM' 1984 ), 1985 // Following tests pass on Windows only because en lang pack does 1986 // not contain localewincharset, in real life lang pack maintainers 1987 // may use only characters that are present in localewincharset 1988 // in format strings! 1989 array( 1990 'tz' => 99, 1991 'str' => 'Žluťoučký koníček %A', 1992 'expected' => 'Žluťoučký koníček Saturday' 1993 ), 1994 array( 1995 'tz' => 99, 1996 'str' => '言語設定言語 %A', 1997 'expected' => '言語設定言語 Saturday' 1998 ), 1999 array( 2000 'tz' => 99, 2001 'str' => '简体中文简体 %A', 2002 'expected' => '简体中文简体 Saturday' 2003 ), 2004 ); 2005 2006 // Note: date_format_string() uses the timezone only to differenciate 2007 // the server time from the UTC time. It does not modify the timestamp. 2008 // Hence similar results for timezones <= 13. 2009 // On different systems case of AM PM changes so compare case insensitive. 2010 foreach ($tests as $test) { 2011 $str = date_format_string(1293876000, $test['str'], $test['tz']); 2012 $this->assertSame(core_text::strtolower($test['expected']), core_text::strtolower($str)); 2013 } 2014 2015 // Restore system default values. 2016 date_default_timezone_set($systemdefaulttimezone); 2017 setlocale(LC_TIME, $oldlocale); 2018 } 2019 2020 public function test_get_config() { 2021 global $CFG; 2022 2023 $this->resetAfterTest(); 2024 2025 // Preparation. 2026 set_config('phpunit_test_get_config_1', 'test 1'); 2027 set_config('phpunit_test_get_config_2', 'test 2', 'mod_forum'); 2028 if (!is_array($CFG->config_php_settings)) { 2029 $CFG->config_php_settings = array(); 2030 } 2031 $CFG->config_php_settings['phpunit_test_get_config_3'] = 'test 3'; 2032 2033 if (!is_array($CFG->forced_plugin_settings)) { 2034 $CFG->forced_plugin_settings = array(); 2035 } 2036 if (!array_key_exists('mod_forum', $CFG->forced_plugin_settings)) { 2037 $CFG->forced_plugin_settings['mod_forum'] = array(); 2038 } 2039 $CFG->forced_plugin_settings['mod_forum']['phpunit_test_get_config_4'] = 'test 4'; 2040 $CFG->phpunit_test_get_config_5 = 'test 5'; 2041 2042 // Testing. 2043 $this->assertSame('test 1', get_config('core', 'phpunit_test_get_config_1')); 2044 $this->assertSame('test 2', get_config('mod_forum', 'phpunit_test_get_config_2')); 2045 $this->assertSame('test 3', get_config('core', 'phpunit_test_get_config_3')); 2046 $this->assertSame('test 4', get_config('mod_forum', 'phpunit_test_get_config_4')); 2047 $this->assertFalse(get_config('core', 'phpunit_test_get_config_5')); 2048 $this->assertFalse(get_config('core', 'phpunit_test_get_config_x')); 2049 $this->assertFalse(get_config('mod_forum', 'phpunit_test_get_config_x')); 2050 2051 // Test config we know to exist. 2052 $this->assertSame($CFG->dataroot, get_config('core', 'dataroot')); 2053 $this->assertSame($CFG->phpunit_dataroot, get_config('core', 'phpunit_dataroot')); 2054 $this->assertSame($CFG->dataroot, get_config('core', 'phpunit_dataroot')); 2055 $this->assertSame(get_config('core', 'dataroot'), get_config('core', 'phpunit_dataroot')); 2056 2057 // Test setting a config var that already exists. 2058 set_config('phpunit_test_get_config_1', 'test a'); 2059 $this->assertSame('test a', $CFG->phpunit_test_get_config_1); 2060 $this->assertSame('test a', get_config('core', 'phpunit_test_get_config_1')); 2061 2062 // Test cache invalidation. 2063 $cache = cache::make('core', 'config'); 2064 $this->assertInternalType('array', $cache->get('core')); 2065 $this->assertInternalType('array', $cache->get('mod_forum')); 2066 set_config('phpunit_test_get_config_1', 'test b'); 2067 $this->assertFalse($cache->get('core')); 2068 set_config('phpunit_test_get_config_4', 'test c', 'mod_forum'); 2069 $this->assertFalse($cache->get('mod_forum')); 2070 } 2071 2072 public function test_get_max_upload_sizes() { 2073 // Test with very low limits so we are not affected by php upload limits. 2074 // Test activity limit smallest. 2075 $sitebytes = 102400; 2076 $coursebytes = 51200; 2077 $modulebytes = 10240; 2078 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2079 2080 $this->assertSame('Activity upload limit (10KB)', $result['0']); 2081 $this->assertCount(2, $result); 2082 2083 // Test course limit smallest. 2084 $sitebytes = 102400; 2085 $coursebytes = 10240; 2086 $modulebytes = 51200; 2087 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2088 2089 $this->assertSame('Course upload limit (10KB)', $result['0']); 2090 $this->assertCount(2, $result); 2091 2092 // Test site limit smallest. 2093 $sitebytes = 10240; 2094 $coursebytes = 102400; 2095 $modulebytes = 51200; 2096 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2097 2098 $this->assertSame('Site upload limit (10KB)', $result['0']); 2099 $this->assertCount(2, $result); 2100 2101 // Test site limit not set. 2102 $sitebytes = 0; 2103 $coursebytes = 102400; 2104 $modulebytes = 51200; 2105 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2106 2107 $this->assertSame('Activity upload limit (50KB)', $result['0']); 2108 $this->assertCount(3, $result); 2109 2110 $sitebytes = 0; 2111 $coursebytes = 51200; 2112 $modulebytes = 102400; 2113 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2114 2115 $this->assertSame('Course upload limit (50KB)', $result['0']); 2116 $this->assertCount(3, $result); 2117 2118 // Test custom bytes in range. 2119 $sitebytes = 102400; 2120 $coursebytes = 51200; 2121 $modulebytes = 51200; 2122 $custombytes = 10240; 2123 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2124 2125 $this->assertCount(3, $result); 2126 2127 // Test custom bytes in range but non-standard. 2128 $sitebytes = 102400; 2129 $coursebytes = 51200; 2130 $modulebytes = 51200; 2131 $custombytes = 25600; 2132 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2133 2134 $this->assertCount(4, $result); 2135 2136 // Test custom bytes out of range. 2137 $sitebytes = 102400; 2138 $coursebytes = 51200; 2139 $modulebytes = 51200; 2140 $custombytes = 102400; 2141 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2142 2143 $this->assertCount(3, $result); 2144 2145 // Test custom bytes out of range and non-standard. 2146 $sitebytes = 102400; 2147 $coursebytes = 51200; 2148 $modulebytes = 51200; 2149 $custombytes = 256000; 2150 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2151 2152 $this->assertCount(3, $result); 2153 2154 // Test site limit only. 2155 $sitebytes = 51200; 2156 $result = get_max_upload_sizes($sitebytes); 2157 2158 $this->assertSame('Site upload limit (50KB)', $result['0']); 2159 $this->assertSame('50KB', $result['51200']); 2160 $this->assertSame('10KB', $result['10240']); 2161 $this->assertCount(3, $result); 2162 2163 // Test no limit. 2164 $result = get_max_upload_sizes(); 2165 $this->assertArrayHasKey('0', $result); 2166 $this->assertArrayHasKey(get_max_upload_file_size(), $result); 2167 } 2168 2169 /** 2170 * Test function password_is_legacy_hash(). 2171 */ 2172 public function test_password_is_legacy_hash() { 2173 // Well formed md5s should be matched. 2174 foreach (array('some', 'strings', 'to_check!') as $string) { 2175 $md5 = md5($string); 2176 $this->assertTrue(password_is_legacy_hash($md5)); 2177 } 2178 // Strings that are not md5s should not be matched. 2179 foreach (array('', AUTH_PASSWORD_NOT_CACHED, 'IPW8WTcsWNgAWcUS1FBVHegzJnw5M2jOmYkmfc8z.xdBOyC4Caeum') as $notmd5) { 2180 $this->assertFalse(password_is_legacy_hash($notmd5)); 2181 } 2182 } 2183 2184 /** 2185 * Test function validate_internal_user_password(). 2186 */ 2187 public function test_validate_internal_user_password() { 2188 // Test bcrypt hashes. 2189 $validhashes = array( 2190 'pw' => '$2y$10$LOSDi5eaQJhutSRun.OVJ.ZSxQZabCMay7TO1KmzMkDMPvU40zGXK', 2191 'abc' => '$2y$10$VWTOhVdsBbWwtdWNDRHSpewjd3aXBQlBQf5rBY/hVhw8hciarFhXa', 2192 'C0mP1eX_&}<?@*&%` |\"' => '$2y$10$3PJf.q.9ywNJlsInPbqc8.IFeSsvXrGvQLKRFBIhVu1h1I3vpIry6', 2193 'ĩńťėŕňăţĩōŋāĹ' => '$2y$10$3A2Y8WpfRAnP3czJiSv6N.6Xp0T8hW3QZz2hUCYhzyWr1kGP1yUve' 2194 ); 2195 2196 foreach ($validhashes as $password => $hash) { 2197 $user = new stdClass(); 2198 $user->auth = 'manual'; 2199 $user->password = $hash; 2200 // The correct password should be validated. 2201 $this->assertTrue(validate_internal_user_password($user, $password)); 2202 // An incorrect password should not be validated. 2203 $this->assertFalse(validate_internal_user_password($user, 'badpw')); 2204 } 2205 } 2206 2207 /** 2208 * Test function hash_internal_user_password(). 2209 */ 2210 public function test_hash_internal_user_password() { 2211 $passwords = array('pw', 'abc123', 'C0mP1eX_&}<?@*&%` |\"', 'ĩńťėŕňăţĩōŋāĹ'); 2212 2213 // Check that some passwords that we convert to hashes can 2214 // be validated. 2215 foreach ($passwords as $password) { 2216 $hash = hash_internal_user_password($password); 2217 $fasthash = hash_internal_user_password($password, true); 2218 $user = new stdClass(); 2219 $user->auth = 'manual'; 2220 $user->password = $hash; 2221 $this->assertTrue(validate_internal_user_password($user, $password)); 2222 2223 // They should not be in md5 format. 2224 $this->assertFalse(password_is_legacy_hash($hash)); 2225 2226 // Check that cost factor in hash is correctly set. 2227 $this->assertRegExp('/\$10\$/', $hash); 2228 $this->assertRegExp('/\$04\$/', $fasthash); 2229 } 2230 } 2231 2232 /** 2233 * Test function update_internal_user_password(). 2234 */ 2235 public function test_update_internal_user_password() { 2236 global $DB; 2237 $this->resetAfterTest(); 2238 $passwords = array('password', '1234', 'changeme', '****'); 2239 foreach ($passwords as $password) { 2240 $user = $this->getDataGenerator()->create_user(array('auth'=>'manual')); 2241 update_internal_user_password($user, $password); 2242 // The user object should have been updated. 2243 $this->assertTrue(validate_internal_user_password($user, $password)); 2244 // The database field for the user should also have been updated to the 2245 // same value. 2246 $this->assertSame($user->password, $DB->get_field('user', 'password', array('id' => $user->id))); 2247 } 2248 2249 $user = $this->getDataGenerator()->create_user(array('auth'=>'manual')); 2250 // Manually set the user's password to the md5 of the string 'password'. 2251 $DB->set_field('user', 'password', '5f4dcc3b5aa765d61d8327deb882cf99', array('id' => $user->id)); 2252 2253 $sink = $this->redirectEvents(); 2254 // Update the password. 2255 update_internal_user_password($user, 'password'); 2256 $events = $sink->get_events(); 2257 $sink->close(); 2258 $event = array_pop($events); 2259 2260 // Password should have been updated to a bcrypt hash. 2261 $this->assertFalse(password_is_legacy_hash($user->password)); 2262 2263 // Verify event information. 2264 $this->assertInstanceOf('\core\event\user_password_updated', $event); 2265 $this->assertSame($user->id, $event->relateduserid); 2266 $this->assertEquals(context_user::instance($user->id), $event->get_context()); 2267 $this->assertEventContextNotUsed($event); 2268 2269 // Verify recovery of property 'auth'. 2270 unset($user->auth); 2271 update_internal_user_password($user, 'newpassword'); 2272 $this->assertDebuggingCalled('User record in update_internal_user_password() must include field auth', 2273 DEBUG_DEVELOPER); 2274 $this->assertEquals('manual', $user->auth); 2275 } 2276 2277 /** 2278 * Testing that if the password is not cached, that it does not update 2279 * the user table and fire event. 2280 */ 2281 public function test_update_internal_user_password_no_cache() { 2282 $this->resetAfterTest(); 2283 2284 $user = $this->getDataGenerator()->create_user(array('auth' => 'cas')); 2285 $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2286 2287 $sink = $this->redirectEvents(); 2288 update_internal_user_password($user, 'wonkawonka'); 2289 $this->assertEquals(0, $sink->count(), 'User updated event should not fire'); 2290 } 2291 2292 /** 2293 * Test if the user has a password hash, but now their auth method 2294 * says not to cache it. Then it should update. 2295 */ 2296 public function test_update_internal_user_password_update_no_cache() { 2297 $this->resetAfterTest(); 2298 2299 $user = $this->getDataGenerator()->create_user(array('password' => 'test')); 2300 $this->assertNotEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2301 $user->auth = 'cas'; // Change to a auth that does not store passwords. 2302 2303 $sink = $this->redirectEvents(); 2304 update_internal_user_password($user, 'wonkawonka'); 2305 $this->assertGreaterThanOrEqual(1, $sink->count(), 'User updated event should fire'); 2306 2307 $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2308 } 2309 2310 public function test_fullname() { 2311 global $CFG; 2312 2313 $this->resetAfterTest(); 2314 2315 // Create a user to test the name display on. 2316 $record = array(); 2317 $record['firstname'] = 'Scott'; 2318 $record['lastname'] = 'Fletcher'; 2319 $record['firstnamephonetic'] = 'スコット'; 2320 $record['lastnamephonetic'] = 'フレチャー'; 2321 $record['alternatename'] = 'No friends'; 2322 $user = $this->getDataGenerator()->create_user($record); 2323 2324 // Back up config settings for restore later. 2325 $originalcfg = new stdClass(); 2326 $originalcfg->fullnamedisplay = $CFG->fullnamedisplay; 2327 $originalcfg->alternativefullnameformat = $CFG->alternativefullnameformat; 2328 2329 // Testing existing fullnamedisplay settings. 2330 $CFG->fullnamedisplay = 'firstname'; 2331 $testname = fullname($user); 2332 $this->assertSame($user->firstname, $testname); 2333 2334 $CFG->fullnamedisplay = 'firstname lastname'; 2335 $expectedname = "$user->firstname $user->lastname"; 2336 $testname = fullname($user); 2337 $this->assertSame($expectedname, $testname); 2338 2339 $CFG->fullnamedisplay = 'lastname firstname'; 2340 $expectedname = "$user->lastname $user->firstname"; 2341 $testname = fullname($user); 2342 $this->assertSame($expectedname, $testname); 2343 2344 $expectedname = get_string('fullnamedisplay', null, $user); 2345 $CFG->fullnamedisplay = 'language'; 2346 $testname = fullname($user); 2347 $this->assertSame($expectedname, $testname); 2348 2349 // Test override parameter. 2350 $CFG->fullnamedisplay = 'firstname'; 2351 $expectedname = "$user->firstname $user->lastname"; 2352 $testname = fullname($user, true); 2353 $this->assertSame($expectedname, $testname); 2354 2355 // Test alternativefullnameformat setting. 2356 // Test alternativefullnameformat that has been set to nothing. 2357 $CFG->alternativefullnameformat = ''; 2358 $expectedname = "$user->firstname $user->lastname"; 2359 $testname = fullname($user, true); 2360 $this->assertSame($expectedname, $testname); 2361 2362 // Test alternativefullnameformat that has been set to 'language'. 2363 $CFG->alternativefullnameformat = 'language'; 2364 $expectedname = "$user->firstname $user->lastname"; 2365 $testname = fullname($user, true); 2366 $this->assertSame($expectedname, $testname); 2367 2368 // Test customising the alternativefullnameformat setting with all additional name fields. 2369 $CFG->alternativefullnameformat = 'firstname lastname firstnamephonetic lastnamephonetic middlename alternatename'; 2370 $expectedname = "$user->firstname $user->lastname $user->firstnamephonetic $user->lastnamephonetic $user->middlename $user->alternatename"; 2371 $testname = fullname($user, true); 2372 $this->assertSame($expectedname, $testname); 2373 2374 // Test additional name fields. 2375 $CFG->fullnamedisplay = 'lastname lastnamephonetic firstname firstnamephonetic'; 2376 $expectedname = "$user->lastname $user->lastnamephonetic $user->firstname $user->firstnamephonetic"; 2377 $testname = fullname($user); 2378 $this->assertSame($expectedname, $testname); 2379 2380 // Test for handling missing data. 2381 $user->middlename = null; 2382 // Parenthesis with no data. 2383 $CFG->fullnamedisplay = 'firstname (middlename) lastname'; 2384 $expectedname = "$user->firstname $user->lastname"; 2385 $testname = fullname($user); 2386 $this->assertSame($expectedname, $testname); 2387 2388 // Extra spaces due to no data. 2389 $CFG->fullnamedisplay = 'firstname middlename lastname'; 2390 $expectedname = "$user->firstname $user->lastname"; 2391 $testname = fullname($user); 2392 $this->assertSame($expectedname, $testname); 2393 2394 // Regular expression testing. 2395 // Remove some data from the user fields. 2396 $user->firstnamephonetic = ''; 2397 $user->lastnamephonetic = ''; 2398 2399 // Removing empty brackets and excess whitespace. 2400 // All of these configurations should resolve to just firstname lastname. 2401 $configarray = array(); 2402 $configarray[] = 'firstname lastname [firstnamephonetic lastnamephonetic]'; 2403 $configarray[] = 'firstname lastname \'middlename\''; 2404 $configarray[] = 'firstname "firstnamephonetic" lastname'; 2405 $configarray[] = 'firstname 「firstnamephonetic」 lastname 「lastnamephonetic」'; 2406 2407 foreach ($configarray as $config) { 2408 $CFG->fullnamedisplay = $config; 2409 $expectedname = "$user->firstname $user->lastname"; 2410 $testname = fullname($user); 2411 $this->assertSame($expectedname, $testname); 2412 } 2413 2414 // Check to make sure that other characters are left in place. 2415 $configarray = array(); 2416 $configarray['0'] = new stdClass(); 2417 $configarray['0']->config = 'lastname firstname, middlename'; 2418 $configarray['0']->expectedname = "$user->lastname $user->firstname,"; 2419 $configarray['1'] = new stdClass(); 2420 $configarray['1']->config = 'lastname firstname + alternatename'; 2421 $configarray['1']->expectedname = "$user->lastname $user->firstname + $user->alternatename"; 2422 $configarray['2'] = new stdClass(); 2423 $configarray['2']->config = 'firstname aka: alternatename'; 2424 $configarray['2']->expectedname = "$user->firstname aka: $user->alternatename"; 2425 $configarray['3'] = new stdClass(); 2426 $configarray['3']->config = 'firstname (alternatename)'; 2427 $configarray['3']->expectedname = "$user->firstname ($user->alternatename)"; 2428 $configarray['4'] = new stdClass(); 2429 $configarray['4']->config = 'firstname [alternatename]'; 2430 $configarray['4']->expectedname = "$user->firstname [$user->alternatename]"; 2431 $configarray['5'] = new stdClass(); 2432 $configarray['5']->config = 'firstname "lastname"'; 2433 $configarray['5']->expectedname = "$user->firstname \"$user->lastname\""; 2434 2435 foreach ($configarray as $config) { 2436 $CFG->fullnamedisplay = $config->config; 2437 $expectedname = $config->expectedname; 2438 $testname = fullname($user); 2439 $this->assertSame($expectedname, $testname); 2440 } 2441 2442 // Test debugging message displays when 2443 // fullnamedisplay setting is "normal". 2444 $CFG->fullnamedisplay = 'firstname lastname'; 2445 unset($user); 2446 $user = new stdClass(); 2447 $user->firstname = 'Stan'; 2448 $user->lastname = 'Lee'; 2449 $namedisplay = fullname($user); 2450 $this->assertDebuggingCalled(); 2451 2452 // Tidy up after we finish testing. 2453 $CFG->fullnamedisplay = $originalcfg->fullnamedisplay; 2454 $CFG->alternativefullnameformat = $originalcfg->alternativefullnameformat; 2455 } 2456 2457 public function test_get_all_user_name_fields() { 2458 $this->resetAfterTest(); 2459 2460 // Additional names in an array. 2461 $testarray = array('firstnamephonetic' => 'firstnamephonetic', 2462 'lastnamephonetic' => 'lastnamephonetic', 2463 'middlename' => 'middlename', 2464 'alternatename' => 'alternatename', 2465 'firstname' => 'firstname', 2466 'lastname' => 'lastname'); 2467 $this->assertEquals($testarray, get_all_user_name_fields()); 2468 2469 // Additional names as a string. 2470 $teststring = 'firstnamephonetic,lastnamephonetic,middlename,alternatename,firstname,lastname'; 2471 $this->assertEquals($teststring, get_all_user_name_fields(true)); 2472 2473 // Additional names as a string with an alias. 2474 $teststring = 't.firstnamephonetic,t.lastnamephonetic,t.middlename,t.alternatename,t.firstname,t.lastname'; 2475 $this->assertEquals($teststring, get_all_user_name_fields(true, 't')); 2476 2477 // Additional name fields with a prefix - object. 2478 $testarray = array('firstnamephonetic' => 'authorfirstnamephonetic', 2479 'lastnamephonetic' => 'authorlastnamephonetic', 2480 'middlename' => 'authormiddlename', 2481 'alternatename' => 'authoralternatename', 2482 'firstname' => 'authorfirstname', 2483 'lastname' => 'authorlastname'); 2484 $this->assertEquals($testarray, get_all_user_name_fields(false, null, 'author')); 2485 2486 // Additional name fields with an alias and a title - string. 2487 $teststring = 'u.firstnamephonetic AS authorfirstnamephonetic,u.lastnamephonetic AS authorlastnamephonetic,u.middlename AS authormiddlename,u.alternatename AS authoralternatename,u.firstname AS authorfirstname,u.lastname AS authorlastname'; 2488 $this->assertEquals($teststring, get_all_user_name_fields(true, 'u', null, 'author')); 2489 2490 // Test the order parameter of the function. 2491 // Returning an array. 2492 $testarray = array('firstname' => 'firstname', 2493 'lastname' => 'lastname', 2494 'firstnamephonetic' => 'firstnamephonetic', 2495 'lastnamephonetic' => 'lastnamephonetic', 2496 'middlename' => 'middlename', 2497 'alternatename' => 'alternatename' 2498 ); 2499 $this->assertEquals($testarray, get_all_user_name_fields(false, null, null, null, true)); 2500 2501 // Returning a string. 2502 $teststring = 'firstname,lastname,firstnamephonetic,lastnamephonetic,middlename,alternatename'; 2503 $this->assertEquals($teststring, get_all_user_name_fields(true, null, null, null, true)); 2504 } 2505 2506 public function test_order_in_string() { 2507 $this->resetAfterTest(); 2508 2509 // Return an array in an order as they are encountered in a string. 2510 $valuearray = array('second', 'firsthalf', 'first'); 2511 $formatstring = 'first firsthalf some other text (second)'; 2512 $expectedarray = array('0' => 'first', '6' => 'firsthalf', '33' => 'second'); 2513 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2514 2515 // Try again with a different order for the format. 2516 $valuearray = array('second', 'firsthalf', 'first'); 2517 $formatstring = 'firsthalf first second'; 2518 $expectedarray = array('0' => 'firsthalf', '10' => 'first', '16' => 'second'); 2519 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2520 2521 // Try again with yet another different order for the format. 2522 $valuearray = array('second', 'firsthalf', 'first'); 2523 $formatstring = 'start seconds away second firstquater first firsthalf'; 2524 $expectedarray = array('19' => 'second', '38' => 'first', '44' => 'firsthalf'); 2525 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2526 } 2527 2528 public function test_complete_user_login() { 2529 global $USER, $DB; 2530 2531 $this->resetAfterTest(); 2532 $user = $this->getDataGenerator()->create_user(); 2533 $this->setUser(0); 2534 2535 $sink = $this->redirectEvents(); 2536 $loginuser = clone($user); 2537 $this->setCurrentTimeStart(); 2538 @complete_user_login($loginuser); // Hide session header errors. 2539 $this->assertSame($loginuser, $USER); 2540 $this->assertEquals($user->id, $USER->id); 2541 $events = $sink->get_events(); 2542 $sink->close(); 2543 2544 $this->assertCount(1, $events); 2545 $event = reset($events); 2546 $this->assertInstanceOf('\core\event\user_loggedin', $event); 2547 $this->assertEquals('user', $event->objecttable); 2548 $this->assertEquals($user->id, $event->objectid); 2549 $this->assertEquals(context_system::instance()->id, $event->contextid); 2550 $this->assertEventContextNotUsed($event); 2551 2552 $user = $DB->get_record('user', array('id'=>$user->id)); 2553 2554 $this->assertTimeCurrent($user->firstaccess); 2555 $this->assertTimeCurrent($user->lastaccess); 2556 2557 $this->assertTimeCurrent($USER->firstaccess); 2558 $this->assertTimeCurrent($USER->lastaccess); 2559 $this->assertTimeCurrent($USER->currentlogin); 2560 $this->assertSame(sesskey(), $USER->sesskey); 2561 $this->assertTimeCurrent($USER->preference['_lastloaded']); 2562 $this->assertObjectNotHasAttribute('password', $USER); 2563 $this->assertObjectNotHasAttribute('description', $USER); 2564 } 2565 2566 /** 2567 * Test require_logout. 2568 */ 2569 public function test_require_logout() { 2570 $this->resetAfterTest(); 2571 $user = $this->getDataGenerator()->create_user(); 2572 $this->setUser($user); 2573 2574 $this->assertTrue(isloggedin()); 2575 2576 // Logout user and capture event. 2577 $sink = $this->redirectEvents(); 2578 require_logout(); 2579 $events = $sink->get_events(); 2580 $sink->close(); 2581 $event = array_pop($events); 2582 2583 // Check if user is logged out. 2584 $this->assertFalse(isloggedin()); 2585 2586 // Test Event. 2587 $this->assertInstanceOf('\core\event\user_loggedout', $event); 2588 $this->assertSame($user->id, $event->objectid); 2589 $this->assertSame('user_logout', $event->get_legacy_eventname()); 2590 $this->assertEventLegacyData($user, $event); 2591 $expectedlogdata = array(SITEID, 'user', 'logout', 'view.php?id='.$event->objectid.'&course='.SITEID, $event->objectid, 0, 2592 $event->objectid); 2593 $this->assertEventLegacyLogData($expectedlogdata, $event); 2594 $this->assertEventContextNotUsed($event); 2595 } 2596 2597 public function test_email_to_user() { 2598 global $CFG; 2599 2600 $this->resetAfterTest(); 2601 2602 $user1 = $this->getDataGenerator()->create_user(); 2603 $user2 = $this->getDataGenerator()->create_user(); 2604 2605 $subject = 'subject'; 2606 $messagetext = 'message text'; 2607 $subject2 = 'subject 2'; 2608 $messagetext2 = 'message text 2'; 2609 2610 $this->assertNotEmpty($CFG->noemailever); 2611 email_to_user($user1, $user2, $subject, $messagetext); 2612 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting'); 2613 2614 unset_config('noemailever'); 2615 2616 email_to_user($user1, $user2, $subject, $messagetext); 2617 $this->assertDebuggingCalled('Unit tests must not send real emails! Use $this->redirectEmails()'); 2618 2619 $sink = $this->redirectEmails(); 2620 email_to_user($user1, $user2, $subject, $messagetext); 2621 email_to_user($user2, $user1, $subject2, $messagetext2); 2622 $this->assertSame(2, $sink->count()); 2623 $result = $sink->get_messages(); 2624 $this->assertCount(2, $result); 2625 $sink->close(); 2626 2627 $this->assertSame($subject, $result[0]->subject); 2628 $this->assertSame($messagetext, trim($result[0]->body)); 2629 $this->assertSame($user1->email, $result[0]->to); 2630 $this->assertSame($user2->email, $result[0]->from); 2631 2632 $this->assertSame($subject2, $result[1]->subject); 2633 $this->assertSame($messagetext2, trim($result[1]->body)); 2634 $this->assertSame($user2->email, $result[1]->to); 2635 $this->assertSame($user1->email, $result[1]->from); 2636 2637 email_to_user($user1, $user2, $subject, $messagetext); 2638 $this->assertDebuggingCalled('Unit tests must not send real emails! Use $this->redirectEmails()'); 2639 2640 // Test $CFG->emailonlyfromnoreplyaddress. 2641 set_config('emailonlyfromnoreplyaddress', 1); 2642 $this->assertNotEmpty($CFG->emailonlyfromnoreplyaddress); 2643 $sink = $this->redirectEmails(); 2644 email_to_user($user1, $user2, $subject, $messagetext); 2645 unset_config('emailonlyfromnoreplyaddress'); 2646 email_to_user($user1, $user2, $subject, $messagetext); 2647 $result = $sink->get_messages(); 2648 $this->assertEquals($CFG->noreplyaddress, $result[0]->from); 2649 $this->assertNotEquals($CFG->noreplyaddress, $result[1]->from); 2650 $sink->close(); 2651 } 2652 2653 /** 2654 * Test setnew_password_and_mail. 2655 */ 2656 public function test_setnew_password_and_mail() { 2657 global $DB, $CFG; 2658 2659 $this->resetAfterTest(); 2660 2661 $user = $this->getDataGenerator()->create_user(); 2662 2663 // Set config to allow email_to_user() to be called. 2664 $CFG->noemailever = false; 2665 2666 // Update user password. 2667 $sink = $this->redirectEvents(); 2668 $sink2 = $this->redirectEmails(); // Make sure we are redirecting emails. 2669 setnew_password_and_mail($user); 2670 $events = $sink->get_events(); 2671 $sink->close(); 2672 $sink2->close(); 2673 $event = array_pop($events); 2674 2675 // Test updated value. 2676 $dbuser = $DB->get_record('user', array('id' => $user->id)); 2677 $this->assertSame($user->firstname, $dbuser->firstname); 2678 $this->assertNotEmpty($dbuser->password); 2679 2680 // Test event. 2681 $this->assertInstanceOf('\core\event\user_password_updated', $event); 2682 $this->assertSame($user->id, $event->relateduserid); 2683 $this->assertEquals(context_user::instance($user->id), $event->get_context()); 2684 $this->assertEventContextNotUsed($event); 2685 } 2686 2687 /** 2688 * Test remove_course_content deletes course contents 2689 * TODO Add asserts to verify other data related to course is deleted as well. 2690 */ 2691 public function test_remove_course_contents() { 2692 2693 $this->resetAfterTest(); 2694 2695 $course = $this->getDataGenerator()->create_course(); 2696 $user = $this->getDataGenerator()->create_user(); 2697 $gen = $this->getDataGenerator()->get_plugin_generator('core_notes'); 2698 $note = $gen->create_instance(array('courseid' => $course->id, 'userid' => $user->id)); 2699 2700 $this->assertNotEquals(false, note_load($note->id)); 2701 remove_course_contents($course->id, false); 2702 $this->assertFalse(note_load($note->id)); 2703 } 2704 2705 /** 2706 * Test function username_load_fields_from_object(). 2707 */ 2708 public function test_username_load_fields_from_object() { 2709 $this->resetAfterTest(); 2710 2711 // This object represents the information returned from an sql query. 2712 $userinfo = new stdClass(); 2713 $userinfo->userid = 1; 2714 $userinfo->username = 'loosebruce'; 2715 $userinfo->firstname = 'Bruce'; 2716 $userinfo->lastname = 'Campbell'; 2717 $userinfo->firstnamephonetic = 'ブルース'; 2718 $userinfo->lastnamephonetic = 'カンベッル'; 2719 $userinfo->middlename = ''; 2720 $userinfo->alternatename = ''; 2721 $userinfo->email = ''; 2722 $userinfo->picture = 23; 2723 $userinfo->imagealt = 'Michael Jordan draining another basket.'; 2724 $userinfo->idnumber = 3982; 2725 2726 // Just user name fields. 2727 $user = new stdClass(); 2728 $user = username_load_fields_from_object($user, $userinfo); 2729 $expectedarray = new stdClass(); 2730 $expectedarray->firstname = 'Bruce'; 2731 $expectedarray->lastname = 'Campbell'; 2732 $expectedarray->firstnamephonetic = 'ブルース'; 2733 $expectedarray->lastnamephonetic = 'カンベッル'; 2734 $expectedarray->middlename = ''; 2735 $expectedarray->alternatename = ''; 2736 $this->assertEquals($user, $expectedarray); 2737 2738 // User information for showing a picture. 2739 $user = new stdClass(); 2740 $additionalfields = explode(',', user_picture::fields()); 2741 $user = username_load_fields_from_object($user, $userinfo, null, $additionalfields); 2742 $user->id = $userinfo->userid; 2743 $expectedarray = new stdClass(); 2744 $expectedarray->id = 1; 2745 $expectedarray->firstname = 'Bruce'; 2746 $expectedarray->lastname = 'Campbell'; 2747 $expectedarray->firstnamephonetic = 'ブルース'; 2748 $expectedarray->lastnamephonetic = 'カンベッル'; 2749 $expectedarray->middlename = ''; 2750 $expectedarray->alternatename = ''; 2751 $expectedarray->email = ''; 2752 $expectedarray->picture = 23; 2753 $expectedarray->imagealt = 'Michael Jordan draining another basket.'; 2754 $this->assertEquals($user, $expectedarray); 2755 2756 // Alter the userinfo object to have a prefix. 2757 $userinfo->authorfirstname = 'Bruce'; 2758 $userinfo->authorlastname = 'Campbell'; 2759 $userinfo->authorfirstnamephonetic = 'ブルース'; 2760 $userinfo->authorlastnamephonetic = 'カンベッル'; 2761 $userinfo->authormiddlename = ''; 2762 $userinfo->authorpicture = 23; 2763 $userinfo->authorimagealt = 'Michael Jordan draining another basket.'; 2764 $userinfo->authoremail = '[email protected]'; 2765 2766 2767 // Return an object with user picture information. 2768 $user = new stdClass(); 2769 $additionalfields = explode(',', user_picture::fields()); 2770 $user = username_load_fields_from_object($user, $userinfo, 'author', $additionalfields); 2771 $user->id = $userinfo->userid; 2772 $expectedarray = new stdClass(); 2773 $expectedarray->id = 1; 2774 $expectedarray->firstname = 'Bruce'; 2775 $expectedarray->lastname = 'Campbell'; 2776 $expectedarray->firstnamephonetic = 'ブルース'; 2777 $expectedarray->lastnamephonetic = 'カンベッル'; 2778 $expectedarray->middlename = ''; 2779 $expectedarray->alternatename = ''; 2780 $expectedarray->email = '[email protected]'; 2781 $expectedarray->picture = 23; 2782 $expectedarray->imagealt = 'Michael Jordan draining another basket.'; 2783 $this->assertEquals($user, $expectedarray); 2784 } 2785 2786 /** 2787 * Test function count_words(). 2788 */ 2789 public function test_count_words() { 2790 $count = count_words("one two three'four"); 2791 $this->assertEquals(3, $count); 2792 2793 $count = count_words('one+two three’four'); 2794 $this->assertEquals(3, $count); 2795 2796 $count = count_words('one"two three-four'); 2797 $this->assertEquals(3, $count); 2798 2799 $count = count_words('one@two three_four'); 2800 $this->assertEquals(4, $count); 2801 2802 $count = count_words('one\two three/four'); 2803 $this->assertEquals(4, $count); 2804 2805 $count = count_words(' one ... two three...four '); 2806 $this->assertEquals(4, $count); 2807 2808 $count = count_words('one.2 3,four'); 2809 $this->assertEquals(4, $count); 2810 2811 $count = count_words('1³ £2 €3.45 $6,789'); 2812 $this->assertEquals(4, $count); 2813 2814 $count = count_words('one—two ブルース カンベッル'); 2815 $this->assertEquals(4, $count); 2816 2817 $count = count_words('one…two ブルース … カンベッル'); 2818 $this->assertEquals(4, $count); 2819 } 2820 /** 2821 * Tests the getremoteaddr() function. 2822 */ 2823 public function test_getremoteaddr() { 2824 $xforwardedfor = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : null; 2825 2826 $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; 2827 $noip = getremoteaddr('1.1.1.1'); 2828 $this->assertEquals('1.1.1.1', $noip); 2829 2830 $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; 2831 $noip = getremoteaddr(); 2832 $this->assertEquals('0.0.0.0', $noip); 2833 2834 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1'; 2835 $singleip = getremoteaddr(); 2836 $this->assertEquals('127.0.0.1', $singleip); 2837 2838 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,127.0.0.2'; 2839 $twoip = getremoteaddr(); 2840 $this->assertEquals('127.0.0.1', $twoip); 2841 2842 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,127.0.0.2, 127.0.0.3'; 2843 $threeip = getremoteaddr(); 2844 $this->assertEquals('127.0.0.1', $threeip); 2845 2846 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1:65535,127.0.0.2'; 2847 $portip = getremoteaddr(); 2848 $this->assertEquals('127.0.0.1', $portip); 2849 2850 $_SERVER['HTTP_X_FORWARDED_FOR'] = '0:0:0:0:0:0:0:1,127.0.0.2'; 2851 $portip = getremoteaddr(); 2852 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 2853 2854 $_SERVER['HTTP_X_FORWARDED_FOR'] = '0::1,127.0.0.2'; 2855 $portip = getremoteaddr(); 2856 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 2857 2858 $_SERVER['HTTP_X_FORWARDED_FOR'] = '[0:0:0:0:0:0:0:1]:65535,127.0.0.2'; 2859 $portip = getremoteaddr(); 2860 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 2861 2862 $_SERVER['HTTP_X_FORWARDED_FOR'] = $xforwardedfor; 2863 2864 } 2865 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |