Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 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 * @package core_backup 19 * @category phpunit 20 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 // Include all the needed stuff 27 global $CFG; 28 require_once($CFG->dirroot . '/backup/util/xml/xml_writer.class.php'); 29 require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php'); 30 require_once($CFG->dirroot . '/backup/util/xml/output/memory_xml_output.class.php'); 31 require_once($CFG->dirroot . '/backup/util/xml/contenttransformer/xml_contenttransformer.class.php'); 32 33 /** 34 * xml_writer tests 35 */ 36 class xml_writer_testcase extends basic_testcase { 37 38 /** 39 * test xml_writer public methods 40 */ 41 function test_xml_writer_public_api() { 42 global $CFG; 43 // Instantiate xml_output 44 $xo = new memory_xml_output(); 45 $this->assertTrue($xo instanceof xml_output); 46 47 // Instantiate xml_writer with null xml_output 48 try { 49 $xw = new mock_xml_writer(null); 50 $this->assertTrue(false, 'xml_writer_exception expected'); 51 } catch (exception $e) { 52 $this->assertTrue($e instanceof xml_writer_exception); 53 $this->assertEquals($e->errorcode, 'invalid_xml_output'); 54 } 55 56 // Instantiate xml_writer with wrong xml_output object 57 try { 58 $xw = new mock_xml_writer(new stdclass()); 59 $this->assertTrue(false, 'xml_writer_exception expected'); 60 } catch (exception $e) { 61 $this->assertTrue($e instanceof xml_writer_exception); 62 $this->assertEquals($e->errorcode, 'invalid_xml_output'); 63 } 64 65 // Instantiate xml_writer with wrong xml_contenttransformer object 66 try { 67 $xw = new mock_xml_writer($xo, new stdclass()); 68 $this->assertTrue(false, 'xml_writer_exception expected'); 69 } catch (exception $e) { 70 $this->assertTrue($e instanceof xml_writer_exception); 71 $this->assertEquals($e->errorcode, 'invalid_xml_contenttransformer'); 72 } 73 74 // Instantiate xml_writer and start it twice 75 $xw = new mock_xml_writer($xo); 76 $xw->start(); 77 try { 78 $xw->start(); 79 $this->assertTrue(false, 'xml_writer_exception expected'); 80 } catch (exception $e) { 81 $this->assertTrue($e instanceof xml_writer_exception); 82 $this->assertEquals($e->errorcode, 'xml_writer_already_started'); 83 } 84 85 // Instantiate xml_writer and stop it twice 86 $xo = new memory_xml_output(); 87 $xw = new mock_xml_writer($xo); 88 $xw->start(); 89 $xw->stop(); 90 try { 91 $xw->stop(); 92 $this->assertTrue(false, 'xml_writer_exception expected'); 93 } catch (exception $e) { 94 $this->assertTrue($e instanceof xml_writer_exception); 95 $this->assertEquals($e->errorcode, 'xml_writer_already_stopped'); 96 } 97 98 // Stop writer without starting it 99 $xo = new memory_xml_output(); 100 $xw = new mock_xml_writer($xo); 101 try { 102 $xw->stop(); 103 $this->assertTrue(false, 'xml_writer_exception expected'); 104 } catch (exception $e) { 105 $this->assertTrue($e instanceof xml_writer_exception); 106 $this->assertEquals($e->errorcode, 'xml_writer_not_started'); 107 } 108 109 // Start writer after stopping it 110 $xo = new memory_xml_output(); 111 $xw = new mock_xml_writer($xo); 112 $xw->start(); 113 $xw->stop(); 114 try { 115 $xw->start(); 116 $this->assertTrue(false, 'xml_writer_exception expected'); 117 } catch (exception $e) { 118 $this->assertTrue($e instanceof xml_writer_exception); 119 $this->assertEquals($e->errorcode, 'xml_writer_already_stopped'); 120 } 121 122 // Try to set prologue/schema after start 123 $xo = new memory_xml_output(); 124 $xw = new mock_xml_writer($xo); 125 $xw->start(); 126 try { 127 $xw->set_nonamespace_schema('http://moodle.org'); 128 $this->assertTrue(false, 'xml_writer_exception expected'); 129 } catch (exception $e) { 130 $this->assertTrue($e instanceof xml_writer_exception); 131 $this->assertEquals($e->errorcode, 'xml_writer_already_started'); 132 } 133 try { 134 $xw->set_prologue('sweet prologue'); 135 $this->assertTrue(false, 'xml_writer_exception expected'); 136 } catch (exception $e) { 137 $this->assertTrue($e instanceof xml_writer_exception); 138 $this->assertEquals($e->errorcode, 'xml_writer_already_started'); 139 } 140 141 // Instantiate properly with memory_xml_output, start and stop. 142 // Must get default UTF-8 prologue 143 $xo = new memory_xml_output(); 144 $xw = new mock_xml_writer($xo); 145 $xw->start(); 146 $xw->stop(); 147 $this->assertEquals($xo->get_allcontents(), $xw->get_default_prologue()); 148 149 // Instantiate, set prologue and schema, put 1 full tag and get results 150 $xo = new memory_xml_output(); 151 $xw = new mock_xml_writer($xo); 152 $xw->set_prologue('CLEARLY WRONG PROLOGUE'); 153 $xw->set_nonamespace_schema('http://moodle.org/littleschema'); 154 $xw->start(); 155 $xw->full_tag('TEST', 'Hello World!', array('id' => 1)); 156 $xw->stop(); 157 $result = $xo->get_allcontents(); 158 // Perform various checks 159 $this->assertEquals(strpos($result, 'WRONG'), 8); 160 $this->assertEquals(strpos($result, '<TEST id="1"'), 22); 161 $this->assertEquals(strpos($result, 'xmlns:xsi='), 39); 162 $this->assertEquals(strpos($result, 'http://moodle.org/littleschema'), 128); 163 $this->assertEquals(strpos($result, 'Hello World'), 160); 164 $this->assertFalse(strpos($result, $xw->get_default_prologue())); 165 166 // Try to close one tag in wrong order 167 $xo = new memory_xml_output(); 168 $xw = new mock_xml_writer($xo); 169 $xw->start(); 170 $xw->begin_tag('first'); 171 $xw->begin_tag('second'); 172 try { 173 $xw->end_tag('first'); 174 $this->assertTrue(false, 'xml_writer_exception expected'); 175 } catch (exception $e) { 176 $this->assertTrue($e instanceof xml_writer_exception); 177 $this->assertEquals($e->errorcode, 'xml_writer_end_tag_no_match'); 178 } 179 180 // Try to close one tag before starting any tag 181 $xo = new memory_xml_output(); 182 $xw = new mock_xml_writer($xo); 183 $xw->start(); 184 try { 185 $xw->end_tag('first'); 186 $this->assertTrue(false, 'xml_writer_exception expected'); 187 } catch (exception $e) { 188 $this->assertTrue($e instanceof xml_writer_exception); 189 $this->assertEquals($e->errorcode, 'xml_writer_end_tag_no_match'); 190 } 191 192 // Full tag without contents (null and empty string) 193 $xo = new memory_xml_output(); 194 $xw = new mock_xml_writer($xo); 195 $xw->set_prologue(''); // empty prologue for easier matching 196 $xw->start(); 197 $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); 198 $xw->full_tag('tagname2', '', array('attrname' => 'attrvalue')); 199 $xw->stop(); 200 $result = $xo->get_allcontents(); 201 $this->assertEquals($result, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue"></tagname2>'); 202 203 204 // Test case-folding is working 205 $xo = new memory_xml_output(); 206 $xw = new mock_xml_writer($xo, null, true); 207 $xw->set_prologue(''); // empty prologue for easier matching 208 $xw->start(); 209 $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attrvalue')); 210 $xw->stop(); 211 $result = $xo->get_allcontents(); 212 $this->assertEquals($result, '<TAGNAME ATTRNAME="attrvalue">textcontent</TAGNAME>'); 213 214 // Test UTF-8 chars in tag and attribute names, attr values and contents 215 $xo = new memory_xml_output(); 216 $xw = new mock_xml_writer($xo); 217 $xw->set_prologue(''); // empty prologue for easier matching 218 $xw->start(); 219 $xw->full_tag('áéíóú', 'ÁÉÍÓÚ', array('àèìòù' => 'ÀÈÌÒÙ')); 220 $xw->stop(); 221 $result = $xo->get_allcontents(); 222 $this->assertEquals($result, '<áéíóú àèìòù="ÀÈÌÒÙ">ÁÉÍÓÚ</áéíóú>'); 223 224 // Try non-safe content in attributes 225 $xo = new memory_xml_output(); 226 $xw = new mock_xml_writer($xo); 227 $xw->set_prologue(''); // empty prologue for easier matching 228 $xw->start(); 229 $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attr' . chr(27) . '\'"value')); 230 $xw->stop(); 231 $result = $xo->get_allcontents(); 232 $this->assertEquals($result, '<tagname attrname="attr\'"value">textcontent</tagname>'); 233 234 // Try non-safe content in text 235 $xo = new memory_xml_output(); 236 $xw = new mock_xml_writer($xo); 237 $xw->set_prologue(''); // empty prologue for easier matching 238 $xw->start(); 239 $xw->full_tag('tagname', "text\r\ncontent\rwith" . chr(27), array('attrname' => 'attrvalue')); 240 $xw->stop(); 241 $result = $xo->get_allcontents(); 242 $this->assertEquals($result, '<tagname attrname="attrvalue">text' . "\ncontent\n" . 'with</tagname>'); 243 244 // Try to stop the writer without clossing all the open tags 245 $xo = new memory_xml_output(); 246 $xw = new mock_xml_writer($xo); 247 $xw->start(); 248 $xw->begin_tag('first'); 249 try { 250 $xw->stop(); 251 $this->assertTrue(false, 'xml_writer_exception expected'); 252 } catch (exception $e) { 253 $this->assertTrue($e instanceof xml_writer_exception); 254 $this->assertEquals($e->errorcode, 'xml_writer_open_tags_remaining'); 255 } 256 257 // Test simple transformer 258 $xo = new memory_xml_output(); 259 $xt = new mock_xml_contenttransformer(); 260 $xw = new mock_xml_writer($xo, $xt); 261 $xw->set_prologue(''); // empty prologue for easier matching 262 $xw->start(); 263 $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); 264 $xw->full_tag('tagname2', 'somecontent', array('attrname' => 'attrvalue')); 265 $xw->stop(); 266 $result = $xo->get_allcontents(); 267 $this->assertEquals($result, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue">testsomecontent</tagname2>'); 268 269 // Build a complex XML file and test results against stored file in fixtures 270 $xo = new memory_xml_output(); 271 $xw = new mock_xml_writer($xo); 272 $xw->start(); 273 $xw->begin_tag('toptag', array('name' => 'toptag', 'level' => 1, 'path' => '/toptag')); 274 $xw->full_tag('secondtag', 'secondvalue', array('name' => 'secondtag', 'level' => 2, 'path' => '/toptag/secondtag', 'value' => 'secondvalue')); 275 $xw->begin_tag('thirdtag', array('name' => 'thirdtag', 'level' => 2, 'path' => '/toptag/thirdtag')); 276 $xw->full_tag('onevalue', 'onevalue', array('name' => 'onevalue', 'level' => 3, 'path' => '/toptag/thirdtag/onevalue')); 277 $xw->full_tag('onevalue', 'anothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'anothervalue')); 278 $xw->full_tag('onevalue', 'yetanothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'yetanothervalue')); 279 $xw->full_tag('twovalue', 'twovalue', array('name' => 'twovalue', 'level' => 3, 'path' => '/toptag/thirdtag/twovalue')); 280 $xw->begin_tag('forthtag', array('name' => 'forthtag', 'level' => 3, 'path' => '/toptag/thirdtag/forthtag')); 281 $xw->full_tag('innervalue', 'innervalue'); 282 $xw->begin_tag('innertag'); 283 $xw->begin_tag('superinnertag', array('name' => 'superinnertag', 'level' => 5)); 284 $xw->full_tag('superinnervalue', 'superinnervalue', array('name' => 'superinnervalue', 'level' => 6)); 285 $xw->end_tag('superinnertag'); 286 $xw->end_tag('innertag'); 287 $xw->end_tag('forthtag'); 288 $xw->begin_tag('fifthtag', array('level' => 3)); 289 $xw->begin_tag('sixthtag', array('level' => 4)); 290 $xw->full_tag('seventh', 'seventh', array('level' => 5)); 291 $xw->end_tag('sixthtag'); 292 $xw->end_tag('fifthtag'); 293 $xw->full_tag('finalvalue', 'finalvalue', array('name' => 'finalvalue', 'level' => 3, 'path' => '/toptag/thirdtag/finalvalue')); 294 $xw->full_tag('finalvalue'); 295 $xw->end_tag('thirdtag'); 296 $xw->end_tag('toptag'); 297 $xw->stop(); 298 $result = $xo->get_allcontents(); 299 $fcontents = file_get_contents($CFG->dirroot . '/backup/util/xml/tests/fixtures/test1.xml'); 300 301 // Normalise carriage return characters. 302 $fcontents = str_replace("\r\n", "\n", $fcontents); 303 $this->assertEquals(trim($result), trim($fcontents)); 304 } 305 } 306 307 /* 308 * helper extended xml_writer class that makes some methods public for testing 309 */ 310 class mock_xml_writer extends xml_writer { 311 public function get_default_prologue() { 312 return parent::get_default_prologue(); 313 } 314 } 315 316 /* 317 * helper extended xml_contenttransformer prepending "test" to all the notnull contents 318 */ 319 class mock_xml_contenttransformer extends xml_contenttransformer { 320 public function process($content) { 321 return is_null($content) ? null : 'test' . $content; 322 } 323 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body