PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/rexml/test_contrib.rb

http://github.com/ruby/ruby
Ruby | 585 lines | 479 code | 56 blank | 50 comment | 4 complexity | 5de064f0ab50ff17b4fdf978cc46d76b MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # coding: binary
  2. # frozen_string_literal: false
  3. require_relative "rexml_test_utils"
  4. require "rexml/document"
  5. require "rexml/parseexception"
  6. require "rexml/formatters/default"
  7. module REXMLTests
  8. class ContribTester < Test::Unit::TestCase
  9. include REXMLTestUtils
  10. include REXML
  11. XML_STRING_01 = <<DELIMITER
  12. <?xml version="1.0" encoding="UTF-8"?>
  13. <biblio>
  14. <entry type="Book">
  15. <author>Thomas, David; Hunt, Andrew</author>
  16. <language>english</language>
  17. <publisher>Addison-Wesley</publisher>
  18. <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
  19. <year>2000</year>
  20. </entry>
  21. <entry type="Book">
  22. <author>Blammo, Blah</author>
  23. <language>english</language>
  24. <publisher>Hubbabubba</publisher>
  25. <title>Foozboozer's Life</title>
  26. <type>Book</type>
  27. <year>2002</year>
  28. </entry>
  29. </biblio>
  30. DELIMITER
  31. XML_STRING_02 = <<DELIMITER
  32. <biblio>
  33. <entry type="Book">
  34. <language>english</language>
  35. <publisher>Addison-Wesley</publisher>
  36. <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
  37. <type>Book</type>
  38. <year>2000</year>
  39. </entry>
  40. <entry type="Book">
  41. <author>Blammo, Blah</author>
  42. <language>english</language>
  43. <publisher>Hubbabubba</publisher>
  44. <title>Foozboozer's Life</title>
  45. <type>Book</type>
  46. <year>2002</year>
  47. </entry>
  48. </biblio>
  49. DELIMITER
  50. # Tobias Reif <tobiasreif@pinkjuice.com>
  51. def test_bad_doctype_Tobias
  52. source = <<-EOF
  53. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
  54. "http://www.w3.org/TR/SVG/DTD/svg10.dtd"
  55. [
  56. <!-- <!ENTITY % fast-slow "0 0 .5 1">-->
  57. <!--<!ENTITY % slow-fast ".5 0 1 1">-->
  58. <!ENTITY hover_ani
  59. '<animateTransform attributeName="transform"
  60. type="scale" restart="whenNotActive" values="1;0.96"
  61. dur="0.5s" calcMode="spline" keySplines="0 0 .5 1"
  62. fill="freeze" begin="mouseover"/>
  63. <animateTransform attributeName="transform"
  64. type="scale" restart="whenNotActive" values="0.96;1"
  65. dur="0.5s" calcMode="spline" keySplines=".5 0 1 1"
  66. fill="freeze" begin="mouseover+0.5s"/>'
  67. >
  68. ]
  69. >
  70. EOF
  71. doc = REXML::Document.new source
  72. doc.write(out="")
  73. assert(out[/>\'>/] != nil, "Couldn't find >'>")
  74. assert(out[/\]>/] != nil, "Couldn't find ]>")
  75. end
  76. # Peter Verhage
  77. def test_namespace_Peter
  78. source = <<-EOF
  79. <?xml version="1.0"?>
  80. <config:myprog-config xmlns:config="http://someurl/program/version">
  81. <!-- main options -->
  82. <config:main>
  83. <config:parameter name="name" value="value"/>
  84. </config:main>
  85. </config:myprog-config>
  86. EOF
  87. doc = REXML::Document.new source
  88. assert_equal "myprog-config", doc.root.name
  89. count = 0
  90. REXML::XPath.each(doc, "x:myprog-config/x:main/x:parameter",
  91. {"x"=>"http://someurl/program/version"}) { |element|
  92. assert_equal "name", element.attributes["name"]
  93. count += 1;
  94. }
  95. assert_equal 1, count
  96. assert_equal "myprog-config", doc.elements["config:myprog-config"].name
  97. end
  98. # Tobias Reif <tobiasreif@pinkjuice.com>
  99. def test_complex_xpath_Tobias
  100. source = <<-EOF
  101. <root>
  102. <foo>
  103. <bar style="baz"/>
  104. <blah style="baz"/>
  105. <blam style="baz"/>
  106. </foo>
  107. <wax>
  108. <fudge>
  109. <noodle/>
  110. </fudge>
  111. </wax>
  112. </root>
  113. EOF
  114. # elements that have child elements
  115. # but not grandchildren
  116. # and not children that don't have a style attribute
  117. # and not children that have a unique style attribute
  118. complex_path = "*[* "+
  119. "and not(*/node()) "+
  120. "and not(*[not(@style)]) "+
  121. "and not(*/@style != */@style)]"
  122. doc = REXML::Document.new source
  123. results = REXML::XPath.match( doc.root, complex_path )
  124. assert(results)
  125. assert_equal 1, results.size
  126. assert_equal "foo", results[0].name
  127. end
  128. # "Chris Morris" <chrismo@charter.net>
  129. def test_extra_newline_on_read_Chris
  130. text = 'test text'
  131. e = REXML::Element.new('Test')
  132. e.add_text(text)
  133. REXML::Formatters::Default.new.write(e,out="")
  134. doc = REXML::Document.new(out)
  135. outtext = doc.root.text
  136. assert_equal(text, outtext)
  137. end
  138. # Tobias Reif <tobiasreif@pinkjuice.com>
  139. def test_other_xpath_Tobias
  140. schema = <<-DELIM
  141. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  142. elementFormDefault="qualified">
  143. <xs:element name="rect">
  144. <xs:complexType>
  145. <xs:attribute name="width" type="xs:byte" use="required"/>
  146. <xs:attribute name="height" type="xs:byte" use="required"/>
  147. </xs:complexType>
  148. </xs:element>
  149. <xs:element name="svg">
  150. <xs:complexType>
  151. <xs:sequence>
  152. <xs:element ref="rect"/>
  153. </xs:sequence>
  154. </xs:complexType>
  155. </xs:element>
  156. </xs:schema>
  157. DELIM
  158. doc = REXML::Document.new schema
  159. result = REXML::XPath.first(doc.root, 'xs:element[descendant::xs:element[@ref]]')
  160. assert result
  161. assert_equal "svg", result.attributes['name']
  162. result = REXML::XPath.first(doc, 'element[descendant::element[@ref]]')
  163. assert_nil result
  164. end
  165. #this first test succeeds, to check if stuff is set up correctly
  166. def test_xpath_01_TobiasReif
  167. doc = Document.new XML_STRING_01.dup
  168. desired_result = Document.new '<author>Thomas, David; Hunt, Andrew</author>'
  169. xpath = '//author'
  170. result = XPath.first(doc, xpath)
  171. assert_equal desired_result.to_s, result.to_s
  172. end
  173. def test_xpath_whitespace_TobiasReif
  174. # same as above, with whitespace in XPath
  175. doc = Document.new(XML_STRING_01.dup)
  176. desired_result = Document.new('<author>Thomas, David; Hunt, Andrew</author>')
  177. xpath = "\/\/author\n \n"
  178. result = XPath.first(doc, xpath)
  179. failure_message = "\n[[[TR: AFAIK, whitespace should be allowed]]]\n"
  180. assert_equal(desired_result.to_s, result.to_s, failure_message)
  181. end
  182. def test_xpath_02_TobiasReif
  183. doc = Document.new XML_STRING_01.dup
  184. desired_result = Document.new '<author>Thomas, David; Hunt, Andrew</author>'
  185. # Could that quirky
  186. # Programmer',&quot;'&quot;,'s
  187. # be handled automatically, somehow?
  188. # Or is there a simpler way? (the below XPath should match the author element above,
  189. # AFAIK; I tested it inside an XSLT)
  190. xpath = %q{/biblio/entry[
  191. title/text()=concat('Programming Ruby. The Pragmatic Programmer',"'",'s Guide')
  192. and
  193. year='2000'
  194. ]/author}
  195. result = XPath.first(doc, xpath)
  196. failure_message = "\nHow to handle the apos inside the string inside the XPath?\nXPath = #{xpath}\n"
  197. assert_equal desired_result.to_s, result.to_s, failure_message
  198. end
  199. def test_xpath_03_TobiasReif
  200. doc = Document.new XML_STRING_02.dup
  201. desired_result_string = "<entry type='Book'>
  202. <language>english</language>
  203. <publisher>Addison-Wesley</publisher>
  204. <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
  205. <type>Book</type>
  206. <year>2000</year>
  207. </entry>"
  208. Document.new desired_result_string
  209. xpath = "/biblio/entry[not(author)]"
  210. result = XPath.first(doc, xpath)
  211. assert_equal desired_result_string, result.to_s
  212. end
  213. def test_umlaut
  214. koln_iso = "K\xf6ln"
  215. koln_utf = "K\xc3\xb6ln"
  216. source_iso = "<?xml version='1.0' encoding='ISO-8859-1'?><test>#{koln_iso}</test>"
  217. source_utf = "<?xml version='1.0' encoding='UTF-8'?><test>#{koln_utf}</test>"
  218. if String.method_defined? :encode
  219. koln_iso.force_encoding('iso-8859-1')
  220. koln_utf.force_encoding('utf-8')
  221. source_iso.force_encoding('iso-8859-1')
  222. source_utf.force_encoding('utf-8')
  223. end
  224. doc = REXML::Document.new(source_iso)
  225. assert_equal('ISO-8859-1', doc.xml_decl.encoding)
  226. assert_equal(koln_utf, doc.root.text)
  227. doc.write(out="")
  228. assert_equal(source_iso, out )
  229. doc.xml_decl.encoding = 'UTF-8'
  230. doc.write(out="")
  231. assert_equal(source_utf, out)
  232. doc = Document.new <<-EOF
  233. <?xml version="1.0" encoding="ISO-8859-1"?>
  234. <intranet>
  235. <position><aktuell datum="01-10-11">Technik</aktuell></position>
  236. <hauptspalte>
  237. <headline>Technik</headline>
  238. Die Technik ist das R\xFCckgrat der meisten Gesch\xFCftsprozesse bei Home of the Brave. Deshalb sollen hier alle relevanten technischen Abl\xFCufe, Daten und Einrichtungen beschrieben werden, damit jeder im Bedarfsfall die n\xFCtigen Informationen, Anweisungen und Verhaltensempfehlungen nachlesen und/oder abrufen kann.
  239. </hauptspalte>
  240. <nebenspalte>
  241. <link ziel="Flash/">Flash</link><umbruch/>
  242. N\xFCtzliches von Flashern f\xFCr Flasher.<umbruch/>
  243. <link neu="ja" ziel="Cvs/">CVS-FAQ</link><umbruch/>
  244. FAQ zur Benutzung von CVS bei HOB
  245. </nebenspalte>
  246. </intranet>
  247. EOF
  248. tn = XPath.first(doc, "//nebenspalte/text()[2]")
  249. expected_iso = "N\xFCtzliches von Flashern f\xFCr Flasher."
  250. expected_utf = expected_iso.unpack('C*').pack('U*')
  251. expected_iso.force_encoding(::Encoding::ISO_8859_1)
  252. expected_utf.force_encoding(::Encoding::UTF_8)
  253. assert_equal(expected_utf, tn.to_s.strip)
  254. f = REXML::Formatters::Default.new
  255. f.write( tn, Output.new(o = "", "ISO-8859-1") )
  256. assert_equal(expected_iso, o.strip)
  257. doc = File.open(fixture_path('xmlfile-bug.xml')) {|file| Document.new file }
  258. tn = XPath.first(doc, "//nebenspalte/text()[2]")
  259. assert_equal(expected_utf, tn.to_s.strip)
  260. f.write( tn, Output.new(o = "", "ISO-8859-1") )
  261. assert_equal(expected_iso, o.strip)
  262. end
  263. def test_element_cloning_namespace_Chris
  264. aDoc = REXML::Document.new '<h1 tpl:content="title" xmlns:tpl="1">Dummy title</h1>'
  265. anElement = anElement = aDoc.elements[1]
  266. elementAttrPrefix = anElement.attributes.get_attribute('content').prefix
  267. aClone = anElement.clone
  268. cloneAttrPrefix = aClone.attributes.get_attribute('content').prefix
  269. assert_equal( elementAttrPrefix , cloneAttrPrefix )
  270. end
  271. def test_namespaces_in_attlist_tobias
  272. in_string = File.open(fixture_path('foo.xml'), 'r') do |file|
  273. file.read
  274. end
  275. doc = Document.new in_string
  276. assert_nil XPath.first(doc,'//leg')
  277. assert_equal 'http://www.foo.com/human', doc.root.elements[1].namespace
  278. assert_equal 'human leg',
  279. XPath.first(doc, '//x:leg/text()', {'x'=>'http://www.foo.com/human'}).to_s
  280. end
  281. # Alun ap Rhisiart
  282. def test_less_than_in_element_content
  283. doc = File.open(fixture_path('ProductionSupport.xml')) do |source|
  284. REXML::Document.new source
  285. end
  286. h = Hash.new
  287. doc.elements.each("//CommonError") { |el|
  288. h[el.elements['Key'].text] = 'okay'
  289. }
  290. assert(h.include?('MotorInsuranceContract(Object)>>#error:'))
  291. end
  292. # XPaths provided by Thomas Sawyer
  293. def test_various_xpath
  294. #@doc = REXML::Document.new('<r a="1"><p><c b="2"/></p></r>')
  295. doc = REXML::Document.new('<r a="1"><p><c b="2">3</c></p></r>')
  296. [['/r', REXML::Element],
  297. ['/r/p/c', REXML::Element],
  298. ['/r/attribute::a', Attribute],
  299. ['/r/@a', Attribute],
  300. ['/r/attribute::*', Attribute],
  301. ['/r/@*', Attribute],
  302. ['/r/p/c/attribute::b', Attribute],
  303. ['/r/p/c/@b', Attribute],
  304. ['/r/p/c/attribute::*', Attribute],
  305. ['/r/p/c/@*', Attribute],
  306. ['//c/attribute::b', Attribute],
  307. ['//c/@b', Attribute],
  308. ['//c/attribute::*', Attribute],
  309. ['//c/@*', Attribute],
  310. ['.//node()', REXML::Node ],
  311. ['.//node()[@a]', REXML::Element ],
  312. ['.//node()[@a="1"]', REXML::Element ],
  313. ['.//node()[@b]', REXML::Element ], # no show, why?
  314. ['.//node()[@b="2"]', REXML::Element ]
  315. ].each do |xpath,kind|
  316. begin
  317. REXML::XPath.each( doc, xpath ) do |what|
  318. assert_kind_of( kind, what, "\n\nWrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n\n" )
  319. end
  320. rescue Exception
  321. puts "PATH WAS: #{xpath}"
  322. raise
  323. end
  324. end
  325. [
  326. ['/r', 'attribute::a', Attribute ],
  327. ['/r', '@a', Attribute ],
  328. ['/r', 'attribute::*', Attribute ],
  329. ['/r', '@*', Attribute ],
  330. ['/r/p/c', 'attribute::b', Attribute ],
  331. ['/r/p/c', '@b', Attribute ],
  332. ['/r/p/c', 'attribute::*', Attribute ],
  333. ['/r/p/c', '@*', Attribute ]
  334. ].each do |nodepath, xpath, kind|
  335. begin
  336. context = REXML::XPath.first(doc, nodepath)
  337. REXML::XPath.each( context, xpath ) do |what|
  338. assert_kind_of kind, what, "Wrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n"
  339. end
  340. rescue Exception
  341. puts "PATH WAS: #{xpath}"
  342. raise
  343. end
  344. end
  345. end
  346. def test_entities_Holden_Glova
  347. document = <<-EOL
  348. <?xml version="1.0" encoding="UTF-8"?>
  349. <!DOCTYPE rubynet [
  350. <!ENTITY rbconfig.MAJOR "1">
  351. <!ENTITY rbconfig.MINOR "7">
  352. <!ENTITY rbconfig.TEENY "2">
  353. <!ENTITY rbconfig.ruby_version "&rbconfig.MAJOR;.&rbconfig.MINOR;">
  354. <!ENTITY rbconfig.arch "i386-freebsd5">
  355. <!ENTITY rbconfig.prefix "/usr/local">
  356. <!ENTITY rbconfig.libdir "&rbconfig.prefix;/lib">
  357. <!ENTITY rbconfig.includedir "&rbconfig.prefix;/include">
  358. <!ENTITY rbconfig.sitedir "&rbconfig.prefix;/lib/ruby/site_ruby">
  359. <!ENTITY rbconfig.sitelibdir "&rbconfig.sitedir;/&rbconfig.ruby_version;">
  360. <!ENTITY rbconfig.sitearchdir "&rbconfig.sitelibdir;/&rbconfig.arch;">
  361. ]>
  362. <rubynet>
  363. <pkg version="version1.0">
  364. <files>
  365. <file>
  366. <filename>uga.rb</filename>
  367. <mode>0444</mode>
  368. <path>&rbconfig.libdir;/rexml</path>
  369. <content encoding="xml">... the file here</content>
  370. </file>
  371. <file>
  372. <filename>booga.h</filename>
  373. <mode>0444</mode>
  374. <path>&rbconfig.includedir;</path>
  375. <content encoding="xml">... the file here</content>
  376. </file>
  377. <file>
  378. <filename>foo.so</filename>
  379. <mode>0555</mode>
  380. <path>&rbconfig.sitearchdir;/rexml</path>
  381. <content encoding="mime64">Li4uIHRoZSBmaWxlIGhlcmU=\n</content>
  382. </file>
  383. </files>
  384. </pkg>
  385. </rubynet>
  386. EOL
  387. file_xpath = '/rubynet/pkg/files/file'
  388. root = REXML::Document.new(document)
  389. root.elements.each(file_xpath) do |metadata|
  390. text = metadata.elements['path'].get_text.value
  391. assert text !~ /&rbconfig/, "'#{text}' failed"
  392. end
  393. #Error occurred in test_package_file_opens(TC_PackageInstall):
  394. # ArgumentError:
  395. #illegal access mode &rbconfig.prefix;/lib/rexml
  396. #
  397. #[synack@Evergreen] src $ ruby --version
  398. #ruby 1.6.7 (2002-03-01) [i686-linux-gnu]
  399. #
  400. #It looks like it expanded the first entity, but didn't reparse it for more
  401. #entities. possible bug - or have I mucked this up?
  402. end
  403. def test_whitespace_after_xml_decl
  404. Document.new <<EOL
  405. <?xml version='1.0'?>
  406. <blo>
  407. <wak>
  408. </wak>
  409. </blo>
  410. EOL
  411. end
  412. def test_external_entity
  413. xp = '//channel/title'
  414. %w{working.rss broken.rss}.each do |path|
  415. File.open(File.join(fixture_path(path))) do |file|
  416. doc = REXML::Document.new file.readlines.join('')
  417. # check to make sure everything is kosher
  418. assert_equal( doc.root.class, REXML::Element )
  419. assert_equal( doc.root.elements.class, REXML::Elements )
  420. # get the title of the feed
  421. assert( doc.root.elements[xp].kind_of?( REXML::Element ) )
  422. end
  423. end
  424. end
  425. def test_maintain_dtd
  426. src = %q{<?xml version="1.0" encoding="UTF-8"?>
  427. <!DOCTYPE ivattacks SYSTEM "../../ivacm.dtd" [
  428. <!ENTITY % extern-packages SYSTEM "../../ivpackages.dtd">
  429. <!ENTITY % extern-packages SYSTEM "../../common-declarations.dtd">
  430. %extern-packages;
  431. %extern-common;
  432. ]>}
  433. doc = Document.new( src )
  434. doc.write( out="" )
  435. src = src.tr('"', "'")
  436. out = out.tr('"', "'")
  437. assert_equal( src, out )
  438. end
  439. def test_text_nodes_nomatch
  440. source = "<root><child>test</child></root>"
  441. d = REXML::Document.new( source )
  442. r = REXML::XPath.match( d, %q{/root/child[text()="no-test"]} )
  443. assert_equal( 0, r.size )
  444. end
  445. def test_raw_Terje_Elde
  446. f = REXML::Formatters::Default.new
  447. txt = 'abc&#248;def'
  448. a = Text.new( txt,false,nil,true )
  449. f.write(a,out="")
  450. assert_equal( txt, out )
  451. txt = '<sean><russell>abc&#248;def</russell></sean>'
  452. a = Document.new( txt, { :raw => ["russell"] } )
  453. f.write(a,out="")
  454. assert_equal( txt, out )
  455. end
  456. def test_indenting_error
  457. a=Element.new("test1")
  458. b=Element.new("test2")
  459. c=Element.new("test3")
  460. b << c
  461. a << b
  462. REXML::Formatters::Pretty.new.write(a,"")
  463. end
  464. def test_pos
  465. require 'tempfile'
  466. Tempfile.create("tidal") {|testfile|
  467. testdata = %Q{<calibration>
  468. <section name="parameters">
  469. <param name="barpress">760</param>
  470. <param name="hertz">50</param>
  471. </section>
  472. </calibration>
  473. }
  474. testfile.puts testdata
  475. testfile.rewind
  476. assert_nothing_raised do
  477. REXML::Document.new(testfile)
  478. end
  479. }
  480. end
  481. def test_deep_clone
  482. a = Document.new( '<?xml version="1.0"?><!DOCTYPE html PUBLIC
  483. "-//W3C//DTD
  484. XHTML 1.0 Transitional//EN"
  485. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html
  486. xmlns="http:///www.w3.org/1999/xhtml"></html>' )
  487. b = a.deep_clone
  488. assert_equal a.to_s, b.to_s
  489. end
  490. def test_double_escaping
  491. data = '<title>AT&amp;T</title>'
  492. xml = "<description><![CDATA[#{data}]]></description>"
  493. doc = REXML::Document.new(xml)
  494. description = doc.find {|e| e.name=="description"}
  495. assert_equal data, description.text
  496. end
  497. def test_ticket_12
  498. cfg = "<element><anotherelement><child1>a</child1><child2>b</child2></anotherelement></element>"
  499. config = REXML::Document.new( cfg )
  500. assert_equal( "a", config.elements[ "//child1" ].text )
  501. end
  502. =begin
  503. # This is a silly test, and is low priority
  504. def test_namespace_serialization_tobi_reif
  505. doc = Document.new '<doc xmlns:b="http://www.foo.foo">
  506. <b:p/>
  507. </doc>'
  508. ns = 'http://www.foo.foo'
  509. ns_declaration={'f'=>ns}
  510. returned = XPath.match(doc,'//f:p',ns_declaration)
  511. # passes:
  512. assert( (returned[0].namespace==ns), 'namespace should be '+ns)
  513. serialized = returned.to_s
  514. serialized_and_parsed = Document.new(serialized)
  515. puts 'serialized: '+serialized
  516. # ... currently brings <b:p/>
  517. # prefix b is undeclared (!)
  518. assert( (serialized_and_parsed.namespace==ns),
  519. 'namespace should still be '+ns.inspect+
  520. ' and not '+serialized_and_parsed.namespace.inspect)
  521. # ... currently results in a failure:
  522. # 'namespace should still be "http://www.foo.foo" and not ""'
  523. end
  524. =end
  525. end
  526. end