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 * Test phpunit_dataset features. 19 * 20 * @package core 21 * @category tests 22 * @copyright 2020 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 declare(strict_types=1); 27 28 namespace core; 29 30 use advanced_testcase; 31 use phpunit_dataset; 32 use org\bovigo\vfs\vfsStream; 33 34 /** 35 * Test phpunit_dataset features. 36 * 37 * @coversDefaultClass \phpunit_dataset 38 */ 39 class phpunit_dataset_test extends advanced_testcase { 40 41 42 /** 43 * @covers ::from_files 44 */ 45 public function test_from_files() { 46 47 $ds = new phpunit_dataset(); 48 49 $files = [ 50 __DIR__ . '/fixtures/sample_dataset.xml', 51 'user2' => __DIR__ . '/fixtures/sample_dataset.csv', 52 ]; 53 54 // We need public properties to check the basis. 55 $dsref = new \ReflectionClass($ds); 56 $dstables = $dsref->getProperty('tables'); 57 $dstables->setAccessible(true); 58 $dscolumns = $dsref->getProperty('columns'); 59 $dscolumns->setAccessible(true); 60 $dsrows = $dsref->getProperty('rows'); 61 $dsrows->setAccessible(true); 62 63 // Expectations. 64 $exptables = ['user', 'user2']; 65 $expcolumns = ['id', 'username', 'email']; 66 $exprows = [ 67 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 68 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 69 ]; 70 71 $ds->from_files($files); 72 73 $this->assertIsArray($dstables->getValue($ds)); 74 $this->assertSame($exptables, $dstables->getValue($ds)); 75 $this->assertIsArray($dscolumns->getValue($ds)); 76 $this->assertSame($expcolumns, $dscolumns->getValue($ds)['user']); 77 $this->assertSame($expcolumns, $dscolumns->getValue($ds)['user2']); 78 $this->assertIsArray($dsrows->getValue($ds)); 79 $this->assertEquals($exprows, $dsrows->getValue($ds)['user']); // Equals because of stringified integers on load. 80 $this->assertEquals($exprows, $dsrows->getValue($ds)['user2']); // Equals because of stringified integers on load. 81 } 82 83 /** 84 * test_from_file() data provider. 85 */ 86 public function from_file_provider() { 87 // Create an unreadable file with vfsStream. 88 $vfsfile = vfsStream::newFile('unreadable', 0222); 89 vfsStream::setup('root')->addChild($vfsfile); 90 91 return [ 92 'file not found' => [ 93 'fullpath' => '/this/does/not/exist', 94 'tablename' => 'user', 95 'exception' => 'from_file, file not found: /this/does/not/exist', 96 'tables' => [], 97 'columns' => [], 98 'rows' => [], 99 ], 100 'file not readable' => [ 101 'fullpath' => $vfsfile->url(), 102 'tablename' => 'user', 103 'exception' => 'from_file, file not readable: ' . $vfsfile->url(), 104 'tables' => [], 105 'columns' => [], 106 'rows' => [], 107 ], 108 'wrong extension' => [ 109 'fullpath' => __DIR__ . '/fixtures/sample_dataset.txt', 110 'tablename' => 'user', 111 'exception' => 'from_file, cannot handle files with extension: txt', 112 'tables' => [], 113 'columns' => [], 114 'rows' => [], 115 ], 116 'csv loads ok' => [ 117 'fullpath' => __DIR__ . '/fixtures/sample_dataset.csv', 118 'tablename' => 'user', 119 'exception' => null, 120 'tables' => ['user'], 121 'columns' => ['user' => 122 ['id', 'username', 'email'] 123 ], 124 'rows' => ['user' => 125 [ 126 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 127 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 128 ] 129 ], 130 ], 131 'xml loads ok' => [ 132 'fullpath' => __DIR__ . '/fixtures/sample_dataset.xml', 133 'tablename' => 'user', 134 'exception' => null, 135 'tables' => ['user'], 136 'columns' => ['user' => 137 ['id', 'username', 'email'] 138 ], 139 'rows' => ['user' => 140 [ 141 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 142 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 143 ] 144 ], 145 ], 146 ]; 147 } 148 149 /** 150 * @dataProvider from_file_provider 151 * @covers ::from_file 152 */ 153 public function test_from_file(string $fullpath, string $tablename, ?string $exception, 154 array $tables, array $columns, array $rows) { 155 156 $ds = new phpunit_dataset(); 157 158 // We need public properties to check the basis. 159 $dsref = new \ReflectionClass($ds); 160 $dstables = $dsref->getProperty('tables'); 161 $dstables->setAccessible(true); 162 $dscolumns = $dsref->getProperty('columns'); 163 $dscolumns->setAccessible(true); 164 $dsrows = $dsref->getProperty('rows'); 165 $dsrows->setAccessible(true); 166 167 // We are expecting an exception. 168 if (!empty($exception)) { 169 $this->expectException('coding_exception'); 170 $this->expectExceptionMessage($exception); 171 } 172 173 $ds->from_file($fullpath, $tablename); 174 175 $this->assertIsArray($dstables->getValue($ds)); 176 $this->assertSame($tables, $dstables->getValue($ds)); 177 $this->assertIsArray($dscolumns->getValue($ds)); 178 $this->assertSame($columns, $dscolumns->getValue($ds)); 179 $this->assertIsArray($dsrows->getValue($ds)); 180 $this->assertEquals($rows, $dsrows->getValue($ds)); // Equals because of stringified integers on load. 181 } 182 183 /** 184 * test_from_string() data provider. 185 */ 186 public function from_string_provider() { 187 188 return [ 189 'wrong type' => [ 190 'content' => file_get_contents(__DIR__ . '/fixtures/sample_dataset.xml'), 191 'type' => 'txt', 192 'tablename' => 'user', 193 'exception' => 'from_string, cannot handle contents of type: txt', 194 'tables' => [], 195 'columns' => [], 196 'rows' => [], 197 ], 198 'missing cvs table' => [ 199 'content' => file_get_contents(__DIR__ . '/fixtures/sample_dataset.csv'), 200 'type' => 'csv', 201 'tablename' => '', 202 'exception' => 'from_string, contents of type "cvs" require a $table to be passed, none found', 203 'tables' => [], 204 'columns' => [], 205 'rows' => [], 206 ], 207 'csv loads ok' => [ 208 'fullpath' => file_get_contents(__DIR__ . '/fixtures/sample_dataset.csv'), 209 'type' => 'csv', 210 'tablename' => 'user', 211 'exception' => null, 212 'tables' => ['user'], 213 'columns' => ['user' => 214 ['id', 'username', 'email'] 215 ], 216 'rows' => ['user' => 217 [ 218 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 219 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 220 ] 221 ], 222 ], 223 'xml loads ok' => [ 224 'fullpath' => file_get_contents(__DIR__ . '/fixtures/sample_dataset.xml'), 225 'type' => 'xml', 226 'tablename' => 'user', 227 'exception' => null, 228 'tables' => ['user'], 229 'columns' => ['user' => 230 ['id', 'username', 'email'] 231 ], 232 'rows' => ['user' => 233 [ 234 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 235 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 236 ] 237 ], 238 ], 239 ]; 240 } 241 242 /** 243 * @dataProvider from_string_provider 244 * @covers ::from_string 245 */ 246 public function test_from_string(string $content, string $type, string $tablename, ?string $exception, 247 array $tables, array $columns, array $rows) { 248 249 $ds = new phpunit_dataset(); 250 251 // We need public properties to check the basis. 252 $dsref = new \ReflectionClass($ds); 253 $dstables = $dsref->getProperty('tables'); 254 $dstables->setAccessible(true); 255 $dscolumns = $dsref->getProperty('columns'); 256 $dscolumns->setAccessible(true); 257 $dsrows = $dsref->getProperty('rows'); 258 $dsrows->setAccessible(true); 259 260 // We are expecting an exception. 261 if (!empty($exception)) { 262 $this->expectException('coding_exception'); 263 $this->expectExceptionMessage($exception); 264 } 265 266 $ds->from_string($content, $type, $tablename); 267 268 $this->assertIsArray($dstables->getValue($ds)); 269 $this->assertSame($tables, $dstables->getValue($ds)); 270 $this->assertIsArray($dscolumns->getValue($ds)); 271 $this->assertSame($columns, $dscolumns->getValue($ds)); 272 $this->assertIsArray($dsrows->getValue($ds)); 273 $this->assertEquals($rows, $dsrows->getValue($ds)); // Equals because of stringified integers on load. 274 } 275 276 /** 277 * test_from_array() data provider. 278 */ 279 public function from_array_provider() { 280 return [ 281 'repeated array table many structures' => [ 282 'structure' => [ 283 'user' => [ 284 ['id' => 5, 'name' => 'John'], 285 ['id' => 6, 'name' => 'Jane'], 286 ], 287 ], 288 'exception' => 'from_array, table already added to dataset: user', 289 'tables' => [], 290 'columns' => [], 291 'rows' => [], 292 'repeated' => true, // To force the table already exists exception. 293 ], 294 'wrong number of columns' => [ 295 'structure' => [ 296 'user' => [ 297 ['id' => 5, 'name' => 'John'], 298 ['id' => 6], 299 ], 300 ], 301 'exception' => 'from_array, number of columns must match number of values, found: 2 vs 1', 302 'tables' => [], 303 'columns' => [], 304 'rows' => [], 305 ], 306 'wrong not matching names of columns' => [ 307 'structure' => [ 308 'user' => [ 309 ['id' => 5, 'name' => 'John'], 310 ['id' => 6, 'noname' => 'Jane'], 311 ], 312 ], 313 'exception' => 'from_array, columns in all elements must match first one, found: id, noname', 314 'tables' => [], 315 'columns' => [], 316 'rows' => [], 317 ], 318 'ok non-associative format' => [ 319 'structure' => [ 320 'user' => [ 321 ['id', 'name'], 322 [5, 'John'], 323 [6, 'Jane'], 324 ], 325 ], 326 'exception' => null, 327 'tables' => ['user'], 328 'columns' => ['user' => 329 ['id', 'name'], 330 ], 331 'rows' => ['user' => 332 [ 333 ['id' => 5, 'name' => 'John'], 334 ['id' => 6, 'name' => 'Jane'], 335 ], 336 ], 337 ], 338 'ok associative format' => [ 339 'structure' => [ 340 'user' => [ 341 ['id' => 5, 'name' => 'John'], 342 ['id' => 6, 'name' => 'Jane'], 343 ], 344 ], 345 'exception' => null, 346 'tables' => ['user'], 347 'columns' => ['user' => 348 ['id', 'name'], 349 ], 350 'rows' => ['user' => 351 [ 352 ['id' => 5, 'name' => 'John'], 353 ['id' => 6, 'name' => 'Jane'], 354 ], 355 ], 356 ], 357 'ok multiple' => [ 358 'structure' => [ 359 'user' => [ 360 ['id' => 5, 'name' => 'John'], 361 ['id' => 6, 'name' => 'Jane'], 362 ], 363 'course' => [ 364 ['id' => 7, 'name' => '101'], 365 ['id' => 8, 'name' => '102'], 366 ], 367 ], 368 'exception' => null, 369 'tables' => ['user', 'course'], 370 'columns' => [ 371 'user' => ['id', 'name'], 372 'course' => ['id', 'name'], 373 ], 374 'rows' => [ 375 'user' => [ 376 ['id' => 5, 'name' => 'John'], 377 ['id' => 6, 'name' => 'Jane'], 378 ], 379 'course' => [ 380 ['id' => 7, 'name' => '101'], 381 ['id' => 8, 'name' => '102'], 382 ], 383 ], 384 ], 385 ]; 386 } 387 388 /** 389 * @dataProvider from_array_provider 390 * @covers ::from_array 391 */ 392 public function test_from_array(array $structure, ?string $exception, 393 array $tables, array $columns, array $rows, ?bool $repeated = false) { 394 395 $ds = new phpunit_dataset(); 396 397 // We need public properties to check the basis. 398 $dsref = new \ReflectionClass($ds); 399 $dstables = $dsref->getProperty('tables'); 400 $dstables->setAccessible(true); 401 $dscolumns = $dsref->getProperty('columns'); 402 $dscolumns->setAccessible(true); 403 $dsrows = $dsref->getProperty('rows'); 404 $dsrows->setAccessible(true); 405 406 // We are expecting an exception. 407 if (!empty($exception)) { 408 $this->expectException('coding_exception'); 409 $this->expectExceptionMessage($exception); 410 } 411 412 $ds->from_array($structure); 413 if ($repeated) { 414 $ds->from_array($structure); 415 } 416 417 $this->assertIsArray($dstables->getValue($ds)); 418 $this->assertSame($tables, $dstables->getValue($ds)); 419 $this->assertIsArray($dscolumns->getValue($ds)); 420 $this->assertSame($columns, $dscolumns->getValue($ds)); 421 $this->assertIsArray($dsrows->getValue($ds)); 422 $this->assertEquals($rows, $dsrows->getValue($ds)); // Equals because of stringified integers on load. 423 } 424 425 /** 426 * test_load_csv() data provider. 427 */ 428 public function load_csv_provider() { 429 430 return [ 431 'repeated csv table many files' => [ 432 'files' => [ 433 __DIR__ . '/fixtures/sample_dataset.xml', 434 'user' => __DIR__ . '/fixtures/sample_dataset.csv', 435 ], 436 'exception' => 'csv_dataset_format, table already added to dataset: user', 437 'tables' => [], 438 'columns' => [], 439 'rows' => [], 440 ], 441 'ok one csv file' => [ 442 'files' => [ 443 'user' => __DIR__ . '/fixtures/sample_dataset.csv', 444 ], 445 'exception' => null, 446 'tables' => ['user'], 447 'columns' => ['user' => 448 ['id', 'username', 'email'] 449 ], 450 'rows' => ['user' => 451 [ 452 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 453 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 454 ] 455 ], 456 ], 457 'ok multiple csv files' => [ 458 'files' => [ 459 'user1' => __DIR__ . '/fixtures/sample_dataset.csv', 460 'user2' => __DIR__ . '/fixtures/sample_dataset.csv', 461 ], 462 'exception' => null, 463 'tables' => ['user1', 'user2'], 464 'columns' => [ 465 'user1' => ['id', 'username', 'email'], 466 'user2' => ['id', 'username', 'email'], 467 ], 468 'rows' => [ 469 'user1' => [ 470 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 471 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 472 ], 473 'user2' => [ 474 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 475 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 476 ], 477 ], 478 ], 479 ]; 480 } 481 482 /** 483 * @dataProvider load_csv_provider 484 * @covers ::load_csv 485 */ 486 public function test_load_csv(array $files, ?string $exception, 487 array $tables, array $columns, array $rows) { 488 489 $ds = new phpunit_dataset(); 490 491 // We need public properties to check the basis. 492 $dsref = new \ReflectionClass($ds); 493 $dstables = $dsref->getProperty('tables'); 494 $dstables->setAccessible(true); 495 $dscolumns = $dsref->getProperty('columns'); 496 $dscolumns->setAccessible(true); 497 $dsrows = $dsref->getProperty('rows'); 498 $dsrows->setAccessible(true); 499 500 // We are expecting an exception. 501 if (!empty($exception)) { 502 $this->expectException('coding_exception'); 503 $this->expectExceptionMessage($exception); 504 } 505 506 $ds->from_files($files); 507 508 $this->assertIsArray($dstables->getValue($ds)); 509 $this->assertSame($tables, $dstables->getValue($ds)); 510 $this->assertIsArray($dscolumns->getValue($ds)); 511 $this->assertSame($columns, $dscolumns->getValue($ds)); 512 $this->assertIsArray($dsrows->getValue($ds)); 513 $this->assertEquals($rows, $dsrows->getValue($ds)); // Equals because of stringified integers on load. 514 } 515 516 /** 517 * test_load_xml() data provider. 518 */ 519 public function load_xml_provider() { 520 521 return [ 522 'repeated xml table multiple files' => [ 523 'files' => [ 524 'user' => __DIR__ . '/fixtures/sample_dataset.csv', 525 __DIR__ . '/fixtures/sample_dataset.xml', 526 ], 527 'exception' => 'xml_dataset_format, table already added to dataset: user', 528 'tables' => [], 529 'columns' => [], 530 'rows' => [], 531 ], 532 'repeated xml table one file' => [ 533 'files' => [__DIR__ . '/fixtures/sample_dataset_repeated.xml'], 534 'exception' => 'xml_dataset_format, table already added to dataset: user', 535 'tables' => [], 536 'columns' => [], 537 'rows' => [], 538 ], 539 'wrong dataset element' => [ 540 'files' => [__DIR__ . '/fixtures/sample_dataset_wrong_dataset.xml'], 541 'exception' => 'xml_dataset_format, main xml element must be "dataset", found: nodataset', 542 'tables' => [], 543 'columns' => [], 544 'rows' => [], 545 ], 546 'wrong table element' => [ 547 'files' => [__DIR__ . '/fixtures/sample_dataset_wrong_table.xml'], 548 'exception' => 'xml_dataset_format, only "table" elements allowed, found: notable', 549 'tables' => [], 550 'columns' => [], 551 'rows' => [], 552 ], 553 'wrong table name attribute' => [ 554 'files' => [__DIR__ . '/fixtures/sample_dataset_wrong_attribute.xml'], 555 'exception' => 'xml_dataset_format, "table" element only allows "name" attribute', 556 'tables' => [], 557 'columns' => [], 558 'rows' => [], 559 ], 560 'only col and row allowed' => [ 561 'files' => [__DIR__ . '/fixtures/sample_dataset_only_colrow.xml'], 562 'exception' => 'xml_dataset_format, only "column or "row" elements allowed, found: nocolumn', 563 'tables' => [], 564 'columns' => [], 565 'rows' => [], 566 ], 567 'wrong value element' => [ 568 'files' => [__DIR__ . '/fixtures/sample_dataset_wrong_value.xml'], 569 'exception' => 'xml_dataset_format, only "value" elements allowed, found: novalue', 570 'tables' => [], 571 'columns' => [], 572 'rows' => [], 573 ], 574 'column before row' => [ 575 'files' => [__DIR__ . '/fixtures/sample_dataset_col_before_row.xml'], 576 'exception' => 'xml_dataset_format, "column" elements always must be before "row" ones', 577 'tables' => [], 578 'columns' => [], 579 'rows' => [], 580 ], 581 'row after column' => [ 582 'files' => [__DIR__ . '/fixtures/sample_dataset_row_after_col.xml'], 583 'exception' => 'xml_dataset_format, "row" elements always must be after "column" ones', 584 'tables' => [], 585 'columns' => [], 586 'rows' => [], 587 ], 588 'number of columns' => [ 589 'files' => [__DIR__ . '/fixtures/sample_dataset_number_of_columns.xml'], 590 'exception' => 'xml_dataset_format, number of columns must match number of values, found: 4 vs 3', 591 'tables' => [], 592 'columns' => [], 593 'rows' => [], 594 ], 595 'ok one xml file' => [ 596 'files' => [__DIR__ . '/fixtures/sample_dataset.xml'], 597 'exception' => null, 598 'tables' => ['user'], 599 'columns' => ['user' => 600 ['id', 'username', 'email'] 601 ], 602 'rows' => ['user' => 603 [ 604 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 605 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 606 ] 607 ], 608 ], 609 'ok multiple xml files' => [ 610 'files' => [ 611 'user1' => __DIR__ . '/fixtures/sample_dataset.csv', 612 __DIR__ . '/fixtures/sample_dataset.xml', 613 ], 614 'exception' => null, 615 'tables' => ['user1', 'user'], 616 'columns' => [ 617 'user1' => ['id', 'username', 'email'], 618 'user' => ['id', 'username', 'email'], 619 ], 620 'rows' => [ 621 'user1' => [ 622 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 623 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 624 ], 625 'user' => [ 626 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 627 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 628 ], 629 ], 630 ], 631 'ok many tables in one xml' => [ 632 'files' => [__DIR__ . '/fixtures/sample_dataset_many.xml'], 633 'exception' => null, 634 'tables' => ['user', 'course'], 635 'columns' => [ 636 'user' => ['id', 'username', 'email'], 637 'course' => ['id', 'shortname', 'fullname'], 638 ], 639 'rows' => [ 640 'user' => [ 641 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 642 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 643 ], 644 'course' => [ 645 ['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 646 ['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 647 ], 648 ], 649 ], 650 ]; 651 } 652 653 /** 654 * @dataProvider load_xml_provider 655 * @covers ::load_xml 656 */ 657 public function test_load_xml(array $files, ?string $exception, 658 array $tables, array $columns, array $rows) { 659 660 $ds = new phpunit_dataset(); 661 662 // We need public properties to check the basis. 663 $dsref = new \ReflectionClass($ds); 664 $dstables = $dsref->getProperty('tables'); 665 $dstables->setAccessible(true); 666 $dscolumns = $dsref->getProperty('columns'); 667 $dscolumns->setAccessible(true); 668 $dsrows = $dsref->getProperty('rows'); 669 $dsrows->setAccessible(true); 670 671 // We are expecting an exception. 672 if (!empty($exception)) { 673 $this->expectException('coding_exception'); 674 $this->expectExceptionMessage($exception); 675 } 676 677 $ds->from_files($files); 678 679 $this->assertIsArray($dstables->getValue($ds)); 680 $this->assertSame($tables, $dstables->getValue($ds)); 681 $this->assertIsArray($dscolumns->getValue($ds)); 682 $this->assertSame($columns, $dscolumns->getValue($ds)); 683 $this->assertIsArray($dsrows->getValue($ds)); 684 $this->assertEquals($rows, $dsrows->getValue($ds)); // Equals because of stringified integers on load. 685 } 686 687 /** 688 * test_to_database() data provider. 689 */ 690 public function to_database_provider() { 691 692 return [ 693 'wrong table requested' => [ 694 'files' => [__DIR__ . '/fixtures/sample_dataset_insert.xml'], 695 'filter' => ['wrongtable'], 696 'exception' => 'dataset_to_database, table is not in the dataset: wrongtable', 697 'columns' => [], 698 'rows' => [], 699 ], 700 'one table insert' => [ 701 'files' => [__DIR__ . '/fixtures/sample_dataset_insert.xml'], 702 'filter' => [], 703 'exception' => null, 704 'columns' => [ 705 'user' => ['username', 'email'], 706 ], 707 'rows' => ['user' => 708 [ 709 (object)['username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 710 (object)['username' => 'pepa.novak', 'email' => 'pepa@example.com'], 711 ] 712 ], 713 ], 714 'one table import' => [ 715 'files' => [__DIR__ . '/fixtures/sample_dataset.xml'], 716 'filter' => [], 717 'exception' => null, 718 'columns' => [ 719 'user' => ['id', 'username', 'email'], 720 ], 721 'rows' => ['user' => 722 [ 723 (object)['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 724 (object)['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 725 ] 726 ], 727 ], 728 'multiple table many files import' => [ 729 'files' => [ 730 __DIR__ . '/fixtures/sample_dataset.xml', 731 __DIR__ . '/fixtures/sample_dataset2.xml', 732 ], 733 'filter' => [], 734 'exception' => null, 735 'columns' => [ 736 'user' => ['id', 'username', 'email'], 737 'course' => ['id', 'shortname', 'fullname'], 738 ], 739 'rows' => [ 740 'user' => [ 741 (object)['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 742 (object)['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 743 ], 744 'course' => [ 745 (object)['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 746 (object)['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 747 ], 748 ], 749 ], 750 'multiple table one file import' => [ 751 'files' => [__DIR__ . '/fixtures/sample_dataset_many.xml'], 752 'filter' => [], 753 'exception' => null, 754 'columns' => [ 755 'user' => ['id', 'username', 'email'], 756 'course' => ['id', 'shortname', 'fullname'], 757 ], 758 'rows' => [ 759 'user' => [ 760 (object)['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 761 (object)['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 762 ], 763 'course' => [ 764 (object)['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 765 (object)['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 766 ], 767 ], 768 ], 769 'filtering tables' => [ 770 'files' => [__DIR__ . '/fixtures/sample_dataset_many.xml'], 771 'filter' => ['course'], 772 'exception' => null, 773 'columns' => [ 774 'user' => ['id', 'username', 'email'], 775 'course' => ['id', 'shortname', 'fullname'], 776 ], 777 'rows' => [ 778 'user' => [], // Table user is being excluded via filter, expect no rows sent to database. 779 'course' => [ 780 (object)['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 781 (object)['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 782 ], 783 ], 784 ], 785 ]; 786 } 787 788 /** 789 * @dataProvider to_database_provider 790 * @covers ::to_database 791 */ 792 public function test_to_database(array $files, ?array $filter, ?string $exception, array $columns, array $rows) { 793 global $DB; 794 795 $this->resetAfterTest(); 796 797 // Grab the status before loading to database. 798 $before = []; 799 foreach ($columns as $tablename => $tablecolumns) { 800 if (!isset($before[$tablename])) { 801 $before[$tablename] = []; 802 } 803 $before[$tablename] = $DB->get_records($tablename, null, '', implode(', ', $tablecolumns)); 804 } 805 806 $ds = new phpunit_dataset(); 807 808 // We are expecting an exception. 809 if (!empty($exception)) { 810 $this->expectException('coding_exception'); 811 $this->expectExceptionMessage($exception); 812 } 813 814 $ds->from_files($files); 815 $ds->to_database($filter); 816 817 // Grab the status after loading to database. 818 $after = []; 819 foreach ($columns as $tablename => $tablecolumns) { 820 if (!isset($after[$tablename])) { 821 $after[$tablename] = []; 822 } 823 $sortandcol = implode(', ', $tablecolumns); 824 $after[$tablename] = $DB->get_records($tablename, null, $sortandcol, $sortandcol); 825 } 826 827 // Differences must match the expectations. 828 foreach ($rows as $tablename => $expectedrows) { 829 $changes = array_udiff($after[$tablename], $before[$tablename], function ($b, $a) { 830 if ((array)$b > (array)$a) { 831 return 1; 832 } else if ((array)$b < (array)$a) { 833 return -1; 834 } else { 835 return 0; 836 } 837 }); 838 $this->assertEquals(array_values($expectedrows), array_values($changes)); 839 } 840 } 841 842 /** 843 * test_get_rows() data provider. 844 */ 845 public function get_rows_provider() { 846 847 return [ 848 'wrong table requested' => [ 849 'files' => [__DIR__ . '/fixtures/sample_dataset_many.xml'], 850 'filter' => ['wrongtable'], 851 'exception' => 'dataset_get_rows, table is not in the dataset: wrongtable', 852 'rows' => [], 853 ], 854 'ok get rows from empty tables' => [ 855 'files' => [__DIR__ . '/fixtures/sample_dataset_many_with_empty.xml'], 856 'filter' => ['empty1', 'empty2'], 857 'exception' => null, 858 'rows' => [ 859 'empty1' => [], 860 'empty2' => [], 861 ], 862 ], 863 'ok get rows from one table' => [ 864 'files' => [__DIR__ . '/fixtures/sample_dataset_many_with_empty.xml'], 865 'filter' => ['user'], 866 'exception' => null, 867 'rows' => [ 868 'user' => [ 869 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 870 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 871 ], 872 ], 873 ], 874 'ok get rows from two tables' => [ 875 'files' => [__DIR__ . '/fixtures/sample_dataset_many_with_empty.xml'], 876 'filter' => ['user', 'course'], 877 'exception' => null, 878 'rows' => [ 879 'user' => [ 880 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 881 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 882 ], 883 'course' => [ 884 ['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 885 ['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 886 ], 887 ], 888 ], 889 'ok get rows from three tables' => [ 890 'files' => [__DIR__ . '/fixtures/sample_dataset_many_with_empty.xml'], 891 'filter' => ['user', 'empty1', 'course'], 892 'exception' => null, 893 'rows' => [ 894 'user' => [ 895 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 896 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 897 ], 898 'empty1' => [], 899 'course' => [ 900 ['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 901 ['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 902 ], 903 ], 904 ], 905 'ok no filter returns all' => [ 906 'files' => [__DIR__ . '/fixtures/sample_dataset_many_with_empty.xml'], 907 'filter' => [], 908 'exception' => null, 909 'rows' => [ 910 'user' => [ 911 ['id' => 5, 'username' => 'bozka.novakova', 'email' => 'bozka@example.com'], 912 ['id' => 7, 'username' => 'pepa.novak', 'email' => 'pepa@example.com'], 913 ], 914 'empty1' => [], 915 'empty2' => [], 916 'course' => [ 917 ['id' => 6, 'shortname' => '101', 'fullname' => '1-0-1'], 918 ['id' => 8, 'shortname' => '202', 'fullname' => '2-0-2'], 919 ], 920 ], 921 ], 922 ]; 923 } 924 925 /** 926 * @dataProvider get_rows_provider 927 * @covers ::get_rows 928 */ 929 public function test_get_rows(array $files, array $filter, ?string $exception, array $rows) { 930 931 $ds = new phpunit_dataset(); 932 933 // We are expecting an exception. 934 if (!empty($exception)) { 935 $this->expectException('coding_exception'); 936 $this->expectExceptionMessage($exception); 937 } 938 939 $ds->from_files($files); 940 $this->assertEquals($rows, $ds->get_rows($filter)); 941 } 942 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body