xml_mini 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ module XmlMini
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,202 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'libxml'
7
+ rescue LoadError
8
+ # Skip libxml tests
9
+ else
10
+
11
+ class LibxmlEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'LibXML'
16
+
17
+ LibXML::XML::Error.set_handler(&lambda { |error| }) #silence libxml, exceptions will do
18
+ end
19
+
20
+ def teardown
21
+ XmlMini.backend = @default_backend
22
+ end
23
+
24
+ def test_exception_thrown_on_expansion_attack
25
+ assert_raises LibXML::XML::Error do
26
+ attack_xml = %{<?xml version="1.0" encoding="UTF-8"?>
27
+ <!DOCTYPE member [
28
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
29
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
30
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
31
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
32
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
33
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
34
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
35
+ ]>
36
+ <member>
37
+ &a;
38
+ </member>
39
+ }
40
+ Hash.from_minixml(attack_xml)
41
+ end
42
+ end
43
+
44
+ def test_setting_libxml_as_backend
45
+ XmlMini.backend = 'LibXML'
46
+ assert_equal XmlMini_LibXML, XmlMini.backend
47
+ end
48
+
49
+ def test_blank_returns_empty_hash
50
+ assert_equal({}, XmlMini.parse(nil))
51
+ assert_equal({}, XmlMini.parse(''))
52
+ end
53
+
54
+ def test_array_type_makes_an_array
55
+ assert_equal_rexml(<<-eoxml)
56
+ <blog>
57
+ <posts type="array">
58
+ <post>a post</post>
59
+ <post>another post</post>
60
+ </posts>
61
+ </blog>
62
+ eoxml
63
+ end
64
+
65
+ def test_one_node_document_as_hash
66
+ assert_equal_rexml(<<-eoxml)
67
+ <products/>
68
+ eoxml
69
+ end
70
+
71
+ def test_one_node_with_attributes_document_as_hash
72
+ assert_equal_rexml(<<-eoxml)
73
+ <products foo="bar"/>
74
+ eoxml
75
+ end
76
+
77
+ def test_products_node_with_book_node_as_hash
78
+ assert_equal_rexml(<<-eoxml)
79
+ <products>
80
+ <book name="awesome" id="12345" />
81
+ </products>
82
+ eoxml
83
+ end
84
+
85
+ def test_products_node_with_two_book_nodes_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products>
88
+ <book name="awesome" id="12345" />
89
+ <book name="america" id="67890" />
90
+ </products>
91
+ eoxml
92
+ end
93
+
94
+ def test_single_node_with_content_as_hash
95
+ assert_equal_rexml(<<-eoxml)
96
+ <products>
97
+ hello world
98
+ </products>
99
+ eoxml
100
+ end
101
+
102
+ def test_children_with_children
103
+ assert_equal_rexml(<<-eoxml)
104
+ <root>
105
+ <products>
106
+ <book name="america" id="67890" />
107
+ </products>
108
+ </root>
109
+ eoxml
110
+ end
111
+
112
+ def test_children_with_text
113
+ assert_equal_rexml(<<-eoxml)
114
+ <root>
115
+ <products>
116
+ hello everyone
117
+ </products>
118
+ </root>
119
+ eoxml
120
+ end
121
+
122
+ def test_children_with_non_adjacent_text
123
+ assert_equal_rexml(<<-eoxml)
124
+ <root>
125
+ good
126
+ <products>
127
+ hello everyone
128
+ </products>
129
+ morning
130
+ </root>
131
+ eoxml
132
+ end
133
+
134
+ def test_parse_from_io
135
+ io = StringIO.new(<<-eoxml)
136
+ <root>
137
+ good
138
+ <products>
139
+ hello everyone
140
+ </products>
141
+ morning
142
+ </root>
143
+ eoxml
144
+ XmlMini.parse(io)
145
+ end
146
+
147
+ def test_children_with_simple_cdata
148
+ assert_equal_rexml(<<-eoxml)
149
+ <root>
150
+ <products>
151
+ <![CDATA[cdatablock]]>
152
+ </products>
153
+ </root>
154
+ eoxml
155
+ end
156
+
157
+ def test_children_with_multiple_cdata
158
+ assert_equal_rexml(<<-eoxml)
159
+ <root>
160
+ <products>
161
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
162
+ </products>
163
+ </root>
164
+ eoxml
165
+ end
166
+
167
+ def test_children_with_text_and_cdata
168
+ assert_equal_rexml(<<-eoxml)
169
+ <root>
170
+ <products>
171
+ hello <![CDATA[cdatablock]]>
172
+ morning
173
+ </products>
174
+ </root>
175
+ eoxml
176
+ end
177
+
178
+ def test_children_with_blank_text
179
+ assert_equal_rexml(<<-eoxml)
180
+ <root>
181
+ <products> </products>
182
+ </root>
183
+ eoxml
184
+ end
185
+
186
+ def test_children_with_blank_text_and_attribute
187
+ assert_equal_rexml(<<-eoxml)
188
+ <root>
189
+ <products type="file"> </products>
190
+ </root>
191
+ eoxml
192
+ end
193
+
194
+
195
+ private
196
+ def assert_equal_rexml(xml)
197
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
198
+ assert_equal(hash, XmlMini.parse(xml))
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,193 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'libxml'
7
+ rescue LoadError
8
+ # Skip libxml tests
9
+ else
10
+
11
+ class LibXMLSAXEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'LibXMLSAX'
16
+ end
17
+
18
+ def teardown
19
+ XmlMini.backend = @default_backend
20
+ end
21
+
22
+ def test_exception_thrown_on_expansion_attack
23
+ assert_raises LibXML::XML::Error do
24
+ attack_xml = <<-EOT
25
+ <?xml version="1.0" encoding="UTF-8"?>
26
+ <!DOCTYPE member [
27
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
28
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
29
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
30
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
31
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
32
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
33
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
34
+ ]>
35
+ <member>
36
+ &a;
37
+ </member>
38
+ EOT
39
+
40
+ Hash.from_minixml(attack_xml)
41
+ end
42
+ end
43
+
44
+ def test_setting_libxml_as_backend
45
+ XmlMini.backend = 'LibXMLSAX'
46
+ assert_equal XmlMini_LibXMLSAX, XmlMini.backend
47
+ end
48
+
49
+ def test_blank_returns_empty_hash
50
+ assert_equal({}, XmlMini.parse(nil))
51
+ assert_equal({}, XmlMini.parse(''))
52
+ end
53
+
54
+ def test_array_type_makes_an_array
55
+ assert_equal_rexml(<<-eoxml)
56
+ <blog>
57
+ <posts type="array">
58
+ <post>a post</post>
59
+ <post>another post</post>
60
+ </posts>
61
+ </blog>
62
+ eoxml
63
+ end
64
+
65
+ def test_one_node_document_as_hash
66
+ assert_equal_rexml(<<-eoxml)
67
+ <products/>
68
+ eoxml
69
+ end
70
+
71
+ def test_one_node_with_attributes_document_as_hash
72
+ assert_equal_rexml(<<-eoxml)
73
+ <products foo="bar"/>
74
+ eoxml
75
+ end
76
+
77
+ def test_products_node_with_book_node_as_hash
78
+ assert_equal_rexml(<<-eoxml)
79
+ <products>
80
+ <book name="awesome" id="12345" />
81
+ </products>
82
+ eoxml
83
+ end
84
+
85
+ def test_products_node_with_two_book_nodes_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products>
88
+ <book name="awesome" id="12345" />
89
+ <book name="america" id="67890" />
90
+ </products>
91
+ eoxml
92
+ end
93
+
94
+ def test_single_node_with_content_as_hash
95
+ assert_equal_rexml(<<-eoxml)
96
+ <products>
97
+ hello world
98
+ </products>
99
+ eoxml
100
+ end
101
+
102
+ def test_children_with_children
103
+ assert_equal_rexml(<<-eoxml)
104
+ <root>
105
+ <products>
106
+ <book name="america" id="67890" />
107
+ </products>
108
+ </root>
109
+ eoxml
110
+ end
111
+
112
+ def test_children_with_text
113
+ assert_equal_rexml(<<-eoxml)
114
+ <root>
115
+ <products>
116
+ hello everyone
117
+ </products>
118
+ </root>
119
+ eoxml
120
+ end
121
+
122
+ def test_children_with_non_adjacent_text
123
+ assert_equal_rexml(<<-eoxml)
124
+ <root>
125
+ good
126
+ <products>
127
+ hello everyone
128
+ </products>
129
+ morning
130
+ </root>
131
+ eoxml
132
+ end
133
+
134
+ def test_parse_from_io
135
+ io = StringIO.new(<<-eoxml)
136
+ <root>
137
+ good
138
+ <products>
139
+ hello everyone
140
+ </products>
141
+ morning
142
+ </root>
143
+ eoxml
144
+ XmlMini.parse(io)
145
+ end
146
+
147
+ def test_children_with_simple_cdata
148
+ assert_equal_rexml(<<-eoxml)
149
+ <root>
150
+ <products>
151
+ <![CDATA[cdatablock]]>
152
+ </products>
153
+ </root>
154
+ eoxml
155
+ end
156
+
157
+ def test_children_with_multiple_cdata
158
+ assert_equal_rexml(<<-eoxml)
159
+ <root>
160
+ <products>
161
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
162
+ </products>
163
+ </root>
164
+ eoxml
165
+ end
166
+
167
+ def test_children_with_text_and_cdata
168
+ assert_equal_rexml(<<-eoxml)
169
+ <root>
170
+ <products>
171
+ hello <![CDATA[cdatablock]]>
172
+ morning
173
+ </products>
174
+ </root>
175
+ eoxml
176
+ end
177
+
178
+ def test_children_with_blank_text
179
+ assert_equal_rexml(<<-eoxml)
180
+ <root>
181
+ <products> </products>
182
+ </root>
183
+ eoxml
184
+ end
185
+
186
+ private
187
+ def assert_equal_rexml(xml)
188
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
189
+ assert_equal(hash, XmlMini.parse(xml))
190
+ end
191
+ end
192
+
193
+ end
@@ -0,0 +1,215 @@
1
+ require 'test_helper'
2
+ # require 'active_support/xml_mini'
3
+ # require 'active_support/core_ext/hash/conversions'
4
+
5
+ begin
6
+ require 'nokogiri'
7
+ rescue LoadError
8
+ # Skip nokogiri tests
9
+ else
10
+
11
+ class NokogiriEngineTest < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ @default_backend = XmlMini.backend
15
+ XmlMini.backend = 'Nokogiri'
16
+ end
17
+
18
+ def teardown
19
+ XmlMini.backend = @default_backend
20
+ end
21
+
22
+ def test_file_from_xml
23
+ hash = Hash.from_minixml(<<-eoxml)
24
+ <blog>
25
+ <logo type="file" name="logo.png" content_type="image/png">
26
+ </logo>
27
+ </blog>
28
+ eoxml
29
+ assert hash.has_key?('blog')
30
+ assert hash['blog'].has_key?('logo')
31
+
32
+ file = hash['blog']['logo']
33
+ assert_equal 'logo.png', file.original_filename
34
+ assert_equal 'image/png', file.content_type
35
+ end
36
+
37
+ def test_exception_thrown_on_expansion_attack
38
+ assert_raises Nokogiri::XML::SyntaxError do
39
+ attack_xml = <<-EOT
40
+ <?xml version="1.0" encoding="UTF-8"?>
41
+ <!DOCTYPE member [
42
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
43
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
44
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
45
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
46
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
47
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
48
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
49
+ ]>
50
+ <member>
51
+ &a;
52
+ </member>
53
+ EOT
54
+ Hash.from_minixml(attack_xml)
55
+ end
56
+ end
57
+
58
+ def test_setting_nokogiri_as_backend
59
+ XmlMini.backend = 'Nokogiri'
60
+ assert_equal XmlMini_Nokogiri, XmlMini.backend
61
+ end
62
+
63
+ def test_blank_returns_empty_hash
64
+ assert_equal({}, XmlMini.parse(nil))
65
+ assert_equal({}, XmlMini.parse(''))
66
+ end
67
+
68
+ def test_array_type_makes_an_array
69
+ assert_equal_rexml(<<-eoxml)
70
+ <blog>
71
+ <posts type="array">
72
+ <post>a post</post>
73
+ <post>another post</post>
74
+ </posts>
75
+ </blog>
76
+ eoxml
77
+ end
78
+
79
+ def test_one_node_document_as_hash
80
+ assert_equal_rexml(<<-eoxml)
81
+ <products/>
82
+ eoxml
83
+ end
84
+
85
+ def test_one_node_with_attributes_document_as_hash
86
+ assert_equal_rexml(<<-eoxml)
87
+ <products foo="bar"/>
88
+ eoxml
89
+ end
90
+
91
+ def test_products_node_with_book_node_as_hash
92
+ assert_equal_rexml(<<-eoxml)
93
+ <products>
94
+ <book name="awesome" id="12345" />
95
+ </products>
96
+ eoxml
97
+ end
98
+
99
+ def test_products_node_with_two_book_nodes_as_hash
100
+ assert_equal_rexml(<<-eoxml)
101
+ <products>
102
+ <book name="awesome" id="12345" />
103
+ <book name="america" id="67890" />
104
+ </products>
105
+ eoxml
106
+ end
107
+
108
+ def test_single_node_with_content_as_hash
109
+ assert_equal_rexml(<<-eoxml)
110
+ <products>
111
+ hello world
112
+ </products>
113
+ eoxml
114
+ end
115
+
116
+ def test_children_with_children
117
+ assert_equal_rexml(<<-eoxml)
118
+ <root>
119
+ <products>
120
+ <book name="america" id="67890" />
121
+ </products>
122
+ </root>
123
+ eoxml
124
+ end
125
+
126
+ def test_children_with_text
127
+ assert_equal_rexml(<<-eoxml)
128
+ <root>
129
+ <products>
130
+ hello everyone
131
+ </products>
132
+ </root>
133
+ eoxml
134
+ end
135
+
136
+ def test_children_with_non_adjacent_text
137
+ assert_equal_rexml(<<-eoxml)
138
+ <root>
139
+ good
140
+ <products>
141
+ hello everyone
142
+ </products>
143
+ morning
144
+ </root>
145
+ eoxml
146
+ end
147
+
148
+ def test_parse_from_io
149
+ io = StringIO.new(<<-eoxml)
150
+ <root>
151
+ good
152
+ <products>
153
+ hello everyone
154
+ </products>
155
+ morning
156
+ </root>
157
+ eoxml
158
+ XmlMini.parse(io)
159
+ end
160
+
161
+ def test_children_with_simple_cdata
162
+ assert_equal_rexml(<<-eoxml)
163
+ <root>
164
+ <products>
165
+ <![CDATA[cdatablock]]>
166
+ </products>
167
+ </root>
168
+ eoxml
169
+ end
170
+
171
+ def test_children_with_multiple_cdata
172
+ assert_equal_rexml(<<-eoxml)
173
+ <root>
174
+ <products>
175
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
176
+ </products>
177
+ </root>
178
+ eoxml
179
+ end
180
+
181
+ def test_children_with_text_and_cdata
182
+ assert_equal_rexml(<<-eoxml)
183
+ <root>
184
+ <products>
185
+ hello <![CDATA[cdatablock]]>
186
+ morning
187
+ </products>
188
+ </root>
189
+ eoxml
190
+ end
191
+
192
+ def test_children_with_blank_text
193
+ assert_equal_rexml(<<-eoxml)
194
+ <root>
195
+ <products> </products>
196
+ </root>
197
+ eoxml
198
+ end
199
+
200
+ def test_children_with_blank_text_and_attribute
201
+ assert_equal_rexml(<<-eoxml)
202
+ <root>
203
+ <products type="file"> </products>
204
+ </root>
205
+ eoxml
206
+ end
207
+
208
+ private
209
+ def assert_equal_rexml(xml)
210
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
211
+ assert_equal(hash, XmlMini.parse(xml))
212
+ end
213
+ end
214
+
215
+ end