tilia-xml 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +32 -0
  4. data/.simplecov +4 -0
  5. data/.travis.yml +3 -0
  6. data/CHANGELOG.sabre.md +167 -0
  7. data/CONTRIBUTING.md +25 -0
  8. data/Gemfile +15 -0
  9. data/Gemfile.lock +56 -0
  10. data/LICENSE +27 -0
  11. data/LICENSE.sabre +27 -0
  12. data/README.md +30 -0
  13. data/Rakefile +17 -0
  14. data/lib/tilia/xml/context_stack_trait.rb +99 -0
  15. data/lib/tilia/xml/element/base.rb +73 -0
  16. data/lib/tilia/xml/element/cdata.rb +53 -0
  17. data/lib/tilia/xml/element/elements.rb +109 -0
  18. data/lib/tilia/xml/element/key_value.rb +110 -0
  19. data/lib/tilia/xml/element/uri.rb +98 -0
  20. data/lib/tilia/xml/element/xml_fragment.rb +128 -0
  21. data/lib/tilia/xml/element.rb +22 -0
  22. data/lib/tilia/xml/lib_xml_exception.rb +9 -0
  23. data/lib/tilia/xml/parse_exception.rb +7 -0
  24. data/lib/tilia/xml/reader.rb +240 -0
  25. data/lib/tilia/xml/service.rb +151 -0
  26. data/lib/tilia/xml/version.rb +9 -0
  27. data/lib/tilia/xml/writer.rb +261 -0
  28. data/lib/tilia/xml/xml_deserializable.rb +29 -0
  29. data/lib/tilia/xml/xml_serializable.rb +27 -0
  30. data/lib/tilia/xml.rb +23 -0
  31. data/test/test_helper.rb +4 -0
  32. data/test/xml/context_stack_test.rb +40 -0
  33. data/test/xml/element/cdata_test.rb +37 -0
  34. data/test/xml/element/eater.rb +60 -0
  35. data/test/xml/element/elements_test.rb +113 -0
  36. data/test/xml/element/key_value_test.rb +187 -0
  37. data/test/xml/element/mock.rb +52 -0
  38. data/test/xml/element/uri_test.rb +55 -0
  39. data/test/xml/element/xml_fragment_test.rb +121 -0
  40. data/test/xml/infite_loop_test.rb +47 -0
  41. data/test/xml/reader_test.rb +407 -0
  42. data/test/xml/service_test.rb +156 -0
  43. data/test/xml/writer_test.rb +260 -0
  44. data/tilia-xml.gemspec +15 -0
  45. metadata +132 -0
