libxml-ruby 5.0.4 → 5.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY +10 -6
  3. data/README.rdoc +1 -1
  4. data/ext/libxml/extconf.rb +5 -0
  5. data/ext/libxml/ruby_xml.c +556 -556
  6. data/ext/libxml/ruby_xml_attributes.h +17 -17
  7. data/ext/libxml/ruby_xml_document.c +1129 -1129
  8. data/ext/libxml/ruby_xml_dtd.c +257 -257
  9. data/ext/libxml/ruby_xml_encoding.c +250 -250
  10. data/ext/libxml/ruby_xml_error.c +1003 -1003
  11. data/ext/libxml/ruby_xml_error.h +14 -14
  12. data/ext/libxml/ruby_xml_html_parser_context.c +351 -351
  13. data/ext/libxml/ruby_xml_input_cbg.c +188 -188
  14. data/ext/libxml/ruby_xml_namespace.c +151 -151
  15. data/ext/libxml/ruby_xml_parser.h +10 -10
  16. data/ext/libxml/ruby_xml_parser_context.c +1009 -1009
  17. data/ext/libxml/ruby_xml_parser_options.c +74 -74
  18. data/ext/libxml/ruby_xml_parser_options.h +10 -10
  19. data/ext/libxml/ruby_xml_sax2_handler.c +326 -326
  20. data/ext/libxml/ruby_xml_sax_parser.c +108 -108
  21. data/ext/libxml/ruby_xml_version.h +9 -9
  22. data/lib/libxml/attr.rb +122 -122
  23. data/lib/libxml/attr_decl.rb +80 -80
  24. data/lib/libxml/attributes.rb +13 -13
  25. data/lib/libxml/document.rb +194 -194
  26. data/lib/libxml/error.rb +95 -95
  27. data/lib/libxml/hpricot.rb +77 -77
  28. data/lib/libxml/html_parser.rb +96 -96
  29. data/lib/libxml/namespace.rb +61 -61
  30. data/lib/libxml/namespaces.rb +37 -37
  31. data/lib/libxml/node.rb +323 -323
  32. data/lib/libxml/parser.rb +102 -102
  33. data/lib/libxml/sax_callbacks.rb +179 -179
  34. data/lib/libxml/sax_parser.rb +40 -40
  35. data/lib/libxml/tree.rb +28 -28
  36. data/lib/libxml.rb +4 -4
  37. data/lib/xml/libxml.rb +10 -10
  38. data/lib/xml.rb +13 -13
  39. data/libxml-ruby.gemspec +50 -49
  40. data/test/test_document.rb +140 -140
  41. data/test/test_document_write.rb +142 -142
  42. data/test/test_dtd.rb +126 -126
  43. data/test/test_encoding.rb +126 -126
  44. data/test/test_error.rb +194 -194
  45. data/test/test_helper.rb +20 -20
  46. data/test/test_namespace.rb +58 -58
  47. data/test/test_node.rb +235 -235
  48. data/test/test_node_write.rb +93 -93
  49. data/test/test_parser.rb +333 -333
  50. data/test/test_reader.rb +364 -364
  51. data/test/test_xml.rb +168 -168
  52. metadata +5 -4
