# -*- coding: utf-8 -*- require "helper" module Nokogiri module XML class TestReader < Nokogiri::TestCase def test_from_io_sets_io_as_source io = File.open SNUGGLES_FILE reader = Nokogiri::XML::Reader.from_io(io) assert_equal io, reader.source end def test_empty_element? reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) Paris eoxml results = reader.map do |node| if node.node_type == Nokogiri::XML::Node::ELEMENT_NODE node.empty_element? end end assert_equal [false, false, nil, nil, true, nil], results end def test_self_closing? reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) Paris eoxml results = reader.map do |node| if node.node_type == Nokogiri::XML::Node::ELEMENT_NODE node.self_closing? end end assert_equal [false, false, nil, nil, true, nil], results end # Issue #831 # Make sure that the reader doesn't block reading the entire input def test_reader_blocking rd, wr = IO.pipe() node_out = nil t = Thread.start do reader = Nokogiri::XML::Reader(rd, 'UTF-8') reader.each do |node| node_out = node break end rd.close end sleep(1) # sleep for one second to make sure the reader will actually block for input begin wr.puts "" wr.puts "" * 10000 wr.flush rescue Errno::EPIPE end res = t.join(5) # wait 5 seconds for the thread to finish wr.close refute_nil node_out, "Didn't read any nodes, exclude the trivial case" refute_nil res, "Reader blocks trying to read the entire stream" end def test_reader_takes_block options = nil Nokogiri::XML::Reader(File.read(XML_FILE), XML_FILE) do |cfg| options = cfg options.nonet.nowarning.dtdattr end assert options.nonet? assert options.nowarning? assert options.dtdattr? end def test_nil_raises assert_raises(ArgumentError) { Nokogiri::XML::Reader.from_memory(nil) } assert_raises(ArgumentError) { Nokogiri::XML::Reader.from_io(nil) } end def test_from_io io = File.open SNUGGLES_FILE reader = Nokogiri::XML::Reader.from_io(io) assert_equal false, reader.default? assert_equal [false, false, false, false, false, false, false], reader.map(&:default?) end def test_io io = File.open SNUGGLES_FILE reader = Nokogiri::XML::Reader(io) assert_equal false, reader.default? assert_equal [false, false, false, false, false, false, false], reader.map(&:default?) end def test_string_io io = StringIO.new(<<-eoxml) snuggles! eoxml reader = Nokogiri::XML::Reader(io) assert_equal false, reader.default? assert_equal [false, false, false, false, false, false, false], reader.map(&:default?) end class ReallyBadIO def read(size) 'a' * size ** 10 end end class ReallyBadIO4Java def read(size=1) 'a' * size ** 10 end end def test_io_that_reads_too_much if Nokogiri.jruby? io = ReallyBadIO4Java.new Nokogiri::XML::Reader(io) else io = ReallyBadIO.new Nokogiri::XML::Reader(io) end end def test_in_memory assert Nokogiri::XML::Reader(<<-eoxml) snuggles! eoxml end def test_reader_holds_on_to_string xml = <<-eoxml snuggles! eoxml reader = Nokogiri::XML::Reader(xml) assert_equal xml, reader.source end def test_default? reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal false, reader.default? assert_equal [false, false, false, false, false, false, false], reader.map(&:default?) end def test_value? reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal false, reader.value? assert_equal [false, true, false, true, false, true, false], reader.map(&:value?) end def test_read_error_document reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_raises(Nokogiri::XML::SyntaxError) do reader.each { |node| } end assert 1, reader.errors.length end def test_errors_is_an_array reader = Nokogiri::XML::Reader(StringIO.new('&bogus;')) assert_raises(SyntaxError) { reader.read } assert_equal [SyntaxError], reader.errors.map(&:class) end def test_pushing_to_non_array_raises_TypeError skip "TODO: JRuby ext does not internally call `errors`" if Nokogiri.jruby? reader = Nokogiri::XML::Reader(StringIO.new('&bogus;')) def reader.errors 1 end assert_raises(TypeError) { reader.read } end def test_attributes? reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal false, reader.attributes? assert_equal [true, false, true, false, true, false, true], reader.map(&:attributes?) end def test_attributes reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal({}, reader.attributes) assert_equal [{'xmlns:tenderlove'=>'http://tenderlovemaking.com/', 'xmlns'=>'http://mothership.connection.com/'}, {}, {"awesome"=>"true"}, {}, {"awesome"=>"true"}, {}, {'xmlns:tenderlove'=>'http://tenderlovemaking.com/', 'xmlns'=>'http://mothership.connection.com/'}], reader.map(&:attributes) end def test_attribute_roundtrip reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml reader.each do |node| node.attributes.each do |key, value| assert_equal value, node.attribute(key) end end end def test_attribute_at reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_nil reader.attribute_at(nil) assert_nil reader.attribute_at(0) assert_equal ['http://tenderlovemaking.com/', nil, 'true', nil, 'true', nil, 'http://tenderlovemaking.com/'], reader.map { |x| x.attribute_at(0) } end def test_attribute reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_nil reader.attribute(nil) assert_nil reader.attribute('awesome') assert_equal [nil, nil, 'true', nil, 'true', nil, nil], reader.map { |x| x.attribute('awesome') } end def test_attribute_length reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal 0, reader.attribute_count assert_equal [1, 0, 1, 0, 0, 0, 0], reader.map(&:attribute_count) end def test_depth reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_equal 0, reader.depth assert_equal [0, 1, 1, 2, 1, 1, 0], reader.map(&:depth) end def test_encoding string = <<-eoxml

