|
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/xml_writer.class.php'); 00032 require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php'); 00033 require_once($CFG->dirroot . '/backup/util/xml/output/memory_xml_output.class.php'); 00034 require_once($CFG->dirroot . '/backup/util/xml/contenttransformer/xml_contenttransformer.class.php'); 00035 00036 /* 00037 * xml_writer tests 00038 */ 00039 class xml_writer_test extends UnitTestCase { 00040 00041 public static $includecoverage = array('backup/util/xml/xml_writer.class.php'); 00042 public static $excludecoverage = array('backup/util/xml/simpletest'); 00043 00044 /* 00045 * test xml_writer public methods 00046 */ 00047 function test_xml_writer_public_api() { 00048 global $CFG; 00049 // Instantiate xml_output 00050 $xo = new memory_xml_output(); 00051 $this->assertTrue($xo instanceof xml_output); 00052 00053 // Instantiate xml_writer with null xml_output 00054 try { 00055 $xw = new mock_xml_writer(null); 00056 $this->assertTrue(false, 'xml_writer_exception expected'); 00057 } catch (exception $e) { 00058 $this->assertTrue($e instanceof xml_writer_exception); 00059 $this->assertEqual($e->errorcode, 'invalid_xml_output'); 00060 } 00061 00062 // Instantiate xml_writer with wrong xml_output object 00063 try { 00064 $xw = new mock_xml_writer(new stdclass()); 00065 $this->assertTrue(false, 'xml_writer_exception expected'); 00066 } catch (exception $e) { 00067 $this->assertTrue($e instanceof xml_writer_exception); 00068 $this->assertEqual($e->errorcode, 'invalid_xml_output'); 00069 } 00070 00071 // Instantiate xml_writer with wrong xml_contenttransformer object 00072 try { 00073 $xw = new mock_xml_writer($xo, new stdclass()); 00074 $this->assertTrue(false, 'xml_writer_exception expected'); 00075 } catch (exception $e) { 00076 $this->assertTrue($e instanceof xml_writer_exception); 00077 $this->assertEqual($e->errorcode, 'invalid_xml_contenttransformer'); 00078 } 00079 00080 // Instantiate xml_writer and start it twice 00081 $xw = new mock_xml_writer($xo); 00082 $xw->start(); 00083 try { 00084 $xw->start(); 00085 $this->assertTrue(false, 'xml_writer_exception expected'); 00086 } catch (exception $e) { 00087 $this->assertTrue($e instanceof xml_writer_exception); 00088 $this->assertEqual($e->errorcode, 'xml_writer_already_started'); 00089 } 00090 00091 // Instantiate xml_writer and stop it twice 00092 $xo = new memory_xml_output(); 00093 $xw = new mock_xml_writer($xo); 00094 $xw->start(); 00095 $xw->stop(); 00096 try { 00097 $xw->stop(); 00098 $this->assertTrue(false, 'xml_writer_exception expected'); 00099 } catch (exception $e) { 00100 $this->assertTrue($e instanceof xml_writer_exception); 00101 $this->assertEqual($e->errorcode, 'xml_writer_already_stopped'); 00102 } 00103 00104 // Stop writer without starting it 00105 $xo = new memory_xml_output(); 00106 $xw = new mock_xml_writer($xo); 00107 try { 00108 $xw->stop(); 00109 $this->assertTrue(false, 'xml_writer_exception expected'); 00110 } catch (exception $e) { 00111 $this->assertTrue($e instanceof xml_writer_exception); 00112 $this->assertEqual($e->errorcode, 'xml_writer_not_started'); 00113 } 00114 00115 // Start writer after stopping it 00116 $xo = new memory_xml_output(); 00117 $xw = new mock_xml_writer($xo); 00118 $xw->start(); 00119 $xw->stop(); 00120 try { 00121 $xw->start(); 00122 $this->assertTrue(false, 'xml_writer_exception expected'); 00123 } catch (exception $e) { 00124 $this->assertTrue($e instanceof xml_writer_exception); 00125 $this->assertEqual($e->errorcode, 'xml_writer_already_stopped'); 00126 } 00127 00128 // Try to set prologue/schema after start 00129 $xo = new memory_xml_output(); 00130 $xw = new mock_xml_writer($xo); 00131 $xw->start(); 00132 try { 00133 $xw->set_nonamespace_schema('http://moodle.org'); 00134 $this->assertTrue(false, 'xml_writer_exception expected'); 00135 } catch (exception $e) { 00136 $this->assertTrue($e instanceof xml_writer_exception); 00137 $this->assertEqual($e->errorcode, 'xml_writer_already_started'); 00138 } 00139 try { 00140 $xw->set_prologue('sweet prologue'); 00141 $this->assertTrue(false, 'xml_writer_exception expected'); 00142 } catch (exception $e) { 00143 $this->assertTrue($e instanceof xml_writer_exception); 00144 $this->assertEqual($e->errorcode, 'xml_writer_already_started'); 00145 } 00146 00147 // Instantiate properly with memory_xml_output, start and stop. 00148 // Must get default UTF-8 prologue 00149 $xo = new memory_xml_output(); 00150 $xw = new mock_xml_writer($xo); 00151 $xw->start(); 00152 $xw->stop(); 00153 $this->assertEqual($xo->get_allcontents(), $xw->get_default_prologue()); 00154 00155 // Instantiate, set prologue and schema, put 1 full tag and get results 00156 $xo = new memory_xml_output(); 00157 $xw = new mock_xml_writer($xo); 00158 $xw->set_prologue('CLEARLY WRONG PROLOGUE'); 00159 $xw->set_nonamespace_schema('http://moodle.org/littleschema'); 00160 $xw->start(); 00161 $xw->full_tag('TEST', 'Hello World!', array('id' => 1)); 00162 $xw->stop(); 00163 $result = $xo->get_allcontents(); 00164 // Perform various checks 00165 $this->assertEqual(strpos($result, 'WRONG'), 8); 00166 $this->assertEqual(strpos($result, '<TEST id="1"'), 22); 00167 $this->assertEqual(strpos($result, 'xmlns:xsi='), 39); 00168 $this->assertEqual(strpos($result, 'http://moodle.org/littleschema'), 128); 00169 $this->assertEqual(strpos($result, 'Hello World'), 160); 00170 $this->assertFalse(strpos($result, $xw->get_default_prologue())); 00171 00172 // Try to close one tag in wrong order 00173 $xo = new memory_xml_output(); 00174 $xw = new mock_xml_writer($xo); 00175 $xw->start(); 00176 $xw->begin_tag('first'); 00177 $xw->begin_tag('second'); 00178 try { 00179 $xw->end_tag('first'); 00180 $this->assertTrue(false, 'xml_writer_exception expected'); 00181 } catch (exception $e) { 00182 $this->assertTrue($e instanceof xml_writer_exception); 00183 $this->assertEqual($e->errorcode, 'xml_writer_end_tag_no_match'); 00184 } 00185 00186 // Try to close one tag before starting any tag 00187 $xo = new memory_xml_output(); 00188 $xw = new mock_xml_writer($xo); 00189 $xw->start(); 00190 try { 00191 $xw->end_tag('first'); 00192 $this->assertTrue(false, 'xml_writer_exception expected'); 00193 } catch (exception $e) { 00194 $this->assertTrue($e instanceof xml_writer_exception); 00195 $this->assertEqual($e->errorcode, 'xml_writer_end_tag_no_match'); 00196 } 00197 00198 // Full tag without contents (null and empty string) 00199 $xo = new memory_xml_output(); 00200 $xw = new mock_xml_writer($xo); 00201 $xw->set_prologue(''); // empty prologue for easier matching 00202 $xw->start(); 00203 $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); 00204 $xw->full_tag('tagname2', '', array('attrname' => 'attrvalue')); 00205 $xw->stop(); 00206 $result = $xo->get_allcontents(); 00207 $this->assertEqual($result, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue"></tagname2>'); 00208 00209 00210 // Test case-folding is working 00211 $xo = new memory_xml_output(); 00212 $xw = new mock_xml_writer($xo, null, true); 00213 $xw->set_prologue(''); // empty prologue for easier matching 00214 $xw->start(); 00215 $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attrvalue')); 00216 $xw->stop(); 00217 $result = $xo->get_allcontents(); 00218 $this->assertEqual($result, '<TAGNAME ATTRNAME="attrvalue">textcontent</TAGNAME>'); 00219 00220 // Test UTF-8 chars in tag and attribute names, attr values and contents 00221 $xo = new memory_xml_output(); 00222 $xw = new mock_xml_writer($xo); 00223 $xw->set_prologue(''); // empty prologue for easier matching 00224 $xw->start(); 00225 $xw->full_tag('áéíóú', 'ÁÉÍÓÚ', array('àèìòù' => 'ÀÈÌÒÙ')); 00226 $xw->stop(); 00227 $result = $xo->get_allcontents(); 00228 $this->assertEqual($result, '<áéíóú àèìòù="ÀÈÌÒÙ">ÁÉÍÓÚ</áéíóú>'); 00229 00230 // Try non-safe content in attributes 00231 $xo = new memory_xml_output(); 00232 $xw = new mock_xml_writer($xo); 00233 $xw->set_prologue(''); // empty prologue for easier matching 00234 $xw->start(); 00235 $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attr' . chr(27) . '\'"value')); 00236 $xw->stop(); 00237 $result = $xo->get_allcontents(); 00238 $this->assertEqual($result, '<tagname attrname="attr\'"value">textcontent</tagname>'); 00239 00240 // Try non-safe content in text 00241 $xo = new memory_xml_output(); 00242 $xw = new mock_xml_writer($xo); 00243 $xw->set_prologue(''); // empty prologue for easier matching 00244 $xw->start(); 00245 $xw->full_tag('tagname', "text\r\ncontent\rwith" . chr(27), array('attrname' => 'attrvalue')); 00246 $xw->stop(); 00247 $result = $xo->get_allcontents(); 00248 $this->assertEqual($result, '<tagname attrname="attrvalue">text' . "\ncontent\n" . 'with</tagname>'); 00249 00250 // Try to stop the writer without clossing all the open tags 00251 $xo = new memory_xml_output(); 00252 $xw = new mock_xml_writer($xo); 00253 $xw->start(); 00254 $xw->begin_tag('first'); 00255 try { 00256 $xw->stop(); 00257 $this->assertTrue(false, 'xml_writer_exception expected'); 00258 } catch (exception $e) { 00259 $this->assertTrue($e instanceof xml_writer_exception); 00260 $this->assertEqual($e->errorcode, 'xml_writer_open_tags_remaining'); 00261 } 00262 00263 // Test simple transformer 00264 $xo = new memory_xml_output(); 00265 $xt = new mock_xml_contenttransformer(); 00266 $xw = new mock_xml_writer($xo, $xt); 00267 $xw->set_prologue(''); // empty prologue for easier matching 00268 $xw->start(); 00269 $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); 00270 $xw->full_tag('tagname2', 'somecontent', array('attrname' => 'attrvalue')); 00271 $xw->stop(); 00272 $result = $xo->get_allcontents(); 00273 $this->assertEqual($result, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue">testsomecontent</tagname2>'); 00274 00275 // Build a complex XML file and test results against stored file in fixtures 00276 $xo = new memory_xml_output(); 00277 $xw = new mock_xml_writer($xo); 00278 $xw->start(); 00279 $xw->begin_tag('toptag', array('name' => 'toptag', 'level' => 1, 'path' => '/toptag')); 00280 $xw->full_tag('secondtag', 'secondvalue', array('name' => 'secondtag', 'level' => 2, 'path' => '/toptag/secondtag', 'value' => 'secondvalue')); 00281 $xw->begin_tag('thirdtag', array('name' => 'thirdtag', 'level' => 2, 'path' => '/toptag/thirdtag')); 00282 $xw->full_tag('onevalue', 'onevalue', array('name' => 'onevalue', 'level' => 3, 'path' => '/toptag/thirdtag/onevalue')); 00283 $xw->full_tag('onevalue', 'anothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'anothervalue')); 00284 $xw->full_tag('onevalue', 'yetanothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'yetanothervalue')); 00285 $xw->full_tag('twovalue', 'twovalue', array('name' => 'twovalue', 'level' => 3, 'path' => '/toptag/thirdtag/twovalue')); 00286 $xw->begin_tag('forthtag', array('name' => 'forthtag', 'level' => 3, 'path' => '/toptag/thirdtag/forthtag')); 00287 $xw->full_tag('innervalue', 'innervalue'); 00288 $xw->begin_tag('innertag'); 00289 $xw->begin_tag('superinnertag', array('name' => 'superinnertag', 'level' => 5)); 00290 $xw->full_tag('superinnervalue', 'superinnervalue', array('name' => 'superinnervalue', 'level' => 6)); 00291 $xw->end_tag('superinnertag'); 00292 $xw->end_tag('innertag'); 00293 $xw->end_tag('forthtag'); 00294 $xw->begin_tag('fifthtag', array('level' => 3)); 00295 $xw->begin_tag('sixthtag', array('level' => 4)); 00296 $xw->full_tag('seventh', 'seventh', array('level' => 5)); 00297 $xw->end_tag('sixthtag'); 00298 $xw->end_tag('fifthtag'); 00299 $xw->full_tag('finalvalue', 'finalvalue', array('name' => 'finalvalue', 'level' => 3, 'path' => '/toptag/thirdtag/finalvalue')); 00300 $xw->full_tag('finalvalue'); 00301 $xw->end_tag('thirdtag'); 00302 $xw->end_tag('toptag'); 00303 $xw->stop(); 00304 $result = $xo->get_allcontents(); 00305 $fcontents = file_get_contents($CFG->dirroot . '/backup/util/xml/simpletest/fixtures/test1.xml'); 00306 00307 // Normalise carriage return characters. 00308 $fcontents = str_replace("\r\n", "\n", $fcontents); 00309 $this->assertEqual(trim($result), trim($fcontents)); 00310 } 00311 } 00312 00313 /* 00314 * helper extended xml_writer class that makes some methods public for testing 00315 */ 00316 class mock_xml_writer extends xml_writer { 00317 public function get_default_prologue() { 00318 return parent::get_default_prologue(); 00319 } 00320 } 00321 00322 /* 00323 * helper extended xml_contenttransformer prepending "test" to all the notnull contents 00324 */ 00325 class mock_xml_contenttransformer extends xml_contenttransformer { 00326 public function process($content) { 00327 return is_null($content) ? null : 'test' . $content; 00328 } 00329 }