C0 code coverage information


Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
Name Total lines Lines of code Total coverage Code coverage
tests.rb 836 634
96.9% 
95.9% 
  1 #!/usr/bin/env ruby
  2 require 'test/unit'
  3 require 'magic_xml'
  4 
  5 # For tests
  6 require 'stringio'
  7 
  8 class XML_Tests < Test::Unit::TestCase
  9     # Test whether XML.new constructors work (without monadic case)
 10     def test_constructors
 11         br = XML.new(:br)
 12         h3 = XML.new(:h3, "Hello")
 13         a  = XML.new(:a, {:href => "http://www.google.com/"}, "Google")
 14         ul = XML.new(:ul, XML.new(:li, "Hello"), XML.new(:li, "world"))
 15 
 16         assert_equal("<br/>", br.to_s, "Constructors should work")
 17         assert_equal("<h3>Hello</h3>", h3.to_s, "Constructors should work")
 18         assert_equal("<a href='http://www.google.com/'>Google</a>", a.to_s, "Constructors should work")
 19         assert_equal("<ul><li>Hello</li><li>world</li></ul>", ul.to_s, "Constructors should work")
 20     end
 21 
 22     # Test character escaping on output, in text and in attribute values
 23     def test_escapes
 24         p = XML.new(:p, "< > &")
 25         foo = XML.new(:foo, {:bar=>"< > ' \" &"})
 26 
 27         assert_equal("<p>&lt; &gt; &amp;</p>", p.to_s, "Character escaping should work")
 28         assert_equal("<foo bar='&lt; &gt; &apos; &quot; &amp;'/>", foo.to_s, "Character escaping in attributes should work")
 29     end
 30 
 31     # Test #sort_by and #children_sort_by
 32     def test_sort_by
 33         doc = XML.parse("<foo><bar id='5'/>a<bar id='3'/>c<bar id='4'/>b<bar id='1'/></foo>")
 34         
 35         doc_by_id = doc.sort_by{|c| c[:id]}
 36         assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/></foo>", doc_by_id.to_s)
 37 
 38         doc_all_by_id = doc.children_sort_by{|c| if c.is_a? XML then [0, c[:id]] else [1, c] end}
 39         assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/>abc</foo>", doc_all_by_id.to_s)
 40     end
 41 
 42     # Test XML#[] and XML#[]= for attribute access
 43     def test_attr
 44         foo = XML.new(:foo, {:x => "1"})
 45         assert_equal("1", foo[:x], "Attribute reading should work")
 46         foo[:x] = "2"
 47         foo[:y] = "3"
 48         assert_equal("2", foo[:x], "Attribute writing should work")
 49         assert_equal("3", foo[:y], "Attribute writing should work")
 50     end
 51    
 52     # Test XML#<< method for adding children
 53     def test_add
 54         a = XML.new(:p, "Hello")
 55         a << ", "
 56         a << "world!"
 57         assert_equal("<p>Hello, world!</p>", a.to_s, "XML#<< should work")
 58 
 59         b = XML.new(:foo)
 60         b << XML.new(:bar)
 61         assert_equal("<foo><bar/></foo>", b.to_s, "XML#<< should work")
 62     end
 63    
 64     # Test XML#each method for iterating over children
 65     def test_each
 66         a = XML.new(:p, "Hello", ", ", "world", XML.new(:br))
 67         b = ""
 68         a.each{|c| b += c.to_s}
 69         assert_equal("Hello, world<br/>", b, "XML#each should work")
 70     end
 71 
 72     # Test XML#map method
 73     def test_map
 74         a = XML.new(:body, XML.new(:h3, "One"), "Hello", XML.new(:h3, "Two"))
 75         b = a.map{|c|
 76             if c.is_a? XML and c.name == :h3
 77                 XML.new(:h2, c.attrs, *c.contents)
 78             else
 79                 c
 80             end
 81         }
 82         assert_equal("<body><h3>One</h3>Hello<h3>Two</h3></body>", a.to_s, "XML#map should not modify the argument")
 83         assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", b.to_s, "XML#map should work")
 84         
 85         d = a.map(:h3) {|c|
 86             XML.new(:h2, c.attrs, *c.contents)
 87         }
 88         assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", d.to_s, "XML#map should accept selectors")
 89     end
 90  
 91     # Test XML#==  
 92     def test_eqeq
 93         a = XML.new(:foo)
 94         b = XML.new(:foo)
 95         c = XML.new(:bar)
 96         assert(a==a, "XML#== should work")
 97         assert(a==b, "XML#== should work")
 98         assert(a!=c, "XML#== should work")
 99        
