summaryrefslogtreecommitdiff
path: root/test/rexml/test_jaxen.rb
blob: 703b2793d04dfffb49eac3e1d3f55dff4ce1a016 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# frozen_string_literal: false
require_relative 'rexml_test_utils'

require "rexml/document"
require "rexml/xpath"

# Harness to test REXML's capabilities against the test suite from Jaxen
# ryan.a.cox@gmail.com

module REXMLTests
  class JaxenTester < Test::Unit::TestCase
    include REXMLTestUtils
    include REXML

    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
    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
    def _test_testNamespaces ; process_test_case("testNamespaces") ; end
    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 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 process_context(doc, context)
      test_context = XPath.match(doc, context.attributes["select"])
      namespaces = context.namespaces
      variables = {}
      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 process_value_of(context, variables, namespaces, value_of)
      expected = value_of.text
      xpath = value_of.attributes["select"]
      matched = XPath.first(context, xpath, namespaces, variables)

      message = user_message(context, xpath, matched)

      if expected.nil?
        assert_nil(matched, message)
      else
        case matched
        when Element
          assert_equal(expected, matched.text, message)
        when Attribute, Text, Comment, TrueClass, FalseClass
          assert_equal(expected, matched.to_s, message)
        when Instruction
          assert_equal(expected, matched.content, message)
        when Integer, Float
          assert_equal(expected.to_f, matched, message)
        when String
          assert_equal(expected, matched, message)
        else
          flunk("#{message}\n" +
                "Unexpected match value: <#{matched.inspect}>")
        end
      end
    end

    # processes a tests/document/context/test node ( where @exception is false or doesn't exist )
    def process_nominal_test(context, variables, namespaces, test)
      xpath = test.attributes["select"]
      matched = XPath.match(context, xpath, namespaces, variables)
      # might be a test with no count attribute, but nested valueOf elements
      expected = test.attributes["count"]
      if expected
        assert_equal(Integer(expected, 10),
                     matched.size,
                     user_message(context, xpath, matched))
      end

      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 process_exceptional_test(context, variables, namespaces, test)
      select = test.attributes["select"]
      assert_raise do
        XPath.match(context, select, namespaces, variables)
      end
    end

    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