data/test/test_parser.rb CHANGED
@@ -1,333 +1,333 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './test_helper'
4
- require 'stringio'
5
-
6
- class TestParser < Minitest::Test
7
- def setup
8
- LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
9
- end
10
-
11
- # ----- Sources -------
12
- def test_document
13
- file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
14
- parser = LibXML::XML::Parser.file(file)
15
- doc = parser.parse
16
-
17
- parser = LibXML::XML::Parser.document(doc)
18
-
19
- doc = parser.parse
20
-
21
- assert_instance_of(LibXML::XML::Document, doc)
22
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
23
- end
24
-
25
- def test_nil_document
26
- error = assert_raises(TypeError) do
27
- LibXML::XML::Parser.document(nil)
28
- end
29
-
30
- assert_equal("Must pass an LibXML::XML::Document object", error.message)
31
- end
32
-
33
- def test_file
34
- file = File.expand_path(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
35
-
36
- parser = LibXML::XML::Parser.file(file)
37
- doc = parser.parse
38
- assert_instance_of(LibXML::XML::Document, doc)
39
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
40
- end
41
-
42
- def test_noexistent_file
43
- error = assert_raises(LibXML::XML::Error) do
44
- LibXML::XML::Parser.file('i_dont_exist.xml')
45
- end
46
-
47
- assert_equal('Warning: failed to load external entity "i_dont_exist.xml".', error.message)
48
- end
49
-
50
- def test_nil_file
51
- error = assert_raises(TypeError) do
52
- LibXML::XML::Parser.file(nil)
53
- end
54
-
55
- assert_match(/nil into String/, error.message)
56
- end
57
-
58
- def test_file_encoding
59
- file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
60
- parser = LibXML::XML::Parser.file(file, :encoding => LibXML::XML::Encoding::ISO_8859_1)
61
-
62
- error = assert_raises(LibXML::XML::Error) do
63
- parser.parse
64
- end
65
-
66
- if windows?
67
- assert_match(/Fatal error: Opening and ending tag mismatch/, error.message)
68
- else
69
- assert_match(/Fatal error: Extra content at the end of the document/, error.message)
70
- end
71
-
72
- parser = LibXML::XML::Parser.file(file, :encoding => LibXML::XML::Encoding::UTF_8)
73
- doc = parser.parse
74
- refute_nil(doc)
75
- end
76
-
77
- def test_file_base_uri
78
- file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
79
-
80
- parser = LibXML::XML::Parser.file(file)
81
- doc = parser.parse
82
- assert(doc.child.base_uri.match(/test\/model\/bands.utf-8.xml/))
83
-
84
- parser = LibXML::XML::Parser.file(file, :base_uri => "http://libxml.org")
85
- doc = parser.parse
86
- assert(doc.child.base_uri.match(/test\/model\/bands.utf-8.xml/))
87
- end
88
-
89
- def test_io
90
- File.open(File.join(File.dirname(__FILE__), 'model/rubynet.xml')) do |io|
91
- parser = LibXML::XML::Parser.io(io)
92
- assert_instance_of(LibXML::XML::Parser, parser)
93
-
94
- doc = parser.parse
95
- assert_instance_of(LibXML::XML::Document, doc)
96
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
97
- end
98
- end
99
-
100
- def test_io_gc
101
- # Test that the reader keeps a reference
102
- # to the io object
103
- file = File.open(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
104
- parser = LibXML::XML::Parser.io(file)
105
- file = nil
106
- GC.start
107
- assert(parser.parse)
108
- end
109
-
110
- def test_nil_io
111
- error = assert_raises(TypeError) do
112
- LibXML::XML::Parser.io(nil)
113
- end
114
-
115
- assert_equal("Must pass in an IO object", error.message)
116
- end
117
-
118
- def test_string_io
119
- data = File.read(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
120
- string_io = StringIO.new(data)
121
- parser = LibXML::XML::Parser.io(string_io)
122
-
123
- doc = parser.parse
124
- assert_instance_of(LibXML::XML::Document, doc)
125
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
126
- end
127
-
128
- def test_string_io_thread
129
- thread = Thread.new do
130
- data = File.read(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
131
- string_io = StringIO.new(data)
132
- parser = LibXML::XML::Parser.io(string_io)
133
-
134
- doc = parser.parse
135
- assert_instance_of(LibXML::XML::Document, doc)
136
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
137
- end
138
-
139
- thread.join
140
- assert(true)
141
- puts 'Thread completed'
142
- end
143
-
144
- def test_string
145
- str = '<ruby_array uga="booga" foo="bar"><fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>'
146
-
147
- parser = LibXML::XML::Parser.string(str)
148
- assert_instance_of(LibXML::XML::Parser, parser)
149
-
150
- doc = parser.parse
151
- assert_instance_of(LibXML::XML::Document, doc)
152
- assert_instance_of(LibXML::XML::Parser::Context, parser.context)
153
- end
154
-
155
- def test_nil_string
156
- error = assert_raises(TypeError) do
157
- LibXML::XML::Parser.string(nil)
158
- end
159
-
160
- assert_equal("wrong argument type nil (expected String)", error.message)
161
- end
162
-
163
- def test_string_options
164
- xml = <<-EOS
165
- <!DOCTYPE foo [<!ENTITY foo 'bar'>]>
166
- <test>
167
- <cdata><![CDATA[something]]></cdata>
168
- <entity>&foo;</entity>
169
- </test>
170
- EOS
171
-
172
- # Parse normally - entities won't be substituted
173
- parser = LibXML::XML::Parser.string(xml)
174
- doc = parser.parse
175
- assert_nil(doc.child.base_uri)
176
-
177
- # Cdata section should be cdata nodes
178
- node = doc.find_first('/test/cdata').child
179
- assert_equal(LibXML::XML::Node::CDATA_SECTION_NODE, node.node_type)
180
-
181
- # Entities should not be substituted
182
- node = doc.find_first('/test/entity')
183
- assert_equal('&foo;', node.child.to_s)
184
-
185
- # Parse with options
186
- parser = LibXML::XML::Parser.string(xml, base_uri: 'http://libxml.rubyforge.org',
187
- options: LibXML::XML::Parser::Options::NOCDATA | LibXML::XML::Parser::Options::NOENT)
188
- doc = parser.parse
189
- assert_equal(doc.child.base_uri, 'http://libxml.rubyforge.org')
190
-
191
- # Cdata section should be text nodes
192
- node = doc.find_first('/test/cdata').child
193
- assert_equal(LibXML::XML::Node::TEXT_NODE, node.node_type)
194
-
195
- # Entities should be subtituted
196
- node = doc.find_first('/test/entity')
197
- assert_equal('bar', node.child.to_s)
198
- end
199
-
200
- def test_string_encoding
201
- # ISO_8859_1:
202
- # ö - f6 in hex, \366 in octal
203
- # ü - fc in hex, \374 in octal
204
-
205
- xml = <<-EOS
206
- <bands>
207
- <metal>m\366tley_cr\374e</metal>
208
- </bands>
209
- EOS
210
-
211
- # Parse as UTF_8
212
- parser = LibXML::XML::Parser.string(xml, :encoding => LibXML::XML::Encoding::UTF_8)
213
-
214
- error = assert_raises(LibXML::XML::Error) do
215
- parser.parse
216
- end
217
-
218
- assert_equal("Fatal error: Input is not proper UTF-8, indicate encoding !\nBytes: 0xF6 0x74 0x6C 0x65 at :2.",
219
- error.message)
220
-
221
- # Parse as ISO_8859_1:
222
- parser = LibXML::XML::Parser.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
223
- doc = parser.parse
224
- node = doc.find_first('//metal')
225
- assert_equal(Encoding::UTF_8, node.content.encoding)
226
- assert_equal("m\303\266tley_cr\303\274e", node.content)
227
- end
228
-
229
- def test_fd_gc
230
- # Test opening # of documents up to the file limit for the OS.
231
- # Ideally it should run until libxml emits a warning,
232
- # thereby knowing we've done a GC sweep. For the time being,
233
- # re-open the same doc `limit descriptors` times.
234
- # If we make it to the end, then we've succeeded,
235
- # otherwise an exception will be thrown.
236
- LibXML::XML::Error.set_handler {|error|}
237
-
238
- max_fd = if RUBY_PLATFORM.match(/mswin32|mswin64|mingw/i)
239
- 500
240
- else
241
- Process.getrlimit(Process::RLIMIT_NOFILE)[0] + 1
242
- end
243
-
244
- file = File.join(File.dirname(__FILE__), 'model/rubynet.xml')
245
- max_fd.times do
246
- LibXML::XML::Parser.file(file).parse
247
- end
248
- LibXML::XML::Error.reset_handler {|error|}
249
- end
250
-
251
- def test_open_many_files
252
- file = File.expand_path(File.join(File.dirname(__FILE__), 'model/atom.xml'))
253
- 1000.times do
254
- LibXML::XML::Parser.file(file).parse
255
- end
256
- end
257
-
258
- # ----- Errors ------
259
- def test_error
260
- error = assert_raises(LibXML::XML::Error) do
261
- LibXML::XML::Parser.string('<foo><bar/></foz>').parse
262
- end
263
-
264
- refute_nil(error)
265
- assert_kind_of(LibXML::XML::Error, error)
266
- assert_equal("Fatal error: Opening and ending tag mismatch: foo line 1 and foz at :1.", error.message)
267
- assert_equal(LibXML::XML::Error::PARSER, error.domain)
268
- assert_equal(LibXML::XML::Error::TAG_NAME_MISMATCH, error.code)
269
- assert_equal(LibXML::XML::Error::FATAL, error.level)
270
- assert_nil(error.file)
271
- assert_equal(1, error.line)
272
- assert_equal('foo', error.str1)
273
- assert_equal('foz', error.str2)
274
- assert_nil(error.str3)
275
- assert_equal(1, error.int1)
276
- assert([18, 20].include?(error.int2))
277
- assert_nil(error.node)
278
- end
279
-
280
- def test_bad_xml
281
- parser = LibXML::XML::Parser.string('<ruby_array uga="booga" foo="bar"<fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>')
282
- error = assert_raises(LibXML::XML::Error) do
283
- refute_nil(parser.parse)
284
- end
285
-
286
- refute_nil(error)
287
- assert_kind_of(LibXML::XML::Error, error)
288
- if windows?
289
- assert_equal("Fatal error: Couldn't find end of Start Tag ruby_array line 1 at :1.", error.message)
290
- assert_equal(LibXML::XML::Error::GT_REQUIRED, error.code)
291
- assert_equal("ruby_array", error.str1)
292
- assert_equal(1, error.int1)
293
- else
294
- assert_equal("Fatal error: Extra content at the end of the document at :1.", error.message)
295
- assert_equal(LibXML::XML::Error::DOCUMENT_END, error.code)
296
- assert_nil(error.str1)
297
- assert_equal(0, error.int1)
298
- end
299
- assert_equal(LibXML::XML::Error::PARSER, error.domain)
300
- assert_equal(LibXML::XML::Error::FATAL, error.level)
301
- assert_nil(error.file)
302
- assert_equal(1, error.line)
303
- assert_nil(error.str2)
304
- assert_nil(error.str3)
305
- assert_equal(34, error.int2)
306
- assert_nil(error.node)
307
- end
308
-
309
- def test_errors_from_background_thread
310
- errors = []
311
- background_errors = []
312
-
313
- begin
314
- LibXML::XML::Error.set_handler do |error|
315
- errors << error
316
- end
317
- parser = LibXML::XML::Parser.string("<moo>")
318
-
319
- thread = Thread.new do
320
- LibXML::XML::Error.set_handler do |error|
321
- background_errors << error
322
- end
323
- parser.parse rescue nil
324
- end
325
- thread.join
326
- ensure
327
- LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
328
- end
329
-
330
- assert_equal(errors.size, 0)
331
- assert_equal(background_errors.size, 1)
332
- end
333
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './test_helper'
4
+ require 'stringio'
5
+
6
+ class TestParser < Minitest::Test
7
+ def setup
8
+ LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
9
+ end
10
+
11
+ # ----- Sources -------
12
+ def test_document
13
+ file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
14
+ parser = LibXML::XML::Parser.file(file)
15
+ doc = parser.parse
16
+
17
+ parser = LibXML::XML::Parser.document(doc)
18
+
19
+ doc = parser.parse
20
+
21
+ assert_instance_of(LibXML::XML::Document, doc)
22
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
23
+ end
24
+
25
+ def test_nil_document
26
+ error = assert_raises(TypeError) do
27
+ LibXML::XML::Parser.document(nil)
28
+ end
29
+
30
+ assert_equal("Must pass an LibXML::XML::Document object", error.message)
31
+ end
32
+
33
+ def test_file
34
+ file = File.expand_path(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
35
+
36
+ parser = LibXML::XML::Parser.file(file)
37
+ doc = parser.parse
38
+ assert_instance_of(LibXML::XML::Document, doc)
39
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
40
+ end
41
+
42
+ def test_noexistent_file
43
+ error = assert_raises(LibXML::XML::Error) do
44
+ LibXML::XML::Parser.file('i_dont_exist.xml')
45
+ end
46
+
47
+ assert_equal('Warning: failed to load external entity "i_dont_exist.xml".', error.message)
48
+ end
49
+
50
+ def test_nil_file
51
+ error = assert_raises(TypeError) do
52
+ LibXML::XML::Parser.file(nil)
53
+ end
54
+
55
+ assert_match(/nil into String/, error.message)
56
+ end
57
+
58
+ def test_file_encoding
59
+ file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
60
+ parser = LibXML::XML::Parser.file(file, :encoding => LibXML::XML::Encoding::ISO_8859_1)
61
+
62
+ error = assert_raises(LibXML::XML::Error) do
63
+ parser.parse
64
+ end
65
+
66
+ if windows?
67
+ assert_match(/Fatal error: Opening and ending tag mismatch/, error.message)
68
+ else
69
+ assert_match(/Fatal error: Extra content at the end of the document/, error.message)
70
+ end
71
+
72
+ parser = LibXML::XML::Parser.file(file, :encoding => LibXML::XML::Encoding::UTF_8)
73
+ doc = parser.parse
74
+ refute_nil(doc)
75
+ end
76
+
77
+ def test_file_base_uri
78
+ file = File.expand_path(File.join(File.dirname(__FILE__), 'model/bands.utf-8.xml'))
79
+
80
+ parser = LibXML::XML::Parser.file(file)
81
+ doc = parser.parse
82
+ assert(doc.child.base_uri.match(/test\/model\/bands.utf-8.xml/))
83
+
84
+ parser = LibXML::XML::Parser.file(file, :base_uri => "http://libxml.org")
85
+ doc = parser.parse
86
+ assert(doc.child.base_uri.match(/test\/model\/bands.utf-8.xml/))
87
+ end
88
+
89
+ def test_io
90
+ File.open(File.join(File.dirname(__FILE__), 'model/rubynet.xml')) do |io|
91
+ parser = LibXML::XML::Parser.io(io)
92
+ assert_instance_of(LibXML::XML::Parser, parser)
93
+
94
+ doc = parser.parse
95
+ assert_instance_of(LibXML::XML::Document, doc)
96
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
97
+ end
98
+ end
99
+
100
+ def test_io_gc
101
+ # Test that the reader keeps a reference
102
+ # to the io object
103
+ file = File.open(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
104
+ parser = LibXML::XML::Parser.io(file)
105
+ file = nil
106
+ GC.start
107
+ assert(parser.parse)
108
+ end
109
+
110
+ def test_nil_io
111
+ error = assert_raises(TypeError) do
112
+ LibXML::XML::Parser.io(nil)
113
+ end
114
+
115
+ assert_equal("Must pass in an IO object", error.message)
116
+ end
117
+
118
+ def test_string_io
119
+ data = File.read(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
120
+ string_io = StringIO.new(data)
121
+ parser = LibXML::XML::Parser.io(string_io)
122
+
123
+ doc = parser.parse
124
+ assert_instance_of(LibXML::XML::Document, doc)
125
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
126
+ end
127
+
128
+ def test_string_io_thread
129
+ thread = Thread.new do
130
+ data = File.read(File.join(File.dirname(__FILE__), 'model/rubynet.xml'))
131
+ string_io = StringIO.new(data)
132
+ parser = LibXML::XML::Parser.io(string_io)
133
+
134
+ doc = parser.parse
135
+ assert_instance_of(LibXML::XML::Document, doc)
136
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
137
+ end
138
+
139
+ thread.join
140
+ assert(true)
141
+ puts 'Thread completed'
142
+ end
143
+
144
+ def test_string
145
+ str = '<ruby_array uga="booga" foo="bar"><fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>'
146
+
147
+ parser = LibXML::XML::Parser.string(str)
148
+ assert_instance_of(LibXML::XML::Parser, parser)
149
+
150
+ doc = parser.parse
151
+ assert_instance_of(LibXML::XML::Document, doc)
152
+ assert_instance_of(LibXML::XML::Parser::Context, parser.context)
153
+ end
154
+
155
+ def test_nil_string
156
+ error = assert_raises(TypeError) do
157
+ LibXML::XML::Parser.string(nil)
158
+ end
159
+
160
+ assert_equal("wrong argument type nil (expected String)", error.message)
161
+ end
162
+
163
+ def test_string_options
164
+ xml = <<-EOS
165
+ <!DOCTYPE foo [<!ENTITY foo 'bar'>]>
166
+ <test>
167
+ <cdata><![CDATA[something]]></cdata>
168
+ <entity>&foo;</entity>
169
+ </test>
170
+ EOS
171
+
172
+ # Parse normally - entities won't be substituted
173
+ parser = LibXML::XML::Parser.string(xml)
174
+ doc = parser.parse
175
+ assert_nil(doc.child.base_uri)
176
+
177
+ # Cdata section should be cdata nodes
178
+ node = doc.find_first('/test/cdata').child
179
+ assert_equal(LibXML::XML::Node::CDATA_SECTION_NODE, node.node_type)
180
+
181
+ # Entities should not be substituted
182
+ node = doc.find_first('/test/entity')
183
+ assert_equal('&foo;', node.child.to_s)
184
+
185
+ # Parse with options
186
+ parser = LibXML::XML::Parser.string(xml, base_uri: 'http://libxml.rubyforge.org',
187
+ options: LibXML::XML::Parser::Options::NOCDATA | LibXML::XML::Parser::Options::NOENT)
188
+ doc = parser.parse
189
+ assert_equal(doc.child.base_uri, 'http://libxml.rubyforge.org')
190
+
191
+ # Cdata section should be text nodes
192
+ node = doc.find_first('/test/cdata').child
193
+ assert_equal(LibXML::XML::Node::TEXT_NODE, node.node_type)
194
+
195
+ # Entities should be subtituted
196
+ node = doc.find_first('/test/entity')
197
+ assert_equal('bar', node.child.to_s)
198
+ end
199
+
200
+ def test_string_encoding
201
+ # ISO_8859_1:
202
+ # ö - f6 in hex, \366 in octal
203
+ # ü - fc in hex, \374 in octal
204
+
205
+ xml = <<-EOS
206
+ <bands>
207
+ <metal>m\366tley_cr\374e</metal>
208
+ </bands>
209
+ EOS
210
+
211
+ # Parse as UTF_8
212
+ parser = LibXML::XML::Parser.string(xml, :encoding => LibXML::XML::Encoding::UTF_8)
213
+
214
+ error = assert_raises(LibXML::XML::Error) do
215
+ parser.parse
216
+ end
217
+
218
+ assert_equal("Fatal error: Input is not proper UTF-8, indicate encoding !\nBytes: 0xF6 0x74 0x6C 0x65 at :2.",
219
+ error.message)
220
+
221
+ # Parse as ISO_8859_1:
222
+ parser = LibXML::XML::Parser.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
223
+ doc = parser.parse
224
+ node = doc.find_first('//metal')
225
+ assert_equal(Encoding::UTF_8, node.content.encoding)
226
+ assert_equal("m\303\266tley_cr\303\274e", node.content)
227
+ end
228
+
229
+ def test_fd_gc
230
+ # Test opening # of documents up to the file limit for the OS.
231
+ # Ideally it should run until libxml emits a warning,
232
+ # thereby knowing we've done a GC sweep. For the time being,
233
+ # re-open the same doc `limit descriptors` times.
234
+ # If we make it to the end, then we've succeeded,
235
+ # otherwise an exception will be thrown.
236
+ LibXML::XML::Error.set_handler {|error|}
237
+
238
+ max_fd = if RUBY_PLATFORM.match(/mswin32|mswin64|mingw/i)
239
+ 500
240
+ else
241
+ Process.getrlimit(Process::RLIMIT_NOFILE)[0] + 1
242
+ end
243
+
244
+ file = File.join(File.dirname(__FILE__), 'model/rubynet.xml')
245
+ max_fd.times do
246
+ LibXML::XML::Parser.file(file).parse
247
+ end
248
+ LibXML::XML::Error.reset_handler {|error|}
249
+ end
250
+
251
+ def test_open_many_files
252
+ file = File.expand_path(File.join(File.dirname(__FILE__), 'model/atom.xml'))
253
+ 1000.times do
254
+ LibXML::XML::Parser.file(file).parse
255
+ end
256
+ end
257
+
258
+ # ----- Errors ------
259
+ def test_error
260
+ error = assert_raises(LibXML::XML::Error) do
261
+ LibXML::XML::Parser.string('<foo><bar/></foz>').parse
262
+ end
263
+
264
+ refute_nil(error)
265
+ assert_kind_of(LibXML::XML::Error, error)
266
+ assert_equal("Fatal error: Opening and ending tag mismatch: foo line 1 and foz at :1.", error.message)
267
+ assert_equal(LibXML::XML::Error::PARSER, error.domain)
268
+ assert_equal(LibXML::XML::Error::TAG_NAME_MISMATCH, error.code)
269
+ assert_equal(LibXML::XML::Error::FATAL, error.level)
270
+ assert_nil(error.file)
271
+ assert_equal(1, error.line)
272
+ assert_equal('foo', error.str1)
273
+ assert_equal('foz', error.str2)
274
+ assert_nil(error.str3)
275
+ assert_equal(1, error.int1)
276
+ assert([18, 20].include?(error.int2))
277
+ assert_nil(error.node)
278
+ end
279
+
280
+ def test_bad_xml
281
+ parser = LibXML::XML::Parser.string('<ruby_array uga="booga" foo="bar"<fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>')
282
+ error = assert_raises(LibXML::XML::Error) do
283
+ refute_nil(parser.parse)
284
+ end
285
+
286
+ refute_nil(error)
287
+ assert_kind_of(LibXML::XML::Error, error)
288
+ if windows?
289
+ assert_equal("Fatal error: Couldn't find end of Start Tag ruby_array line 1 at :1.", error.message)
290
+ assert_equal(LibXML::XML::Error::GT_REQUIRED, error.code)
291
+ assert_equal("ruby_array", error.str1)
292
+ assert_equal(1, error.int1)
293
+ else
294
+ assert_equal("Fatal error: Extra content at the end of the document at :1.", error.message)
295
+ assert_equal(LibXML::XML::Error::DOCUMENT_END, error.code)
296
+ assert_nil(error.str1)
297
+ assert_equal(0, error.int1)
298
+ end
299
+ assert_equal(LibXML::XML::Error::PARSER, error.domain)
300
+ assert_equal(LibXML::XML::Error::FATAL, error.level)
301
+ assert_nil(error.file)
302
+ assert_equal(1, error.line)
303
+ assert_nil(error.str2)
304
+ assert_nil(error.str3)
305
+ assert_equal(34, error.int2)
306
+ assert_nil(error.node)
307
+ end
308
+
309
+ def test_errors_from_background_thread
310
+ errors = []
311
+ background_errors = []
312
+
313
+ begin
314
+ LibXML::XML::Error.set_handler do |error|
315
+ errors << error
316
+ end
317
+ parser = LibXML::XML::Parser.string("<moo>")
318
+
319
+ thread = Thread.new do
320
+ LibXML::XML::Error.set_handler do |error|
321
+ background_errors << error
322
+ end
323
+ parser.parse rescue nil
324
+ end
325
+ thread.join
326
+ ensure
327
+ LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
328
+ end
329
+
330
+ assert_equal(errors.size, 0)
331
+ assert_equal(background_errors.size, 1)
332
+ end
333
+ end