100         d = XML.new(:foo, {:bar => "1"})
101         e = XML.new(:foo, {:bar => "1"})
102         f = XML.new(:foo, {:bar => "2"})
103         assert(d==d, "XML#== should work")
104         assert(d==e, "XML#== should work")
105         assert(d!=f, "XML#== should work")
106        
107         a = XML.new(:foo, "Hello, world!")
108         b = XML.new(:foo, "Hello, world!")
109         c = XML.new(:foo, "Hello", ", world!")
110         d = XML.new(:foo, "Hello")
111         e = XML.new(:foo, "Hello", "")
112         assert(a==a, "XML#== should work")
113         assert(a==b, "XML#== should work")
114         assert(a==c, "XML#== should work")
115         assert(a!=d, "XML#== should work")
116         assert(d==e, "Empty children should not affect XML#==")
117        
118         # Highly pathological case
119         a = XML.new(:foo, "ab", "cde", "", "fg", "hijk", "", "")
120         b = XML.new(:foo, "", "abc", "d", "efg", "h", "ijk")
121         assert(a==b, "XML#== should work with differently split Strings too")
122         
123         # String vs XML
124         a = XML.new(:foo, "Hello")
125         b = XML.new(:foo) {foo!}
126         c = XML.new(:foo) {bar!}
127         assert(a!=b, "XML#== should work with children of different types")
128         assert(b!=c, "XML#== should work recursively")
129 
130         a = XML.new(:foo) {foo!; bar!}
131         b = XML.new(:foo) {foo!; foo!}
132         assert(a!=b, "XML#== should work recursively")
133     end
134    
135     # Test dup-with-block method
136     def test_dup
137         a = XML.new(:foo, {:a => "1"}, "Hello")
138         b = a.dup{ @name = :bar }
139         c = a.dup{ self[:a] = "2" }
140         d = a.dup{ self << ", world!" }
141        
142         assert_equal("<foo a='1'>Hello</foo>", a.to_s, "XML#dup{} should not modify its argument")
143         assert_equal("<bar a='1'>Hello</bar>", b.to_s, "XML#dup{} should work")
144         assert_equal("<foo a='2'>Hello</foo>", c.to_s, "XML#dup{} should work")
145         assert_equal("<foo a='1'>Hello, world!</foo>", d.to_s, "XML#dup{} should work")
146        
147         # Deep copy test
148         a = XML.new(:h3, "Hello")
149         b = XML.new(:foo, XML.new(:bar, a))
150         c = b.dup
151         a << ", world!"
152        
153         assert_equal("<foo><bar><h3>Hello, world!</h3></bar></foo>", b.to_s, "XML#dup should make a deep copy")
154         assert_equal("<foo><bar><h3>Hello</h3></bar></foo>", c.to_s, "XML#dup should make a deep copy")
155     end
156    
157     # Test XML#normalize! method
158     def test_normalize
159         a = XML.new(:foo, "He", "", "llo")
160         b = XML.new(:foo, "")
161         c = XML.new(:foo, "", XML.new(:bar, "1"), "", XML.new(:bar, "2", ""), "X", XML.new(:bar, "", "3"), "")
162 
163         a.normalize!
164         b.normalize!
165         c.normalize!
166 
167         assert_equal(["Hello"], a.contents, "XML#normalize! should work")
168         assert_equal([], b.contents, "XML#normalize! should work")
169         assert_equal([XML.new(:bar, "1"), XML.new(:bar, "2"), "X", XML.new(:bar, "3")], c.contents, "XML#normalize! should work")
170     end
171 
172     # Test the "monadic" interface, that is constructors
173     # with instance_eval'd blocks passed to them:
174     # XML.new(:foo) { bar! } # -> <foo><bar/></foo>
175     def test_monadic
176         a = XML.new(:foo) { bar!; xml!(:xxx) }
177         b = xml(:div) {
178             ul! {
179                 li!(XML.a("Hello"))
180             }
181         }
182         assert_equal("<foo><bar/><xxx/></foo>", a.to_s, "Monadic interface should work")
183         assert_equal("<div><ul><li><a>Hello</a></li></ul></div>", b.to_s, "Monadic interface should work")
184     end
185     
186     # Test if parsing and printing gives the right results
187     # We test mostly round-trip
188     def test_parse
189         a = "<foo/>"
190         b = "<foo a='1'/>"
191         c = "<foo>Hello</foo>"
192         d = "<foo a='1'><bar b='2'>Hello</bar><bar b='3'>world</bar></foo>"
193         e = "<foo>&gt; &lt; &amp;</foo>"
194         f = "<foo a='b&amp;c'/>"
195         
196         assert_equal(a, XML.parse(a).to_s, "XML.parse(x).to_s should equal x for normalized x")
197         assert_equal(b, XML.parse(b).to_s, "XML.parse(x).to_s should equal x for normalized x")
198         assert_equal(c, XML.parse(c).to_s, "XML.parse(x).to_s should equal x for normalized x")
199         assert_equal(d, XML.parse(d).to_s, "XML.parse(x).to_s should equal x for normalized x")
200         assert_equal(e, XML.parse(e).to_s, "XML.parse(x).to_s should equal x for normalized x")
201         assert_equal(f, XML.parse(f).to_s, "XML.parse(x).to_s should equal x for normalized x")
202     end
203 
204     # Test parsing &-entities
205     def test_parse_extra_escapes
206         a     = "<foo>&quot; &apos;</foo>"
207         a_out = "<foo>\" '</foo>"
208 
209         assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should normalize entities in x")
210     end
211 
212     # Test handling extra cruft
213     # Some things are best ignored or normalized
214     def test_parse_extra_cdata
215         a     = "<foo><![CDATA[<greeting>Hello, world!</greeting>]]></foo>"
216         a_out = "<foo>&lt;greeting&gt;Hello, world!&lt;/greeting&gt;</foo>"
217         assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should equal normalized x")
218     end
219 
220     # Test handling (=ignoring) XML declarations
221     def test_parse_extra_qxml
222         b     = "<?xml version=\"1.0\"?><greeting>Hello, world!</greeting>"
223         b_out = "<greeting>Hello, world!</greeting>"
224         assert_equal(b_out, XML.parse(b).to_s, "XML.parse(x).to_s should equal normalized x")
225     end
226 
227     # Test handling (=ignoring) DTDs
228     def test_parse_extra_dtd
229         c     = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]><greeting>Hello, world!</greeting>"
230         c_out = "<greeting>Hello, world!</greeting>"
231         assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
232     end
233 
234     # Test handling (=ignoring) DTDs
235     def test_parse_extra_comment
236         c     = "<!-- this is a comment --><greeting>Hello,<!-- another comment --> world!</greeting>"
237         c_out = "<greeting>Hello, world!</greeting>"
238         assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
239     end
240 
241     # Test reading from a file
242     def test_parse_file
243         a = File.open("test.xml").xml_parse
244         b = XML.from_file("test.xml")
245         c = XML.from_url("file:test.xml")
246         d = XML.from_url("string:<foo><bar></bar></foo>")
247         e = XML.parse("<foo><bar></bar></foo>")
248         f = "<foo><bar></bar></foo>".xml_parse
249         g = XML.foo { bar! }
250         
251         assert_equal(g.to_s, a.to_s, "File#xml_parse should work")
252         assert_equal(g.to_s, b.to_s, "XML.from_file should work")
253         assert_equal(g.to_s, c.to_s, "XML.from_url(\"file:...\") should work")
254         assert_equal(g.to_s, d.to_s, "XML.from_url(\"string:...\") should work")
255         assert_equal(g.to_s, e.to_s, "XML.parse should work")
256         assert_equal(g.to_s, f.to_s, "String#xml_parse should work")
257     end
258 
259     # Test XML#children and Array#children
260     def test_chilrden
261         a = XML.bar({:x=>"1"})
262         b = XML.bar({:x=>"3"})
263         c = XML.bar({:x=>"2"}, b)
264         d = XML.foo(a,c)
265         e = d.children(:bar)
266         f = e.children(:bar)
267         assert_equal([a,c], e, "XML#children(tag) should return tag-tagged children")
268         assert_equal([b], f, "Array#children(tag) should return tag-tagged children of its elements")
269     end
270     
271     # Test XML#descendants and Array#descendants
272     def test_descendants
273         a = XML.bar({:x=>"1"})
274         b = XML.bar({:x=>"3"})
275         c = XML.bar({:x=>"2"}, b)
276         d = XML.foo(a,c)
277         e = d.descendants(:bar)
278         f = e.descendants(:bar)
279         assert_equal([a,c,b], e, "XML#descendants(tag) should return tag-tagged descendants")
280         assert_equal([b], f, "Array#descendants(tag) should return tag-tagged descendants of its elements")
281     end
282 
283     # Test XML#exec! monadic interface
284     def test_exec
285         a = XML.foo
286         a.exec! {
287             bar! { text! "Hello" }
288             text! "world"
289         }
290         assert_equal("<foo><bar>Hello</bar>world</foo>", a.to_s, "XML#exec! should work")
291     end
292 
293     # Test XML#child
294     def test_child
295         a = XML.parse("<foo></foo>")
296         b = XML.parse("<foo><bar a='1'/></foo>")
297         c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
298 
299         assert_equal(nil, a.child(:bar), "XML#child should return nil if there are no matching children")
300         assert_equal("<bar a='1'/>", b.child(:bar).to_s, "XML#child should work")
301         assert_equal("<bar a='1'/>", c.child(:bar).to_s, "XML#child should return first child if there are many")
302         assert_equal("<bar a='2'/>", c.child({:a => '2'}).to_s, "XML#child should support patterns")
303     end
304 
305     # Test XML#descendant
306     def test_descendant
307         a = XML.parse("<foo></foo>")
308         b = XML.parse("<foo><bar a='1'/></foo>")
309         c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
310         d = XML.parse("<foo><bar a='1'><bar a='2'/></bar><bar a='3'/></foo>")
311         e = XML.parse("<foo><foo><bar a='1'/></foo><bar a='2'/></foo>")
312         
313         assert_equal(nil, a.descendant(:bar), "XML#descendant should return nil if there are no matching descendants")
314         assert_equal("<bar a='1'/>", b.descendant(:bar).to_s, "XML#descendant should work")
315         assert_equal("<bar a='1'/>", c.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
316         assert_equal("<bar a='1'><bar a='2'/></bar>", d.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
317         assert_equal("<bar a='1'/>", e.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
318         assert_equal("<bar a='2'/>", c.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
319         assert_equal("<bar a='2'/>", d.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
320         assert_equal("<bar a='2'/>", e.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
321     end
322     
323     # Test XML#text
324     def test_text
325         a = XML.parse("<foo>Hello</foo>")
326         b = XML.parse("<foo></foo>")
327         c = XML.parse("<foo><bar>Hello</bar></foo>")
328         d = XML.parse("<foo>He<bar>llo</bar></foo>")
329 
330         assert_equal("Hello", a.text, "XML#text should work")
331         assert_equal("", b.text, "XML#text should work")
332         assert_equal("Hello", c.text, "XML#text should work")
333         assert_equal("Hello", d.text, "XML#text should work")
334     end
335     
336     # Test XML#renormalize and XML#renormalize_sequence
337     def test_renormalize
338         a = "<foo></foo>"
339         b = "<foo></foo><bar></bar>"
340         
341         assert_equal("<foo/>", XML.renormalize(a), "XML#renormalize should work")
342         assert_equal("<foo/>", XML.renormalize_sequence(a), "XML#renormalize_sequence should work")
343         assert_equal("<foo/><bar/>", XML.renormalize_sequence(b), "XML#renormalize_sequence should work")
344     end
345     
346     # Test XML#range
347     def test_range
348         a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
349         b = a.children(:bar)
350         
351         # Non-recursive case
352         ar_n_n = a.range(nil, nil)
353         ar_0_n = a.range(b[0], nil)
354         ar_1_n = a.range(b[1], nil)
355         ar_4_n = a.range(b[4], nil)
356         ar_n_4 = a.range(nil, b[4])
357         ar_n_3 = a.range(nil, b[3])
358         ar_n_0 = a.range(nil, b[0])
359         
360         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.to_s, "XML#range should work")
361         assert_equal("<foo><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_0_n.to_s, "XML#range should work")
362         assert_equal("<foo><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_1_n.to_s, "XML#range should work")
363         assert_equal("<foo/>", ar_4_n.to_s, "XML#range should work")
364         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.to_s, "XML#range should work")
365         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.to_s, "XML#range should work")
366         assert_equal("<foo/>", ar_n_0.to_s, "XML#range should work")
367         
368         a = XML.parse "<a>
369                        <b i='0'><c i='0'/><c i='1'/><c i='2'/></b>
370                        <b i='1'><c i='3'/><c i='4'/><c i='5'/></b>
371                        <b i='2'><c i='6'/><c i='7'/><c i='8'/></b>
372                        </a>"
373         c = a.descendants(:c)
374        
375         c.each_with_index{|ci,i|
376             c.each_with_index{|cj,j|
377                 next unless i < j
378                 ar = a.range(ci,cj)
379                 cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
380                 assert_equal(((i+1)...j).to_a, cs_present, "XML#range(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar}")
381             }
382             ar = a.range(ci,nil)
383             cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
384             assert_equal(((i+1)..8).to_a, cs_present, "XML#range(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar}")
385             
386             ar = a.range(nil,ci)
387             cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
388             assert_equal((0...i).to_a, cs_present, "XML#range(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar}")
389         }
390     end
391 
392     # Test XML#subsequence
393     def test_subsequence
394         a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
395         b = a.children(:bar)
396         
397         # Non-recursive case
398         ar_n_n = a.subsequence(nil, nil)
399         ar_0_n = a.subsequence(b[0], nil)
400         ar_1_n = a.subsequence(b[1], nil)
401         ar_4_n = a.subsequence(b[4], nil)
402         ar_n_4 = a.subsequence(nil, b[4])
403         ar_n_3 = a.subsequence(nil, b[3])
404         ar_n_0 = a.subsequence(nil, b[0])
405         
406         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.to_s, "XML#subsequence should work")
407         assert_equal("<bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/>", ar_0_n.to_s, "XML#subsequence should work")
408         assert_equal("<bar i='2'/><bar i='3'/><bar i='4'/>", ar_1_n.to_s, "XML#subsequence should work")
409         assert_equal("", ar_4_n.to_s, "XML#subsequence should work")
410         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.to_s, "XML#subsequence should work")
411         assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.to_s, "XML#subsequence should work")
412         assert_equal("<foo/>", ar_n_0.to_s, "XML#subsequence should work")
413         
414         a = XML.parse "<a>
415                        <b j='0'><c i='0'/><c i='1'/><c i='2'/></b>
416                        <b j='1'><c i='3'/><c i='4'/><c i='5'/></b>
417                        <b j='2'><c i='6'/><c i='7'/><c i='8'/></b>
418                        </a>"
419         c = a.descendants(:c)
420        
421         # (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}
422         # instead of ar.descendants(:c) because 
423         # we might have returned [<c i='?'/>] as a result,
424         # and then it's not a descendant of the result then.
425         # This is ugly, and it should be fixed somewhere in magic/xml
426         c.each_with_index{|ci,i|
427             c.each_with_index{|cj,j|
428                 next unless i < j
429                 ar = a.subsequence(ci,cj)
430                 cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
431                 assert_equal(((i+1)...j).to_a, cs_present, "XML#subsequence(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar}")
432             }
433             ar = a.subsequence(ci,nil)
434             cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
435             assert_equal(((i+1)..8).to_a, cs_present, "XML#subsequence(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar}")
436             
437             ar = a.subsequence(nil,ci)
438             cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
439             assert_equal((0...i).to_a, cs_present, "XML#subsequence(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar}")
440         }
441     end
442     
443     # Test xml! at top level
444     def test_xml_bang
445         real_stdout = $stdout
446         $stdout = StringIO.new
447         xml!(:foo)
448         assert_equal("<foo/>", $stdout.string, "xml! should work")
449         
450         $stdout = StringIO.new
451         XML.bar!
452         assert_equal("<bar/>", $stdout.string, "XML#foo! should work")
453         $stdout = real_stdout
454     end
455     
456     # Methods XML#foo! are all catched,
457     # but how about other methods ?
458     def test_real_method_missing
459         foo = XML.new(:foo)
460         exception_raised = false
461         begin 
462             foo.bar()
463         rescue NoMethodError
464             exception_raised = true
465         end
466         # FIXME: There are other assertions than assert_equal ;-)
467         assert_equal(true, exception_raised, "XML#bar should raise NoMethodError")
468     end
469     
470     # Test XML#parse_as_twigs interface
471     def test_parse_as_twigs
472         stream = "<foo><p><ul><li>1</li><li>2</li><li>3</li></ul></p><p><br/></p><p/><p><bar/></p></foo>"
473         i = 0
474         results = []
475         XML.parse_as_twigs(stream) {|n|
476             n.complete! if i == 1 or i == 3
477             results << n
478             i += 1
479         }
480         assert_equal("<foo/>", results[0].to_s, "XML.parse_as_twigs should work")
481         assert_equal("<p><ul><li>1</li><li>2</li><li>3</li></ul></p>", results[1].to_s, "XML.parse_as_twigs should work")
482         assert_equal("<p/>", results[2].to_s, "XML.parse_as_twigs should work")
483         assert_equal("<br/>", results[3].to_s, "XML.parse_as_twigs should work")
484         assert_equal("<p/>", results[4].to_s, "XML.parse_as_twigs should work")
485         assert_equal("<p/>", results[5].to_s, "XML.parse_as_twigs should work")
486         assert_equal("<bar/>", results[6].to_s, "XML.parse_as_twigs should work")
487         assert_equal(7, results.size, "XML.parse_as_twigs should work")
488     end
489 
490     # Test XML#inspect
491     def test_inpsect
492         a = xml(:a, xml(:b, xml(:c)))
493         d = xml(:d)
494         
495         assert_equal("<a>...</a>", a.inspect, "XML#inspect should work")
496         assert_equal("<a>...</a>", a.inspect(0), "XML#inspect(levels) should work")
497         assert_equal("<a><b>...</b></a>", a.inspect(1), "XML#inspect(levels) should work")
498         assert_equal("<a><b><c/></b></a>", a.inspect(2), "XML#inspect(levels) should work")
499         assert_equal("<a><b><c/></b></a>", a.inspect(3), "XML#inspect(levels) should work")
500         assert_equal("<d/>", d.inspect, "XML#inspect should work")
501         assert_equal("<d/>", d.inspect(0), "XML#inspect should work")
502         assert_equal("<d/>", d.inspect(1), "XML#inspect should work")
503     end
504     
505     # Test XML#[:@foo] pseudoattributes
506     def test_pseudoattributes_read
507         # Ignore the second <x>...</x>
508         a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
509         
510         assert_equal("10", a[:x],  "XML#[] real attributes should work")
511         assert_nil(a[:y],  "XML#[] real attributes should work")
512         assert_nil(a[:z],  "XML#[] real attributes should work")
513         assert_equal("20", a[:@x], "XML#[] pseudoattributes should work")
514         assert_equal("30", a[:@y], "XML#[] pseudoattributes should work")
515         assert_nil(a[:@z], "XML#[] pseudoattributes should work")
516     end
517 
518     # Test XML#[:@foo] pseudoattributes
519     def test_pseudoattributes_write
520         # Ignore the second <x>...</x>
521         a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
522         
523         a[:x] = 100
524         a[:y] = 200
525         a[:z] = 300
526         a[:@x] = 1000
527         a[:@y] = 2000
528         a[:@z] = 3000
529         
530         assert_equal("<foo x='100' y='200' z='300'><x>1000</x><y>2000</y><x>40</x><z>3000</z></foo>", a.to_s, "XML#[]= pseudoattributes should work")
531     end
532     
533     # Test entity unescaping
534     def test_entities
535         a = XML.parse("<foo>&#xA5;&#xFC;&#x2020;</foo>")
536         b = XML.parse("<foo>&#165;&#252;&#8224;</foo>")
537         c = XML.parse("<foo>&yen;&uuml;&dagger;</foo>")
538         d = ""
539         
540         assert_equal(b.text, a.text, "Entity unescaping on XML#Parse should work")
541         assert_equal(c.text, a.text, "Entity unescaping on XML#Parse should work")
542 
543         assert_equal(b.to_s, a.to_s, "Entity escaping on XML#to_s should work")
544         assert_equal(c.to_s, a.to_s, "Entity escaping on XML#to_s should work")
545 
546         # The escapes assume \XXX are byte escapes and the encoding is UTF-8
547         assert_equal("\302\245\303\274\342\200\240", a.text, "Entity unescaping on XML#Parse should work")
548         assert_equal("<foo>\302\245\303\274\342\200\240</foo>", a.to_s, "Entity escaping on XML#to_s should work")
549     end
550 
551     # Test patterns support
552     def test_patterns
553         a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
554         a.normalize!
555         
556         blue    = []
557         nocolor = []
558         bar     = []
559         #hello   = []
560         
561         a.descendants {|d|
562             case d
563             when :bar
564                 bar << d
565             end
566 
567             case d
568             when {:color => 'blue'}
569                 blue << d
570             end
571         
572             case d
573             when {:color => nil}
574                 nocolor << d
575             end
576         
577             #case d
578             #when /Hello/
579             #    hello << d
580             #end
581         }
582         
583         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
584         assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
585         assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
586         # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
587         #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
588     end
589 
590     # Test pattern support in #descendants (works the same way in #children)
591     def test_patterns_2
592         a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl color='blue'>!</excl></foo>"
593         a.normalize!
594         
595         bar      = a.descendants(:bar)
596         blue     = a.descendants({:color=>'blue'})
597         blue_bar = a.descendants(all(:bar, {:color=>'blue'}))
598         #hello    = a.descendants(/Hello/)
599         xml      = a.descendants(XML)
600         string   = a.descendants(String)
601     
602         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
603         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<excl color='blue'>!</excl>")], blue, "Pattern matching should work")
604         assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue_bar, "Pattern matching should work")
605         # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
606         #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
607         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>"), XML.parse("<excl color='blue'>!</excl>")], xml, "Pattern matching should work")
608         assert_equal(['Hello', ', ', 'world', '!'], string, "Pattern matching should work")
609     end
610 
611     # Test patterns =~ support
612     def test_patterns_3
613         a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
614         a.normalize!
615         
616         blue    = []
617         nocolor = []
618         bar     = []
619         hello   = []
620         
621         a.descendants {|d|
622             if d =~ :bar
623                 bar << d
624             end
625 
626             if d =~ {:color => 'blue'}
627                 blue << d
628             end
629         
630             if d =~ {:color => nil}
631                 nocolor << d
632             end
633         
634             if d =~ /Hello/
635                 hello << d
636             end
637         }
638         
639         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
640         assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
641         assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
642         assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
643     end
644 
645     def test_patterns_any_all
646         a = XML.parse "<foo>
647         <bar color='blue' size='big'>1</bar>
648         <bar color='blue'>2</bar>
649         <bar color='blue' size='normal'>3</bar>
650         <bar color='red' size='big'>4</bar>
651         <bar color='red'>5</bar>
652         <bar color='red' size='normal'>6</bar>
653         </foo>"
654         
655         p = all({:color => 'red'}, any({:size => nil}, {:size => 'normal'}))
656         # Select childern which color red and size either normal or not specified
657         b = a.children(p)
658         c = a.find_all{|x| x =~ p }
659         d = a.find_all{|x| p === x }
660         
661         assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", b.to_s, "Pattern matching with any/all should work")
662         assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", c.to_s, "Pattern matching with any/all should work")
663         assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", d.to_s, "Pattern matching with any/all should work")
664     end
665 
666     # Test parse option :ignore_pretty_printing
667     def test_remove_pretty_printing
668         a = "<foo><bar>100</bar><bar>200</bar></foo>"
669         b = "<foo>
670                <bar>
671                  100
672                </bar>
673                <bar>
674                  200
675                </bar>
676              </foo>"
677          c = XML.parse(a)
678          d = XML.parse(b)
679          e = XML.parse(b)
680          e.remove_pretty_printing!
681          
682          assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
683          assert_equal(c.to_s, e.to_s, "XML#remove_pretty_printing! should work")
684          
685          f = XML.parse("<foo> <bar>Hello    world</bar> </foo>")
686          f.remove_pretty_printing!
687          g = XML.parse("<foo><bar>Hello world</bar></foo>")
688          assert_equal(f.to_s, g.to_s, "XML#remove_pretty_printing! should work")
689     end
690 
691     # Test remove_pretty_printing! with exception list
692     def test_remove_pretty_printing_conditional
693         a = "<foo>
694                <pre>
695                  <a> 100 </a>
696                </pre>
697                <xyzzy>
698                  <a> 200 </a>
699                </xyzzy>
700              </foo>"
701         b = "<foo><pre>
702                  <a> 100 </a>
703                </pre><xyzzy><a>200</a></xyzzy></foo>"
704 
705         ax = XML.parse(a)
706         bx = XML.parse(b)
707         
708         ax.remove_pretty_printing!([:pre])
709 
710         assert_equal(bx.to_s, ax.to_s, "XML#remove_pretty_printing!(exceptions) should work")
711     end
712     
713     # Test extra arguments to XML#parse - :comments and :pi
714     def test_parsing_extras
715         a = "<foo><?xml-stylesheet href='http://www.blogger.com/styles/atom.css' type='text/css'?></foo>"
716         b = "<foo><!-- This is a comment --></foo>"
717         
718         ax = XML.parse(a)
719         bx = XML.parse(b)
720         
721         assert_equal("<foo/>", ax.to_s, "XML#parse should drop PI by default")
722         assert_equal("<foo/>", bx.to_s, "XML#parse should drop comments by default")
723         
724         ay = XML.parse(a, :comments => true, :pi => true)
725         by = XML.parse(b, :comments => true, :pi => true)
726 
727         assert_equal(a, ay.to_s, "XML#parse(str, :pi=>true) should include PI")
728         assert_equal(b, by.to_s, "XML#parse(str, :comments=>true) should include comments")
729     end
730     
731     # Test extra arguments to XML#parse - :remove_pretty_printing.
732     # FIXME: How about a shorter (but still mnemonic) name for that ?
733     def test_parsing_nopp
734         a = "<foo><bar>100</bar><bar>200</bar></foo>"
735         b = "<foo>
736                <bar>
737                  100
738                </bar>
739                <bar>
740                  200
741                </bar>
742              </foo>"
743         c = XML.parse(a)
744         d = XML.parse(b)
745         e = XML.parse(b, :remove_pretty_printing => true)
746 
747         assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
748         assert_equal(c.to_s, e.to_s, "XML#parse(str, :remove_pretty_printing=>true) should work")
749     end
750     
751     # Test XML.parse(str, :extra_entities => ...)
752     def test_parsing_entities
753         a = "<foo>&cat; &amp; &dog;</foo>"
754         b = XML.parse(a, :extra_entities => lambda{|e|
755             case e
756             when "cat"
757                 "neko"
758             when "dog"
759                  "inu"
760             end
761         })
762         c = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
763         
764         assert_equal("neko & inu", b.text, "XML#parse(str, :extra_entities=>Proc) should work")
765         assert_equal("neko & inu", c.text, "XML#parse(str, :extra_entities=>Hash) should work")
766         
767         d = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
768         
769         # Central European characters escapes
770         e = "<foo>&zdot;&oacute;&lstrok;w</foo>"
771         f = XML.parse(e, :extra_entities => {"zdot" => 380, "oacute" => 243, "lstrok" => 322})
772         
773         # Assumes \number does bytes, UTF8
774         assert_equal("\305\274\303\263\305\202w", f.text, "XML#parse(str, :extra_entities=>...) should work with integer codepoints")
775     end
776     
777     # Test XML.load
778     def test_load
779         a = XML.load("test.xml")
780         b = XML.load(File.open("test.xml"))
781         c = XML.load("string:<foo><bar></bar></foo>")
782         d = XML.load("file:test.xml")
783         
784         assert_equal("<foo><bar/></foo>", a.to_s, "XML#load should work")
785         assert_equal("<foo><bar/></foo>", b.to_s, "XML#load should work")
786         assert_equal("<foo><bar/></foo>", c.to_s, "XML#load should work")
787         assert_equal("<foo><bar/></foo>", d.to_s, "XML#load should work")
788     end
789     
790     # Test multielement selectors
791     def test_multielement_selectors
792         a = XML.parse("<foo><bar color='blue'><x/></bar><bar color='red'><x><y i='1'/></x><y i='2'/></bar></foo>")
793         assert_equal("<x/><x><y i='1'/></x>", a.children(:bar, :x).to_s, "Multielement selectors should work")
794         assert_equal("<y i='2'/>", a.children(:bar, :y).to_s, "Multielement selectors should work")
795         assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).to_s, "Multielement selectors should work")
796         assert_equal("<y i='1'/>", a.descendants(:x, :y).to_s, "Multielement selectors should work")
797         assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).to_s, "Multielement selectors should work")
798     end
799     
800     # Test deep_map
801     def test_deep_map
802         a = XML.parse("<foo><bar>x</bar> <foo><bar>y</bar></foo></foo>")
803         b = a.deep_map(:bar) {|c| XML.new(c.text.to_sym) }
804         assert_equal("<foo><x/> <foo><y/></foo></foo>", b.to_s, "XML#deep_map should work")
805 
806         c = XML.parse("<foo><bar>x</bar> <bar><bar>y</bar></bar></foo>")
807         d = c.deep_map(:bar) {|c| XML.new(:xyz, c.attrs, *c.children) }
808         assert_equal("<foo><xyz>x</xyz> <xyz><bar>y</bar></xyz></foo>", d.to_s, "XML#deep_map should work")
809     end
810 
811     # Test XML.load
812     def test_pretty_printer
813         a = XML.parse("<foo><bar>x</bar>Boo!<bar><y><z>f</z></y></bar><xyzzy /><bar>Mutiline\nText\n:-)</bar></foo>")
814         a.add_pretty_printing!
815         expected = "<foo>
816   <bar>
817     x
818   </bar>
819   Boo!
820   <bar>
821     <y>
822       <z>
823         f
824       </z>
825     </y>
826   </bar>
827   <xyzzy/>
828   <bar>
829     Mutiline
830     Text
831     :-)
832   </bar>
833 </foo>"
834         assert_equal(expected, a.to_s, "XML#pretty_print! should work")
835     end
836 end

Generated using the rcov code coverage analysis tool for Ruby version 0.8.0.

Valid XHTML 1.0! Valid CSS!