@@ -0,0 +1,121 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module Xml
5
+ class XmlFragmentTest < Minitest::Test
6
+ # Data provider for serialize and deserialize tests.
7
+ #
8
+ # Returns three items per test:
9
+ #
10
+ # 1. Input data for the reader.
11
+ # 2. Expected output for XmlFragment deserializer
12
+ # 3. Expected output after serializing that value again.
13
+ #
14
+ # If 3 is not set, use 1 for 3.
15
+ #
16
+ # @return [Array]
17
+ def xml_provider
18
+ [
19
+ [
20
+ 'hello',
21
+ 'hello'
22
+ ],
23
+ [
24
+ '<element>hello</element>',
25
+ '<element xmlns="http://sabredav.org/ns">hello</element>'
26
+ ],
27
+ [
28
+ '<element foo="bar">hello</element>',
29
+ '<element xmlns="http://sabredav.org/ns" foo="bar">hello</element>'
30
+ ],
31
+ [
32
+ '<element x1:foo="bar" xmlns:x1="http://example.org/ns">hello</element>',
33
+ '<element xmlns:x1="http://example.org/ns" xmlns="http://sabredav.org/ns" x1:foo="bar">hello</element>'
34
+ ],
35
+ [
36
+ '<element xmlns="http://example.org/ns">hello</element>',
37
+ '<element xmlns="http://example.org/ns">hello</element>',
38
+ '<x1:element xmlns:x1="http://example.org/ns">hello</x1:element>'
39
+ ],
40
+ [
41
+ '<element xmlns:foo="http://example.org/ns">hello</element>',
42
+ '<element xmlns:foo="http://example.org/ns" xmlns="http://sabredav.org/ns">hello</element>',
43
+ '<element>hello</element>'
44
+ ],
45
+ [
46
+ '<foo:element xmlns:foo="http://example.org/ns">hello</foo:element>',
47
+ '<foo:element xmlns:foo="http://example.org/ns">hello</foo:element>',
48
+ '<x1:element xmlns:x1="http://example.org/ns">hello</x1:element>'
49
+ ],
50
+ [
51
+ '<foo:element xmlns:foo="http://example.org/ns"><child>hello</child></foo:element>',
52
+ '<foo:element xmlns:foo="http://example.org/ns" xmlns="http://sabredav.org/ns"><child>hello</child></foo:element>',
53
+ '<x1:element xmlns:x1="http://example.org/ns"><child>hello</child></x1:element>'
54
+ ],
55
+ [
56
+ '<foo:element xmlns:foo="http://example.org/ns"><child/></foo:element>',
57
+ '<foo:element xmlns:foo="http://example.org/ns" xmlns="http://sabredav.org/ns"><child/></foo:element>',
58
+ '<x1:element xmlns:x1="http://example.org/ns"><child/></x1:element>'
59
+ ],
60
+ [
61
+ '<foo:element xmlns:foo="http://example.org/ns"><child a="b"/></foo:element>',
62
+ '<foo:element xmlns:foo="http://example.org/ns" xmlns="http://sabredav.org/ns"><child a="b"/></foo:element>',
63
+ '<x1:element xmlns:x1="http://example.org/ns"><child a="b"/></x1:element>'
64
+ ]
65
+ ]
66
+ end
67
+
68
+ def test_deserialize
69
+ xml_provider.each do |data|
70
+ (input, expected) = data
71
+ input = <<BLA
72
+ <?xml version="1.0"?>
73
+ <root xmlns="http://sabredav.org/ns">
74
+ <fragment>#{input}</fragment>
75
+ </root>
76
+ BLA
77
+ reader = Tilia::Xml::Reader.new
78
+ reader.element_map = { '{http://sabredav.org/ns}fragment' => Tilia::Xml::Element::XmlFragment }
79
+ reader.xml(input)
80
+ output = reader.parse
81
+
82
+ result = {
83
+ 'name' => '{http://sabredav.org/ns}root',
84
+ 'value' => [
85
+ {
86
+ 'name' => '{http://sabredav.org/ns}fragment',
87
+ 'value' => Tilia::Xml::Element::XmlFragment.new(expected),
88
+ 'attributes' => {}
89
+ }
90
+ ],
91
+ 'attributes' => {}
92
+ }
93
+ assert_equal(result, output)
94
+ end
95
+ end
96
+
97
+ def test_serialize
98
+ xml_provider.each do |data|
99
+ (expected_fallback, input, expected) = data
100
+
101
+ expected = expected_fallback if expected.nil?
102
+
103
+ writer = Tilia::Xml::Writer.new
104
+ writer.namespace_map = { 'http://sabredav.org/ns' => nil }
105
+ writer.open_memory
106
+ writer.start_document
107
+ writer.write('{http://sabredav.org/ns}root' => { '{http://sabredav.org/ns}fragment' => Tilia::Xml::Element::XmlFragment.new(input) })
108
+ output = writer.output_memory
109
+
110
+ result = <<XML
111
+ <?xml version="1.0"?>
112
+ <root xmlns="http://sabredav.org/ns"><fragment>#{expected}</fragment></root>
113
+ XML
114
+ result.chomp!
115
+
116
+ assert_equal(result, output)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module Xml
5
+ class InfiteLoopTest < Minitest::Test
6
+ # This particular xml body caused the parser to go into an infinite loop.
7
+ # Need to know why.
8
+ def test_deserialize
9
+ body = <<XML
10
+ <?xml version="1.0"?>
11
+ <d:propertyupdate xmlns:d="DAV:" xmlns:s="http://sabredav.org/NS/test">
12
+ <d:set><d:prop></d:prop></d:set>
13
+ <d:set><d:prop></d:prop></d:set>
14
+ </d:propertyupdate>
15
+ XML
16
+ reader = Reader.new
17
+ reader.element_map = { '{DAV:}set' => Element::KeyValue }
18
+ reader.xml(body)
19
+
20
+ output = reader.parse
21
+
22
+ expected = {
23
+ 'name' => '{DAV:}propertyupdate',
24
+ 'value' => [
25
+ {
26
+ 'name' => '{DAV:}set',
27
+ 'value' => {
28
+ '{DAV:}prop' => nil
29
+ },
30
+ 'attributes' => {}
31
+ },
32
+ {
33
+ 'name' => '{DAV:}set',
34
+ 'value' => {
35
+ '{DAV:}prop' => nil
36
+ },
37
+ 'attributes' => {}
38
+ }
39
+ ],
40
+ 'attributes' => {}
41
+ }
42
+
43
+ assert_equal(expected, output)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,407 @@
1
+ require 'test_helper'
2
+ require 'xml/element/mock'
3
+ require 'xml/element/eater'
4
+
5
+ module Tilia
6
+ module Xml
7
+ class ReaderTest < Minitest::Test
8
+ def setup
9
+ @reader = Reader.new
10
+ end
11
+
12
+ def test_should_load_clark
13
+ input = <<BLA
14
+ <?xml version="1.0"?>
15
+ <root xmlns="http://sabredav.org/ns" />
16
+ BLA
17
+ @reader.xml(input)
18
+ @reader.next
19
+ assert_equal('{http://sabredav.org/ns}root', @reader.clark)
20
+ end
21
+
22
+ def test_should_get_clark_without_ns
23
+ input = <<BLA
24
+ <?xml version="1.0"?>
25
+ <root />
26
+ BLA
27
+ @reader.xml(input)
28
+ @reader.next
29
+ assert_equal('{}root', @reader.clark)
30
+ end
31
+
32
+ def test_should_load_clark_on_an_element
33
+ input = <<BLA
34
+ <?xml version="1.0"?>
35
+ <root />
36
+ BLA
37
+ @reader.xml(input)
38
+ assert_nil(@reader.clark)
39
+ end
40
+
41
+ def test_should_parse_a_simple_xml_file
42
+ input = <<BLA
43
+ <?xml version="1.0"?>
44
+ <root xmlns="http://sabredav.org/ns">
45
+ <elem1 attr="val" />
46
+ <elem2>
47
+ <elem3>Hi!</elem3>
48
+ </elem2>
49
+ </root>
50
+ BLA
51
+ @reader.xml(input)
52
+ output = @reader.parse
53
+
54
+ expected = {
55
+ 'name' => '{http://sabredav.org/ns}root',
56
+ 'value' => [
57
+ {
58
+ 'name' => '{http://sabredav.org/ns}elem1',
59
+ 'value' => nil,
60
+ 'attributes' => {
61
+ 'attr' => 'val'
62
+ }
63
+ },
64
+ {
65
+ 'name' => '{http://sabredav.org/ns}elem2',
66
+ 'value' => [
67
+ {
68
+ 'name' => '{http://sabredav.org/ns}elem3',
69
+ 'value' => 'Hi!',
70
+ 'attributes' => {}
71
+ }
72
+ ],
73
+ 'attributes' => {}
74
+ }
75
+ ],
76
+ 'attributes' => {}
77
+ }
78
+
79
+ assert_equal(expected, output)
80
+ end
81
+
82
+ def test_should_work_with_cdata
83
+ input = <<BLA
84
+ <?xml version="1.0"?>
85
+ <root xmlns="http://sabredav.org/ns">
86
+ <foo><![CDATA[bar]]></foo>
87
+ </root>
88
+ BLA
89
+ @reader.xml(input)
90
+ output = @reader.parse
91
+
92
+ expected = {
93
+ 'name' => '{http://sabredav.org/ns}root',
94
+ 'value' => [
95
+ {
96
+ 'name' => '{http://sabredav.org/ns}foo',
97
+ 'value' => 'bar',
98
+ 'attributes' => {}
99
+ }
100
+ ],
101
+ 'attributes' => {}
102
+ }
103
+
104
+ assert_equal(expected, output)
105
+ end
106
+
107
+ def test_should_read_simple_namespaced_attributes
108
+ input = <<BLA
109
+ <?xml version="1.0"?>
110
+ <root xmlns="http://sabredav.org/ns" xmlns:foo="urn:foo">
111
+ <elem1 foo:attr="val" />
112
+ </root>
113
+ BLA
114
+ @reader.xml(input)
115
+ output = @reader.parse
116
+
117
+ expected = {
118
+ 'name' => '{http://sabredav.org/ns}root',
119
+ 'value' => [
120
+ {
121
+ 'name' => '{http://sabredav.org/ns}elem1',
122
+ 'value' => nil,
123
+ 'attributes' => {
124
+ '{urn:foo}attr' => 'val'
125
+ }
126
+ }
127
+ ],
128
+ 'attributes' => {}
129
+ }
130
+
131
+ assert_equal(expected, output)
132
+ end
133
+
134
+ def test_should_read_mapped_elements
135
+ input = <<BLA
136
+ <?xml version="1.0"?>
137
+ <root xmlns="http://sabredav.org/ns">
138
+ <elem1 />
139
+ </root>
140
+ BLA
141
+ @reader.element_map = {
142
+ '{http://sabredav.org/ns}elem1' => Element::Mock
143
+ }
144
+ @reader.xml(input)
145
+ output = @reader.parse
146
+
147
+ expected = {
148
+ 'name' => '{http://sabredav.org/ns}root',
149
+ 'value' => [
150
+ {
151
+ 'name' => '{http://sabredav.org/ns}elem1',
152
+ 'value' => 'foobar',
153
+ 'attributes' => {}
154
+ }
155
+ ],
156
+ 'attributes' => {}
157
+ }
158
+
159
+ assert_equal(expected, output)
160
+ end
161
+
162
+ def test_should_activate_mapped_element_callbacks
163
+ input = <<BLA
164
+ <?xml version="1.0"?>
165
+ <root xmlns="http://sabredav.org/ns">
166
+ <elem1 />
167
+ </root>
168
+ BLA
169
+ @reader.element_map = {
170
+ '{http://sabredav.org/ns}elem1' => lambda do |reader|
171
+ reader.next
172
+ 'foobar'
173
+ end
174
+ }
175
+ @reader.xml(input)
176
+ output = @reader.parse
177
+
178
+ expected = {
179
+ 'name' => '{http://sabredav.org/ns}root',
180
+ 'value' => [
181
+ {
182
+ 'name' => '{http://sabredav.org/ns}elem1',
183
+ 'value' => 'foobar',
184
+ 'attributes' => {}
185
+ }
186
+ ],
187
+ 'attributes' => {}
188
+ }
189
+
190
+ assert_equal(expected, output)
191
+ end
192
+
193
+ def test_should_read_text
194
+ input = <<BLA
195
+ <?xml version="1.0"?>
196
+ <root xmlns="http://sabredav.org/ns">
197
+ <elem1>
198
+ <elem2>hello </elem2>
199
+ <elem2>world</elem2>
200
+ </elem1>
201
+ </root>
202
+ BLA
203
+ @reader.element_map = {
204
+ '{http://sabredav.org/ns}elem1' => ->(reader) { reader.read_text }
205
+ }
206
+ @reader.xml(input)
207
+ output = @reader.parse
208
+
209
+ expected = {
210
+ 'name' => '{http://sabredav.org/ns}root',
211
+ 'value' => [
212
+ {
213
+ 'name' => '{http://sabredav.org/ns}elem1',
214
+ 'value' => 'hello world',
215
+ 'attributes' => {}
216
+ }
217
+ ],
218
+ 'attributes' => {}
219
+ }
220
+
221
+ assert_equal(expected, output)
222
+ end
223
+
224
+ def test_should_raise_exceptions
225
+ input = <<BLA
226
+ <?xml version="1.0"?>
227
+ <root xmlns="http://sabredav.org/ns">
228
+ BLA
229
+ @reader.element_map = {
230
+ '{http://sabredav.org/ns}elem1' => Element::Mock
231
+ }
232
+ @reader.xml(input)
233
+
234
+ assert_raises(LibXmlException) { @reader.parse }
235
+ end
236
+
237
+ def test_should_handle_broken_parser
238
+ input = <<BLA
239
+ <?xml version="1.0"?>
240
+ <root xmlns="http://sabredav.org/ns">
241
+ <elem1 />
242
+ </root>
243
+ BLA
244
+ @reader.element_map = {
245
+ '{http://sabredav.org/ns}elem1' => Element::Eater
246
+ }
247
+ @reader.xml(input)
248
+ assert_raises(ParseException) { @reader.parse }
249
+ end
250
+
251
+ def test_should_handle_invalid_xml
252
+ input = <<BLA
253
+ <test>
254
+ <hello>
255
+ </hello>
256
+ </sffsdf>
257
+ BLA
258
+ @reader.xml(input)
259
+ assert_raises(LibXmlException) { @reader.parse }
260
+ end
261
+
262
+ def test_should_handle_invalid_xml_2
263
+ input = <<BLA
264
+ <?xml version="1.0" encoding="UTF-8"?>
265
+ <definitions>
266
+ <collaboration>
267
+ <participant id="sid-A33D08EB-A2DE-448F-86FE-A2B62E98818" name="Company" processRef="sid-A0A6A196-3C9A-4C69-88F6-7ED7DDFDD264">
268
+ <extensionElements>
269
+ <signavio:signavioMetaData metaKey="bgcolor" />
270
+ ""Administrative w">
271
+ <extensionElements>
272
+ <signavio:signavioMetaData metaKey="bgcolor" metaValue=""/>
273
+ </extensionElements>
274
+ </lan
275
+ BLA
276
+ @reader.xml(input)
277
+ assert_raises(LibXmlException) { @reader.parse }
278
+ end
279
+
280
+ def test_should_parse_an_inner_tree
281
+ input = <<BLA
282
+ <?xml version="1.0"?>
283
+ <root xmlns="http://sabredav.org/ns">
284
+ <elem1>
285
+ <elem1 />
286
+ </elem1>
287
+ </root>
288
+ BLA
289
+ @reader.element_map = {
290
+ '{http://sabredav.org/ns}elem1' => lambda do |reader|
291
+ inner_tree = reader.parse_inner_tree(
292
+ '{http://sabredav.org/ns}elem1' => lambda do |lambda_reader|
293
+ lambda_reader.next
294
+ 'foobar'
295
+ end
296
+ )
297
+ inner_tree
298
+ end
299
+ }
300
+ @reader.xml(input)
301
+ output = @reader.parse
302
+
303
+ expected = {
304
+ 'name' => '{http://sabredav.org/ns}root',
305
+ 'value' => [
306
+ {
307
+ 'name' => '{http://sabredav.org/ns}elem1',
308
+ 'value' => [
309
+ {
310
+ 'name' => '{http://sabredav.org/ns}elem1',
311
+ 'value' => 'foobar',
312
+ 'attributes' => {}
313
+ }
314
+ ],
315
+ 'attributes' => {}
316
+ }
317
+ ],
318
+ 'attributes' => {}
319
+ }
320
+
321
+ assert_equal(expected, output)
322
+ end
323
+
324
+ def test_should_use_parse_get_elements
325
+ input = <<BLA
326
+ <?xml version="1.0"?>
327
+ <root xmlns="http://sabredav.org/ns">
328
+ <elem1>
329
+ <elem1 />
330
+ </elem1>
331
+ </root>
332
+ BLA
333
+ @reader.element_map = {
334
+ '{http://sabredav.org/ns}elem1' => lambda do |reader|
335
+ inner_tree = reader.parse_get_elements(
336
+ '{http://sabredav.org/ns}elem1' => lambda do |lambda_reader|
337
+ lambda_reader.next
338
+ 'foobar'
339
+ end
340
+ )
341
+ inner_tree
342
+ end
343
+ }
344
+ @reader.xml(input)
345
+ output = @reader.parse
346
+
347
+ expected = {
348
+ 'name' => '{http://sabredav.org/ns}root',
349
+ 'value' => [
350
+ {
351
+ 'name' => '{http://sabredav.org/ns}elem1',
352
+ 'value' => [
353
+ {
354
+ 'name' => '{http://sabredav.org/ns}elem1',
355
+ 'value' => 'foobar',
356
+ 'attributes' => {}
357
+ }
358
+ ],
359
+ 'attributes' => {}
360
+ }
361
+ ],
362
+ 'attributes' => {}
363
+ }
364
+
365
+ assert_equal(expected, output)
366
+ end
367
+
368
+ def test_should_work_with_no_elements
369
+ input = <<BLA
370
+ <?xml version="1.0"?>
371
+ <root xmlns="http://sabredav.org/ns">
372
+ <elem1>
373
+ hi
374
+ </elem1>
375
+ </root>
376
+ BLA
377
+ @reader.element_map = {
378
+ '{http://sabredav.org/ns}elem1' => lambda do |reader|
379
+ inner_tree = reader.parse_get_elements(
380
+ '{http://sabredav.org/ns}elem1' => lambda do |lambda_reader|
381
+ lambda_reader.next
382
+ 'foobar'
383
+ end
384
+ )
385
+ inner_tree
386
+ end
387
+ }
388
+ @reader.xml(input)
389
+ output = @reader.parse
390
+
391
+ expected = {
392
+ 'name' => '{http://sabredav.org/ns}root',
393
+ 'value' => [
394
+ {
395
+ 'name' => '{http://sabredav.org/ns}elem1',
396
+ 'value' => [],
397
+ 'attributes' => {}
398
+ }
399
+ ],
400
+ 'attributes' => {}
401
+ }
402
+
403
+ assert_equal(expected, output)
404
+ end
405
+ end
406
+ end
407
+ end