-
-
Notifications
You must be signed in to change notification settings - Fork 896
/
test_entity_reference.rb
318 lines (267 loc) · 9.89 KB
/
test_entity_reference.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# frozen_string_literal: true
require "helper"
module Nokogiri
module XML
class TestEntityReference < Nokogiri::TestCase
def setup
super
@xml = Nokogiri::XML(File.open(XML_FILE), XML_FILE)
end
def test_new
assert(ref = EntityReference.new(@xml, "ent4"))
assert_instance_of(EntityReference, ref)
end
def test_many_references
100.times { EntityReference.new(@xml, "foo") }
end
def test_newline_node
# issue 719
xml = <<~EOF
<?xml version="1.0" ?>
<item></item>
EOF
doc = Nokogiri::XML(xml)
lf_node = Nokogiri::XML::EntityReference.new(doc, "#xa")
doc.xpath("/item").first.add_child(lf_node)
assert_match(/
/, doc.to_xml)
end
def test_children_should_always_be_empty
# https://github.com/sparklemotion/nokogiri/issues/1238
#
# libxml2 will create a malformed child node for predefined
# entities. because any use of that child is likely to cause a
# segfault, we shall pretend that it doesn't exist.
entity = Nokogiri::XML::EntityReference.new(@xml, "amp")
assert_equal(0, entity.children.length)
entity.inspect # should not segfault
end
end
module Common
PATH = "test/files/test_document_url/"
attr_accessor :path, :parser
def xml_document
File.join(path, "document.xml")
end
class << self
def included(base)
def base.test_relative_and_absolute_path(method_name, &block)
test_relative_path(method_name, &block)
test_absolute_path(method_name, &block)
end
def base.test_absolute_path(method_name, &block)
define_method("#{method_name}_with_absolute_path") do
self.path = "#{File.expand_path(PATH)}/"
instance_eval(&block)
end
end
def base.test_relative_path(method_name, &block)
define_method(method_name) do
self.path = PATH
instance_eval(&block)
end
end
end
end
end
class TestDOMEntityReference < Nokogiri::TestCase
include Common
def setup
super
@parser = Nokogiri::XML::Document
end
test_relative_and_absolute_path :test_dom_entity_reference_with_dtdload do
# Make sure that we can parse entity references and include them in the document
xml = File.read(xml_document)
doc = @parser.parse(xml, path) do |cfg|
cfg.default_xml
cfg.dtdload
cfg.noent
end
assert_empty doc.errors
assert_equal "foobar", doc.xpath("//blah").text
end
test_relative_and_absolute_path :test_dom_entity_reference_with_dtdvalid do
# Make sure that we can parse entity references and include them in the document
xml = File.read(xml_document)
doc = @parser.parse(xml, path) do |cfg|
cfg.default_xml
cfg.dtdvalid
cfg.noent
end
assert_empty doc.errors
assert_equal "foobar", doc.xpath("//blah").text
end
test_absolute_path :test_dom_dtd_loading_with_absolute_path do
# Make sure that we can parse entity references and include them in the document
xml = <<~XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE document SYSTEM "#{path}/document.dtd">
<document>
<body>&bar;</body>
</document>
XML
doc = @parser.parse(xml, xml_document) do |cfg|
cfg.default_xml
cfg.dtdvalid
cfg.noent
end
assert_empty doc.errors
assert_equal "foobar", doc.xpath("//blah").text
end
test_relative_and_absolute_path :test_dom_entity_reference_with_io do
# Make sure that we can parse entity references and include them in the document
xml = File.open(xml_document)
doc = @parser.parse(xml, nil) do |cfg|
cfg.default_xml
cfg.dtdload
cfg.noent
end
assert_empty doc.errors
assert_equal "foobar", doc.xpath("//blah").text
end
test_relative_and_absolute_path :test_dom_entity_reference_without_noent do
# Make sure that we don't include entity references unless NOENT is set to true
xml = File.read(xml_document)
doc = @parser.parse(xml, path) do |cfg|
cfg.default_xml
cfg.dtdload
end
assert_empty doc.errors
assert_kind_of Nokogiri::XML::EntityReference, doc.xpath("//body").first.children.first
end
test_relative_and_absolute_path :test_dom_entity_reference_without_dtdload do
# Make sure that we don't include entity references unless NOENT is set to true
xml = File.read(xml_document)
doc = @parser.parse(xml, path, &:default_xml)
assert_kind_of Nokogiri::XML::EntityReference, doc.xpath("//body").first.children.first
if Nokogiri.uses_libxml?(">= 2.13.0") # gnome/libxml2@b717abdd
assert_equal ["5:14: WARNING: Entity 'bar' not defined"], doc.errors.map(&:to_s)
elsif Nokogiri.uses_libxml?
assert_equal ["5:14: ERROR: Entity 'bar' not defined"], doc.errors.map(&:to_s)
end
end
test_relative_and_absolute_path :test_document_dtd_loading_with_nonet do
# Make sure that we don't include remote entities unless NOENT is set to true
xml = <<~XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE document SYSTEM "http://foo.bar.com/">
<document>
<body>&bar;</body>
</document>
XML
doc = @parser.parse(xml, path) do |cfg|
cfg.default_xml
cfg.dtdload
end
assert_kind_of Nokogiri::XML::EntityReference, doc.xpath("//body").first.children.first
expected = if Nokogiri.uses_libxml?(">= 2.13") # many gnome/libxml2 changes made in 2023-12
[
"2:49: WARNING: failed to load \"http://foo.bar.com/\": Attempt to load network entity",
"ERROR: Attempt to load network entity: http://foo.bar.com/",
"4:14: WARNING: Entity 'bar' not defined", # gnome/libxml2@b717abdd
]
elsif Nokogiri.uses_libxml?
[
"ERROR: Attempt to load network entity http://foo.bar.com/",
"4:14: ERROR: Entity 'bar' not defined",
]
else # jruby
["Attempt to load network entity http://foo.bar.com/"]
end
assert_equal(expected, doc.errors.map(&:to_s))
end
# TODO: can we retrieve a resource pointing to localhost when NONET is set to true ?
end
class TestSaxEntityReference < Nokogiri::SAX::TestCase
include Common
def setup
super
@parser = XML::SAX::Parser.new(Doc.new) do |ctx|
ctx.replace_entities = true
end
end
test_relative_and_absolute_path :test_sax_entity_reference do
# Make sure that we can parse entity references and include them in the document
xml = File.read(xml_document)
@parser.parse(xml)
actual = if Nokogiri.uses_libxml?(">= 2.13.0") # gnome/libxml2@b717abdd
@parser.document.warnings
else
@parser.document.errors
end
actual = actual.map { |e| e.to_s.strip }
expected = if truffleruby_system_libraries?
["error_func: %s"]
else
["Entity 'bar' not defined"]
end
assert_equal(expected, actual)
end
test_relative_and_absolute_path :test_more_sax_entity_reference do
# Make sure that we don't include entity references unless NOENT is set to true
xml = <<~XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE document SYSTEM "http://foo.bar.com/">
<document>
<body>&bar;</body>
</document>
XML
@parser.parse(xml)
actual = if Nokogiri.uses_libxml?(">= 2.13.0") # gnome/libxml2@b717abdd
@parser.document.warnings
else
@parser.document.errors
end
refute_nil(actual)
refute_empty(actual)
actual = actual.map { |e| e.to_s.strip }
expected = if truffleruby_system_libraries?
["error_func: %s"]
else
["Entity 'bar' not defined"]
end
assert_equal(expected, actual)
end
end
class TestReaderEntityReference < Nokogiri::TestCase
include Common
def setup
super
end
test_relative_and_absolute_path :test_reader_entity_reference do
# Make sure that we can parse entity references and include them in the document
xml = File.read(xml_document)
reader = Nokogiri::XML::Reader(xml, path) do |cfg|
cfg.default_xml
cfg.dtdload
cfg.noent
end
nodes = reader.map(&:value)
assert_equal ["foobar"], nodes.compact.map(&:strip).reject(&:empty?)
end
test_relative_and_absolute_path :test_reader_entity_reference_without_noent do
# Make sure that we can parse entity references and include them in the document
xml = File.read(xml_document)
reader = Nokogiri::XML::Reader(xml, path) do |cfg|
cfg.default_xml
cfg.dtdload
end
nodes = reader.map(&:value)
assert_empty nodes.compact.map(&:strip).reject(&:empty?)
end
test_relative_and_absolute_path :test_reader_entity_reference_without_dtdload do
xml = File.read(xml_document)
reader = Nokogiri::XML::Reader(xml, path, &:default_xml)
if Nokogiri.uses_libxml?(">= 2.9.0")
# Unknown entity is not fatal in libxml2 >= 2.9
assert_equal 8, reader.count
else
assert_raises(Nokogiri::XML::SyntaxError) do
reader.count
end
end
assert_operator reader.errors.size, :>, 0
end
end
end
end