|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00025 // Prevent direct access to this file 00026 if (!defined('MOODLE_INTERNAL')) { 00027 die('Direct access to this script is forbidden.'); 00028 } 00029 00030 // Include all the needed stuff 00031 require_once($CFG->dirroot . '/backup/util/xml/parser/progressive_parser.class.php'); 00032 require_once($CFG->dirroot . '/backup/util/xml/parser/processors/progressive_parser_processor.class.php'); 00033 require_once($CFG->dirroot . '/backup/util/xml/parser/processors/simplified_parser_processor.class.php'); 00034 require_once($CFG->dirroot . '/backup/util/xml/parser/processors/grouped_parser_processor.class.php'); 00035 00036 /* 00037 * progressive_parser and progressive_parser_processor tests 00038 */ 00039 class progressive_parser_test extends UnitTestCase { 00040 00041 public static $includecoverage = array('backup/util/xml/parser'); 00042 public static $excludecoverage = array('backup/util/xml/parser/simpletest'); 00043 00044 /* 00045 * test progressive_parser public methods 00046 */ 00047 function test_parser_public_api() { 00048 global $CFG; 00049 // Instantiate progressive_parser 00050 $pp = new progressive_parser(); 00051 $this->assertTrue($pp instanceof progressive_parser); 00052 $pr = new mock_parser_processor(); 00053 $this->assertTrue($pr instanceof progressive_parser_processor); 00054 00055 // Try to process without processor 00056 try { 00057 $pp->process(); 00058 $this->assertTrue(false); 00059 } catch (exception $e) { 00060 $this->assertTrue($e instanceof progressive_parser_exception); 00061 $this->assertEqual($e->errorcode, 'undefined_parser_processor'); 00062 } 00063 00064 // Assign processor to parser 00065 $pp->set_processor($pr); 00066 00067 // Try to process without file and contents 00068 try { 00069 $pp->process(); 00070 $this->assertTrue(false); 00071 } catch (exception $e) { 00072 $this->assertTrue($e instanceof progressive_parser_exception); 00073 $this->assertEqual($e->errorcode, 'undefined_xml_to_parse'); 00074 } 00075 00076 // Assign *invalid* processor to parser 00077 try { 00078 $pp->set_processor(new stdClass()); 00079 $this->assertTrue(false); 00080 } catch (exception $e) { 00081 $this->assertTrue($e instanceof progressive_parser_exception); 00082 $this->assertEqual($e->errorcode, 'invalid_parser_processor'); 00083 } 00084 00085 // Set file from fixtures (test1.xml) and process it 00086 $pp = new progressive_parser(); 00087 $pr = new mock_parser_processor(); 00088 $pp->set_processor($pr); 00089 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test1.xml'); 00090 $pp->process(); 00091 $serfromfile = serialize($pr->get_chunks()); // Get serialized results (to compare later) 00092 // Set *unexisting* file from fixtures 00093 try { 00094 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test0.xml'); 00095 $this->assertTrue(false); 00096 } catch (exception $e) { 00097 $this->assertTrue($e instanceof progressive_parser_exception); 00098 $this->assertEqual($e->errorcode, 'invalid_file_to_parse'); 00099 } 00100 00101 // Set contents from fixtures (test1.xml) and process it 00102 $pp = new progressive_parser(); 00103 $pr = new mock_parser_processor(); 00104 $pp->set_processor($pr); 00105 $pp->set_contents(file_get_contents($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test1.xml')); 00106 $pp->process(); 00107 $serfrommemory = serialize($pr->get_chunks()); // Get serialized results (to compare later) 00108 // Set *empty* contents 00109 try { 00110 $pp->set_contents(''); 00111 $this->assertTrue(false); 00112 } catch (exception $e) { 00113 $this->assertTrue($e instanceof progressive_parser_exception); 00114 $this->assertEqual($e->errorcode, 'invalid_contents_to_parse'); 00115 } 00116 00117 // Check that both results from file processing and content processing are equal 00118 $this->assertEqual($serfromfile, $serfrommemory); 00119 00120 // Check case_folding is working ok 00121 $pp = new progressive_parser(true); 00122 $pr = new mock_parser_processor(); 00123 $pp->set_processor($pr); 00124 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test1.xml'); 00125 $pp->process(); 00126 $chunks = $pr->get_chunks(); 00127 $this->assertTrue($chunks[0]['path'] === '/FIRSTTAG'); 00128 $this->assertTrue($chunks[0]['tags']['SECONDTAG']['name'] === 'SECONDTAG'); 00129 $this->assertTrue($chunks[0]['tags']['SECONDTAG']['attrs']['NAME'] === 'secondtag'); 00130 00131 // Check invalid XML exception is working ok 00132 $pp = new progressive_parser(true); 00133 $pr = new mock_parser_processor(); 00134 $pp->set_processor($pr); 00135 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test2.xml'); 00136 try { 00137 $pp->process(); 00138 } catch (exception $e) { 00139 $this->assertTrue($e instanceof progressive_parser_exception); 00140 $this->assertEqual($e->errorcode, 'xml_parsing_error'); 00141 } 00142 00143 // Check double process throws exception 00144 $pp = new progressive_parser(true); 00145 $pr = new mock_parser_processor(); 00146 $pp->set_processor($pr); 00147 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test1.xml'); 00148 $pp->process(); 00149 try { // Second process, will throw exception 00150 $pp->process(); 00151 $this->assertTrue(false); 00152 } catch (exception $e) { 00153 $this->assertTrue($e instanceof progressive_parser_exception); 00154 $this->assertEqual($e->errorcode, 'progressive_parser_already_used'); 00155 } 00156 } 00157 00158 /* 00159 * test progressive_parser parsing results using testing_parser_processor and test1.xml 00160 * auto-described file from fixtures 00161 */ 00162 function test_parser_results() { 00163 global $CFG; 00164 // Instantiate progressive_parser 00165 $pp = new progressive_parser(); 00166 // Instantiate processor, passing the unit test as param 00167 $pr = new mock_auto_parser_processor($this); 00168 $this->assertTrue($pr instanceof progressive_parser_processor); 00169 // Assign processor to parser 00170 $pp->set_processor($pr); 00171 // Set file from fixtures 00172 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test3.xml'); 00173 // Process the file, the autotest processor will perform a bunch of automatic tests 00174 $pp->process(); 00175 // Get processor debug info 00176 $debug = $pr->debug_info(); 00177 $this->assertTrue(is_array($debug)); 00178 $this->assertTrue(array_key_exists('chunks', $debug)); 00179 // Check the number of chunks is correct for the file 00180 $this->assertEqual($debug['chunks'], 10); 00181 } 00182 00183 /* 00184 * test progressive_parser parsing results using simplified_parser_processor and test4.xml 00185 * (one simple glossary backup file example) 00186 */ 00187 function test_simplified_parser_results() { 00188 global $CFG; 00189 // Instantiate progressive_parser 00190 $pp = new progressive_parser(); 00191 // Instantiate simplified_parser_processor declaring the interesting paths 00192 $pr = new mock_simplified_parser_processor(array( 00193 '/activity', 00194 '/activity/glossary', 00195 '/activity/glossary/entries/entry', 00196 '/activity/glossary/entries/entry/aliases/alias', 00197 '/activity/glossary/entries/entry/ratings/rating', 00198 '/activity/glossary/categories/category', 00199 '/activity/glossary/onetest', 00200 '/activity/glossary/othertest')); 00201 $this->assertTrue($pr instanceof progressive_parser_processor); 00202 // Assign processor to parser 00203 $pp->set_processor($pr); 00204 // Set file from fixtures 00205 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test4.xml'); 00206 // Process the file 00207 $pp->process(); 00208 // Get processor debug info 00209 $debug = $pr->debug_info(); 00210 $this->assertTrue(is_array($debug)); 00211 $this->assertTrue(array_key_exists('chunks', $debug)); 00212 00213 // Check the number of chunks is correct for the file 00214 $this->assertEqual($debug['chunks'], 12); 00215 // Get all the simplified chunks and perform various validations 00216 $chunks = $pr->get_chunks(); 00217 // Check we have received the correct number of chunks 00218 $this->assertEqual(count($chunks), 12); 00219 00220 // chunk[0] (/activity) tests 00221 $this->assertEqual(count($chunks[0]), 3); 00222 $this->assertEqual($chunks[0]['path'], '/activity'); 00223 $this->assertEqual($chunks[0]['level'],'2'); 00224 $tags = $chunks[0]['tags']; 00225 $this->assertEqual(count($tags), 4); 00226 $this->assertEqual($tags['id'], 1); 00227 $this->assertEqual($tags['moduleid'], 5); 00228 $this->assertEqual($tags['modulename'], 'glossary'); 00229 $this->assertEqual($tags['contextid'], 26); 00230 $this->assertEqual($chunks[0]['level'],'2'); 00231 00232 // chunk[1] (/activity/glossary) tests 00233 $this->assertEqual(count($chunks[1]), 3); 00234 $this->assertEqual($chunks[1]['path'], '/activity/glossary'); 00235 $this->assertEqual($chunks[1]['level'],'3'); 00236 $tags = $chunks[1]['tags']; 00237 $this->assertEqual(count($tags), 24); 00238 $this->assertEqual($tags['id'], 1); 00239 $this->assertEqual($tags['intro'], '<p>One simple glossary to test backup & restore. Here it\'s the standard image:</p>'. 00240 "\n". 00241 '<p><img src="@@PLUGINFILE@@/88_31.png" alt="pwd by moodle" width="88" height="31" /></p>'); 00242 $this->assertEqual($tags['timemodified'], 1275639747); 00243 $this->assertTrue(!isset($tags['categories'])); 00244 00245 // chunk[5] (second /activity/glossary/entries/entry) tests 00246 $this->assertEqual(count($chunks[5]), 3); 00247 $this->assertEqual($chunks[5]['path'], '/activity/glossary/entries/entry'); 00248 $this->assertEqual($chunks[5]['level'],'5'); 00249 $tags = $chunks[5]['tags']; 00250 $this->assertEqual(count($tags), 15); 00251 $this->assertEqual($tags['id'], 2); 00252 $this->assertEqual($tags['concept'], 'cat'); 00253 $this->assertTrue(!isset($tags['aliases'])); 00254 $this->assertTrue(!isset($tags['entries'])); 00255 00256 // chunk[6] (second /activity/glossary/entries/entry/aliases/alias) tests 00257 $this->assertEqual(count($chunks[6]), 3); 00258 $this->assertEqual($chunks[6]['path'], '/activity/glossary/entries/entry/aliases/alias'); 00259 $this->assertEqual($chunks[6]['level'],'7'); 00260 $tags = $chunks[6]['tags']; 00261 $this->assertEqual(count($tags), 2); 00262 $this->assertEqual($tags['id'], 2); 00263 $this->assertEqual($tags['alias_text'], 'cats'); 00264 00265 // chunk[7] (second /activity/glossary/entries/entry/aliases/alias) tests 00266 $this->assertEqual(count($chunks[7]), 3); 00267 $this->assertEqual($chunks[7]['path'], '/activity/glossary/entries/entry/aliases/alias'); 00268 $this->assertEqual($chunks[7]['level'],'7'); 00269 $tags = $chunks[7]['tags']; 00270 $this->assertEqual(count($tags), 2); 00271 $this->assertEqual($tags['id'], 3); 00272 $this->assertEqual($tags['alias_text'], 'felines'); 00273 00274 // chunk[8] (second /activity/glossary/entries/entry/ratings/rating) tests 00275 $this->assertEqual(count($chunks[8]), 3); 00276 $this->assertEqual($chunks[8]['path'], '/activity/glossary/entries/entry/ratings/rating'); 00277 $this->assertEqual($chunks[8]['level'],'7'); 00278 $tags = $chunks[8]['tags']; 00279 $this->assertEqual(count($tags), 6); 00280 $this->assertEqual($tags['id'], 1); 00281 $this->assertEqual($tags['timemodified'], '1275639779'); 00282 00283 // chunk[9] (first /activity/glossary/onetest) tests 00284 $this->assertEqual(count($chunks[9]), 3); 00285 $this->assertEqual($chunks[9]['path'], '/activity/glossary/onetest'); 00286 $this->assertEqual($chunks[9]['level'],'4'); 00287 $tags = $chunks[9]['tags']; 00288 $this->assertEqual(count($tags), 2); 00289 $this->assertEqual($tags['name'], 1); 00290 $this->assertEqual($tags['value'], 1); 00291 00292 // chunk[10] (second /activity/glossary/onetest) tests 00293 $this->assertEqual(count($chunks[10]), 3); 00294 $this->assertEqual($chunks[10]['path'], '/activity/glossary/onetest'); 00295 $this->assertEqual($chunks[10]['level'],'4'); 00296 $tags = $chunks[10]['tags']; 00297 $this->assertEqual(count($tags), 2); 00298 $this->assertEqual($tags['name'], 2); 00299 $this->assertEqual($tags['value'], 2); 00300 00301 // chunk[11] (first /activity/glossary/othertest) tests 00302 // note we don't allow repeated "final" element, so we only return the last one 00303 $this->assertEqual(count($chunks[11]), 3); 00304 $this->assertEqual($chunks[11]['path'], '/activity/glossary/othertest'); 00305 $this->assertEqual($chunks[11]['level'],'4'); 00306 $tags = $chunks[11]['tags']; 00307 $this->assertEqual(count($tags), 2); 00308 $this->assertEqual($tags['name'], 4); 00309 $this->assertEqual($tags['value'], 5); 00310 00311 // Now check start notifications 00312 $snotifs = $pr->get_start_notifications(); 00313 // Check we have received the correct number of notifications 00314 $this->assertEqual(count($snotifs), 12); 00315 // Check first, sixth and last notifications 00316 $this->assertEqual($snotifs[0], '/activity'); 00317 $this->assertEqual($snotifs[5], '/activity/glossary/entries/entry'); 00318 $this->assertEqual($snotifs[11], '/activity/glossary/othertest'); 00319 00320 // Now check end notifications 00321 $enotifs = $pr->get_end_notifications(); 00322 // Check we have received the correct number of notifications 00323 $this->assertEqual(count($snotifs), 12); 00324 // Check first, sixth and last notifications 00325 $this->assertEqual($enotifs[0], '/activity/glossary/entries/entry/aliases/alias'); 00326 $this->assertEqual($enotifs[5], '/activity/glossary/entries/entry/ratings/rating'); 00327 $this->assertEqual($enotifs[11], '/activity'); 00328 00329 // Check start and end notifications are balanced 00330 sort($snotifs); 00331 sort($enotifs); 00332 $this->assertEqual($snotifs, $enotifs); 00333 00334 // Now verify that the start/process/end order is correct 00335 $allnotifs = $pr->get_all_notifications(); 00336 $this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count 00337 // Check integrity of the notifications 00338 $errcount = $this->helper_check_notifications_order_integrity($allnotifs); 00339 $this->assertEqual($errcount, 0); // No errors found, plz 00340 } 00341 00347 function test_simplified_david_backup19_file_fragment() { 00348 global $CFG; 00349 // Instantiate progressive_parser 00350 $pp = new progressive_parser(); 00351 // Instantiate grouped_parser_processor 00352 $pr = new mock_simplified_parser_processor(); 00353 // Add interesting paths 00354 $pr->add_path('/MOODLE_BACKUP/COURSE'); 00355 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION'); 00356 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00357 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD/ROLES_OVERRIDES'); 00358 $this->assertTrue($pr instanceof progressive_parser_processor); 00359 // Assign processor to parser 00360 $pp->set_processor($pr); 00361 // Set file from fixtures 00362 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test5.xml'); 00363 // Process the file 00364 $pp->process(); 00365 00366 // Get all the simplified chunks and perform various validations 00367 $chunks = $pr->get_chunks(); 00368 $this->assertEqual(count($chunks), 3); // Only 3, because 7 (COURSE, ROLES_OVERRIDES and 5 MOD) are empty, aka no chunk 00369 00370 // Now check start notifications 00371 $snotifs = $pr->get_start_notifications(); 00372 // Check we have received the correct number of notifications 00373 $this->assertEqual(count($snotifs), 10); // Start tags are dispatched for empties (ROLES_OVERRIDES) 00374 // Check first and last notifications 00375 $this->assertEqual($snotifs[0], '/MOODLE_BACKUP/COURSE'); 00376 $this->assertEqual($snotifs[1], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION'); 00377 $this->assertEqual($snotifs[2], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00378 $this->assertEqual($snotifs[3], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD/ROLES_OVERRIDES'); 00379 $this->assertEqual($snotifs[7], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00380 $this->assertEqual($snotifs[8], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00381 $this->assertEqual($snotifs[9], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00382 00383 // Now check end notifications 00384 $enotifs = $pr->get_end_notifications(); 00385 // Check we have received the correct number of notifications 00386 $this->assertEqual(count($snotifs), 10); // End tags are dispatched for empties (ROLES_OVERRIDES) 00387 // Check first, and last notifications 00388 $this->assertEqual($enotifs[0], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD/ROLES_OVERRIDES'); 00389 $this->assertEqual($enotifs[1], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00390 $this->assertEqual($enotifs[2], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00391 $this->assertEqual($enotifs[3], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00392 $this->assertEqual($enotifs[7], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00393 $this->assertEqual($enotifs[8], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION'); 00394 $this->assertEqual($enotifs[9], '/MOODLE_BACKUP/COURSE'); 00395 00396 // Check start and end notifications are balanced 00397 sort($snotifs); 00398 sort($enotifs); 00399 $this->assertEqual($snotifs, $enotifs); 00400 00401 // Now verify that the start/process/end order is correct 00402 $allnotifs = $pr->get_all_notifications(); 00403 $this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count 00404 // Check integrity of the notifications 00405 $errcount = $this->helper_check_notifications_order_integrity($allnotifs); 00406 $this->assertEqual($errcount, 0); // No errors found, plz 00407 } 00408 00409 /* 00410 * test progressive_parser parsing results using grouped_parser_processor and test4.xml 00411 * (one simple glossary backup file example) 00412 */ 00413 function test_grouped_parser_results() { 00414 global $CFG; 00415 // Instantiate progressive_parser 00416 $pp = new progressive_parser(); 00417 // Instantiate grouped_parser_processor 00418 $pr = new mock_grouped_parser_processor(); 00419 // Add interesting paths 00420 $pr->add_path('/activity'); 00421 $pr->add_path('/activity/glossary', true); 00422 $pr->add_path('/activity/glossary/entries/entry'); 00423 $pr->add_path('/activity/glossary/entries/entry/aliases/alias'); 00424 $pr->add_path('/activity/glossary/entries/entry/ratings/rating'); 00425 $pr->add_path('/activity/glossary/categories/category'); 00426 $pr->add_path('/activity/glossary/onetest'); 00427 $pr->add_path('/activity/glossary/othertest'); 00428 $this->assertTrue($pr instanceof progressive_parser_processor); 00429 // Assign processor to parser 00430 $pp->set_processor($pr); 00431 // Set file from fixtures 00432 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test4.xml'); 00433 // Process the file 00434 $pp->process(); 00435 // Get processor debug info 00436 $debug = $pr->debug_info(); 00437 $this->assertTrue(is_array($debug)); 00438 $this->assertTrue(array_key_exists('chunks', $debug)); 00439 00440 // Check the number of chunks is correct for the file 00441 $this->assertEqual($debug['chunks'], 2); 00442 // Get all the simplified chunks and perform various validations 00443 $chunks = $pr->get_chunks(); 00444 // Check we have received the correct number of chunks 00445 $this->assertEqual(count($chunks), 2); 00446 00447 // chunk[0] (/activity) tests 00448 $this->assertEqual(count($chunks[0]), 3); 00449 $this->assertEqual($chunks[0]['path'], '/activity'); 00450 $this->assertEqual($chunks[0]['level'],'2'); 00451 $tags = $chunks[0]['tags']; 00452 $this->assertEqual(count($tags), 4); 00453 $this->assertEqual($tags['id'], 1); 00454 $this->assertEqual($tags['moduleid'], 5); 00455 $this->assertEqual($tags['modulename'], 'glossary'); 00456 $this->assertEqual($tags['contextid'], 26); 00457 $this->assertEqual($chunks[0]['level'],'2'); 00458 00459 // chunk[1] (grouped /activity/glossary tests) 00460 $this->assertEqual(count($chunks[1]), 3); 00461 $this->assertEqual($chunks[1]['path'], '/activity/glossary'); 00462 $this->assertEqual($chunks[1]['level'],'3'); 00463 $tags = $chunks[1]['tags']; 00464 $this->assertEqual(count($tags), 27); 00465 $this->assertEqual($tags['id'], 1); 00466 $this->assertEqual($tags['intro'], '<p>One simple glossary to test backup & restore. Here it\'s the standard image:</p>'. 00467 "\n". 00468 '<p><img src="@@PLUGINFILE@@/88_31.png" alt="pwd by moodle" width="88" height="31" /></p>'); 00469 $this->assertEqual($tags['timemodified'], 1275639747); 00470 $this->assertTrue(!isset($tags['categories'])); 00471 $this->assertTrue(isset($tags['entries'])); 00472 $this->assertTrue(isset($tags['onetest'])); 00473 $this->assertTrue(isset($tags['othertest'])); 00474 00475 // Various tests under the entries 00476 $entries = $chunks[1]['tags']['entries']['entry']; 00477 $this->assertEqual(count($entries), 2); 00478 00479 // First entry 00480 $entry1 = $entries[0]; 00481 $this->assertEqual(count($entry1), 17); 00482 $this->assertEqual($entry1['id'], 1); 00483 $this->assertEqual($entry1['userid'], 2); 00484 $this->assertEqual($entry1['concept'], 'dog'); 00485 $this->assertEqual($entry1['definition'], '<p>Traditional enemies of cats</p>'); 00486 $this->assertTrue(isset($entry1['aliases'])); 00487 $this->assertTrue(isset($entry1['ratings'])); 00488 // aliases of first entry 00489 $aliases = $entry1['aliases']['alias']; 00490 $this->assertEqual(count($aliases), 1); 00491 // first alias 00492 $alias1 = $aliases[0]; 00493 $this->assertEqual(count($alias1), 2); 00494 $this->assertEqual($alias1['id'], 1); 00495 $this->assertEqual($alias1['alias_text'], 'dogs'); 00496 // ratings of first entry 00497 $ratings = $entry1['ratings']['rating']; 00498 $this->assertEqual(count($ratings), 1); 00499 // first rating 00500 $rating1 = $ratings[0]; 00501 $this->assertEqual(count($rating1), 6); 00502 $this->assertEqual($rating1['id'], 2); 00503 $this->assertEqual($rating1['value'], 6); 00504 $this->assertEqual($rating1['timemodified'], '1275639797'); 00505 00506 // Second entry 00507 $entry2 = $entries[1]; 00508 $this->assertEqual(count($entry2), 17); 00509 $this->assertEqual($entry2['id'], 2); 00510 $this->assertEqual($entry2['userid'], 2); 00511 $this->assertEqual($entry2['concept'], 'cat'); 00512 $this->assertEqual($entry2['definition'], '<p>traditional enemies of dogs</p>'); 00513 $this->assertTrue(isset($entry2['aliases'])); 00514 $this->assertTrue(isset($entry2['ratings'])); 00515 // aliases of first entry 00516 $aliases = $entry2['aliases']['alias']; 00517 $this->assertEqual(count($aliases), 2); 00518 // first alias 00519 $alias1 = $aliases[0]; 00520 $this->assertEqual(count($alias1), 2); 00521 $this->assertEqual($alias1['id'], 2); 00522 $this->assertEqual($alias1['alias_text'], 'cats'); 00523 // second alias 00524 $alias2 = $aliases[1]; 00525 $this->assertEqual(count($alias2), 2); 00526 $this->assertEqual($alias2['id'], 3); 00527 $this->assertEqual($alias2['alias_text'], 'felines'); 00528 // ratings of first entry 00529 $ratings = $entry2['ratings']['rating']; 00530 $this->assertEqual(count($ratings), 1); 00531 // first rating 00532 $rating1 = $ratings[0]; 00533 $this->assertEqual(count($rating1), 6); 00534 $this->assertEqual($rating1['id'], 1); 00535 $this->assertEqual($rating1['value'], 5); 00536 $this->assertEqual($rating1['scaleid'], 10); 00537 00538 // Onetest test (only 1 level nested) 00539 $onetest = $tags['onetest']; 00540 $this->assertEqual(count($onetest), 2); 00541 $this->assertEqual(count($onetest[0]), 2); 00542 $this->assertEqual($onetest[0]['name'], 1); 00543 $this->assertEqual($onetest[0]['value'], 1); 00544 $this->assertEqual(count($onetest[1]), 2); 00545 $this->assertEqual($onetest[1]['name'], 2); 00546 $this->assertEqual($onetest[1]['value'], 2); 00547 00548 // Other test (0 level nested, only last one is retrieved) 00549 $othertest = $tags['othertest']; 00550 $this->assertEqual(count($othertest), 1); 00551 $this->assertEqual(count($othertest[0]), 2); 00552 $this->assertEqual($othertest[0]['name'], 4); 00553 $this->assertEqual($othertest[0]['value'], 5); 00554 00555 // Now check start notifications 00556 $snotifs = $pr->get_start_notifications(); 00557 // Check we have received the correct number of notifications 00558 $this->assertEqual(count($snotifs), 2); 00559 // Check first and last notifications 00560 $this->assertEqual($snotifs[0], '/activity'); 00561 $this->assertEqual($snotifs[1], '/activity/glossary'); 00562 00563 // Now check end notifications 00564 $enotifs = $pr->get_end_notifications(); 00565 // Check we have received the correct number of notifications 00566 $this->assertEqual(count($snotifs), 2); 00567 // Check first, and last notifications 00568 $this->assertEqual($enotifs[0], '/activity/glossary'); 00569 $this->assertEqual($enotifs[1], '/activity'); 00570 00571 // Check start and end notifications are balanced 00572 sort($snotifs); 00573 sort($enotifs); 00574 $this->assertEqual($snotifs, $enotifs); 00575 00576 // Now verify that the start/process/end order is correct 00577 $allnotifs = $pr->get_all_notifications(); 00578 $this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count 00579 // Check integrity of the notifications 00580 $errcount = $this->helper_check_notifications_order_integrity($allnotifs); 00581 $this->assertEqual($errcount, 0); // No errors found, plz 00582 } 00583 00589 function test_grouped_david_backup19_file_fragment() { 00590 global $CFG; 00591 // Instantiate progressive_parser 00592 $pp = new progressive_parser(); 00593 // Instantiate grouped_parser_processor 00594 $pr = new mock_grouped_parser_processor(); 00595 // Add interesting paths 00596 $pr->add_path('/MOODLE_BACKUP/COURSE'); 00597 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION', true); 00598 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD'); 00599 $pr->add_path('/MOODLE_BACKUP/COURSE/SECTIONS/SECTION/MODS/MOD/ROLES_OVERRIDES'); 00600 $this->assertTrue($pr instanceof progressive_parser_processor); 00601 // Assign processor to parser 00602 $pp->set_processor($pr); 00603 // Set file from fixtures 00604 $pp->set_file($CFG->dirroot . '/backup/util/xml/parser/simpletest/fixtures/test5.xml'); 00605 // Process the file 00606 $pp->process(); 00607 00608 // Get all the simplified chunks and perform various validations 00609 $chunks = $pr->get_chunks(); 00610 $this->assertEqual(count($chunks), 1); // Only 1, the SECTION one 00611 00612 // Now check start notifications 00613 $snotifs = $pr->get_start_notifications(); 00614 // Check we have received the correct number of notifications 00615 $this->assertEqual(count($snotifs), 2); 00616 // Check first and last notifications 00617 $this->assertEqual($snotifs[0], '/MOODLE_BACKUP/COURSE'); 00618 $this->assertEqual($snotifs[1], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION'); 00619 00620 // Now check end notifications 00621 $enotifs = $pr->get_end_notifications(); 00622 // Check we have received the correct number of notifications 00623 $this->assertEqual(count($snotifs), 2); // End tags are dispatched for empties (ROLES_OVERRIDES) 00624 // Check first, and last notifications 00625 $this->assertEqual($enotifs[0], '/MOODLE_BACKUP/COURSE/SECTIONS/SECTION'); 00626 $this->assertEqual($enotifs[1], '/MOODLE_BACKUP/COURSE'); 00627 00628 // Check start and end notifications are balanced 00629 sort($snotifs); 00630 sort($enotifs); 00631 $this->assertEqual($snotifs, $enotifs); 00632 00633 // Now verify that the start/process/end order is correct 00634 $allnotifs = $pr->get_all_notifications(); 00635 $this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count 00636 // Check integrity of the notifications 00637 $errcount = $this->helper_check_notifications_order_integrity($allnotifs); 00638 $this->assertEqual($errcount, 0); // No errors found, plz 00639 } 00640 00641 00652 function helper_check_notifications_order_integrity($notifications) { 00653 $numerrors = 0; 00654 $notifpile = array('pilebase' => 'start'); 00655 $lastnotif = 'start:pilebase'; 00656 foreach ($notifications as $notif) { 00657 00658 $lastpiletype = end($notifpile); 00659 $lastpilepath = key($notifpile); 00660 $lastpilelevel = strlen(preg_replace('/[^\/]/', '', $lastpilepath)); 00661 00662 $lastnotiftype = preg_replace('/:.*/', '', $lastnotif); 00663 $lastnotifpath = preg_replace('/.*:/', '', $lastnotif); 00664 $lastnotiflevel = strlen(preg_replace('/[^\/]/', '', $lastnotifpath)); 00665 00666 $notiftype = preg_replace('/:.*/', '', $notif); 00667 $notifpath = preg_replace('/.*:/', '', $notif); 00668 $notiflevel = strlen(preg_replace('/[^\/]/', '', $notifpath)); 00669 00670 switch ($notiftype) { 00671 case 'process': 00672 if ($lastnotifpath != $notifpath or $lastnotiftype != 'start') { 00673 $numerrors++; // Only start for same path from last notification is allowed before process 00674 } 00675 $notifpile[$notifpath] = 'process'; // Update the status in the pile 00676 break; 00677 case 'end': 00678 if ($lastpilepath != $notifpath or ($lastpiletype != 'process' and $lastpiletype != 'start')) { 00679 $numerrors++; // Only process and start for same path from last pile is allowed before end 00680 } 00681 unset($notifpile[$notifpath]); // Delete from the pile 00682 break; 00683 case 'start': 00684 if (array_key_exists($notifpath, $notifpile) or $notiflevel <= $lastpilelevel) { 00685 $numerrors++; // Only non existing in pile and with level > last pile is allowed on start 00686 } 00687 $notifpile[$notifpath] = 'start'; // Add to the pile 00688 break; 00689 default: 00690 $numerrors++; // Incorrect type of notification => error 00691 } 00692 // Update lastnotif 00693 $lastnotif = $notif; 00694 } 00695 return $numerrors; 00696 } 00697 } 00698 00699 /* 00700 * helper processor able to perform various auto-cheks based on attributes while processing 00701 * the test1.xml file available in the fixtures dir. It performs these checks: 00702 * - name equal to "name" attribute of the tag (if present) 00703 * - level equal to "level" attribute of the tag (if present) 00704 * - path + tagname equal to "path" attribute of the tag (if present) 00705 * - cdata, if not empty is: 00706 * - equal to "value" attribute of the tag (if present) 00707 * - else, equal to tag name 00708 * 00709 * We pass the whole UnitTestCase object to the processor in order to be 00710 * able to perform the tests in the straight in the process 00711 */ 00712 class mock_auto_parser_processor extends progressive_parser_processor { 00713 00714 private $utc = null; // To store the unit test case 00715 00716 public function __construct($unit_test_case) { 00717 parent::__construct(); 00718 $this->utc = $unit_test_case; 00719 } 00720 00721 public function process_chunk($data) { 00722 // Perform auto-checks based in the rules above 00723 if (isset($data['tags'])) { 00724 foreach ($data['tags'] as $tag) { 00725 if (isset($tag['attrs']['name'])) { // name tests 00726 $this->utc->assertEqual($tag['name'], $tag['attrs']['name']); 00727 } 00728 if (isset($tag['attrs']['level'])) { // level tests 00729 $this->utc->assertEqual($data['level'], $tag['attrs']['level']); 00730 } 00731 if (isset($tag['attrs']['path'])) { // path tests 00732 $this->utc->assertEqual(rtrim($data['path'], '/') . '/' . $tag['name'], $tag['attrs']['path']); 00733 } 00734 if (!empty($tag['cdata'])) { // cdata tests 00735 if (isset($tag['attrs']['value'])) { 00736 $this->utc->assertEqual($tag['cdata'], $tag['attrs']['value']); 00737 } else { 00738 $this->utc->assertEqual($tag['cdata'], $tag['name']); 00739 } 00740 } 00741 } 00742 } 00743 } 00744 } 00745 00746 /* 00747 * helper processor that accumulates all the chunks, resturning them with the get_chunks() method 00748 */ 00749 class mock_parser_processor extends progressive_parser_processor { 00750 00751 private $chunksarr = array(); // To accumulate the found chunks 00752 00753 public function process_chunk($data) { 00754 $this->chunksarr[] = $data; 00755 } 00756 00757 public function get_chunks() { 00758 return $this->chunksarr; 00759 } 00760 } 00761 00762 /* 00763 * helper processor that accumulates simplified chunks, returning them with the get_chunks() method 00764 */ 00765 class mock_simplified_parser_processor extends simplified_parser_processor { 00766 00767 private $chunksarr = array(); // To accumulate the found chunks 00768 private $startarr = array(); // To accumulate all the notified path starts 00769 private $endarr = array(); // To accumulate all the notified path ends 00770 private $allnotif = array(); // To accumulate all the notified and dispatched events in an ordered way 00771 00772 public function dispatch_chunk($data) { 00773 $this->chunksarr[] = $data; 00774 $this->allnotif[] = 'process:' . $data['path']; 00775 } 00776 00777 public function notify_path_start($path) { 00778 $this->startarr[] = $path; 00779 $this->allnotif[] = 'start:' . $path; 00780 } 00781 00782 public function notify_path_end($path) { 00783 $this->endarr[] = $path; 00784 $this->allnotif[] = 'end:' . $path; 00785 } 00786 00787 public function get_chunks() { 00788 return $this->chunksarr; 00789 } 00790 00791 public function get_start_notifications() { 00792 return $this->startarr; 00793 } 00794 00795 public function get_end_notifications() { 00796 return $this->endarr; 00797 } 00798 00799 public function get_all_notifications() { 00800 return $this->allnotif; 00801 } 00802 } 00803 00804 /* 00805 * helper processor that accumulates grouped chunks, returning them with the get_chunks() method 00806 */ 00807 class mock_grouped_parser_processor extends grouped_parser_processor { 00808 00809 private $chunksarr = array(); // To accumulate the found chunks 00810 private $startarr = array(); // To accumulate all the notified path starts 00811 private $endarr = array(); // To accumulate all the notified path ends 00812 private $allnotif = array(); // To accumulate all the notified and dispatched events in an ordered way 00813 00814 public function dispatch_chunk($data) { 00815 $this->chunksarr[] = $data; 00816 $this->allnotif[] = 'process:' . $data['path']; 00817 } 00818 00819 public function notify_path_start($path) { 00820 $this->startarr[] = $path; 00821 $this->allnotif[] = 'start:' . $path; 00822 } 00823 00824 public function notify_path_end($path) { 00825 $this->endarr[] = $path; 00826 $this->allnotif[] = 'end:' . $path; 00827 } 00828 00829 public function get_chunks() { 00830 return $this->chunksarr; 00831 } 00832 00833 public function get_start_notifications() { 00834 return $this->startarr; 00835 } 00836 00837 public function get_end_notifications() { 00838 return $this->endarr; 00839 } 00840 00841 public function get_all_notifications() { 00842 return $this->allnotif; 00843 } 00844 }