The quick brown fox jumps over the lazy dog.

日本語が上手です

eoxml reader = Nokogiri::XML::Reader.from_memory(string, nil, 'UTF-8') assert_equal ['UTF-8'], reader.map(&:encoding).uniq end def test_xml_version reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_nil reader.xml_version assert_equal ['1.0'], reader.map(&:xml_version).uniq end def test_lang reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)

The quick brown fox jumps over the lazy dog.

日本語が上手です

eoxml assert_nil reader.lang assert_equal [nil, nil, "en", "en", "en", nil, "ja", "ja", "ja", nil, nil], reader.map(&:lang) end def test_value reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) snuggles! eoxml assert_nil reader.value assert_equal [nil, "\n ", nil, "snuggles!", nil, "\n ", nil], reader.map(&:value) end def test_prefix reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml assert_nil reader.prefix assert_equal [nil, nil, "edi", nil, "edi", nil, nil], reader.map(&:prefix) end def test_node_type reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml assert_equal 0, reader.node_type assert_equal [1, 14, 1, 3, 15, 14, 15], reader.map(&:node_type) end def test_inner_xml str = "hello" reader = Nokogiri::XML::Reader.from_memory(str) reader.read assert_equal "hello", reader.inner_xml end def test_outer_xml str = ["hello", "hello", "hello", "", ""] reader = Nokogiri::XML::Reader.from_memory(str.first) xml = [] reader.map { |node| xml << node.outer_xml } assert_equal str, xml end def test_outer_xml_with_empty_nodes str = ["", "", ""] reader = Nokogiri::XML::Reader.from_memory(str.first) xml = [] reader.map { |node| xml << node.outer_xml } assert_equal str, xml end def test_state reader = Nokogiri::XML::Reader.from_memory('bar
') assert reader.state end def test_ns_uri reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml assert_nil reader.namespace_uri assert_equal([nil, nil, "http://ecommerce.example.org/schema", nil, "http://ecommerce.example.org/schema", nil, nil], reader.map(&:namespace_uri)) end def test_namespaced_attributes reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml attr_ns = [] while reader.read if reader.node_type == Nokogiri::XML::Node::ELEMENT_NODE reader.attribute_nodes.each {|attr| attr_ns << (attr.namespace.nil? ? nil : attr.namespace.prefix) } end end assert_equal(['commons', 'edi', nil], attr_ns) end def test_local_name reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml assert_nil reader.local_name assert_equal(["x", "#text", "foo", "#text", "foo", "#text", "x"], reader.map(&:local_name)) end def test_name reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) hello eoxml assert_nil reader.name assert_equal(["x", "#text", "edi:foo", "#text", "edi:foo", "#text", "x"], reader.map(&:name)) end def test_base_uri reader = Nokogiri::XML::Reader.from_memory(<<-eoxml) eoxml assert_nil reader.base_uri assert_equal(["http://base.example.org/base/", "http://base.example.org/base/", "http://base.example.org/base/", "http://base.example.org/base/", "http://other.example.org/", "http://base.example.org/base/", "http://base.example.org/base/relative", "http://base.example.org/base/relative", "http://base.example.org/base/relative", "http://base.example.org/base/relative", "http://base.example.org/base/relative", "http://base.example.org/base/", "http://base.example.org/base/"], reader.map(&:base_uri)) end def test_xlink_href_without_base_uri reader = Nokogiri::XML::Reader(<<-eoxml) Link Linked Element eoxml reader.each do |node| if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT if node.name == 'link' assert_nil node.base_uri end end end end def test_xlink_href_with_base_uri reader = Nokogiri::XML::Reader(<<-eoxml) Link Linked Element eoxml reader.each do |node| if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT assert_equal node.base_uri, "http://base.example.org/base/" end end end def test_read_from_memory called = false reader = Nokogiri::XML::Reader.from_memory('bar') reader.each do |node| called = true assert node end assert called end def test_large_document_smoke_test # simply run on a large document to verify that there no GC issues xml = [] xml << "" 10000.times { |j| xml << "" } xml << "" xml = xml.join("\n") Nokogiri::XML::Reader.from_memory(xml).each do |e| e.attributes end end def test_correct_outer_xml_inclusion xml = Nokogiri::XML::Reader.from_io(StringIO.new(<<-eoxml)) child-1 child-2 child-3 eoxml nodelengths = [] has_child2 = [] xml.each do |node| if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT and node.name == "child" nodelengths << node.outer_xml.length has_child2 << !!(node.outer_xml =~ /child-2/) end end assert_equal(nodelengths[0], nodelengths[1]) assert(has_child2[1]) assert(!has_child2[0]) end def test_correct_inner_xml_inclusion xml = Nokogiri::XML::Reader.from_io(StringIO.new(<<-eoxml)) child-1 child-2 child-3 eoxml nodelengths = [] has_child2 = [] xml.each do |node| if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT and node.name == "child" nodelengths << node.inner_xml.length has_child2 << !!(node.inner_xml =~ /child-2/) end end assert_equal(nodelengths[0], nodelengths[1]) assert(has_child2[1]) assert(!has_child2[0]) end def test_nonexistent_attribute require 'nokogiri' reader = Nokogiri::XML::Reader("") reader.read # root reader.read # el assert_equal nil, reader.attribute('other') end end end end