-
-
-
-
-
-
-
+ def test_entity_expansion_text_limit
+ xml = <<-XML
+
+
+
+
+
+
]>
-
-EOF
+&a;
+ XML
- REXML::Document.new(xml)
- REXML::Security.entity_expansion_limit = 90
- assert_equal(90, REXML::Security.entity_expansion_limit)
- assert_raise(REXML::ParseException) do
- REXML::Document.new(xml)
- end
+ REXML::Security.entity_expansion_text_limit = 90
+ doc = REXML::Document.new(xml)
+ assert_equal(90, doc.root.children.first.value.bytesize)
end
end
end
@@ -198,9 +171,45 @@ def test_xml_declaration_standalone
assert_equal('no', doc.stand_alone?, bug2539)
end
+ def test_each_recursive
+ xml_source = <<~XML
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ XML
+
+ expected_names = %w[
+ root
+ 1_1 1_2 1_3
+ 2_1 2_2 2_3
+ ]
+
+ document = REXML::Document.new(xml_source)
+
+ # Node#each_recursive iterates elements only.
+ # This does not iterate XML declarations, comments, attributes, CDATA sections, etc.
+ actual_names = []
+ document.each_recursive do |element|
+ actual_names << element.attributes["name"]
+ end
+ assert_equal(expected_names, actual_names)
+ end
+
class WriteTest < Test::Unit::TestCase
def setup
- @document = REXML::Document.new(<<-EOX)
+ @document = REXML::Document.new(<<-EOX.chomp)
Hello world!
EOX
@@ -210,7 +219,7 @@ class ArgumentsTest < self
def test_output
output = ""
@document.write(output)
- assert_equal(<<-EOX, output)
+ assert_equal(<<-EOX.chomp, output)
Hello world!
EOX
@@ -233,7 +242,7 @@ def test_transitive
indent = 2
transitive = true
@document.write(output, indent, transitive)
- assert_equal(<<-EOX, output)
+ assert_equal(<<-EOX.chomp, output)
Hello world!
#{japanese_text}
EOX
@@ -273,7 +282,7 @@ class OptionsTest < self
def test_output
output = ""
@document.write(:output => output)
- assert_equal(<<-EOX, output)
+ assert_equal(<<-EOX.chomp, output)
Hello world!
EOX
@@ -293,7 +302,7 @@ def test_indent
def test_transitive
output = ""
@document.write(:output => output, :indent => 2, :transitive => true)
- assert_equal(<<-EOX, output)
+ assert_equal(<<-EOX.chomp, output)
Hello world! output, :encoding => encoding)
- assert_equal(<<-EOX.encode(encoding), output)
+ assert_equal(<<-EOX.chomp.encode(encoding), output)
#{japanese_text}
EOX
@@ -399,7 +408,7 @@ def test_utf_16
actual_xml = ""
document.write(actual_xml)
- expected_xml = <<-EOX.encode("UTF-16BE")
+ expected_xml = <<-EOX.chomp.encode("UTF-16BE")
\ufeff
Hello world!
EOX
diff --git a/test/test_encoding.rb b/test/test_encoding.rb
index 09495c58..6887ffbe 100644
--- a/test/test_encoding.rb
+++ b/test/test_encoding.rb
@@ -67,7 +67,7 @@ def test_in_different_out
# * Given an encoded document, accessing text and attribute nodes
# should provide UTF-8 text.
def test_in_different_access
- doc = Document.new <<-EOL
+ doc = Document.new <<~EOL
\xFF
EOL
@@ -79,7 +79,7 @@ def test_in_different_access
def test_ticket_89
- doc = Document.new <<-EOL
+ doc = Document.new <<~EOL
EOL
diff --git a/test/test_entity.rb b/test/test_entity.rb
index a2b262f7..89f83894 100644
--- a/test/test_entity.rb
+++ b/test/test_entity.rb
@@ -59,8 +59,7 @@ def test_parse_entity
def test_constructor
one = [ %q{},
- %q{},
- %q{},
+ %q{},
'',
'' ]
source = %q{
-
-
+
',
+ "a",
+ "B",
+ "B",
+ "B",
+ ],
+ [
+ entity.to_s,
+ entity.name,
+ entity.value,
+ entity.normalized,
+ entity.unnormalized,
+ ])
+ end
+
+ def test_readers_without_reference
+ entity = REXML::Entity.new([:entitydecl, "a", "&b;"])
+ assert_equal([
+ '',
+ "a",
+ "&b;",
+ "&b;",
+ "&b;",
+ ],
+ [
+ entity.to_s,
+ entity.name,
+ entity.value,
+ entity.normalized,
+ entity.unnormalized,
+ ])
+ end
+
+ def test_readers_with_nested_references
+ doctype = REXML::DocType.new('root')
+ doctype.add(REXML::Entity.new([:entitydecl, "a", "&b;"]))
+ doctype.add(REXML::Entity.new([:entitydecl, "b", "X"]))
+ assert_equal([
+ "a",
+ "&b;",
+ "&b;",
+ "X",
+ "b",
+ "X",
+ "X",
+ "X",
+ ],
+ [
+ doctype.entities["a"].name,
+ doctype.entities["a"].value,
+ doctype.entities["a"].normalized,
+ doctype.entities["a"].unnormalized,
+ doctype.entities["b"].name,
+ doctype.entities["b"].value,
+ doctype.entities["b"].normalized,
+ doctype.entities["b"].unnormalized,
+ ])
+ end
+
+ def test_parameter_entity_reference_forbidden_by_internal_subset_in_parser
+ source = ' ]>'
+ parser = REXML::Parsers::BaseParser.new(source)
+ exception = assert_raise(REXML::ParseException) do
+ while parser.has_next?
+ parser.pull
+ end
+ end
+ assert_equal(<<-DETAIL, exception.to_s)
+Parameter entity references forbidden in internal subset: "%a;"
+Line: 1
+Position: 54
+Last 80 unconsumed characters:
+ DETAIL
+ end
+
def test_entity_string_limit
template = ' ]> $'
len = 5120 # 5k per entity
@@ -122,22 +198,6 @@ def test_entity_string_limit
end
end
- def test_entity_string_limit_for_parameter_entity
- template = ' ]>'
- len = 5120 # 5k per entity
- template.sub!(/\^/, "B" * len)
-
- # 10k is OK
- entities = '%a;' * 2 # 5k entity * 2 = 10k
- REXML::Document.new(template.sub(/\$/, entities))
-
- # above 10k explodes
- entities = '%a;' * 3 # 5k entity * 2 = 15k
- assert_raise(REXML::ParseException) do
- REXML::Document.new(template.sub(/\$/, entities))
- end
- end
-
def test_raw
source = '
@@ -161,7 +221,7 @@ def test_lazy_evaluation
def test_entity_replacement
source = %q{
- ]>
+ ]>
&WhatHeSaid;}
d = REXML::Document.new( source )
diff --git a/test/test_light.rb b/test/test_light.rb
index 54b2c52e..c556c978 100644
--- a/test/test_light.rb
+++ b/test/test_light.rb
@@ -62,7 +62,7 @@ def test_access_child_elements
assert_equal( 'c', a[1].name )
end
- def test_itterate_over_children
+ def test_iterate_over_children
foo = make_small_document
ctr = 0
foo[0].each { ctr += 1 }
diff --git a/test/test_pullparser.rb b/test/test_pullparser.rb
index 53a985ba..005a106a 100644
--- a/test/test_pullparser.rb
+++ b/test/test_pullparser.rb
@@ -62,6 +62,63 @@ def test_entity_replacement
end
end
+ def test_character_references
+ source = 'AB'
+ parser = REXML::Parsers::PullParser.new( source )
+
+ events = {}
+ element_name = ''
+ while parser.has_next?
+ event = parser.pull
+ case event.event_type
+ when :start_element
+ element_name = event[0]
+ when :text
+ events[element_name] = event[1]
+ end
+ end
+
+ assert_equal('A', events['a'])
+ assert_equal("B", events['b'])
+ end
+
+ def test_text_entity_references
+ source = '<P> <I> <B> Text </B> </I>'
+ parser = REXML::Parsers::PullParser.new( source )
+
+ events = []
+ while parser.has_next?
+ event = parser.pull
+ case event.event_type
+ when :text
+ events << event[1]
+ end
+ end
+
+ assert_equal([" Text "], events)
+ end
+
+ def test_text_content_with_line_breaks
+ source = "AB\nC\r\n"
+ parser = REXML::Parsers::PullParser.new( source )
+
+ events = {}
+ element_name = ''
+ while parser.has_next?
+ event = parser.pull
+ case event.event_type
+ when :start_element
+ element_name = event[0]
+ when :text
+ events[element_name] = event[1]
+ end
+ end
+
+ assert_equal('A', events['a'])
+ assert_equal("B\n", events['b'])
+ assert_equal("C\n", events['c'])
+ end
+
def test_peek_unshift
source = ""
REXML::Parsers::PullParser.new(source)
@@ -98,5 +155,163 @@ def test_peek
end
assert_equal( 0, names.length )
end
+
+ class EntityExpansionLimitTest < Test::Unit::TestCase
+ def setup
+ @default_entity_expansion_limit = REXML::Security.entity_expansion_limit
+ @default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
+ end
+
+ def teardown
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
+ end
+
+ class GeneralEntityTest < self
+ def test_have_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ parser = REXML::Parsers::PullParser.new(source)
+ assert_raise(RuntimeError.new("entity expansion has grown too large")) do
+ while parser.has_next?
+ parser.pull
+ end
+ end
+ end
+
+ def test_empty_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ REXML::Security.entity_expansion_limit = 100000
+ parser = REXML::Parsers::PullParser.new(source)
+ while parser.has_next?
+ parser.pull
+ end
+ assert_equal(11111, parser.entity_expansion_count)
+
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ parser = REXML::Parsers::PullParser.new(source)
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ while parser.has_next?
+ parser.pull
+ end
+ end
+ assert do
+ parser.entity_expansion_count > @default_entity_expansion_limit
+ end
+ end
+
+ def test_with_default_entity
+ source = <<-XML
+
+
+
+]>
+
+&a;
+&a2;
+<
+
+ XML
+
+ REXML::Security.entity_expansion_limit = 4
+ parser = REXML::Parsers::PullParser.new(source)
+ while parser.has_next?
+ parser.pull
+ end
+
+ REXML::Security.entity_expansion_limit = 3
+ parser = REXML::Parsers::PullParser.new(source)
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ while parser.has_next?
+ parser.pull
+ end
+ end
+ end
+
+ def test_with_only_default_entities
+ member_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>"
+ source = <<-XML
+
+
+#{member_value}
+
+ XML
+
+ parser = REXML::Parsers::PullParser.new(source)
+ events = {}
+ element_name = ''
+ while parser.has_next?
+ event = parser.pull
+ case event.event_type
+ when :start_element
+ element_name = event[0]
+ when :text
+ events[element_name] = event[1]
+ end
+ end
+
+ expected_value = "
#{'A' * @default_entity_expansion_text_limit}
"
+ assert_equal(expected_value, events['member'].strip)
+ assert_equal(0, parser.entity_expansion_count)
+ assert do
+ events['member'].bytesize > @default_entity_expansion_text_limit
+ end
+ end
+
+ def test_entity_expansion_text_limit
+ source = <<-XML
+
+
+
+
+
+]>
+&a;
+ XML
+
+ REXML::Security.entity_expansion_text_limit = 90
+ parser = REXML::Parsers::PullParser.new(source)
+ events = {}
+ element_name = ''
+ while parser.has_next?
+ event = parser.pull
+ case event.event_type
+ when :start_element
+ element_name = event[0]
+ when :text
+ events[element_name] = event[1]
+ end
+ end
+ assert_equal(90, events['member'].size)
+ end
+ end
+ end
end
end
diff --git a/test/test_sax.rb b/test/test_sax.rb
index 6f775183..ae17e364 100644
--- a/test/test_sax.rb
+++ b/test/test_sax.rb
@@ -31,6 +31,17 @@ def test_entity_replacement
assert_equal '--1234--', results[1]
end
+ def test_characters_predefined_entities
+ source = '<P> <I> <B> Text </B> </I>'
+
+ sax = Parsers::SAX2Parser.new( source )
+ results = []
+ sax.listen(:characters) {|x| results << x }
+ sax.parse
+
+ assert_equal([" Text "], results)
+ end
+
def test_sax2
File.open(fixture_path("documentation.xml")) do |f|
parser = Parsers::SAX2Parser.new( f )
@@ -88,6 +99,142 @@ def test_sax2
end
end
+ class EntityExpansionLimitTest < Test::Unit::TestCase
+ def setup
+ @default_entity_expansion_limit = REXML::Security.entity_expansion_limit
+ @default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
+ end
+
+ def teardown
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
+ end
+
+ class GeneralEntityTest < self
+ def test_have_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ assert_raise(RuntimeError.new("entity expansion has grown too large")) do
+ sax.parse
+ end
+ end
+
+ def test_empty_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ REXML::Security.entity_expansion_limit = 100000
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ sax.parse
+ assert_equal(11111, sax.entity_expansion_count)
+
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ sax.parse
+ end
+ assert do
+ sax.entity_expansion_count > @default_entity_expansion_limit
+ end
+ end
+
+ def test_with_default_entity
+ source = <<-XML
+
+
+
+]>
+
+&a;
+&a2;
+<
+
+ XML
+
+ REXML::Security.entity_expansion_limit = 4
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ sax.parse
+
+ REXML::Security.entity_expansion_limit = 3
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ sax.parse
+ end
+ end
+
+ def test_with_only_default_entities
+ member_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>"
+ source = <<-XML
+
+
+#{member_value}
+
+ XML
+
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ text_value = nil
+ sax.listen(:characters, ["member"]) do |text|
+ text_value = text
+ end
+ sax.parse
+
+ expected_value = "
#{'A' * @default_entity_expansion_text_limit}
"
+ assert_equal(expected_value, text_value.strip)
+ assert_equal(0, sax.entity_expansion_count)
+ assert do
+ text_value.bytesize > @default_entity_expansion_text_limit
+ end
+ end
+
+ def test_entity_expansion_text_limit
+ source = <<-XML
+
+
+
+
+
+]>
+&a;
+ XML
+
+ REXML::Security.entity_expansion_text_limit = 90
+ sax = REXML::Parsers::SAX2Parser.new(source)
+ text_size = nil
+ sax.listen(:characters, ["member"]) do |text|
+ text_size = text.size
+ end
+ sax.parse
+ assert_equal(90, text_size)
+ end
+ end
+ end
+
# used by test_simple_doctype_listener
# submitted by Jeff Barczewski
class SimpleDoctypeListener
@@ -109,7 +256,7 @@ def doctype(name, pub_sys, long_name, uri)
# test simple non-entity doctype in sax listener
# submitted by Jeff Barczewski
def test_simple_doctype_listener
- xml = <<-END
+ xml = <<~END
Hello, world!
@@ -140,8 +287,8 @@ def test_simple_doctype_listener
# test doctype with missing name, should throw ParseException
# submitted by Jeff Barczewseki
- def test_doctype_with_mising_name_throws_exception
- xml = <<-END
+ def test_doctype_with_missing_name_throws_exception
+ xml = <<~END
Hello, world!
diff --git a/test/test_stream.rb b/test/test_stream.rb
index 545d5349..782066c2 100644
--- a/test/test_stream.rb
+++ b/test/test_stream.rb
@@ -87,8 +87,184 @@ def entity(content)
assert_equal(["ISOLat2"], listener.entities)
end
+
+ def test_entity_replacement
+ source = <<-XML
+
+
+
+]>&la;&lala;
+ XML
+
+ listener = MyListener.new
+ class << listener
+ attr_accessor :text_values
+ def text(text)
+ @text_values << text
+ end
+ end
+ listener.text_values = []
+ REXML::Document.parse_stream(source, listener)
+ assert_equal(["1234", "--1234--"], listener.text_values)
+ end
+
+ def test_characters_predefined_entities
+ source = '<P> <I> <B> Text </B> </I>'
+
+ listener = MyListener.new
+ class << listener
+ attr_accessor :text_value
+ def text(text)
+ @text_value << text
+ end
+ end
+ listener.text_value = ""
+ REXML::Document.parse_stream(source, listener)
+ assert_equal(" Text ", listener.text_value)
+ end
end
+ class EntityExpansionLimitTest < Test::Unit::TestCase
+ def setup
+ @default_entity_expansion_limit = REXML::Security.entity_expansion_limit
+ @default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
+ end
+
+ def teardown
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
+ end
+
+ def test_have_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ assert_raise(RuntimeError.new("entity expansion has grown too large")) do
+ REXML::Document.parse_stream(source, MyListener.new)
+ end
+ end
+
+ def test_empty_value
+ source = <<-XML
+
+
+
+
+
+
+]>
+
+&a;
+
+ XML
+
+ listener = MyListener.new
+ REXML::Security.entity_expansion_limit = 100000
+ parser = REXML::Parsers::StreamParser.new( source, listener )
+ parser.parse
+ assert_equal(11111, parser.entity_expansion_count)
+
+ REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
+ parser = REXML::Parsers::StreamParser.new( source, listener )
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ parser.parse
+ end
+ assert do
+ parser.entity_expansion_count > @default_entity_expansion_limit
+ end
+ end
+
+ def test_with_default_entity
+ source = <<-XML
+
+
+
+]>
+
+&a;
+&a2;
+<
+
+ XML
+
+ listener = MyListener.new
+ REXML::Security.entity_expansion_limit = 4
+ REXML::Document.parse_stream(source, listener)
+
+ REXML::Security.entity_expansion_limit = 3
+ assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
+ REXML::Document.parse_stream(source, listener)
+ end
+ end
+
+ def test_with_only_default_entities
+ member_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>"
+ source = <<-XML
+
+
+#{member_value}
+
+ XML
+
+ listener = MyListener.new
+ class << listener
+ attr_accessor :text_value
+ def text(text)
+ @text_value << text
+ end
+ end
+ listener.text_value = ""
+ parser = REXML::Parsers::StreamParser.new( source, listener )
+ parser.parse
+
+ expected_value = "
#{'A' * @default_entity_expansion_text_limit}
"
+ assert_equal(expected_value, listener.text_value.strip)
+ assert_equal(0, parser.entity_expansion_count)
+ assert do
+ listener.text_value.bytesize > @default_entity_expansion_text_limit
+ end
+ end
+
+ def test_entity_expansion_text_limit
+ source = <<-XML
+
+
+
+
+
+]>
+&a;
+ XML
+
+ listener = MyListener.new
+ class << listener
+ attr_accessor :text_value
+ def text(text)
+ @text_value << text
+ end
+ end
+ listener.text_value = ""
+ REXML::Security.entity_expansion_text_limit = 90
+ REXML::Document.parse_stream(source, listener)
+
+ assert_equal(90, listener.text_value.size)
+ end
+ end
# For test_listener
class RequestReader
diff --git a/test/test_text_check.rb b/test/test_text_check.rb
new file mode 100644
index 00000000..11cf65a3
--- /dev/null
+++ b/test/test_text_check.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: false
+
+module REXMLTests
+ class TextCheckTester < Test::Unit::TestCase
+
+ def check(string)
+ REXML::Text.check(string, REXML::Text::NEEDS_A_SECOND_CHECK, nil)
+ end
+
+ def assert_check(string)
+ assert_nothing_raised { check(string) }
+ end
+
+ def assert_check_failed(string, illegal_part)
+ message = "Illegal character #{illegal_part.inspect} in raw string #{string.inspect}"
+ assert_raise(RuntimeError.new(message)) do
+ check(string)
+ end
+ end
+
+ class TestValid < self
+ def test_entity_name_start_char_colon
+ assert_check("&:;")
+ end
+
+ def test_entity_name_start_char_under_score
+ assert_check("&_;")
+ end
+
+ def test_entity_name_mix
+ assert_check("&A.b-0123;")
+ end
+
+ def test_character_reference_decimal
+ assert_check("¢")
+ end
+
+ def test_character_reference_hex
+ assert_check("")
+ end
+
+ def test_entity_name_non_ascii
+ # U+3042 HIRAGANA LETTER A
+ # U+3044 HIRAGANA LETTER I
+ assert_check("&\u3042\u3044;")
+ end
+
+ def test_normal_string
+ assert_check("foo")
+ end
+ end
+
+ class TestInvalid < self
+ def test_lt
+ assert_check_failed("<;", "<")
+ end
+
+ def test_lt_mix
+ assert_check_failed("ab
@@ -24,7 +24,7 @@ def test_validate
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
@@ -33,7 +33,7 @@ def test_validate
def test_sequence
- rng = %q{
+ rng = <<-XML
@@ -45,7 +45,7 @@ def test_sequence
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -56,7 +56,7 @@ def test_sequence
def test_choice
- rng = %q{
+ rng = <<-XML
@@ -70,7 +70,7 @@ def test_choice
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -79,7 +79,7 @@ def test_choice
end
def test_optional
- rng = %q{
+ rng = <<-XML
@@ -90,7 +90,7 @@ def test_optional
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
@@ -100,7 +100,7 @@ def test_optional
end
def test_zero_or_more
- rng = %q{
+ rng = <<-XML
@@ -111,7 +111,7 @@ def test_zero_or_more
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
no_error( validator, %q{} )
@@ -119,7 +119,7 @@ def test_zero_or_more
error( validator, %q{} )
error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -133,7 +133,7 @@ def test_zero_or_more
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
@@ -143,7 +143,7 @@ def test_zero_or_more
end
def test_one_or_more
- rng = %q{
+ rng = <<-XML
@@ -154,7 +154,7 @@ def test_one_or_more
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -165,13 +165,13 @@ def test_one_or_more
end
def test_attribute
- rng = %q{
+ rng = <<-XML
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -181,7 +181,7 @@ def test_attribute
end
def test_choice_attributes
- rng = %q{
+ rng = <<-XML
@@ -189,7 +189,7 @@ def test_choice_attributes
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -199,7 +199,7 @@ def test_choice_attributes
end
def test_choice_attribute_element
- rng = %q{
+ rng = <<-XML
@@ -207,7 +207,7 @@ def test_choice_attribute_element
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -217,12 +217,12 @@ def test_choice_attribute_element
end
def test_empty
- rng = %q{
+ rng = <<-XML
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -231,12 +231,12 @@ def test_empty
end
def test_text_val
- rng = %q{
+ rng = <<-XML
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -245,7 +245,7 @@ def test_text_val
end
def test_choice_text
- rng = %q{
+ rng = <<-XML
@@ -253,7 +253,7 @@ def test_choice_text
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{Text} )
@@ -263,7 +263,7 @@ def test_choice_text
end
def test_group
- rng = %q{
+ rng = <<-XML
@@ -274,7 +274,7 @@ def test_group
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -282,7 +282,7 @@ def test_group
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -291,7 +291,7 @@ def test_group
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -302,14 +302,14 @@ def test_group
def test_value
# Values as text nodes
- rng = %q{
+ rng = <<-XML
VaLuE
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{X} )
@@ -317,7 +317,7 @@ def test_value
no_error( validator, %q{VaLuE} )
# Values as text nodes, via choice
- rng = %q{
+ rng = <<-XML
@@ -327,7 +327,7 @@ def test_value
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -336,14 +336,14 @@ def test_value
no_error( validator, %q{Option 2} )
# Attribute values
- rng = %q{
+ rng = <<-XML
VaLuE
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -352,7 +352,7 @@ def test_value
no_error( validator, %q{} )
# Attribute values via choice
- rng = %q{
+ rng = <<-XML
@@ -362,7 +362,7 @@ def test_value
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -372,7 +372,7 @@ def test_value
end
def test_interleave
- rng = %q{
+ rng = <<-XML
@@ -383,7 +383,7 @@ def test_interleave
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -396,7 +396,7 @@ def test_interleave
end
def test_mixed
- rng = %q{
+ rng = <<-XML
@@ -405,7 +405,7 @@ def test_mixed
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{Text} )
@@ -413,7 +413,7 @@ def test_mixed
end
def test_ref_sequence
- rng = %q{
+ rng = <<-XML
@@ -429,7 +429,7 @@ def test_ref_sequence
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
@@ -437,7 +437,7 @@ def test_ref_sequence
end
def test_ref_choice
- rng = %q{
+ rng = <<-XML
@@ -453,7 +453,7 @@ def test_ref_choice
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -461,7 +461,7 @@ def test_ref_choice
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -477,7 +477,7 @@ def test_ref_choice
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -485,7 +485,7 @@ def test_ref_choice
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -502,7 +502,7 @@ def test_ref_choice
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -513,7 +513,7 @@ def test_ref_choice
def test_ref_zero_plus
- rng = %q{
+ rng = <<-XML
@@ -530,7 +530,7 @@ def test_ref_zero_plus
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -538,7 +538,7 @@ def test_ref_zero_plus
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -555,7 +555,7 @@ def test_ref_zero_plus
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -566,7 +566,7 @@ def test_ref_zero_plus
def test_ref_one_plus
- rng = %q{
+ rng = <<-XML
@@ -583,7 +583,7 @@ def test_ref_one_plus
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -591,7 +591,7 @@ def test_ref_one_plus
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -608,7 +608,7 @@ def test_ref_one_plus
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -618,7 +618,7 @@ def test_ref_one_plus
end
def test_ref_interleave
- rng = %q{
+ rng = <<-XML
@@ -634,7 +634,7 @@ def test_ref_interleave
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -643,7 +643,7 @@ def test_ref_interleave
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -659,7 +659,7 @@ def test_ref_interleave
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -668,7 +668,7 @@ def test_ref_interleave
no_error( validator, %q{} )
no_error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -687,7 +687,7 @@ def test_ref_interleave
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -698,7 +698,7 @@ def test_ref_interleave
end
def test_ref_recurse
- rng = %q{
+ rng = <<-XML
@@ -715,7 +715,7 @@ def test_ref_recurse
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
error( validator, %q{} )
@@ -724,7 +724,7 @@ def test_ref_recurse
end
def test_ref_optional
- rng = %q{
+ rng = <<-XML
@@ -740,7 +740,7 @@ def test_ref_optional
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
@@ -748,7 +748,7 @@ def test_ref_optional
error( validator, %q{} )
error( validator, %q{} )
- rng = %q{
+ rng = <<-XML
@@ -764,7 +764,7 @@ def test_ref_optional
- }
+ XML
validator = REXML::Validation::RelaxNG.new( rng )
no_error( validator, %q{} )
diff --git a/test/test_xml_declaration.rb b/test/test_xml_declaration.rb
index 6db54bab..6a1f4df0 100644
--- a/test/test_xml_declaration.rb
+++ b/test/test_xml_declaration.rb
@@ -6,7 +6,7 @@
module REXMLTests
class TestXmlDeclaration < Test::Unit::TestCase
def setup
- xml = <<-XML
+ xml = <<~XML
diff --git a/test/xpath/test_base.rb b/test/xpath/test_base.rb
index 5156bbbe..1dacd69d 100644
--- a/test/xpath/test_base.rb
+++ b/test/xpath/test_base.rb
@@ -451,6 +451,46 @@ def test_following
# puts results
#end
+ def test_nested_predicates
+ doc = Document.new <<-EOF
+
+
+ ab
+ cd
+
+
+ ef
+ gh
+
+
+ hi
+
+
+ EOF
+
+ matches = XPath.match(doc, '(/div/div/test[0])').map(&:text)
+ assert_equal [], matches
+ matches = XPath.match(doc, '(/div/div/test[1])').map(&:text)
+ assert_equal ["ab", "ef", "hi"], matches
+ matches = XPath.match(doc, '(/div/div/test[2])').map(&:text)
+ assert_equal ["cd", "gh"], matches
+ matches = XPath.match(doc, '(/div/div/test[3])').map(&:text)
+ assert_equal [], matches
+
+ matches = XPath.match(doc, '(/div/div/test[1])[1]').map(&:text)
+ assert_equal ["ab"], matches
+ matches = XPath.match(doc, '(/div/div/test[1])[2]').map(&:text)
+ assert_equal ["ef"], matches
+ matches = XPath.match(doc, '(/div/div/test[1])[3]').map(&:text)
+ assert_equal ["hi"], matches
+ matches = XPath.match(doc, '(/div/div/test[2])[1]').map(&:text)
+ assert_equal ["cd"], matches
+ matches = XPath.match(doc, '(/div/div/test[2])[2]').map(&:text)
+ assert_equal ["gh"], matches
+ matches = XPath.match(doc, '(/div/div/test[2])[3]').map(&:text)
+ assert_equal [], matches
+ end
+
# Contributed by Mike Stok
def test_starts_with
source = <<-EOF
@@ -611,7 +651,7 @@ def test_comparisons
source = ""
doc = REXML::Document.new(source)
- # NOTE TO SER: check that number() is required
+ # NOTE: check that number() is required
assert_equal 2, REXML::XPath.match(doc, "//b[number(@id) > 1]").size
assert_equal 3, REXML::XPath.match(doc, "//b[number(@id) >= 1]").size
assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) <= 1]").size
diff --git a/test/xpath/test_predicate.rb b/test/xpath/test_predicate.rb
index c8520712..278e3765 100644
--- a/test/xpath/test_predicate.rb
+++ b/test/xpath/test_predicate.rb
@@ -6,7 +6,7 @@
module REXMLTests
class TestXPathPredicate < Test::Unit::TestCase
include REXML
- SRC=<<-EOL
+ SRC=<<~EOL