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.
- checksums.yaml +4 -4
- data/HISTORY +10 -6
- data/README.rdoc +1 -1
- data/ext/libxml/extconf.rb +5 -0
- data/ext/libxml/ruby_xml.c +556 -556
- data/ext/libxml/ruby_xml_attributes.h +17 -17
- data/ext/libxml/ruby_xml_document.c +1129 -1129
- data/ext/libxml/ruby_xml_dtd.c +257 -257
- data/ext/libxml/ruby_xml_encoding.c +250 -250
- data/ext/libxml/ruby_xml_error.c +1003 -1003
- data/ext/libxml/ruby_xml_error.h +14 -14
- data/ext/libxml/ruby_xml_html_parser_context.c +351 -351
- data/ext/libxml/ruby_xml_input_cbg.c +188 -188
- data/ext/libxml/ruby_xml_namespace.c +151 -151
- data/ext/libxml/ruby_xml_parser.h +10 -10
- data/ext/libxml/ruby_xml_parser_context.c +1009 -1009
- data/ext/libxml/ruby_xml_parser_options.c +74 -74
- data/ext/libxml/ruby_xml_parser_options.h +10 -10
- data/ext/libxml/ruby_xml_sax2_handler.c +326 -326
- data/ext/libxml/ruby_xml_sax_parser.c +108 -108
- data/ext/libxml/ruby_xml_version.h +9 -9
- data/lib/libxml/attr.rb +122 -122
- data/lib/libxml/attr_decl.rb +80 -80
- data/lib/libxml/attributes.rb +13 -13
- data/lib/libxml/document.rb +194 -194
- data/lib/libxml/error.rb +95 -95
- data/lib/libxml/hpricot.rb +77 -77
- data/lib/libxml/html_parser.rb +96 -96
- data/lib/libxml/namespace.rb +61 -61
- data/lib/libxml/namespaces.rb +37 -37
- data/lib/libxml/node.rb +323 -323
- data/lib/libxml/parser.rb +102 -102
- data/lib/libxml/sax_callbacks.rb +179 -179
- data/lib/libxml/sax_parser.rb +40 -40
- data/lib/libxml/tree.rb +28 -28
- data/lib/libxml.rb +4 -4
- data/lib/xml/libxml.rb +10 -10
- data/lib/xml.rb +13 -13
- data/libxml-ruby.gemspec +50 -49
- data/test/test_document.rb +140 -140
- data/test/test_document_write.rb +142 -142
- data/test/test_dtd.rb +126 -126
- data/test/test_encoding.rb +126 -126
- data/test/test_error.rb +194 -194
- data/test/test_helper.rb +20 -20
- data/test/test_namespace.rb +58 -58
- data/test/test_node.rb +235 -235
- data/test/test_node_write.rb +93 -93
- data/test/test_parser.rb +333 -333
- data/test/test_reader.rb +364 -364
- data/test/test_xml.rb +168 -168
- 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
|