|
1 #!/usr/local/bin/lua5.1 |
|
2 -- See Copyright Notice in license.html |
|
3 -- $Id: test.lua,v 1.6 2006/06/08 20:34:52 tomas Exp $ |
|
4 |
|
5 require"lxp" |
|
6 print (lxp._VERSION) |
|
7 |
|
8 -- basic test with no preamble |
|
9 local p = lxp.new{} |
|
10 p:setencoding("ISO-8859-1") |
|
11 assert(p:parse[[<tag cap="5">hi</tag>]]) |
|
12 p:close() |
|
13 |
|
14 |
|
15 preamble = [[ |
|
16 <?xml version="1.0" encoding="ISO-8859-1"?> |
|
17 |
|
18 <!DOCTYPE greeting [ |
|
19 <!ENTITY xuxu "is this a xuxu?"> |
|
20 |
|
21 <!ATTLIST to |
|
22 method CDATA #FIXED "POST" |
|
23 > |
|
24 |
|
25 <!ENTITY test-entity |
|
26 SYSTEM "entity1.xml"> |
|
27 |
|
28 <!NOTATION TXT SYSTEM "txt"> |
|
29 |
|
30 <!ENTITY test-unparsed SYSTEM "unparsed.txt" NDATA txt> |
|
31 |
|
32 <!ATTLIST hihi |
|
33 explanation ENTITY #REQUIRED> |
|
34 |
|
35 ]> |
|
36 ]] |
|
37 |
|
38 local X |
|
39 function getargs (...) X = arg end |
|
40 |
|
41 function xgetargs (c) |
|
42 return function (...) |
|
43 table.insert(arg, 1, c) |
|
44 table.insert(X, arg) |
|
45 end |
|
46 end |
|
47 |
|
48 |
|
49 ------------------------------- |
|
50 print("testing start/end tags") |
|
51 callbacks = { |
|
52 StartElement = getargs, |
|
53 EndElement = getargs, |
|
54 } |
|
55 p = lxp.new(callbacks) |
|
56 assert(p:getcallbacks() == callbacks) |
|
57 assert(p:parse(preamble)) |
|
58 assert(p:parse([[ |
|
59 <to priority="10" xu = "hi"> |
|
60 ]])) |
|
61 assert(X.n == 3 and X[1] == p and X[2] == "to") |
|
62 x = X[3] |
|
63 assert(x.priority=="10" and x.xu=="hi" and x.method=="POST") |
|
64 assert(x[1] == "priority" and x[2] == "xu" and table.getn(x) == 2) |
|
65 assert(p:parse("</to>")) |
|
66 assert(p:parse()) |
|
67 p:close() |
|
68 |
|
69 |
|
70 ------------------------------- |
|
71 print("testing CharacterData/Cdata") |
|
72 callbacks = { |
|
73 CharacterData = getargs, |
|
74 } |
|
75 p = lxp.new(callbacks) |
|
76 assert(p:parse(preamble)) |
|
77 assert(p:parse"<to>a basic text<<![CDATA[<<ha>>]]></to>") |
|
78 assert(X[1] == p and X[2] == "a basic text<<<ha>>") |
|
79 callbacks.chardata = error -- no more calls to `chardata' |
|
80 assert(p:parse("")) |
|
81 assert(p:parse()) |
|
82 -- assert(p:parse()) -- no problem to finish twice. alas, it has problems |
|
83 assert(p:getcallbacks() == callbacks) |
|
84 p:close() |
|
85 |
|
86 ------------------------------- |
|
87 callbacks = { |
|
88 CharacterData = xgetargs"c", |
|
89 StartCdataSection = xgetargs"s", |
|
90 EndCdataSection = xgetargs"e", |
|
91 } |
|
92 X = {} |
|
93 p = lxp.new(callbacks) |
|
94 assert(p:parse(preamble)) |
|
95 assert(p:parse"<to>") |
|
96 assert(p:parse"<![CDATA[hi]]>") |
|
97 assert(table.getn(X) == 3) |
|
98 assert(X[1][1] == "s" and X[1][2] == p) |
|
99 assert(X[2][1] == "c" and X[2][2] == p and X[2][3] == "hi") |
|
100 assert(X[3][1] == "e" and X[3][2] == p) |
|
101 assert(p:parse"</to>") |
|
102 p:close() |
|
103 |
|
104 |
|
105 ------------------------------- |
|
106 print("testing ProcessingInstruction") |
|
107 callbacks = {ProcessingInstruction = getargs} |
|
108 p = lxp.new(callbacks) |
|
109 assert(p:parse[[ |
|
110 <to> |
|
111 <?lua how is this passed to <here>? ?> |
|
112 </to> |
|
113 ]]) |
|
114 assert(X[1] == p and X[2] == "lua" and |
|
115 X[3] == "how is this passed to <here>? ") |
|
116 p:close() |
|
117 |
|
118 |
|
119 ------------------------------ |
|
120 print("testing Comment") |
|
121 callbacks = {Comment = xgetargs"c"; CharacterData = xgetargs"t"} |
|
122 X = {} |
|
123 p = lxp.new(callbacks) |
|
124 assert(p:parse[[ |
|
125 <to>some text |
|
126 <!-- <a comment> with some & symbols --> |
|
127 some more text</to> |
|
128 |
|
129 ]]) |
|
130 p:close() |
|
131 |
|
132 assert(X[1][1] == "t" and X[2][1] == "c" and X[3][1] == "t") |
|
133 assert(X[1][2] == X[2][2] and X[2][2] == X[3][2] and X[3][2] == p) |
|
134 assert(X[1][3] == "some text\n") |
|
135 assert(X[2][3] == " <a comment> with some & symbols ") |
|
136 assert(X[3][3] == "\nsome more text") |
|
137 |
|
138 |
|
139 ---------------------------- |
|
140 print("testing ExternalEntity") |
|
141 entities = { |
|
142 ["entity1.xml"] = "<hi/>" |
|
143 } |
|
144 |
|
145 callbacks = {StartElement = xgetargs"s", EndElement = xgetargs"e", |
|
146 ExternalEntityRef = function (p, context, base, systemID, publicId) |
|
147 assert(base == "/base") |
|
148 return context:parse(entities[systemID]) |
|
149 end} |
|
150 |
|
151 X = {} |
|
152 p = lxp.new(callbacks) |
|
153 p:setbase("/base") |
|
154 assert(p:parse(preamble)) |
|
155 assert(p:parse[[ |
|
156 <to> &test-entity; |
|
157 </to> |
|
158 ]]) |
|
159 assert(p:getbase() == "/base") |
|
160 p:close() |
|
161 assert(X[1][1] == "s" and X[1][3] == "to") |
|
162 assert(X[2][1] == "s" and X[2][3] == "hi") |
|
163 assert(X[3][1] == "e" and X[3][3] == "hi") |
|
164 assert(X[4][1] == "e" and X[4][3] == "to") |
|
165 |
|
166 |
|
167 ---------------------------- |
|
168 print("testing default handles") |
|
169 text = [[<to> hi &xuxu; </to>]] |
|
170 local t = "" |
|
171 |
|
172 callbacks = { Default = function (p, s) t = t .. s end } |
|
173 p = lxp.new(callbacks) |
|
174 assert(p:parse(preamble)) |
|
175 assert(p:parse(text)) |
|
176 p:close() |
|
177 assert(t == preamble..text) |
|
178 |
|
179 t = "" |
|
180 callbacks = { DefaultExpand = function (p, s) t = t .. s end } |
|
181 p = lxp.new(callbacks) |
|
182 assert(p:parse(preamble)) |
|
183 assert(p:parse(text)) |
|
184 p:close() |
|
185 assert(t == preamble..string.gsub(text, "&xuxu;", "is this a xuxu?")) |
|
186 |
|
187 |
|
188 ---------------------------- |
|
189 print("testing notation declarations and unparsed entities") |
|
190 |
|
191 callbacks = { |
|
192 UnparsedEntityDecl = getargs, |
|
193 NotationDecl = function (p, name, base, systemId, publicId) |
|
194 assert(name == "TXT" and systemId == "txt" and base == "/base") |
|
195 end, |
|
196 } |
|
197 p = lxp.new(callbacks) |
|
198 p:setbase("/base") |
|
199 assert(p:parse(preamble)) |
|
200 assert(p:parse[[<hihi explanation="test-unparsed"/>]]) |
|
201 p:close() |
|
202 assert(X[2] == "test-unparsed" and X[3] == "/base" and |
|
203 X[4] == "unparsed.txt" and X[6] == "txt" and X.n == 6) |
|
204 |
|
205 |
|
206 |
|
207 ---------------------------- |
|
208 print("testing namespace declarations") |
|
209 callbacks = { StartNamespaceDecl = xgetargs"sn", |
|
210 EndNamespaceDecl = xgetargs"en", |
|
211 StartElement = xgetargs"s", |
|
212 EndElement = xgetargs"e", |
|
213 } |
|
214 X = {} |
|
215 p = lxp.new(callbacks, "?") |
|
216 assert(p:parse[[ |
|
217 <x xmlns:space='a/namespace'> |
|
218 <space:a/> |
|
219 </x> |
|
220 ]]) |
|
221 p:close() |
|
222 x = X[1] |
|
223 assert(x[1] == "sn" and x[3] == "space" and x[4] == "a/namespace" and table.getn(x) == 4) |
|
224 x = X[3] |
|
225 assert(x[1] == "s" and x[3] == "a/namespace?a") |
|
226 x = X[4] |
|
227 assert(x[1] == "e" and x[3] == "a/namespace?a") |
|
228 x = X[6] |
|
229 assert(x[1] == "en" and x[3] == "space" and table.getn(x) == 3) |
|
230 |
|
231 |
|
232 |
|
233 -- Error reporting |
|
234 p = lxp.new{} |
|
235 data = [[ |
|
236 <tag> |
|
237 <other< </other> |
|
238 </tag> |
|
239 ]] |
|
240 local status, msg, line, col, byte = p:parse(data) |
|
241 assert(status == nil and type(msg) == "string" and line == 2 and col == 9) |
|
242 assert(string.sub(data, byte, byte) == "<") |
|
243 |
|
244 p = lxp.new{} |
|
245 p:parse("<to>") |
|
246 local status, msg, line, col, byte = p:parse() |
|
247 assert(status == nil and line == 1 and col == 5 and byte == 5) |
|
248 |
|
249 |
|
250 -- position reporting |
|
251 callbacks = { ProcessingInstruction = function (p) |
|
252 X = {p:pos()} |
|
253 end |
|
254 } |
|
255 |
|
256 p = lxp.new(callbacks) |
|
257 assert(p:parse[[ |
|
258 <to> <?test where is `pos'? ?> |
|
259 </to> |
|
260 ]]) |
|
261 p:close() |
|
262 assert(X[1] == 1 and X[2] == 6 and X[3] == 6) -- line, column, abs. position |
|
263 |
|
264 |
|
265 |
|
266 print("testing errors") |
|
267 -- invalid keys |
|
268 assert(not pcall(lxp.new, {StatCdata=print})) |
|
269 assert(pcall(lxp.new, {StatCdata=print, _nonstrict = true})) |
|
270 |
|
271 -- invalid sequences |
|
272 p = lxp.new{} |
|
273 assert(p:parse[[<to></to>]]) |
|
274 assert(p:parse()) |
|
275 assert(p:parse(" ") == nil) |
|
276 |
|
277 -- closing unfinished document |
|
278 p = lxp.new{} |
|
279 assert(p:parse[[<to>]]) |
|
280 local status, err = pcall(p.close, p) |
|
281 assert(not status and string.find(err, "error closing parser")) |
|
282 |
|
283 |
|
284 -- test for GC |
|
285 print("\ntesting garbage collection") |
|
286 collectgarbage(); collectgarbage() |
|
287 local x = gcinfo() |
|
288 for i=1,100000 do |
|
289 -- due to a small bug in Lua... |
|
290 if math.mod(i, 100) == 0 then collectgarbage() end |
|
291 lxp.new({}) |
|
292 end |
|
293 collectgarbage(); collectgarbage() |
|
294 assert(math.abs(gcinfo() - x) <= 2) |
|
295 |
|
296 |
|
297 print"OK" |
|
298 |