File: writertester.rb

package info (click to toggle)
nqxml 1.1.3p1-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 412 kB
  • ctags: 331
  • sloc: ruby: 3,177; makefile: 89; xml: 41
file content (245 lines) | stat: -rw-r--r-- 7,080 bytes parent folder | download | duplicates (2)
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#
# Copyright (c) 2001 by Jim Menard <jimm@io.com>
#
# Released under the same license as Ruby. See
# http://www.ruby-lang.org/en/LICENSE.txt.
#

require 'nqxml/writer'

class WriterTester < NQXMLTester

    def test_prettify
	compare_test_prettify(true)
    end

    def test_no_prettify
	compare_test_prettify(false)
    end

    # NOTE: this test will break if we add so many nested tags that the
    # writer would start replacing leading spaces with tabs. Since we only
    # have one indentation level, all is well.
    def compare_test_prettify(prettify)
	f_xml = f_answer = nil
	begin
	    suffix = prettify ? "\n" : ''

	    f_xml = Tempfile.new('xml_writer')
	    f_answer = Tempfile.new('xml_writer_answer')

	    w = NQXML::Writer.new(f_xml, prettify)

	    f_answer.print("<?xml version=\"1.0\"?>#{suffix}")
	    w.processingInstruction('xml', 'version="1.0"')

	    f_answer.print("<tag1>#{suffix}")
	    w.startElement('tag1')

	    f_answer.print(' ' * NQXML::Writer::INDENT_OFFSET) if prettify
	    f_answer.print("<tag2 attr1=\"foo\" attr2=\"b&amp;r\">#{suffix}")
	    w.startElement('tag2')
	    w.attribute('attr1', 'foo')
	    w.attribute('attr2', 'b&r')

	    f_answer.print("data &amp; &lt;stuff&gt;\n")
	    w.write("data & <stuff>\n")

	    f_answer.print(' '* NQXML::Writer::INDENT_OFFSET) if prettify
	    f_answer.print("</tag2>#{suffix}")
	    w.endElement('tag2')

	    f_answer.print(' ' * NQXML::Writer::INDENT_OFFSET) if prettify
	    f_answer.print("<empty-tag/>#{suffix}")
	    w.startElement('empty-tag')
	    w.endElement('empty-tag')

	    f_answer.print("</tag1>#{suffix}")
	    w.endElement('tag1')

	    f_answer.close()
	    f_xml.close()

	    assert(File.compare(f_answer.path(), f_xml.path()))
	rescue NQXML::WriterError
	    assert_fail($!)
	ensure
	    f_answer.close(true)
	    f_xml.close(true)
	end
    end

    # Makes sure that writers can accept strings.
    def test_string_arg
	str = ''
	w = NQXML::Writer.new(str)

	w.write('data')
	assert_equals('data', str)

	w.comment('foo')
	assert_equals('data<!--foo-->', str)
    end

    # Makes sure that writers can accept arrays. Not sure when this would
    # be useful, but what the heck. Arrays respond to '<<', so why not?
    def test_array_arg
	array = Array.new
	w = NQXML::Writer.new(array)

	w.write('data')
	assert_equals(['data'], array)

	w.comment('foo')
	assert_equals(['data', '<!--foo-->'], array)
    end

    # Creates a writer and passes it in to a block. Expect a parser error
    # that matches `regex'. If line is not nil, expect the error to occur
    # in the specified position(s)
    def expect_error(regex)
	io = Tempfile.new('writer_error')
	begin
	    writer = NQXML::Writer.new(io)
	    yield writer
	    assert_fail("expected exception '#{regex.source}'")
	rescue NQXML::WriterError => ex
	    assert_match($!, regex)
	ensure
	    io.close(true)
	end
    end

    def test_writer_errors
	expect_error(/attribute outside of tag start/) { | w |
	    w.attribute('illegal', 'because no tag yet')
	}
	expect_error(/end element without start element/) { | w |
	    w.endElement('illegal because no tag yet')
	}
	expect_error(/does not match open element name/) { | w |
	    w.startElement('foo')
	    w.endElement('bar')
	}
    end

    # Compares the text read from the IO object to a normalized version of
    # @rsrc.xml.
    def compare_to_rsrc_xml(io, sourceFooToBletch)
	writtenLines = io.read()

	# What we expect is slightly different than the original XML
	# because entities have been replaced and the output tags and
	# attribute values have been normalized.
	normalizedXml = @rsrc.xml.dup()
	normalizedXml.gsub!(/&foo;/, 'bletch')
	normalizedXml.gsub!('/>', '></inner:tag>')
	normalizedXml.gsub!("tabs\tto\tspaces", "tabs to spaces")

	# The writer's output won't have the same whitespace.
	normalizedXml.gsub!(/^\s+\<(!ENTITY|!ELEMENT|!ATTLIST|!NOTATION|\?|!--)/,
			    '<\1')
	# Get rid of one newline that the writer doesn't output.
	normalizedXml.gsub!(/(<!DOCTYPE(.+?))[\n]]>/m, '\1]>')

	assert_equal(normalizedXml, writtenLines)
    end

    # Makes sure that a writer writes what a tree parser parses, except
    # for tag and text differences because of normalization. For example,
    # the tag '<foo/>' will be written as '<foo></foo>'.
    def test_writing_document
	io = nil
	begin
	    doc = NQXML::TreeParser.new(@rsrc.xml).document

	    io = Tempfile.new('writer_document')
	    writer = NQXML::Writer.new(io)
	    writer.writeDocument(doc)

	    io.open()		# closes, then opens for reading
	    compare_to_rsrc_xml(io, true)
	ensure
	    io.close(true) if io
	end
    end

    # Reconstructs @rsrc.xml from document and node objects and compares
    # the result with the tree-parsed version of the origial @rsrc.xml
    # text. Since we already have the entities we need inside @rsrc,
    # lets be lazy and use them. We're really exercising the document
    # object here.
    def test_creating_document
	doc = NQXML::Document.new()

	prologEntities = [
	    @rsrc.xmlDecl, @rsrc.newlineTok,
	    @rsrc.piWithArgs, @rsrc.newlineTok,
	    @rsrc.piNoArgs, @rsrc.newlineTok,
	    @rsrc.doctype, @rsrc.newlineTok, @rsrc.comment,
	    @rsrc.newlineTok
	]
	rootChildren = [
	    @rsrc.textDataWithSub, @rsrc.simpleTagStart,
	    @rsrc.newlineTok, @rsrc.innerTagStart,
	    @rsrc.cdata, @rsrc.newlineTok, @rsrc.pTagStart, @rsrc.newlineTok
	]
	paragraphChildren = [
	    @rsrc.textText, @rsrc.bTagStart, # bold text here
	    @rsrc.moreTextText
	]
	# @rsrc.boldText inside bold tag

	# Add prolog entities to document.
	prologEntities.each { | entity | doc.addToProlog(entity) }

	# Set root node.
	doc.setRoot(@rsrc.outerStart)
	assert_equal(@rsrc.outerStart, doc.rootNode.entity)
	assert_nil(doc.rootNode.parent)

	# Add children of root node.
	rootChildren.each { | entity | doc.rootNode.addChild(entity) }
	assert_equal(rootChildren.length, doc.rootNode.children.length)

	# Find simpleTag and add child.
	node = doc.rootNode.children.detect { | n |
	    n.entity.instance_of?(NQXML::Tag) && n.entity.name == 'simpleTag'
	}
	assert_not_nil(node)
	node.addChild(@rsrc.simpleTextData)
	assert_equal(1, node.children.length)

	# Find paragraph node and add children.
	node = doc.rootNode.children.detect { | n |
	    n.entity.instance_of?(NQXML::Tag) && n.entity.name == 'p'
	}
	assert_not_nil(node)
	paragraphChildren.each { | entity | node.addChild(entity) }
	assert_equal(paragraphChildren.length, node.children.length)

	# Find bold node and add text child.
	node = node.children.detect { | n |
	    n.entity.instance_of?(NQXML::Tag) && n.entity.name == 'b'
	}
	assert_not_nil(node)
	node.addChild(@rsrc.boldText)

	# Now write this document and compare it to writing out
	# the document created by parsing @rsrc.xml.
	io = nil
	begin
	    io = Tempfile.new('writer_document')
	    writer = NQXML::Writer.new(io)
	    writer.writeDocument(doc)
	    io.open()		# closes, then opens for reading
	    compare_to_rsrc_xml(io, false)
	ensure
	    io.close(true) if io
	end
    end

    def test_entity_substitution
    end

end