require"lxp"
print(' lxp ===================================================')
print (lxp._VERSION)
-- basic test with no preamble
local p = lxp.new{}
p:setencoding("ISO-8859-1")
assert(p:parse[[hi]])
p:close()
preamble = [[
]>
]]
local X
function getargs (...) X = arg end
function xgetargs (c)
return function (...)
table.insert(arg, 1, c)
table.insert(X, arg)
end
end
-------------------------------
print("testing start/end tags")
callbacks = {
StartElement = getargs,
EndElement = getargs,
}
p = lxp.new(callbacks)
assert(p:getcallbacks() == callbacks)
assert(p:parse(preamble))
assert(p:parse([[
]]))
assert(X.n == 3 and X[1] == p and X[2] == "to")
x = X[3]
assert(x.priority=="10" and x.xu=="hi" and x.method=="POST")
assert(x[1] == "priority" and x[2] == "xu" and table.getn(x) == 2)
assert(p:parse(""))
assert(p:parse())
p:close()
-------------------------------
print("testing CharacterData/Cdata")
callbacks = {
CharacterData = getargs,
}
p = lxp.new(callbacks)
assert(p:parse(preamble))
assert(p:parse"a basic text<>]]>")
assert(X[1] == p and X[2] == "a basic text<<>")
callbacks.chardata = error -- no more calls to `chardata'
assert(p:parse(""))
assert(p:parse())
-- assert(p:parse()) -- no problem to finish twice. alas, it has problems
assert(p:getcallbacks() == callbacks)
p:close()
-------------------------------
callbacks = {
CharacterData = xgetargs"c",
StartCdataSection = xgetargs"s",
EndCdataSection = xgetargs"e",
}
X = {}
p = lxp.new(callbacks)
assert(p:parse(preamble))
assert(p:parse"")
assert(p:parse"")
assert(table.getn(X) == 3)
assert(X[1][1] == "s" and X[1][2] == p)
assert(X[2][1] == "c" and X[2][2] == p and X[2][3] == "hi")
assert(X[3][1] == "e" and X[3][2] == p)
assert(p:parse"")
p:close()
-------------------------------
print("testing ProcessingInstruction")
callbacks = {ProcessingInstruction = getargs}
p = lxp.new(callbacks)
assert(p:parse[[
? ?>
]])
assert(X[1] == p and X[2] == "lua" and
X[3] == "how is this passed to ? ")
p:close()
------------------------------
print("testing Comment")
callbacks = {Comment = xgetargs"c"; CharacterData = xgetargs"t"}
X = {}
p = lxp.new(callbacks)
assert(p:parse[[
some text
some more text
]])
p:close()
assert(X[1][1] == "t" and X[2][1] == "c" and X[3][1] == "t")
assert(X[1][2] == X[2][2] and X[2][2] == X[3][2] and X[3][2] == p)
assert(X[1][3] == "some text\n")
assert(X[2][3] == " with some & symbols ")
assert(X[3][3] == "\nsome more text")
----------------------------
print("testing ExternalEntity")
entities = {
["entity1.xml"] = ""
}
callbacks = {StartElement = xgetargs"s", EndElement = xgetargs"e",
ExternalEntityRef = function (p, context, base, systemID, publicId)
assert(base == "/base")
return context:parse(entities[systemID])
end}
X = {}
p = lxp.new(callbacks)
p:setbase("/base")
assert(p:parse(preamble))
assert(p:parse[[
&test-entity;
]])
assert(p:getbase() == "/base")
p:close()
assert(X[1][1] == "s" and X[1][3] == "to")
assert(X[2][1] == "s" and X[2][3] == "hi")
assert(X[3][1] == "e" and X[3][3] == "hi")
assert(X[4][1] == "e" and X[4][3] == "to")
----------------------------
print("testing default handles")
text = [[ hi &xuxu; ]]
local t = ""
callbacks = { Default = function (p, s) t = t .. s end }
p = lxp.new(callbacks)
assert(p:parse(preamble))
assert(p:parse(text))
p:close()
assert(t == preamble..text)
t = ""
callbacks = { DefaultExpand = function (p, s) t = t .. s end }
p = lxp.new(callbacks)
assert(p:parse(preamble))
assert(p:parse(text))
p:close()
assert(t == preamble..string.gsub(text, "&xuxu;", "is this a xuxu?"))
----------------------------
print("testing notation declarations and unparsed entities")
callbacks = {
UnparsedEntityDecl = getargs,
NotationDecl = function (p, name, base, systemId, publicId)
assert(name == "TXT" and systemId == "txt" and base == "/base")
end,
}
p = lxp.new(callbacks)
p:setbase("/base")
assert(p:parse(preamble))
assert(p:parse[[]])
p:close()
assert(X[2] == "test-unparsed" and X[3] == "/base" and
X[4] == "unparsed.txt" and X[6] == "txt" and X.n == 6)
----------------------------
print("testing namespace declarations")
callbacks = { StartNamespaceDecl = xgetargs"sn",
EndNamespaceDecl = xgetargs"en",
StartElement = xgetargs"s",
EndElement = xgetargs"e",
}
X = {}
p = lxp.new(callbacks, "?")
assert(p:parse[[
]])
p:close()
x = X[1]
assert(x[1] == "sn" and x[3] == "space" and x[4] == "a/namespace" and table.getn(x) == 4)
x = X[3]
assert(x[1] == "s" and x[3] == "a/namespace?a")
x = X[4]
assert(x[1] == "e" and x[3] == "a/namespace?a")
x = X[6]
assert(x[1] == "en" and x[3] == "space" and table.getn(x) == 3)
-- Error reporting
p = lxp.new{}
data = [[
]]
local status, msg, line, col, byte = p:parse(data)
assert(status == nil and type(msg) == "string" and line == 2 and col == 9)
assert(string.sub(data, byte, byte) == "<")
p = lxp.new{}
p:parse("")
local status, msg, line, col, byte = p:parse()
assert(status == nil and line == 1 and col == 5)
-- position reporting
callbacks = { ProcessingInstruction = function (p)
X = {p:pos()}
end
}
p = lxp.new(callbacks)
assert(p:parse[[
]])
p:close()
assert(X[1] == 1 and X[2] == 6 and X[3] == 6) -- line, column, abs. position
print("testing errors")
-- invalid keys
assert(not pcall(lxp.new, {StatCdata=print}))
assert(pcall(lxp.new, {StatCdata=print, _nonstrict = true}))
-- invalid sequences
p = lxp.new{}
assert(p:parse[[]])
assert(p:parse())
assert(p:parse(" ") == nil)
-- closing unfinished document
p = lxp.new{}
assert(p:parse[[]])
local status, err = pcall(p.close, p)
assert(not status and string.find(err, "error closing parser"))
-- test for GC
print("\ntesting garbage collection")
collectgarbage(); collectgarbage()
local x = gcinfo()
for i=1,100000 do
-- due to a small bug in Lua...
if math.mod(i, 100) == 0 then collectgarbage() end
lxp.new({})
end
collectgarbage(); collectgarbage()
assert(math.abs(gcinfo() - x) <= 2)
print"OK"
print(' lxp ===================================================')
print(' lxp.lom ================================================')
require "modules.lom"
local lom = lxp.lom
local tests = {
[[inside tag `abc']],
[[
some text
]],
}
function table._tostring (tab, indent, spacing)
local s = {}
spacing = spacing or ""
indent = indent or "\t"
table.insert (s, "{\n")
for nome, val in pairs (tab) do
table.insert (s, spacing..indent)
local t = type(nome)
if t == "string" then
table.insert (s, string.format ("[%q] = ", tostring (nome)))
elseif t == "number" or t == "boolean" then
table.insert (s, string.format ("[%s] = ", tostring (nome)))
else
table.insert (s, t)
end
t = type(val)
if t == "string" or t == "number" then
table.insert (s, string.format ("%q", val))
elseif t == "table" then
table.insert (s, table._tostring (val, indent, spacing..indent))
else
table.insert (s, t)
end
table.insert (s, ",\n")
end
table.insert (s, spacing.."}")
return table.concat (s)
end
function table.print (tab, indent, spacing)
io.write (table._tostring (tab, indent, spacing))
end
for i, s in ipairs(tests) do
--s = string.gsub (s, "[\n\r\t]", "")
local ds = assert (lom.parse ([[]]..s))
print(table._tostring(ds))
end
print(' lxp.lom ================================================')