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) EOF - assert_raise(REXML::ParseException) do - REXML::Document.new(xml) - end - REXML::Security.entity_expansion_limit = 100 - assert_equal(100, REXML::Security.entity_expansion_limit) + 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 @@ -203,6 +202,49 @@ EOX assert_equal('no', doc.stand_alone?, bug2539) end + def test_gt_linear_performance_attribute_value + seq = [10000, 50000, 100000, 150000, 200000] + assert_linear_performance(seq, rehearsal: 10) do |n| + REXML::Document.new('" * n + '">') + end + end + + def test_each_recursive + xml_source = <<~XML + + + + + + + + + + + + + + cdata + + 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) diff --git a/test/rexml/test_element.rb b/test/rexml/test_element.rb index 82830b4..2021689 100644 --- a/test/rexml/test_element.rb +++ b/test/rexml/test_element.rb @@ -1,8 +1,5 @@ # frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" - module REXMLTests class ElementTester < Test::Unit::TestCase def test_array_reference_string diff --git a/test/rexml/test_elements.rb b/test/rexml/test_elements.rb index a850e62..c0f1b22 100644 --- a/test/rexml/test_elements.rb +++ b/test/rexml/test_elements.rb @@ -1,6 +1,4 @@ # frozen_string_literal: false -require 'test/unit/testcase' -require 'rexml/document' module REXMLTests class ElementsTester < Test::Unit::TestCase @@ -115,5 +113,10 @@ module REXMLTests } assert_equal 6, r end + + def test_parent + doc = Document.new( "" ) + assert_equal('a', doc.root.elements.parent.name) + end end end diff --git a/test/rexml/test_encoding.rb b/test/rexml/test_encoding.rb index 919db13..6887ffb 100644 --- a/test/rexml/test_encoding.rb +++ b/test/rexml/test_encoding.rb @@ -1,14 +1,13 @@ -# coding: binary +# coding: utf-8 # frozen_string_literal: false -require_relative "rexml_test_utils" - require 'rexml/source' require 'rexml/document' module REXMLTests class EncodingTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture + include Helper::Global include REXML def setup @@ -23,7 +22,7 @@ module REXMLTests doc = Document.new( @encoded ) doc.write( out="" ) out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @encoded, out ) + assert_equal( @encoded.b, out ) end # Given an encoded document, try to change the encoding and write it out @@ -33,10 +32,10 @@ module REXMLTests assert_equal("UTF-8", doc.encoding) REXML::Formatters::Default.new.write( doc.root, out="" ) out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @not_encoded, out ) + assert_equal( @not_encoded.b, out ) char = XPath.first( doc, "/a/b/text()" ).to_s char.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( "ĉ", char ) + assert_equal( "ĉ".b, char ) end # * Given an encoded document, try to write it to a different encoding @@ -44,7 +43,7 @@ module REXMLTests doc = Document.new( @encoded ) REXML::Formatters::Default.new.write( doc.root, Output.new( out="", "UTF-8" ) ) out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @not_encoded, out ) + assert_equal( @not_encoded.b, out ) end # * Given a non-encoded document, change the encoding @@ -54,7 +53,7 @@ module REXMLTests assert_equal("ISO-8859-3", doc.encoding) doc.write( out="" ) out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( @encoded, out ) + assert_equal( @encoded.b, out ) end # * Given a non-encoded document, write to a different encoding @@ -62,13 +61,13 @@ module REXMLTests doc = Document.new( @not_encoded ) doc.write( Output.new( out="", "ISO-8859-3" ) ) out.force_encoding(::Encoding::ASCII_8BIT) - assert_equal( "#{@encoded_root}", out ) + assert_equal( "#{@encoded_root}".b, out ) end # * 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 @@ -80,7 +79,7 @@ module REXMLTests def test_ticket_89 - doc = Document.new <<-EOL + doc = Document.new <<~EOL EOL @@ -97,7 +96,7 @@ module REXMLTests end def test_parse_utf16_with_utf8_default_internal - EnvUtil.with_default_internal("UTF-8") do + with_default_internal("UTF-8") do utf16 = File.open(fixture_path("utf16.xml")) do |f| REXML::Document.new(f) end diff --git a/test/rexml/test_entity.rb b/test/rexml/test_entity.rb index 6dc6637..a2b262f 100644 --- a/test/rexml/test_entity.rb +++ b/test/rexml/test_entity.rb @@ -1,7 +1,5 @@ # frozen_string_literal: false -require "test/unit/testcase" -require 'rexml/document' require 'rexml/entity' require 'rexml/source' diff --git a/test/rexml/test_functions_number.rb b/test/rexml/test_functions_number.rb deleted file mode 100644 index 84ec5c7..0000000 --- a/test/rexml/test_functions_number.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: false -require 'rexml/document' -require 'test/unit' -require 'rexml/functions' - -module REXMLTests - class TC_Rexml_Functions_Number < Test::Unit::TestCase - - def test_functions_number_int - telem = REXML::Element.new("elem") - telem.text="9" - assert_equal(9, REXML::Functions::number(telem)) - end - def test_functions_number_float - telem = REXML::Element.new("elem") - telem.text="10.4" - assert_equal(10.4, REXML::Functions::number(telem)) - end - def test_functions_number_negative_int - telem = REXML::Element.new("elem") - telem.text="-9" - assert_equal(-9, REXML::Functions::number(telem)) - end - def test_functions_number_negative_float - telem = REXML::Element.new("elem") - telem.text="-9.13" - assert_equal(-9.13, REXML::Functions::number(telem)) - end - #def test_functions_number_scientific_notation - # telem = REXML::Element.new("elem") - # telem.text="9.13E12" - # assert_equal(9.13E12, REXML::Functions::number(telem)) - #end - end -end diff --git a/test/rexml/test_instruction.rb b/test/rexml/test_instruction.rb new file mode 100644 index 0000000..5451e36 --- /dev/null +++ b/test/rexml/test_instruction.rb @@ -0,0 +1,12 @@ +module REXMLTests + class InstructionTest < Test::Unit::TestCase + def test_target_nil + error = assert_raise(ArgumentError) do + REXML::Instruction.new(nil) + end + assert_equal("processing instruction target must be String or " + + "REXML::Instruction: ", + error.message) + end + end +end diff --git a/test/rexml/test_jaxen.rb b/test/rexml/test_jaxen.rb index 9cd7bee..6038e88 100644 --- a/test/rexml/test_jaxen.rb +++ b/test/rexml/test_jaxen.rb @@ -1,5 +1,4 @@ # frozen_string_literal: false -require_relative 'rexml_test_utils' require "rexml/document" require "rexml/xpath" @@ -9,122 +8,123 @@ require "rexml/xpath" module REXMLTests class JaxenTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML - def test_axis ; test("axis") ; end - def test_basic ; test("basic") ; end - def test_basicupdate ; test("basicupdate") ; end - def test_contents ; test("contents") ; end - def test_defaultNamespace ; test("defaultNamespace") ; end - def test_fibo ; test("fibo") ; end - def test_id ; test("id") ; end - def test_jaxen24 ; test("jaxen24") ; end - def test_lang ; test("lang") ; end - def test_message ; test("message") ; end - def test_moreover ; test("moreover") ; end - def test_much_ado ; test("much_ado") ; end - def test_namespaces ; test("namespaces") ; end - def test_nitf ; test("nitf") ; end - def test_numbers ; test("numbers") ; end - def test_pi ; test("pi") ; end - def test_pi2 ; test("pi2") ; end - def test_simple ; test("simple") ; end - def test_testNamespaces ; test("testNamespaces") ; end - def test_text ; test("text") ; end - def test_underscore ; test("underscore") ; end - def test_web ; test("web") ; end - def test_web2 ; test("web2") ; end + def test_axis ; process_test_case("axis") ; end + def test_basic ; process_test_case("basic") ; end + def test_basicupdate ; process_test_case("basicupdate") ; end + def test_contents ; process_test_case("contents") ; end + def test_defaultNamespace ; process_test_case("defaultNamespace") ; end + def test_fibo ; process_test_case("fibo") ; end + def test_id ; process_test_case("id") ; end + def test_jaxen24 ; process_test_case("jaxen24") ; end + def test_lang ; process_test_case("lang") ; end + # document() function for XSLT isn't supported + def _test_message ; process_test_case("message") ; end + def test_moreover ; process_test_case("moreover") ; end + def test_much_ado ; process_test_case("much_ado") ; end + def test_namespaces ; process_test_case("namespaces") ; end + def test_nitf ; process_test_case("nitf") ; end + # Exception should be considered + def _test_numbers ; process_test_case("numbers") ; end + def test_pi ; process_test_case("pi") ; end + def test_pi2 ; process_test_case("pi2") ; end + def test_simple ; process_test_case("simple") ; end + # TODO: namespace node is needed + def _test_testNamespaces ; process_test_case("testNamespaces") ; end + # document() function for XSLT isn't supported + def _test_text ; process_test_case("text") ; end + def test_underscore ; process_test_case("underscore") ; end + def _test_web ; process_test_case("web") ; end + def test_web2 ; process_test_case("web2") ; end private - def test( fname ) -# Dir.entries( xml_dir ).each { |fname| -# if fname =~ /\.xml$/ - doc = File.open(fixture_path(fname+".xml")) do |file| - Document.new(file) - end - XPath.each( doc, "/tests/document" ) {|e| handleDocument(e)} -# end -# } + def process_test_case(name) + xml_path = "#{name}.xml" + doc = File.open(fixture_path(xml_path)) do |file| + Document.new(file) + end + test_doc = File.open(fixture_path("test/tests.xml")) do |file| + Document.new(file) + end + XPath.each(test_doc, + "/tests/document[@url='xml/#{xml_path}']/context") do |context| + process_context(doc, context) + end end # processes a tests/document/context node - def handleContext( testDoc, ctxElement) - testCtx = XPath.match( testDoc, ctxElement.attributes["select"] )[0] - namespaces = {} - if testCtx.class == Element - testCtx.prefixes.each { |pre| handleNamespace( testCtx, pre, namespaces ) } - end + def process_context(doc, context) + test_context = XPath.match(doc, context.attributes["select"]) + namespaces = context.namespaces + namespaces.delete("var") + namespaces = nil if namespaces.empty? variables = {} - XPath.each( ctxElement, "@*[namespace-uri() = 'http://jaxen.org/test-harness/var']") { |attrib| handleVariable(testCtx, variables, attrib) } - XPath.each( ctxElement, "valueOf") { |e| handleValueOf(testCtx, variables, namespaces, e) } - XPath.each( ctxElement, "test[not(@exception) or (@exception != 'true') ]") { |e| handleNominalTest(testCtx,variables, namespaces, e) } - XPath.each( ctxElement, "test[@exception = 'true']") { |e| handleExceptionalTest(testCtx,variables, namespaces, e) } + var_namespace = "http://jaxen.org/test-harness/var" + XPath.each(context, + "@*[namespace-uri() = '#{var_namespace}']") do |attribute| + variables[attribute.name] = attribute.value + end + XPath.each(context, "valueOf") do |value| + process_value_of(test_context, variables, namespaces, value) + end + XPath.each(context, + "test[not(@exception) or (@exception != 'true')]") do |test| + process_nominal_test(test_context, variables, namespaces, test) + end + XPath.each(context, + "test[@exception = 'true']") do |test| + process_exceptional_test(test_context, variables, namespaces, test) + end end # processes a tests/document/context/valueOf or tests/document/context/test/valueOf node - def handleValueOf(ctx,variables, namespaces, valueOfElement) - expected = valueOfElement.text - got = XPath.match( ctx, valueOfElement.attributes["select"], namespaces, variables )[0] - assert_true( (got.nil? && expected.nil?) || !got.nil? ) - case got.class - when Element - assert_equal( got.class, Element ) - when Attribute, Text, Comment, TrueClass, FalseClass - assert_equal( expected, got.to_s ) - when Instruction - assert_equal( expected, got.content ) - when Integer - assert_equal( exected.to_f, got ) - when String - # normalize values for comparison - got = "" if got == nil or got == "" - expected = "" if expected == nil or expected == "" - assert_equal( expected, got ) - else - assert_fail( "Wassup?" ) - end - end + def process_value_of(context, variables, namespaces, value_of) + expected = value_of.text + xpath = value_of.attributes["select"] + matched = XPath.match(context, xpath, namespaces, variables, strict: true) + message = user_message(context, xpath, matched) + assert_equal(expected || "", + REXML::Functions.string(matched), + message) + end # processes a tests/document/context/test node ( where @exception is false or doesn't exist ) - def handleNominalTest(ctx, variables, namespaces, testElement) - expected = testElement.attributes["count"] - got = XPath.match( ctx, testElement.attributes["select"], namespaces, variables ) + def process_nominal_test(context, variables, namespaces, test) + xpath = test.attributes["select"] + matched = XPath.match(context, xpath, namespaces, variables, strict: true) # might be a test with no count attribute, but nested valueOf elements - assert( expected == got.size.to_s ) if !expected.nil? + expected = test.attributes["count"] + if expected + assert_equal(Integer(expected, 10), + matched.size, + user_message(context, xpath, matched)) + end - XPath.each( testElement, "valueOf") { |e| - handleValueOf(got, variables, namespaces, e) - } + XPath.each(test, "valueOf") do |value_of| + process_value_of(matched, variables, namespaces, value_of) + end end # processes a tests/document/context/test node ( where @exception is true ) - def handleExceptionalTest(ctx, variables, namespaces, testElement) - assert_raise( Exception ) { - XPath.match( ctx, testElement.attributes["select"], namespaces, variables ) - } - end - - # processes a tests/document node - def handleDocument(docElement) - puts "- Processing document: #{docElement.attributes['url']}" - testFile = File.new( docElement.attributes["url"] ) - testDoc = Document.new testFile - XPath.each( docElement, "context") { |e| handleContext(testDoc, e) } - end - - # processes a variable definition in a namespace like - def handleVariable( ctx, variables, attrib ) - puts "--- Found attribute: #{attrib.name}" - variables[attrib.name] = attrib.value + def process_exceptional_test(context, variables, namespaces, test) + xpath = test.attributes["select"] + assert_raise(REXML::ParseException) do + XPath.match(context, xpath, namespaces, variables, strict: true) + end end - # processes a namespace definition like - def handleNamespace( ctx, prefix, namespaces ) - puts "--- Found namespace: #{prefix}" - namespaces[prefix] = ctx.namespaces[prefix] + def user_message(context, xpath, matched) + message = "" + context.each_with_index do |node, i| + message << "Node#{i}:\n" + message << "#{node}\n" + end + message << "XPath: <#{xpath}>\n" + message << "Matched <#{matched}>" + message end - end end diff --git a/test/rexml/test_light.rb b/test/rexml/test_light.rb index 99bd9ca..c556c97 100644 --- a/test/rexml/test_light.rb +++ b/test/rexml/test_light.rb @@ -1,18 +1,18 @@ # frozen_string_literal: false -require_relative "rexml_test_utils" + require "rexml/light/node" require "rexml/parsers/lightparser" module REXMLTests class LightTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML::Light def test_parse_large - xml_string = fixture_path("documentation.xml") + xml_string = File.read(fixture_path("documentation.xml")) parser = REXML::Parsers::LightParser.new(xml_string) tag, content = parser.parse - assert_equal([:document, :text], [tag, content.first]) + assert_equal([:document, :xmldecl], [tag, content.first]) end # FIXME INCOMPLETE @@ -62,7 +62,7 @@ module REXMLTests 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/rexml/test_lightparser.rb b/test/rexml/test_lightparser.rb index 1aeac07..533f9fb 100644 --- a/test/rexml/test_lightparser.rb +++ b/test/rexml/test_lightparser.rb @@ -1,10 +1,10 @@ # frozen_string_literal: false -require_relative 'rexml_test_utils' + require 'rexml/parsers/lightparser' module REXMLTests class LightParserTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML def test_parsing File.open(fixture_path("documentation.xml")) do |f| diff --git a/test/rexml/test_listener.rb b/test/rexml/test_listener.rb index 322d368..5e40d7f 100644 --- a/test/rexml/test_listener.rb +++ b/test/rexml/test_listener.rb @@ -1,14 +1,11 @@ # coding: binary # frozen_string_literal: false -require_relative 'rexml_test_utils' - -require 'rexml/document' require 'rexml/streamlistener' module REXMLTests class BaseTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture def test_empty return unless defined? @listener # Empty. diff --git a/test/rexml/test_martin_fowler.rb b/test/rexml/test_martin_fowler.rb index da685a8..ce27d72 100644 --- a/test/rexml/test_martin_fowler.rb +++ b/test/rexml/test_martin_fowler.rb @@ -1,9 +1,7 @@ # frozen_string_literal: false -require 'test/unit' -require 'rexml/document' module REXMLTests - class OrderTester < Test::Unit::TestCase + class OrderTesterMF < Test::Unit::TestCase DOC = < Remove this element and figs order differently @@ -18,12 +16,12 @@ module REXMLTests END - def initialize n + def setup @doc = REXML::Document.new(DOC) @figs = REXML::XPath.match(@doc,'//figure') @names = @figs.collect {|f| f.attributes['src']} - super end + def test_fig1 assert_equal 'fig1', @figs[0].attributes['src'] end diff --git a/test/rexml/test_namespace.rb b/test/rexml/test_namespace.rb index 90e1d36..a41e505 100644 --- a/test/rexml/test_namespace.rb +++ b/test/rexml/test_namespace.rb @@ -1,11 +1,8 @@ # frozen_string_literal: false -require_relative "rexml_test_utils" - -require "rexml/document" module REXMLTests class TestNamespace < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML def setup diff --git a/test/rexml/test_order.rb b/test/rexml/test_order.rb index 807d9fa..f3f9cc5 100644 --- a/test/rexml/test_order.rb +++ b/test/rexml/test_order.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false -require_relative 'rexml_test_utils' -require 'rexml/document' + begin require 'zlib' rescue LoadError @@ -8,7 +7,7 @@ end module REXMLTests class OrderTester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture TESTDOC = < diff --git a/test/rexml/test_preceding_sibling.rb b/test/rexml/test_preceding_sibling.rb index d89a1e1..7e661eb 100644 --- a/test/rexml/test_preceding_sibling.rb +++ b/test/rexml/test_preceding_sibling.rb @@ -1,7 +1,5 @@ # frozen_string_literal: false # ISSUE 32 -require 'test/unit' -require 'rexml/document' module REXMLTests # daz - for report by Dan Kohn in: diff --git a/test/rexml/test_pullparser.rb b/test/rexml/test_pullparser.rb index 31b5b74..b6a48c9 100644 --- a/test/rexml/test_pullparser.rb +++ b/test/rexml/test_pullparser.rb @@ -1,5 +1,4 @@ # frozen_string_literal: false -require "test/unit/testcase" require 'rexml/parsers/pullparser' @@ -63,6 +62,26 @@ module REXMLTests end end + def test_character_references + source = 'AB' + parser = REXML::Parsers::PullParser.new( source ) + element_name = '' + while parser.has_next? + event = parser.pull + case event.event_type + when :start_element + element_name = event[0] + when :text + case element_name + when 'a' + assert_equal('A', event[1]) + when 'b' + assert_equal('B', event[1]) + end + end + end + end + def test_peek_unshift source = "" REXML::Parsers::PullParser.new(source) diff --git a/test/rexml/test_rexml_issuezilla.rb b/test/rexml/test_rexml_issuezilla.rb index 1c54c9d..7bcbefc 100644 --- a/test/rexml/test_rexml_issuezilla.rb +++ b/test/rexml/test_rexml_issuezilla.rb @@ -1,10 +1,8 @@ # frozen_string_literal: false -require_relative 'rexml_test_utils' -require 'rexml/document' module REXMLTests class TestIssuezillaParsing < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture def test_rexml doc = File.open(fixture_path("ofbiz-issues-full-177.xml")) do |f| REXML::Document.new(f) diff --git a/test/rexml/test_sax.rb b/test/rexml/test_sax.rb index 00539f0..8e905f2 100644 --- a/test/rexml/test_sax.rb +++ b/test/rexml/test_sax.rb @@ -1,12 +1,11 @@ # frozen_string_literal: false -require_relative "rexml_test_utils" + require 'rexml/sax2listener' require 'rexml/parsers/sax2parser' -require 'rexml/document' module REXMLTests class SAX2Tester < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML def test_characters d = Document.new( "@blah@" ) @@ -110,7 +109,7 @@ module REXMLTests # test simple non-entity doctype in sax listener # submitted by Jeff Barczewski def test_simple_doctype_listener - xml = <<-END + xml = <<~END Hello, world! @@ -141,8 +140,8 @@ module REXMLTests # 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/rexml/test_stream.rb b/test/rexml/test_stream.rb index d7ceedc..545d534 100644 --- a/test/rexml/test_stream.rb +++ b/test/rexml/test_stream.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" + require 'rexml/streamlistener' require 'stringio' @@ -15,8 +14,8 @@ module REXMLTests def test_listener data = %Q{\n} - b = RequestReader.new( data ) - b = RequestReader.new( data ) + RequestReader.new( data ) + RequestReader.new( data ) end def test_ticket_49 diff --git a/test/rexml/test_text.rb b/test/rexml/test_text.rb index 3f8036e..bae2165 100644 --- a/test/rexml/test_text.rb +++ b/test/rexml/test_text.rb @@ -1,10 +1,55 @@ # frozen_string_literal: false -require "rexml/text" module REXMLTests class TextTester < Test::Unit::TestCase include REXML + def test_new_text_response_whitespace_default + text = Text.new("a b\t\tc", true) + assert_equal("a b\tc", Text.new(text).to_s) + end + + def test_new_text_response_whitespace_true + text = Text.new("a b\t\tc", true) + assert_equal("a b\t\tc", Text.new(text, true).to_s) + end + + def test_new_text_raw_default + text = Text.new("&lt;", false, nil, true) + assert_equal("&lt;", Text.new(text).to_s) + end + + def test_new_text_raw_false + text = Text.new("&lt;", false, nil, true) + assert_equal("&amp;lt;", Text.new(text, false, nil, false).to_s) + end + + def test_new_text_entity_filter_default + document = REXML::Document.new(<<-XML) + + +]> + + XML + text = Text.new("aaa bbb", false, document.root, nil, ["a"]) + assert_equal("aaa &b;", + Text.new(text, false, document.root).to_s) + end + + def test_new_text_entity_filter_custom + document = REXML::Document.new(<<-XML) + + +]> + + XML + text = Text.new("aaa bbb", false, document.root, nil, ["a"]) + assert_equal("&a; bbb", + Text.new(text, false, document.root, nil, ["b"]).to_s) + end + def test_shift_operator_chain text = Text.new("original\r\n") text << "append1\r\n" << "append2\r\n" @@ -18,5 +63,11 @@ module REXMLTests text << "append3\r\n" << "append4\r\n" assert_equal("original\nappend1\nappend2\nappend3\nappend4\n", text.to_s) end + + def test_clone + text = Text.new("&lt; <") + assert_equal(text.to_s, + text.clone.to_s) + end end end diff --git a/test/rexml/test_ticket_80.rb b/test/rexml/test_ticket_80.rb index ab6a57e..daebdc5 100644 --- a/test/rexml/test_ticket_80.rb +++ b/test/rexml/test_ticket_80.rb @@ -7,9 +7,6 @@ # copy: (C) CopyLoose 2006 Bib Development Team atdot #------------------------------------------------------------------------------ -require 'test/unit' -require 'rexml/document' - module REXMLTests class Ticket80 < Test::Unit::TestCase diff --git a/test/rexml/test_validation_rng.rb b/test/rexml/test_validation_rng.rb index b5b5045..4872396 100644 --- a/test/rexml/test_validation_rng.rb +++ b/test/rexml/test_validation_rng.rb @@ -1,7 +1,5 @@ # frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" require "rexml/validation/relaxng" module REXMLTests @@ -9,7 +7,7 @@ module REXMLTests include REXML def test_validate - rng = %q{ + rng = <<-XML @@ -26,7 +24,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) @@ -35,7 +33,7 @@ module REXMLTests def test_sequence - rng = %q{ + rng = <<-XML @@ -47,7 +45,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -58,7 +56,7 @@ module REXMLTests def test_choice - rng = %q{ + rng = <<-XML @@ -72,7 +70,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -81,7 +79,7 @@ module REXMLTests end def test_optional - rng = %q{ + rng = <<-XML @@ -92,7 +90,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) @@ -102,7 +100,7 @@ module REXMLTests end def test_zero_or_more - rng = %q{ + rng = <<-XML @@ -113,7 +111,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) no_error( validator, %q{} ) @@ -121,7 +119,7 @@ module REXMLTests error( validator, %q{} ) error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -135,7 +133,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) @@ -145,7 +143,7 @@ module REXMLTests end def test_one_or_more - rng = %q{ + rng = <<-XML @@ -156,7 +154,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -167,13 +165,13 @@ module REXMLTests end def test_attribute - rng = %q{ + rng = <<-XML - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -183,7 +181,7 @@ module REXMLTests end def test_choice_attributes - rng = %q{ + rng = <<-XML @@ -191,7 +189,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -201,7 +199,7 @@ module REXMLTests end def test_choice_attribute_element - rng = %q{ + rng = <<-XML @@ -209,7 +207,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -219,12 +217,12 @@ module REXMLTests end def test_empty - rng = %q{ + rng = <<-XML - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -233,12 +231,12 @@ module REXMLTests end def test_text_val - rng = %q{ + rng = <<-XML - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -247,7 +245,7 @@ module REXMLTests end def test_choice_text - rng = %q{ + rng = <<-XML @@ -255,7 +253,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{Text} ) @@ -265,7 +263,7 @@ module REXMLTests end def test_group - rng = %q{ + rng = <<-XML @@ -276,7 +274,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -284,7 +282,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -293,7 +291,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -304,14 +302,14 @@ module REXMLTests def test_value # Values as text nodes - rng = %q{ + rng = <<-XML VaLuE - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{X} ) @@ -319,7 +317,7 @@ module REXMLTests no_error( validator, %q{VaLuE} ) # Values as text nodes, via choice - rng = %q{ + rng = <<-XML @@ -329,7 +327,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -338,14 +336,14 @@ module REXMLTests no_error( validator, %q{Option 2} ) # Attribute values - rng = %q{ + rng = <<-XML VaLuE - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -354,7 +352,7 @@ module REXMLTests no_error( validator, %q{} ) # Attribute values via choice - rng = %q{ + rng = <<-XML @@ -364,7 +362,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -374,7 +372,7 @@ module REXMLTests end def test_interleave - rng = %q{ + rng = <<-XML @@ -385,7 +383,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -398,7 +396,7 @@ module REXMLTests end def test_mixed - rng = %q{ + rng = <<-XML @@ -407,7 +405,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{Text} ) @@ -415,7 +413,7 @@ module REXMLTests end def test_ref_sequence - rng = %q{ + rng = <<-XML @@ -431,7 +429,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) @@ -439,7 +437,7 @@ module REXMLTests end def test_ref_choice - rng = %q{ + rng = <<-XML @@ -455,7 +453,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -463,7 +461,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -479,7 +477,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -487,7 +485,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -504,7 +502,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -515,7 +513,7 @@ module REXMLTests def test_ref_zero_plus - rng = %q{ + rng = <<-XML @@ -532,7 +530,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -540,7 +538,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -557,7 +555,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -568,7 +566,7 @@ module REXMLTests def test_ref_one_plus - rng = %q{ + rng = <<-XML @@ -585,7 +583,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -593,7 +591,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -610,7 +608,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -620,7 +618,7 @@ module REXMLTests end def test_ref_interleave - rng = %q{ + rng = <<-XML @@ -636,7 +634,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -645,7 +643,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -661,7 +659,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -670,7 +668,7 @@ module REXMLTests no_error( validator, %q{} ) no_error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -689,7 +687,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -700,7 +698,7 @@ module REXMLTests end def test_ref_recurse - rng = %q{ + rng = <<-XML @@ -717,7 +715,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) error( validator, %q{} ) @@ -726,7 +724,7 @@ module REXMLTests end def test_ref_optional - rng = %q{ + rng = <<-XML @@ -742,7 +740,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) @@ -750,7 +748,7 @@ module REXMLTests error( validator, %q{} ) error( validator, %q{} ) - rng = %q{ + rng = <<-XML @@ -766,7 +764,7 @@ module REXMLTests - } + XML validator = REXML::Validation::RelaxNG.new( rng ) no_error( validator, %q{} ) diff --git a/test/rexml/test_xml_declaration.rb b/test/rexml/test_xml_declaration.rb index a4d97c4..6a1f4df 100644 --- a/test/rexml/test_xml_declaration.rb +++ b/test/rexml/test_xml_declaration.rb @@ -1,20 +1,16 @@ -# -*- coding: utf-8 -*- # frozen_string_literal: false # # Created by Henrik Mårtensson on 2007-02-18. # Copyright (c) 2007. All rights reserved. -require "rexml/document" -require "test/unit" - module REXMLTests class TestXmlDeclaration < Test::Unit::TestCase def setup - xml = <<-'END_XML' + xml = <<~XML - END_XML + XML @doc = REXML::Document.new xml @root = @doc.root @xml_declaration = @doc.children[0] @@ -32,5 +28,18 @@ module REXMLTests assert_kind_of(REXML::XMLDecl, @root.previous_sibling.previous_sibling) assert_kind_of(REXML::Element, @xml_declaration.next_sibling.next_sibling) end + + def test_write_prologue_quote + @doc.context[:prologue_quote] = :quote + assert_equal("", + @xml_declaration.to_s) + end + + def test_is_writethis_attribute_copied_by_clone + assert_equal(true, @xml_declaration.clone.writethis) + @xml_declaration.nowrite + assert_equal(false, @xml_declaration.clone.writethis) + end end end diff --git a/test/rexml/xpath/test_attribute.rb b/test/rexml/xpath/test_attribute.rb index 9304db4..b778ff8 100644 --- a/test/rexml/xpath/test_attribute.rb +++ b/test/rexml/xpath/test_attribute.rb @@ -1,13 +1,11 @@ # frozen_string_literal: false -require 'test/unit' -require 'rexml/document' module REXMLTests class TestXPathAttribute < Test::Unit::TestCase def setup @xml = <<-XML - + child1 child2 child3 @@ -26,5 +24,13 @@ module REXMLTests children = REXML::XPath.each(@document, "/root/child[@name='two']") assert_equal(["child2"], children.collect(&:text)) end + + def test_no_namespace + children = REXML::XPath.match(@document, + "/root/child[@nothing:name='two']", + "" => "http://example.com/", + "nothing" => "") + assert_equal(["child2"], children.collect(&:text)) + end end end diff --git a/test/rexml/xpath/test_axis_preceding_sibling.rb b/test/rexml/xpath/test_axis_preceding_sibling.rb index 5842c6b..9c44ad6 100644 --- a/test/rexml/xpath/test_axis_preceding_sibling.rb +++ b/test/rexml/xpath/test_axis_preceding_sibling.rb @@ -1,6 +1,4 @@ # frozen_string_literal: false -require "test/unit/testcase" -require "rexml/document" module REXMLTests class TestXPathAxisPredcedingSibling < Test::Unit::TestCase diff --git a/test/rexml/xpath/test_axis_self.rb b/test/rexml/xpath/test_axis_self.rb new file mode 100644 index 0000000..4e422f5 --- /dev/null +++ b/test/rexml/xpath/test_axis_self.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: false + +module REXMLTests + class TestXPathAxisSelf < Test::Unit::TestCase + def test_only + doc = REXML::Document.new("") + assert_equal([doc.root], + REXML::XPath.match(doc.root, ".")) + end + + def test_have_predicate + doc = REXML::Document.new("") + error = assert_raise(REXML::ParseException) do + REXML::XPath.match(doc.root, ".[child]") + end + assert_equal("Garbage component exists at the end: <[child]>: <.[child]>", + error.message) + end + end +end diff --git a/test/rexml/xpath/test_base.rb b/test/rexml/xpath/test_base.rb index 5079fdd..1dacd69 100644 --- a/test/rexml/xpath/test_base.rb +++ b/test/rexml/xpath/test_base.rb @@ -1,11 +1,8 @@ # frozen_string_literal: false -require_relative "../rexml_test_utils" - -require "rexml/document" module REXMLTests class TestXPathBase < Test::Unit::TestCase - include REXMLTestUtils + include Helper::Fixture include REXML SOURCE = <<-EOF @@ -369,11 +366,15 @@ module REXMLTests assert_equal 2, c end + def match(xpath) + XPath.match(@@doc, xpath).collect(&:to_s) + end + def test_grouping - t = XPath.first( @@doc, "a/d/*[name()='d' and (name()='f' or name()='q')]" ) - assert_nil t - t = XPath.first( @@doc, "a/d/*[(name()='d' and name()='f') or name()='q']" ) - assert_equal 'q', t.name + assert_equal([], + match("a/d/*[name()='d' and (name()='f' or name()='q')]")) + assert_equal([""], + match("a/d/*[(name()='d' and name()='f') or name()='q']")) end def test_preceding @@ -450,6 +451,46 @@ module REXMLTests # 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 @@ -610,7 +651,7 @@ module REXMLTests 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 @@ -632,29 +673,36 @@ module REXMLTests + + ") - 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