From 20017eea807e8fa386aa5c79ae779004d8b366dd Mon Sep 17 00:00:00 2001
From: Sutou Kouhei
Date: Tue, 25 Jun 2024 11:26:33 +0900
Subject: [PATCH] Add 3.3.1 entry
Backport from https://github.com/ruby/rexml/tree/v3.3.1/test
---
test/rexml/data/much_ado.xml | 2 +-
test/rexml/data/ofbiz-issues-full-177.xml | 4 +-
test/rexml/data/t75.xml | 2 +-
test/rexml/data/test/tests.xml | 4 +-
test/rexml/data/tutorial.xml | 2 +-
test/rexml/formatter/test_default.rb | 17 ++
.../test_base.rb} | 45 ++++
test/rexml/functions/test_boolean.rb | 75 ++++++
test/rexml/functions/test_local_name.rb | 44 +++
test/rexml/functions/test_number.rb | 38 +++
test/rexml/helper.rb | 35 +++
test/rexml/parse/test_comment.rb | 109 ++++++++
.../parse/test_document_type_declaration.rb | 60 +++++
test/rexml/parse/test_element.rb | 13 +
test/rexml/parse/test_entity_declaration.rb | 36 +++
test/rexml/parse/test_notation_declaration.rb | 2 +-
.../parse/test_processing_instruction.rb | 44 +++
test/rexml/parser/test_base_parser.rb | 27 ++
test/rexml/parser/test_ultra_light.rb | 2 +-
test/rexml/parser/test_xpath.rb | 115 ++++++++
test/rexml/rexml_test_utils.rb | 7 -
test/rexml/test_attribute.rb | 12 +
test/rexml/test_attributes.rb | 13 +-
test/rexml/test_attributes_mixin.rb | 2 -
test/rexml/test_comment.rb | 3 -
test/rexml/test_contrib.rb | 10 +-
test/rexml/test_core.rb | 114 ++++++--
test/rexml/test_doctype.rb | 173 +++++++++++-
test/rexml/test_document.rb | 58 +++-
test/rexml/test_element.rb | 3 -
test/rexml/test_elements.rb | 7 +-
test/rexml/test_encoding.rb | 25 +-
test/rexml/test_entity.rb | 2 -
test/rexml/test_functions_number.rb | 35 ---
test/rexml/test_instruction.rb | 12 +
test/rexml/test_jaxen.rb | 192 ++++++-------
test/rexml/test_light.rb | 10 +-
test/rexml/test_lightparser.rb | 4 +-
test/rexml/test_listener.rb | 5 +-
test/rexml/test_martin_fowler.rb | 8 +-
test/rexml/test_namespace.rb | 5 +-
test/rexml/test_order.rb | 5 +-
test/rexml/test_preceding_sibling.rb | 2 -
test/rexml/test_pullparser.rb | 21 +-
test/rexml/test_rexml_issuezilla.rb | 4 +-
test/rexml/test_sax.rb | 11 +-
test/rexml/test_stream.rb | 7 +-
test/rexml/test_text.rb | 53 +++-
test/rexml/test_ticket_80.rb | 3 -
test/rexml/test_validation_rng.rb | 142 +++++-----
test/rexml/test_xml_declaration.rb | 21 +-
test/rexml/xpath/test_attribute.rb | 12 +-
.../xpath/test_axis_preceding_sibling.rb | 2 -
test/rexml/xpath/test_axis_self.rb | 20 ++
test/rexml/xpath/test_base.rb | 180 +++++++++----
test/rexml/xpath/test_compare.rb | 252 ++++++++++++++++++
test/rexml/xpath/test_node.rb | 4 -
test/rexml/xpath/test_predicate.rb | 14 +-
test/rexml/xpath/test_text.rb | 3 +-
59 files changed, 1727 insertions(+), 405 deletions(-)
create mode 100644 test/rexml/formatter/test_default.rb
rename test/rexml/{test_functions.rb => functions/test_base.rb} (87%)
create mode 100644 test/rexml/functions/test_boolean.rb
create mode 100644 test/rexml/functions/test_local_name.rb
create mode 100644 test/rexml/functions/test_number.rb
create mode 100644 test/rexml/helper.rb
create mode 100644 test/rexml/parse/test_comment.rb
create mode 100644 test/rexml/parse/test_entity_declaration.rb
create mode 100644 test/rexml/parse/test_processing_instruction.rb
create mode 100644 test/rexml/parser/test_base_parser.rb
create mode 100644 test/rexml/parser/test_xpath.rb
delete mode 100644 test/rexml/rexml_test_utils.rb
create mode 100644 test/rexml/test_attribute.rb
delete mode 100644 test/rexml/test_functions_number.rb
create mode 100644 test/rexml/test_instruction.rb
create mode 100644 test/rexml/xpath/test_axis_self.rb
create mode 100644 test/rexml/xpath/test_compare.rb
diff --git a/test/rexml/data/much_ado.xml b/test/rexml/data/much_ado.xml
index f008fad..0040088 100644
--- a/test/rexml/data/much_ado.xml
+++ b/test/rexml/data/much_ado.xml
@@ -4735,7 +4735,7 @@ CLAUDIO, BENEDICK, HERO, BEATRICE, and Attendants
But they shall find, awaked in such a kind,
Both strength of limb and policy of mind,
Ability in means and choice of friends,
-To quit me of them throughly.
+To quit me of them thoroughly.
diff --git a/test/rexml/data/ofbiz-issues-full-177.xml b/test/rexml/data/ofbiz-issues-full-177.xml
index bfff771..e1f7bdf 100644
--- a/test/rexml/data/ofbiz-issues-full-177.xml
+++ b/test/rexml/data/ofbiz-issues-full-177.xml
@@ -152,8 +152,8 @@
-
-
+
+
diff --git a/test/rexml/data/t75.xml b/test/rexml/data/t75.xml
index 0911fb1..eb3ccce 100644
--- a/test/rexml/data/t75.xml
+++ b/test/rexml/data/t75.xml
@@ -1,4 +1,4 @@
-
+
-
+
web-app
web-app
web-app
@@ -318,7 +318,7 @@
-
+
web-app
web-app
web-app
diff --git a/test/rexml/data/tutorial.xml b/test/rexml/data/tutorial.xml
index bf5783d..9c4639b 100644
--- a/test/rexml/data/tutorial.xml
+++ b/test/rexml/data/tutorial.xml
@@ -286,7 +286,7 @@ el1 << Text.new(" cruel world")
strings.
I can't emphasize this enough, because people do have problems with
- this. REXML can't possibly alway guess correctly how your text is
+ this. REXML can't possibly always guess correctly how your text is
encoded, so it always assumes the text is UTF-8. It also does not warn
you when you try to add text which isn't properly encoded, for the
same reason. You must make sure that you are adding UTF-8 text.
diff --git a/test/rexml/formatter/test_default.rb b/test/rexml/formatter/test_default.rb
new file mode 100644
index 0000000..aa403db
--- /dev/null
+++ b/test/rexml/formatter/test_default.rb
@@ -0,0 +1,17 @@
+module REXMLTests
+ class DefaultFormatterTest < Test::Unit::TestCase
+ def format(node)
+ formatter = REXML::Formatters::Default.new
+ output = +""
+ formatter.write(node, output)
+ output
+ end
+
+ class InstructionTest < self
+ def test_content_nil
+ instruction = REXML::Instruction.new("target")
+ assert_equal("", format(instruction))
+ end
+ end
+ end
+end
diff --git a/test/rexml/test_functions.rb b/test/rexml/functions/test_base.rb
similarity index 87%
rename from test/rexml/test_functions.rb
rename to test/rexml/functions/test_base.rb
index a77be38..daa3815 100644
--- a/test/rexml/test_functions.rb
+++ b/test/rexml/functions/test_base.rb
@@ -3,9 +3,16 @@ require "test/unit/testcase"
require "rexml/document"
+# TODO: Split me
module REXMLTests
class FunctionsTester < Test::Unit::TestCase
include REXML
+
+ def setup
+ super
+ REXML::Functions.context = nil
+ end
+
def test_functions
# trivial text() test
# confuse-a-function
@@ -222,6 +229,44 @@ module REXMLTests
assert_equal( [REXML::Comment.new("COMMENT A")], m )
end
+ def test_normalize_space_strings
+ source = <<-XML
+breakfast boosts\t\t
+
+concentration
+Coffee beans
+ aroma
+
+
+
+ Dessert
+ \t\t after dinner
+ XML
+ normalized_texts = REXML::XPath.each(REXML::Document.new(source), "normalize-space(//text())").to_a
+ assert_equal([
+ "breakfast boosts concentration",
+ "Coffee beans aroma",
+ "Dessert after dinner",
+ ],
+ normalized_texts)
+ end
+
+ def test_string_nil_without_context
+ doc = REXML::Document.new(<<~XML)
+
+
+
+
+
+ XML
+
+ assert_equal([doc.root.elements[2]],
+ REXML::XPath.match(doc,
+ "//foo[@bar=$n]",
+ nil,
+ {"n" => nil}))
+ end
+
def test_unregistered_method
doc = Document.new("")
assert_nil(XPath::first(doc.root, "to_s()"))
diff --git a/test/rexml/functions/test_boolean.rb b/test/rexml/functions/test_boolean.rb
new file mode 100644
index 0000000..b3e2117
--- /dev/null
+++ b/test/rexml/functions/test_boolean.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: false
+
+require "test/unit"
+require "rexml/document"
+require "rexml/functions"
+
+module REXMLTests
+ class TestFunctionsBoolean < Test::Unit::TestCase
+ def setup
+ REXML::Functions.context = nil
+ end
+
+ def test_true
+ assert_equal(true, REXML::Functions.boolean(true))
+ end
+
+ def test_false
+ assert_equal(false, REXML::Functions.boolean(false))
+ end
+
+ def test_integer_true
+ assert_equal(true, REXML::Functions.boolean(1))
+ end
+
+ def test_integer_positive_zero
+ assert_equal(false, REXML::Functions.boolean(0))
+ end
+
+ def test_integer_negative_zero
+ assert_equal(false, REXML::Functions.boolean(-0))
+ end
+
+ def test_float_true
+ assert_equal(true, REXML::Functions.boolean(1.1))
+ end
+
+ def test_float_positive_zero
+ assert_equal(false, REXML::Functions.boolean(-0.0))
+ end
+
+ def test_float_negative_zero
+ assert_equal(false, REXML::Functions.boolean(-0.0))
+ end
+
+ def test_float_nan
+ assert_equal(false, REXML::Functions.boolean(Float::NAN))
+ end
+
+ def test_string_true
+ assert_equal(true, REXML::Functions.boolean("content"))
+ end
+
+ def test_string_empty
+ assert_equal(false, REXML::Functions.boolean(""))
+ end
+
+ def test_node_set_true
+ root = REXML::Document.new("").root
+ assert_equal(true, REXML::Functions.boolean([root]))
+ end
+
+ def test_node_set_empty
+ assert_equal(false, REXML::Functions.boolean([]))
+ end
+
+ def test_nil
+ assert_equal(false, REXML::Functions.boolean(nil))
+ end
+
+ def test_context
+ REXML::Functions.context = {node: true}
+ assert_equal(true, REXML::Functions.boolean())
+ end
+ end
+end
diff --git a/test/rexml/functions/test_local_name.rb b/test/rexml/functions/test_local_name.rb
new file mode 100644
index 0000000..97c9e74
--- /dev/null
+++ b/test/rexml/functions/test_local_name.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: false
+
+require "test/unit"
+require "rexml/document"
+require "rexml/functions"
+
+module REXMLTests
+ class TestFunctionsLocalName < Test::Unit::TestCase
+ def setup
+ REXML::Functions.context = nil
+ end
+
+ def test_one
+ document = REXML::Document.new(<<-XML)
+
+
+
+ XML
+ node_set = document.root.children
+ assert_equal("child", REXML::Functions.local_name(node_set))
+ end
+
+ def test_multiple
+ document = REXML::Document.new(<<-XML)
+
+
+
+
+ XML
+ node_set = document.root.children
+ assert_equal("child1", REXML::Functions.local_name(node_set))
+ end
+
+ def test_nonexistent
+ assert_equal("", REXML::Functions.local_name([]))
+ end
+
+ def test_context
+ document = REXML::Document.new("")
+ REXML::Functions.context = {node: document.root}
+ assert_equal("root", REXML::Functions.local_name())
+ end
+ end
+end
diff --git a/test/rexml/functions/test_number.rb b/test/rexml/functions/test_number.rb
new file mode 100644
index 0000000..16e6357
--- /dev/null
+++ b/test/rexml/functions/test_number.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: false
+
+require "test/unit"
+require "rexml/document"
+require "rexml/functions"
+
+module REXMLTests
+ class TestFunctionsNumber < Test::Unit::TestCase
+ def setup
+ REXML::Functions.context = nil
+ end
+
+ def test_true
+ assert_equal(1, REXML::Functions.number(true))
+ end
+
+ def test_false
+ assert_equal(0, REXML::Functions.number(false))
+ end
+
+ def test_numeric
+ assert_equal(29, REXML::Functions.number(29))
+ end
+
+ def test_string_integer
+ assert_equal(100, REXML::Functions.number("100"))
+ end
+
+ def test_string_float
+ assert_equal(-9.13, REXML::Functions.number("-9.13"))
+ end
+
+ def test_node_set
+ root = REXML::Document.new("100").root
+ assert_equal(100, REXML::Functions.number([root]))
+ end
+ end
+end
diff --git a/test/rexml/helper.rb b/test/rexml/helper.rb
new file mode 100644
index 0000000..3de1327
--- /dev/null
+++ b/test/rexml/helper.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: false
+
+require "test-unit"
+
+require "rexml/document"
+
+module Helper
+ module Fixture
+ def fixture_path(*components)
+ File.join(__dir__, "data", *components)
+ end
+ end
+
+ module Global
+ def suppress_warning
+ verbose = $VERBOSE
+ begin
+ $VERBOSE = nil
+ yield
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ def with_default_internal(encoding)
+ default_internal = Encoding.default_internal
+ begin
+ suppress_warning {Encoding.default_internal = encoding}
+ yield
+ ensure
+ suppress_warning {Encoding.default_internal = default_internal}
+ end
+ end
+ end
+end
diff --git a/test/rexml/parse/test_comment.rb b/test/rexml/parse/test_comment.rb
new file mode 100644
index 0000000..ce6678e
--- /dev/null
+++ b/test/rexml/parse/test_comment.rb
@@ -0,0 +1,109 @@
+require "test/unit"
+require "rexml/document"
+
+module REXMLTests
+ class TestParseComment < Test::Unit::TestCase
+ def parse(xml)
+ REXML::Document.new(xml)
+ end
+
+ class TestInvalid < self
+ def test_toplevel_unclosed_comment
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 11
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+
+ def test_toplevel_malformed_comment_end
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 9
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+
+ def test_doctype_malformed_comment_inner
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 26
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+
+ def test_doctype_malformed_comment_end
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 24
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+
+ def test_after_doctype_malformed_comment_short
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL.chomp, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 8
+ Last 80 unconsumed characters:
+ -->
+ DETAIL
+ end
+
+ def test_after_doctype_malformed_comment_inner
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 14
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+
+ def test_after_doctype_malformed_comment_end
+ exception = assert_raise(REXML::ParseException) do
+ parse("")
+ end
+ assert_equal(<<~DETAIL, exception.to_s)
+ Malformed comment
+ Line: 1
+ Position: 12
+ Last 80 unconsumed characters:
+ DETAIL
+ end
+ end
+ end
+end
diff --git a/test/rexml/parse/test_document_type_declaration.rb b/test/rexml/parse/test_document_type_declaration.rb
index 5571390..3ca0b53 100644
--- a/test/rexml/parse/test_document_type_declaration.rb
+++ b/test/rexml/parse/test_document_type_declaration.rb
@@ -36,6 +36,66 @@ Last 80 unconsumed characters:
+ r SYSTEM "urn:x-rexml:test" [ ]>
DETAIL
end
+
+ def test_no_name
+ exception = assert_raise(REXML::ParseException) do
+ parse(<<-DOCTYPE)
+
+ DOCTYPE
+ end
+ assert_equal(<<-DETAIL.chomp, exception.to_s)
+Malformed DOCTYPE: name is missing
+Line: 3
+Position: 17
+Last 80 unconsumed characters:
+
+ DETAIL
+ end
+ end
+
+ class TestUnclosed < self
+ def test_no_extra_node
+ exception = assert_raise(REXML::ParseException) do
+ REXML::Document.new("
+ DOCTYPE
+ end
+ assert_equal(<<~DETAIL.chomp, exception.to_s)
+ Malformed DOCTYPE: invalid declaration
+ Line: 1
+ Position: 20
+ Last 80 unconsumed characters:
+ #{' '}
+ DETAIL
+ end
+
+ def test_text
+ exception = assert_raise(REXML::ParseException) do
+ REXML::Document.new(<<~DOCTYPE)
+
Line: 1
Position: 13
Last 80 unconsumed characters:
+:a="">
+ DETAIL
+ end
+ def test_empty_namespace_attribute_name_with_utf8_character
+ exception = assert_raise(REXML::ParseException) do
+ parse("") # U+200B ZERO WIDTH SPACE
+ end
+ assert_equal(<<-DETAIL.chomp.force_encoding("ASCII-8BIT"), exception.to_s)
+Invalid attribute name: <:\xE2\x80\x8B>
+Line: 1
+Position: 8
+Last 80 unconsumed characters:
+:\xE2\x80\x8B>
DETAIL
end
diff --git a/test/rexml/parse/test_entity_declaration.rb b/test/rexml/parse/test_entity_declaration.rb
new file mode 100644
index 0000000..e15deec
--- /dev/null
+++ b/test/rexml/parse/test_entity_declaration.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'rexml/document'
+
+module REXMLTests
+ class TestParseEntityDeclaration < Test::Unit::TestCase
+ private
+ def xml(internal_subset)
+ <<-XML
+
+
+ XML
+ end
+
+ def parse(internal_subset)
+ REXML::Document.new(xml(internal_subset)).doctype
+ end
+
+ def test_empty
+ exception = assert_raise(REXML::ParseException) do
+ parse(<<-INTERNAL_SUBSET)
+
+ INTERNAL_SUBSET
+ end
+ assert_equal(<<-DETAIL.chomp, exception.to_s)
+Malformed notation declaration: name is missing
+Line: 5
+Position: 72
+Last 80 unconsumed characters:
+ ]>
+ DETAIL
+ end
+ end
+end
diff --git a/test/rexml/parse/test_notation_declaration.rb b/test/rexml/parse/test_notation_declaration.rb
index 19a0536..9e81b6a 100644
--- a/test/rexml/parse/test_notation_declaration.rb
+++ b/test/rexml/parse/test_notation_declaration.rb
@@ -35,7 +35,7 @@ Malformed notation declaration: name is missing
Line: 5
Position: 72
Last 80 unconsumed characters:
- ]>
+ ]>
DETAIL
end
diff --git a/test/rexml/parse/test_processing_instruction.rb b/test/rexml/parse/test_processing_instruction.rb
new file mode 100644
index 0000000..f0c0c24
--- /dev/null
+++ b/test/rexml/parse/test_processing_instruction.rb
@@ -0,0 +1,44 @@
+require "test/unit"
+require "rexml/document"
+
+module REXMLTests
+ class TestParseProcessinInstruction < Test::Unit::TestCase
+ def parse(xml)
+ REXML::Document.new(xml)
+ end
+
+ class TestInvalid < self
+ def test_no_name
+ exception = assert_raise(REXML::ParseException) do
+ parse("?>")
+ end
+ assert_equal(<<-DETAIL.chomp, exception.to_s)
+Invalid processing instruction node
+Line: 1
+Position: 4
+Last 80 unconsumed characters:
+?>
+ DETAIL
+ end
+
+ def test_garbage_text
+ # TODO: This should be parse error.
+ # Create test/parse/test_document.rb or something and move this to it.
+ doc = parse(<<-XML)
+x?>
+
+ XML
+ pi = doc.children[1]
+ assert_equal([
+ "x",
+ "y\n
@@ -379,7 +377,7 @@ EOF
end
def test_entities_Holden_Glova
- document = <<-EOL
+ document = <<~EOL
diff --git a/test/rexml/test_core.rb b/test/rexml/test_core.rb
index ee5438d..44e2e7e 100644
--- a/test/rexml/test_core.rb
+++ b/test/rexml/test_core.rb
@@ -1,8 +1,6 @@
-# coding: utf-8
+# -*- coding: utf-8 -*-
# frozen_string_literal: false
-require_relative "rexml_test_utils"
-
require "rexml/document"
require "rexml/parseexception"
require "rexml/output"
@@ -14,10 +12,10 @@ require_relative "listener"
module REXMLTests
class Tester < Test::Unit::TestCase
- include REXMLTestUtils
+ include Helper::Fixture
include REXML
def setup
- @xsa_source = <<-EOL
+ @xsa_source = <<~EOL
+
+
+
+
+ XML
+ end
+ end
+
+ def test_attribute_default_namespace
+ # https://www.w3.org/TR/xml-names/#uniqAttrs
+ document = Document.new(<<-XML)
+
+
+
+
+
+ XML
+ attributes = document.root.elements.collect do |element|
+ element.attributes.each_attribute.collect do |attribute|
+ [attribute.prefix, attribute.namespace, attribute.name]
+ end
+ end
+ assert_equal([
+ [
+ ["", "", "a"],
+ ["", "", "b"],
+ ],
+ [
+ ["", "", "a"],
+ ["n1", "http://www.w3.org", "a"],
+ ],
+ ],
+ attributes)
+ end
+
def test_cdata
test = "The quick brown fox jumped
& < & < \" '
@@ -681,7 +728,7 @@ module REXMLTests
koln_iso_8859_1 = "K\xF6ln"
koln_utf8 = "K\xc3\xb6ln"
source = Source.new( koln_iso_8859_1, 'iso-8859-1' )
- results = source.scan(/.*/)[0]
+ results = source.match(/.*/)[0]
koln_utf8.force_encoding('UTF-8') if koln_utf8.respond_to?(:force_encoding)
assert_equal koln_utf8, results
output << results
@@ -823,7 +870,7 @@ EOL
assert_equal 'two', doc.root.elements[1].namespace
assert_equal 'foo', doc.root.namespace
- doc = Document.new <<-EOL
+ doc = Document.new <<~EOL
@@ -877,18 +924,18 @@ EOL
EOL
# The most common case. People not caring about the namespaces much.
- assert_equal( "XY", XPath.match( doc, "/test/a/text()" ).join )
- assert_equal( "XY", XPath.match( doc, "/test/x:a/text()" ).join )
+ assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()" ).join )
+ assert_equal( "XY", XPath.match( doc, "/*:test/x:a/text()" ).join )
# Surprising? I don't think so, if you believe my definition of the "common case"
- assert_equal( "XYZ", XPath.match( doc, "//a/text()" ).join )
+ assert_equal( "XYZ", XPath.match( doc, "//*:a/text()" ).join )
# These are the uncommon cases. Namespaces are actually important, so we define our own
# mappings, and pass them in.
assert_equal( "XY", XPath.match( doc, "/f:test/f:a/text()", { "f" => "1" } ).join )
# The namespaces are defined, and override the original mappings
- assert_equal( "", XPath.match( doc, "/test/a/text()", { "f" => "1" } ).join )
+ assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()", { "f" => "1" } ).join )
assert_equal( "", XPath.match( doc, "/x:test/x:a/text()", { "f" => "1" } ).join )
- assert_equal( "", XPath.match( doc, "//a/text()", { "f" => "1" } ).join )
+ assert_equal( "XYZ", XPath.match( doc, "//*:a/text()", { "f" => "1" } ).join )
end
def test_processing_instruction
@@ -900,7 +947,7 @@ EOL
end
def test_oses_with_bad_EOLs
- Document.new("\n\n\n\n\n\n\n\n")
+ Document.new("\n\n\n\n\n")
end
# Contributed (with patch to fix bug) by Kouhei
@@ -927,7 +974,7 @@ EOL
end
def test_hyphens_in_doctype
- doc = REXML::Document.new <<-EOQ
+ doc = REXML::Document.new <<~EOQ
@@ -1043,7 +1090,7 @@ EOL
def test_text_raw
# From the REXML tutorial
# (http://www.germane-software.com/software/rexml/test/data/tutorial.html)
- doc = Document.new <<-EOL
+ doc = Document.new <<~EOL
@@ -1277,11 +1324,26 @@ EOL
exception = assert_raise(ParseException) do
Document.new(src)
end
- assert_equal(<<-DETAIL, exception.to_s)
+ assert_equal(<<-DETAIL.chomp, exception.to_s)
Missing attribute value start quote:
Line: 1
Position: 16
Last 80 unconsumed characters:
+value/>
+ DETAIL
+ end
+
+ def test_parse_exception_on_missing_attribute_end_quote
+ src = '
+Line: 1
+Position: 17
+Last 80 unconsumed characters:
+value/>
DETAIL
end
@@ -1377,7 +1439,7 @@ ENDXML
d.root.add_element( "bah" )
p=REXML::Formatters::Pretty.new(2)
p.compact = true # Don't add whitespace to text nodes unless necessary
- p.write(d,out="")
+ p.write(d,out=+"")
assert_equal( expected, out )
end
@@ -1391,8 +1453,8 @@ ENDXML
def test_ticket_102
doc = REXML::Document.new ' '
- assert_equal( "foo", doc.root.elements["item"].attribute("name","ns").to_s )
- assert_equal( "item", doc.root.elements["item[@name='foo']"].name )
+ assert_equal( "foo", doc.root.elements["*:item"].attribute("name","ns").to_s )
+ assert_equal( "item", doc.root.elements["*:item[@name='foo']"].name )
end
def test_ticket_14
@@ -1421,11 +1483,11 @@ ENDXML
doc = REXML::Document.new(
'- text
'
)
- assert_equal 'text', doc.text( "/doc/item[@name='foo']" )
+ assert_equal 'text', doc.text( "/*:doc/*:item[@name='foo']" )
assert_equal "name='foo'",
- doc.root.elements["item"].attribute("name", "ns").inspect
+ doc.root.elements["*:item"].attribute("name", "ns").inspect
assert_equal "- text
",
- doc.root.elements["item[@name='foo']"].to_s
+ doc.root.elements["*:item[@name='foo']"].to_s
end
def test_ticket_135
@@ -1453,8 +1515,10 @@ ENDXML
"" => attribute("version", "1.0"),
},
}
- assert_equal(expected, doc.root.attributes)
- assert_equal(expected, REXML::Document.new(doc.root.to_s).root.attributes)
+ assert_equal(expected,
+ doc.root.attributes.to_h)
+ assert_equal(expected,
+ REXML::Document.new(doc.root.to_s).root.attributes.to_h)
end
def test_empty_doc
diff --git a/test/rexml/test_doctype.rb b/test/rexml/test_doctype.rb
index d728cba..b20d30a 100644
--- a/test/rexml/test_doctype.rb
+++ b/test/rexml/test_doctype.rb
@@ -1,6 +1,4 @@
# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
module REXMLTests
class TestDocTypeAccessor < Test::Unit::TestCase
@@ -41,6 +39,12 @@ module REXMLTests
@doc_type_public_system.to_s)
end
+ def test_to_s_apostrophe
+ @doc_type_public_system.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ @doc_type_public_system.to_s)
+ end
+
def test_system
assert_equal([
@sysid,
@@ -82,6 +86,35 @@ module REXMLTests
assert_equal("",
doctype.to_s)
end
+
+ def test_to_s_apostrophe
+ doctype = REXML::DocType.new(["root", "SYSTEM", nil, "root.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
+
+ def test_to_s_single_quote_apostrophe
+ doctype = REXML::DocType.new(["root", "SYSTEM", nil, "root'.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ # This isn't used.
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
+
+ def test_to_s_double_quote
+ doctype = REXML::DocType.new(["root", "SYSTEM", nil, "root\".dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ # This isn't used.
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
end
end
@@ -92,6 +125,25 @@ module REXMLTests
assert_equal("",
doctype.to_s)
end
+
+ def test_to_s_apostrophe
+ doctype = REXML::DocType.new(["root", "PUBLIC", "pub", "root.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
+
+ def test_to_s_apostrophe_include_apostrophe
+ doctype = REXML::DocType.new(["root", "PUBLIC", "pub'", "root.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ # This isn't used.
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
end
class TestSystemLiteral < self
@@ -101,6 +153,25 @@ module REXMLTests
doctype.to_s)
end
+ def test_to_s_apostrophe
+ doctype = REXML::DocType.new(["root", "PUBLIC", "pub", "root.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
+
+ def test_to_s_apostrophe_include_apostrophe
+ doctype = REXML::DocType.new(["root", "PUBLIC", "pub", "root'.dtd"])
+ doc = REXML::Document.new
+ doc << doctype
+ # This isn't used.
+ doctype.parent.context[:prologue_quote] = :apostrophe
+ assert_equal("",
+ doctype.to_s)
+ end
+
def test_to_s_double_quote
doctype = REXML::DocType.new(["root", "PUBLIC", "pub", "root\".dtd"])
assert_equal("",
@@ -143,6 +214,62 @@ module REXMLTests
decl(@id, "system\"literal").to_s)
end
+ def test_to_s_apostrophe
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
+ def test_to_s_apostrophe_pubid_literal_include_apostrophe
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ # This isn't used for PubidLiteral because PubidChar includes '.
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
+ def test_to_s_apostrophe_system_literal_include_apostrophe
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ # This isn't used for SystemLiteral because SystemLiteral includes '.
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
+ def test_to_s_apostrophe_system_literal_include_double_quote
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ # This isn't used for SystemLiteral because SystemLiteral includes ".
+ # But quoted by ' because SystemLiteral includes ".
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
private
def decl(id, uri)
REXML::NotationDecl.new(@name, "PUBLIC", id, uri)
@@ -170,6 +297,48 @@ module REXMLTests
decl("#{@id}\"").to_s)
end
+ def test_to_s_apostrophe
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
+ def test_to_s_apostrophe_include_apostrophe
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ # This isn't used for SystemLiteral because SystemLiteral includes '.
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
+ def test_to_s_apostrophe_include_double_quote
+ document = REXML::Document.new(<<-XML)
+
+
+ XML
+ # This isn't used for SystemLiteral because SystemLiteral includes ".
+ # But quoted by ' because SystemLiteral includes ".
+ document.context[:prologue_quote] = :apostrophe
+ notation = document.doctype.notations[0]
+ assert_equal("",
+ notation.to_s)
+ end
+
private
def decl(id)
REXML::NotationDecl.new(@name, "SYSTEM", nil, id)
diff --git a/test/rexml/test_document.rb b/test/rexml/test_document.rb
index c0faae4..2b0a8a7 100644
--- a/test/rexml/test_document.rb
+++ b/test/rexml/test_document.rb
@@ -1,13 +1,14 @@
# -*- coding: utf-8 -*-
# frozen_string_literal: false
-require "rexml/document"
-require "test/unit"
+require 'core_assertions'
module REXMLTests
class TestDocument < Test::Unit::TestCase
+ include Test::Unit::CoreAssertions
+
def test_version_attributes_to_s
- doc = REXML::Document.new(<<-eoxml)
+ doc = REXML::Document.new(<<~eoxml)
")
- assert_equal( 1, REXML::XPath.match(doc,
- "//*[local-name()='c' and @id='b']").size )
- assert_equal( 1, REXML::XPath.match(doc,
- "//*[ local-name()='c' and @id='b' ]").size )
- assert_equal( 1, REXML::XPath.match(doc,
- "//*[ local-name() = 'c' and @id = 'b' ]").size )
- assert_equal( 1,
- REXML::XPath.match(doc, '/a/c[@id]').size )
- assert_equal( 1,
- REXML::XPath.match(doc, '/a/c[(@id)]').size )
- assert_equal( 1,
- REXML::XPath.match(doc, '/a/c[ @id ]').size )
- assert_equal( 1,
- REXML::XPath.match(doc, '/a/c[ (@id) ]').size )
- assert_equal( 1,
- REXML::XPath.match(doc, '/a/c[( @id )]').size )
- assert_equal( 1, REXML::XPath.match(doc.root,
- '/a/c[ ( @id ) ]').size )
- assert_equal( 1, REXML::XPath.match(doc,
- '/a/c [ ( @id ) ] ').size )
- assert_equal( 1, REXML::XPath.match(doc,
- ' / a / c [ ( @id ) ] ').size )
+ match = lambda do |xpath|
+ REXML::XPath.match(doc, xpath).collect(&:to_s)
+ end
+ assert_equal([""],
+ match.call("//*[local-name()='c' and @id='b']"))
+ assert_equal([""],
+ match.call("//*[ local-name()='c' and @id='b' ]"))
+ assert_equal([""],
+ match.call("//*[ local-name() = 'c' and @id = 'b' ]"))
+ assert_equal(["", ""],
+ match.call('/a/c[@id]'))
+ assert_equal(["", ""],
+ match.call('/a/c[(@id)]'))
+ assert_equal(["", ""],
+ match.call('/a/c[ @id ]'))
+ assert_equal(["", ""],
+ match.call('/a/c[ (@id) ]'))
+ assert_equal(["", ""],
+ match.call('/a/c[( @id )]'))
+ assert_equal(["", ""],
+ match.call('/a/c[ ( @id ) ]'))
+ assert_equal(["", ""],
+ match.call('/a/c [ ( @id ) ] '))
+ assert_equal(["", ""],
+ match.call(' / a / c [ ( @id ) ] '))
+ assert_equal(["", ""],
+ match.call('/ a / child:: c [( @id )] /'))
end
def test_text_nodes
@@ -692,11 +740,22 @@ module REXMLTests
end
def test_ordering
- source = ""
+ source = <<-XML
+
+
+
+
+
+
+
+
+
+
+ XML
d = REXML::Document.new( source )
r = REXML::XPath.match( d, %q{/a/*/*[1]} )
- assert_equal( 1, r.size )
- r.each { |el| assert_equal( '1', el.attribute('id').value ) }
+ assert_equal(["1", "3"],
+ r.collect {|element| element.attribute("id").value})
end
def test_descendant_or_self_ordering
@@ -830,31 +889,44 @@ module REXMLTests
EOL
d = REXML::Document.new( string )
- c1 = XPath.match( d, '/a/*/*[1]' )
- assert_equal( 1, c1.length )
- assert_equal( 'c1', c1[0].name )
+ cs = XPath.match( d, '/a/*/*[1]' )
+ assert_equal(["c1", "c2"], cs.collect(&:name))
end
def test_sum
- d = Document.new(""+
- "123"+
- "12"+
- ""+
- "")
-
- for v,p in [[6, "sum(/a/b)"],
- [9, "sum(//b | //d)"],
- [3, "sum(/a/e/@*)"] ]
- assert_equal( v, XPath::match( d, p ).first )
- end
+ d = Document.new(<<-XML)
+
+ 1
+ 2
+ 3
+
+ 1
+ 2
+
+
+
+
+ XML
+
+ assert_equal([6], XPath::match(d, "sum(/a/b)"))
+ assert_equal([9], XPath::match(d, "sum(//b | //d)"))
+ assert_equal([3], XPath::match(d, "sum(/a/e/@*)"))
end
def test_xpath_namespace
- d = REXML::Document.new("xa")
- x = d.root
- num = 0
- x.each_element('tada') { num += 1 }
- assert_equal(1, num)
+ d = REXML::Document.new(<<-XML)
+
+
+ xa
+ xb
+
+ XML
+ actual = []
+ d.root.each_element('tada') do |element|
+ actual << element.to_s
+ end
+ assert_equal(["xa", "xb"],
+ actual)
end
def test_ticket_39
@@ -990,7 +1062,7 @@ EOF
"
d = Document.new(data)
res = d.elements.to_a( "//c" ).collect {|e| e.attributes['id'].to_i}
- assert_equal( res, res.sort )
+ assert_equal((1..12).to_a, res)
end
def ticket_61_fixture(doc, xpath)
diff --git a/test/rexml/xpath/test_compare.rb b/test/rexml/xpath/test_compare.rb
new file mode 100644
index 0000000..11d11e5
--- /dev/null
+++ b/test/rexml/xpath/test_compare.rb
@@ -0,0 +1,252 @@
+# frozen_string_literal: false
+
+module REXMLTests
+ class TestXPathCompare < Test::Unit::TestCase
+ def match(xml, xpath)
+ document = REXML::Document.new(xml)
+ REXML::XPath.match(document, xpath)
+ end
+
+ class TestEqual < self
+ class TestNodeSet < self
+ def test_boolean_true
+ xml = <<-XML
+
+
+
+
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child=true()"))
+ end
+
+ def test_boolean_false
+ xml = <<-XML
+
+
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child=true()"))
+ end
+
+ def test_number_true
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child=100"))
+ end
+
+ def test_number_false
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child=300"))
+ end
+
+ def test_string_true
+ xml = <<-XML
+
+
+ text
+ string
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child='string'"))
+ end
+
+ def test_string_false
+ xml = <<-XML
+
+
+ text
+ string
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child='nonexistent'"))
+ end
+ end
+
+ class TestBoolean < self
+ def test_number_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "true()=1"))
+ end
+
+ def test_number_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "true()=0"))
+ end
+
+ def test_string_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "true()='string'"))
+ end
+
+ def test_string_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "true()=''"))
+ end
+ end
+
+ class TestNumber < self
+ def test_string_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "1='1'"))
+ end
+
+ def test_string_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "1='2'"))
+ end
+ end
+ end
+
+ class TestGreaterThan < self
+ class TestNodeSet < self
+ def test_boolean_truex
+ xml = <<-XML
+
+
+
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child>false()"))
+ end
+
+ def test_boolean_false
+ xml = <<-XML
+
+
+
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child>true()"))
+ end
+
+ def test_number_true
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child>199"))
+ end
+
+ def test_number_false
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child>200"))
+ end
+
+ def test_string_true
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([true],
+ match(xml, "/root/child>'199'"))
+ end
+
+ def test_string_false
+ xml = <<-XML
+
+
+ 100
+ 200
+
+ XML
+ assert_equal([false],
+ match(xml, "/root/child>'200'"))
+ end
+ end
+
+ class TestBoolean < self
+ def test_string_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "true()>'0'"))
+ end
+
+ def test_string_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "true()>'1'"))
+ end
+ end
+
+ class TestNumber < self
+ def test_boolean_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "true()>0"))
+ end
+
+ def test_number_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "true()>1"))
+ end
+
+ def test_string_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "1>'0'"))
+ end
+
+ def test_string_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "1>'1'"))
+ end
+ end
+
+ class TestString < self
+ def test_string_true
+ xml = ""
+ assert_equal([true],
+ match(xml, "'1'>'0'"))
+ end
+
+ def test_string_false
+ xml = ""
+ assert_equal([false],
+ match(xml, "'1'>'1'"))
+ end
+ end
+ end
+ end
+end
diff --git a/test/rexml/xpath/test_node.rb b/test/rexml/xpath/test_node.rb
index e0e958e..742bfbb 100644
--- a/test/rexml/xpath/test_node.rb
+++ b/test/rexml/xpath/test_node.rb
@@ -1,10 +1,6 @@
# -*- coding: utf-8 -*-
# frozen_string_literal: false
-require_relative "../rexml_test_utils"
-
-require "rexml/document"
-
module REXMLTests
class TestXPathNode < Test::Unit::TestCase
def matches(xml, xpath)
diff --git a/test/rexml/xpath/test_predicate.rb b/test/rexml/xpath/test_predicate.rb
index ce1aaa3..278e376 100644
--- a/test/rexml/xpath/test_predicate.rb
+++ b/test/rexml/xpath/test_predicate.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: false
-require "test/unit/testcase"
-require "rexml/document"
+
require "rexml/xpath"
require "rexml/parsers/xpathparser"
module REXMLTests
class TestXPathPredicate < Test::Unit::TestCase
include REXML
- SRC=<<-EOL
+ SRC=<<~EOL
free flowing text.
@@ -29,6 +28,15 @@ module REXMLTests
end
+ def test_predicate_only
+ error = assert_raise(REXML::ParseException) do
+ do_path("[article]")
+ end
+ assert_equal("Garbage component exists at the end: " +
+ "<[article]>: <[article]>",
+ error.message)
+ end
+
def test_predicates_parent
path = '//section[../self::section[@role="division"]]'
m = do_path( path )
diff --git a/test/rexml/xpath/test_text.rb b/test/rexml/xpath/test_text.rb
index 7222388..dccc4c8 100644
--- a/test/rexml/xpath/test_text.rb
+++ b/test/rexml/xpath/test_text.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
+
require 'rexml/element'
require 'rexml/xpath'
--
2.27.0