See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Persistent class tests. 19 * 20 * @package core 21 * @copyright 2015 Frédéric Massart - FMCorz.net 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 global $CFG; 27 28 /** 29 * Persistent testcase. 30 * 31 * @package core 32 * @copyright 2015 Frédéric Massart - FMCorz.net 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class core_persistent_testcase extends advanced_testcase { 36 37 public function setUp() { 38 $this->make_persistent_table(); 39 $this->resetAfterTest(); 40 } 41 42 /** 43 * Make the table for the persistent. 44 */ 45 protected function make_persistent_table() { 46 global $DB; 47 $dbman = $DB->get_manager(); 48 49 $table = new xmldb_table(core_testable_persistent::TABLE); 50 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 51 $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, null, null, null); 52 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null); 53 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null); 54 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); 55 $table->add_field('parentid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 56 $table->add_field('path', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 57 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 58 $table->add_field('scaleid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 59 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 60 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 61 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 62 63 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 64 65 if ($dbman->table_exists($table)) { 66 $dbman->drop_table($table); 67 } 68 69 $dbman->create_table($table); 70 } 71 72 public function test_properties_definition() { 73 $expected = array( 74 'shortname' => array( 75 'type' => PARAM_TEXT, 76 'default' => '', 77 'null' => NULL_NOT_ALLOWED 78 ), 79 'idnumber' => array( 80 'type' => PARAM_TEXT, 81 'null' => NULL_NOT_ALLOWED 82 ), 83 'description' => array( 84 'type' => PARAM_TEXT, 85 'default' => '', 86 'null' => NULL_NOT_ALLOWED 87 ), 88 'descriptionformat' => array( 89 'choices' => array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN), 90 'type' => PARAM_INT, 91 'default' => FORMAT_HTML, 92 'null' => NULL_NOT_ALLOWED 93 ), 94 'parentid' => array( 95 'type' => PARAM_INT, 96 'default' => 0, 97 'null' => NULL_NOT_ALLOWED 98 ), 99 'path' => array( 100 'type' => PARAM_RAW, 101 'default' => '', 102 'null' => NULL_NOT_ALLOWED 103 ), 104 'sortorder' => array( 105 'type' => PARAM_INT, 106 'message' => new lang_string('invalidrequest', 'error'), 107 'null' => NULL_NOT_ALLOWED 108 ), 109 'scaleid' => array( 110 'default' => null, 111 'type' => PARAM_INT, 112 'null' => NULL_ALLOWED 113 ), 114 'id' => array( 115 'default' => 0, 116 'type' => PARAM_INT, 117 'null' => NULL_NOT_ALLOWED 118 ), 119 'timecreated' => array( 120 'default' => 0, 121 'type' => PARAM_INT, 122 'null' => NULL_NOT_ALLOWED 123 ), 124 'timemodified' => array( 125 'default' => 0, 126 'type' => PARAM_INT, 127 'null' => NULL_NOT_ALLOWED 128 ), 129 'usermodified' => array( 130 'default' => 0, 131 'type' => PARAM_INT, 132 'null' => NULL_NOT_ALLOWED 133 ), 134 ); 135 $this->assertEquals($expected, core_testable_persistent::properties_definition()); 136 } 137 138 public function test_to_record() { 139 $p = new core_testable_persistent(); 140 $expected = (object) array( 141 'shortname' => '', 142 'idnumber' => null, 143 'description' => '', 144 'descriptionformat' => FORMAT_HTML, 145 'parentid' => 0, 146 'path' => '', 147 'sortorder' => null, 148 'id' => 0, 149 'timecreated' => 0, 150 'timemodified' => 0, 151 'usermodified' => 0, 152 'scaleid' => null, 153 ); 154 $this->assertEquals($expected, $p->to_record()); 155 } 156 157 public function test_from_record() { 158 $p = new core_testable_persistent(); 159 $data = (object) array( 160 'shortname' => 'ddd', 161 'idnumber' => 'abc', 162 'description' => 'xyz', 163 'descriptionformat' => FORMAT_PLAIN, 164 'parentid' => 999, 165 'path' => '/a/b/c', 166 'sortorder' => 12, 167 'id' => 1, 168 'timecreated' => 2, 169 'timemodified' => 3, 170 'usermodified' => 4, 171 'scaleid' => null, 172 ); 173 $p->from_record($data); 174 $this->assertEquals($data, $p->to_record()); 175 } 176 177 /** 178 * @expectedException coding_exception 179 */ 180 public function test_from_record_invalid_param() { 181 $p = new core_testable_persistent(); 182 $data = (object) array( 183 'invalidparam' => 'abc' 184 ); 185 186 $p->from_record($data); 187 } 188 189 public function test_validate() { 190 $data = (object) array( 191 'idnumber' => 'abc', 192 'sortorder' => 0 193 ); 194 $p = new core_testable_persistent(0, $data); 195 $this->assertFalse(isset($p->beforevalidate)); 196 $this->assertTrue($p->validate()); 197 $this->assertTrue(isset($p->beforevalidate)); 198 $this->assertTrue($p->is_valid()); 199 $this->assertEquals(array(), $p->get_errors()); 200 $p->set('descriptionformat', -100); 201 202 $expected = array( 203 'descriptionformat' => new lang_string('invaliddata', 'error'), 204 ); 205 $this->assertEquals($expected, $p->validate()); 206 $this->assertFalse($p->is_valid()); 207 $this->assertEquals($expected, $p->get_errors()); 208 } 209 210 public function test_validation_required() { 211 $data = (object) array( 212 'idnumber' => 'abc' 213 ); 214 $p = new core_testable_persistent(0, $data); 215 $expected = array( 216 'sortorder' => new lang_string('requiredelement', 'form'), 217 ); 218 $this->assertFalse($p->is_valid()); 219 $this->assertEquals($expected, $p->get_errors()); 220 } 221 222 public function test_validation_custom() { 223 $data = (object) array( 224 'idnumber' => 'abc', 225 'sortorder' => 10, 226 ); 227 $p = new core_testable_persistent(0, $data); 228 $expected = array( 229 'sortorder' => new lang_string('invalidkey', 'error'), 230 ); 231 $this->assertFalse($p->is_valid()); 232 $this->assertEquals($expected, $p->get_errors()); 233 } 234 235 public function test_validation_custom_message() { 236 $data = (object) array( 237 'idnumber' => 'abc', 238 'sortorder' => 'abc', 239 ); 240 $p = new core_testable_persistent(0, $data); 241 $expected = array( 242 'sortorder' => new lang_string('invalidrequest', 'error'), 243 ); 244 $this->assertFalse($p->is_valid()); 245 $this->assertEquals($expected, $p->get_errors()); 246 } 247 248 public function test_validation_choices() { 249 $data = (object) array( 250 'idnumber' => 'abc', 251 'sortorder' => 0, 252 'descriptionformat' => -100 253 ); 254 $p = new core_testable_persistent(0, $data); 255 $expected = array( 256 'descriptionformat' => new lang_string('invaliddata', 'error'), 257 ); 258 $this->assertFalse($p->is_valid()); 259 $this->assertEquals($expected, $p->get_errors()); 260 } 261 262 public function test_validation_type() { 263 $data = (object) array( 264 'idnumber' => 'abc', 265 'sortorder' => 'NaN' 266 ); 267 $p = new core_testable_persistent(0, $data); 268 $this->assertFalse($p->is_valid()); 269 $this->assertArrayHasKey('sortorder', $p->get_errors()); 270 } 271 272 public function test_validation_null() { 273 $data = (object) array( 274 'idnumber' => null, 275 'sortorder' => 0, 276 'scaleid' => 'bad!' 277 ); 278 $p = new core_testable_persistent(0, $data); 279 $this->assertFalse($p->is_valid()); 280 $this->assertArrayHasKey('idnumber', $p->get_errors()); 281 $this->assertArrayHasKey('scaleid', $p->get_errors()); 282 $p->set('idnumber', 'abc'); 283 $this->assertFalse($p->is_valid()); 284 $this->assertArrayNotHasKey('idnumber', $p->get_errors()); 285 $this->assertArrayHasKey('scaleid', $p->get_errors()); 286 $p->set('scaleid', null); 287 $this->assertTrue($p->is_valid()); 288 $this->assertArrayNotHasKey('scaleid', $p->get_errors()); 289 } 290 291 public function test_create() { 292 global $DB; 293 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 294 $this->assertFalse(isset($p->beforecreate)); 295 $this->assertFalse(isset($p->aftercreate)); 296 $p->create(); 297 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 298 $expected = $p->to_record(); 299 $this->assertTrue(isset($p->beforecreate)); 300 $this->assertTrue(isset($p->aftercreate)); 301 $this->assertEquals($expected->sortorder, $record->sortorder); 302 $this->assertEquals($expected->idnumber, $record->idnumber); 303 $this->assertEquals($expected->id, $record->id); 304 $this->assertTrue($p->is_valid()); // Should always be valid after a create. 305 } 306 307 public function test_update() { 308 global $DB; 309 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 310 $p->create(); 311 $id = $p->get('id'); 312 $p->set('sortorder', 456); 313 $p->from_record((object) array('idnumber' => 'def')); 314 $this->assertFalse(isset($p->beforeupdate)); 315 $this->assertFalse(isset($p->afterupdate)); 316 $p->update(); 317 318 $expected = $p->to_record(); 319 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 320 $this->assertTrue(isset($p->beforeupdate)); 321 $this->assertTrue(isset($p->afterupdate)); 322 $this->assertEquals($id, $record->id); 323 $this->assertEquals(456, $record->sortorder); 324 $this->assertEquals('def', $record->idnumber); 325 $this->assertTrue($p->is_valid()); // Should always be valid after an update. 326 } 327 328 public function test_save() { 329 global $DB; 330 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 331 $this->assertFalse(isset($p->beforecreate)); 332 $this->assertFalse(isset($p->aftercreate)); 333 $this->assertFalse(isset($p->beforeupdate)); 334 $this->assertFalse(isset($p->beforeupdate)); 335 $p->save(); 336 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 337 $expected = $p->to_record(); 338 $this->assertTrue(isset($p->beforecreate)); 339 $this->assertTrue(isset($p->aftercreate)); 340 $this->assertFalse(isset($p->beforeupdate)); 341 $this->assertFalse(isset($p->beforeupdate)); 342 $this->assertEquals($expected->sortorder, $record->sortorder); 343 $this->assertEquals($expected->idnumber, $record->idnumber); 344 $this->assertEquals($expected->id, $record->id); 345 $this->assertTrue($p->is_valid()); // Should always be valid after a save/create. 346 347 $p->set('idnumber', 'abcd'); 348 $p->save(); 349 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 350 $expected = $p->to_record(); 351 $this->assertTrue(isset($p->beforeupdate)); 352 $this->assertTrue(isset($p->beforeupdate)); 353 $this->assertEquals($expected->sortorder, $record->sortorder); 354 $this->assertEquals($expected->idnumber, $record->idnumber); 355 $this->assertEquals($expected->id, $record->id); 356 $this->assertTrue($p->is_valid()); // Should always be valid after a save/update. 357 } 358 359 public function test_read() { 360 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 361 $p->create(); 362 unset($p->beforevalidate); 363 unset($p->beforecreate); 364 unset($p->aftercreate); 365 366 $p2 = new core_testable_persistent($p->get('id')); 367 $this->assertEquals($p, $p2); 368 369 $p3 = new core_testable_persistent(); 370 $p3->set('id', $p->get('id')); 371 $p3->read(); 372 $this->assertEquals($p, $p3); 373 } 374 375 public function test_delete() { 376 global $DB; 377 378 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 379 $p->create(); 380 $this->assertNotEquals(0, $p->get('id')); 381 $this->assertTrue($DB->record_exists_select(core_testable_persistent::TABLE, 'id = ?', array($p->get('id')))); 382 $this->assertFalse(isset($p->beforedelete)); 383 $this->assertFalse(isset($p->afterdelete)); 384 385 $p->delete(); 386 $this->assertFalse($DB->record_exists_select(core_testable_persistent::TABLE, 'id = ?', array($p->get('id')))); 387 $this->assertEquals(0, $p->get('id')); 388 $this->assertEquals(true, $p->beforedelete); 389 $this->assertEquals(true, $p->afterdelete); 390 } 391 392 public function test_has_property() { 393 $this->assertFalse(core_testable_persistent::has_property('unknown')); 394 $this->assertTrue(core_testable_persistent::has_property('idnumber')); 395 } 396 397 public function test_custom_setter_getter() { 398 global $DB; 399 400 $path = array(1, 2, 3); 401 $json = json_encode($path); 402 403 $p = new core_testable_persistent(0, (object) array('sortorder' => 0, 'idnumber' => 'abc')); 404 $p->set('path', $path); 405 $this->assertEquals($path, $p->get('path')); 406 $this->assertEquals($json, $p->to_record()->path); 407 408 $p->create(); 409 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), 'id, path', MUST_EXIST); 410 $this->assertEquals($json, $record->path); 411 } 412 413 public function test_record_exists() { 414 global $DB; 415 $this->assertFalse($DB->record_exists(core_testable_persistent::TABLE, array('idnumber' => 'abc'))); 416 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 417 $p->create(); 418 $id = $p->get('id'); 419 $this->assertTrue(core_testable_persistent::record_exists($id)); 420 $this->assertTrue($DB->record_exists(core_testable_persistent::TABLE, array('idnumber' => 'abc'))); 421 $p->delete(); 422 $this->assertFalse(core_testable_persistent::record_exists($id)); 423 } 424 425 public function test_get_sql_fields() { 426 $expected = '' . 427 'c.id AS prefix_id, ' . 428 'c.shortname AS prefix_shortname, ' . 429 'c.idnumber AS prefix_idnumber, ' . 430 'c.description AS prefix_description, ' . 431 'c.descriptionformat AS prefix_descriptionformat, ' . 432 'c.parentid AS prefix_parentid, ' . 433 'c.path AS prefix_path, ' . 434 'c.sortorder AS prefix_sortorder, ' . 435 'c.scaleid AS prefix_scaleid, ' . 436 'c.timecreated AS prefix_timecreated, ' . 437 'c.timemodified AS prefix_timemodified, ' . 438 'c.usermodified AS prefix_usermodified'; 439 $this->assertEquals($expected, core_testable_persistent::get_sql_fields('c', 'prefix_')); 440 } 441 442 /** 443 * @expectedException coding_exception 444 * @expectedExceptionMessageRegExp /The alias .+ exceeds 30 characters/ 445 */ 446 public function test_get_sql_fields_too_long() { 447 core_testable_persistent::get_sql_fields('c'); 448 } 449 } 450 451 /** 452 * Example persistent class. 453 * 454 * @package core 455 * @copyright 2015 Frédéric Massart - FMCorz.net 456 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 457 */ 458 class core_testable_persistent extends \core\persistent { 459 460 const TABLE = 'phpunit_persistent'; 461 462 protected static function define_properties() { 463 return array( 464 'shortname' => array( 465 'type' => PARAM_TEXT, 466 'default' => '' 467 ), 468 'idnumber' => array( 469 'type' => PARAM_TEXT, 470 ), 471 'description' => array( 472 'type' => PARAM_TEXT, 473 'default' => '' 474 ), 475 'descriptionformat' => array( 476 'choices' => array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN), 477 'type' => PARAM_INT, 478 'default' => FORMAT_HTML 479 ), 480 'parentid' => array( 481 'type' => PARAM_INT, 482 'default' => 0 483 ), 484 'path' => array( 485 'type' => PARAM_RAW, 486 'default' => '' 487 ), 488 'sortorder' => array( 489 'type' => PARAM_INT, 490 'message' => new lang_string('invalidrequest', 'error') 491 ), 492 'scaleid' => array( 493 'type' => PARAM_INT, 494 'default' => null, 495 'null' => NULL_ALLOWED 496 ) 497 ); 498 } 499 500 protected function before_validate() { 501 $this->beforevalidate = true; 502 } 503 504 protected function before_create() { 505 $this->beforecreate = true; 506 } 507 508 protected function before_update() { 509 $this->beforeupdate = true; 510 } 511 512 protected function before_delete() { 513 $this->beforedelete = true; 514 } 515 516 protected function after_create() { 517 $this->aftercreate = true; 518 } 519 520 protected function after_update($result) { 521 $this->afterupdate = true; 522 } 523 524 protected function after_delete($result) { 525 $this->afterdelete = true; 526 } 527 528 protected function get_path() { 529 $value = $this->raw_get('path'); 530 if (!empty($value)) { 531 $value = json_decode($value); 532 } 533 return $value; 534 } 535 536 protected function set_path($value) { 537 if (!empty($value)) { 538 $value = json_encode($value); 539 } 540 $this->raw_set('path', $value); 541 } 542 543 protected function validate_sortorder($value) { 544 if ($value == 10) { 545 return new lang_string('invalidkey', 'error'); 546 } 547 return true; 548 } 549 550 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body