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
|
|
|
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>< > &</p>", p.to_s, "Character escaping should work")
28 assert_equal("<foo bar='< > ' " &'/>", 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>> < &</foo>"
194 f = "<foo a='b&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>" '</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><greeting>Hello, world!</greeting></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>¥ü†</foo>")
536 b = XML.parse("<foo>¥ü†</foo>")
537 c = XML.parse("<foo>¥ü†</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; & &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>żół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.