ea46cdc474
While Lua's built-in pattern support is ok for simple things, many people end up wanting a real regex engine. Since Wireshark already includes the GLib Regex library (a wrapper for PCRE), it makes sense to expose that library to Lua scripts. This has been done using Lrexlib, one of the most popular regex bindings for Lua. Lrexlib didn't support binding GLib's Regex in particular - it does for PCRE but GLib is a different API - so I've done that. A fairly thorough testsuite came along with that, which has been incorporated into the wireshark wslua testuites as well in this commit. Change-Id: I05811d1edf7af8d7c9f4f081de6850f31c0717c7 Reviewed-on: https://code.wireshark.org/review/332 Reviewed-by: Anders Broman <a.broman58@gmail.com>
175 lines
4.4 KiB
Lua
Executable file
175 lines
4.4 KiB
Lua
Executable file
-- See Copyright Notice in the file LICENSE
|
|
|
|
-- arrays: deep comparison
|
|
local function eq (t1, t2, lut)
|
|
if t1 == t2 then return true end
|
|
if type(t1) ~= "table" or type(t2) ~= "table" or #t1 ~= #t2 then
|
|
return false
|
|
end
|
|
|
|
lut = lut or {} -- look-up table: are these 2 arrays already compared?
|
|
lut[t1] = lut[t1] or {}
|
|
if lut[t1][t2] then return true end
|
|
lut[t2] = lut[t2] or {}
|
|
lut[t1][t2], lut[t2][t1] = true, true
|
|
|
|
for k,v in ipairs (t1) do
|
|
if not eq (t2[k], v, lut) then return false end -- recursion
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- a "nil GUID", to be used instead of nils in datasets
|
|
local NT = "b5f74fe5-46f4-483a-8321-e58ba2fa0e17"
|
|
|
|
-- pack vararg in table, replacing nils with "NT" items
|
|
local function packNT (...)
|
|
local t = {}
|
|
for i=1, select ("#", ...) do
|
|
local v = select (i, ...)
|
|
t[i] = (v == nil) and NT or v
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- unpack table into vararg, replacing "NT" items with nils
|
|
local function unpackNT (t)
|
|
local len = #t
|
|
local function unpack_from (i)
|
|
local v = t[i]
|
|
if v == NT then v = nil end
|
|
if i == len then return v end
|
|
return v, unpack_from (i+1)
|
|
end
|
|
if len > 0 then return unpack_from (1) end
|
|
end
|
|
|
|
-- print results (deep into arrays)
|
|
local function print_results (val, indent, lut)
|
|
indent = indent or ""
|
|
lut = lut or {} -- look-up table
|
|
local str = tostring (val)
|
|
if type (val) == "table" then
|
|
if lut[val] then
|
|
io.write (indent, str, "\n")
|
|
else
|
|
lut[val] = true
|
|
io.write (indent, str, "\n")
|
|
for i,v in ipairs (val) do
|
|
print_results (v, " " .. indent, lut) -- recursion
|
|
end
|
|
end
|
|
else
|
|
io.write (indent, val == NT and "nil" or str, "\n")
|
|
end
|
|
end
|
|
|
|
-- returns:
|
|
-- 1) true, if success; false, if failure
|
|
-- 2) test results table or error_message
|
|
local function test_function (test, func)
|
|
local res
|
|
local t = packNT (pcall (func, unpackNT (test[1])))
|
|
if t[1] then
|
|
table.remove (t, 1)
|
|
res = t
|
|
if alien then
|
|
local subject = test[1][1]
|
|
local buf = alien.buffer (#subject)
|
|
if #subject > 0 then
|
|
alien.memmove (buf:topointer (), subject, #subject)
|
|
end
|
|
test[1][1] = buf
|
|
local t = packNT (pcall (func, unpackNT (test[1])))
|
|
if t[1] then
|
|
table.remove (t, 1)
|
|
res = t
|
|
else
|
|
print "alien test failed"
|
|
res = t[2] --> error_message
|
|
end
|
|
end
|
|
else
|
|
res = t[2] --> error_message
|
|
end
|
|
local how = (type (res) == type (test[2])) and
|
|
(type (res) == "string" or eq (res, test[2])) -- allow error messages to differ
|
|
return how, res
|
|
end
|
|
|
|
-- returns:
|
|
-- 1) true, if success; false, if failure
|
|
-- 2) test results table or error_message
|
|
-- 3) test results table or error_message
|
|
local function test_method (test, constructor, name)
|
|
local res1, res2
|
|
local subject = test[2][1]
|
|
local ok, r = pcall (constructor, unpackNT (test[1]))
|
|
if ok then
|
|
local t = packNT (pcall (r[name], r, unpackNT (test[2])))
|
|
if t[1] then
|
|
table.remove (t, 1)
|
|
res1, res2 = t
|
|
else
|
|
res1, res2 = 2, t[2] --> 2, error_message
|
|
end
|
|
else
|
|
res1, res2 = 1, r --> 1, error_message
|
|
end
|
|
return eq (res1, test[3]), res1, res2
|
|
end
|
|
|
|
-- returns: a list of failed tests
|
|
local function test_set (set, lib, verbose)
|
|
local list = {}
|
|
|
|
if type (set.Func) == "function" then
|
|
local func = set.Func
|
|
|
|
for i,test in ipairs (set) do
|
|
if verbose then
|
|
io.write (" running function test "..i.."...")
|
|
io.flush ()
|
|
end
|
|
local ok, res = test_function (test, func)
|
|
if not ok then
|
|
if verbose then io.stdout:write("failed!\n") end
|
|
table.insert (list, {i=i, test[2], res})
|
|
elseif verbose then
|
|
io.write ("passed\n")
|
|
io.flush ()
|
|
end
|
|
end
|
|
|
|
elseif type (set.Method) == "string" then
|
|
for i,test in ipairs (set) do
|
|
if verbose then
|
|
io.write (" running method test "..i.."...")
|
|
io.flush ()
|
|
end
|
|
local ok, res1, res2 = test_method (test, lib.new, set.Method)
|
|
if not ok then
|
|
if verbose then io.stdout:write("failed!\n") end
|
|
table.insert (list, {i=i, test[3], res1, res2})
|
|
elseif verbose then
|
|
io.write ("passed\n")
|
|
io.flush ()
|
|
end
|
|
end
|
|
|
|
else
|
|
error ("neither set.Func nor set.Method is valid")
|
|
end
|
|
|
|
return list
|
|
end
|
|
|
|
return {
|
|
eq = eq,
|
|
NT = NT,
|
|
print_results = print_results,
|
|
test_function = test_function,
|
|
test_method = test_method,
|
|
test_set = test_set,
|
|
}
|