gsize byteset[32 / sizeof(gsize)];
const char *p = s, *end = s + len;
+ if (!e[0]) {
+ /* Empty set - nothing matches */
+ return 0;
+ }
+
if (!e[1]) {
+ /* Single character optimization */
for (; p < end && *p == *e; p++);
return p - s;
}
local getfenv = _G.getfenv or compat_env.getfenv
local setfenv = _G.setfenv or compat_env.setfenv
+-- Lua 5.2+ compatibility: unpack was moved to table.unpack
+local unpack = _G.unpack or table.unpack
+
local _VERSION = "0.6.0"
context("Regexp unit tests", function()
local re = require("rspamd_regexp")
-
+
test("Regexp creation", function()
assert_not_nil(re.create_cached('/test$/m'))
assert_not_nil(re.create_cached('^test$', 'm'))
-- Cyrillic utf8 letter
{'/\\S<[-\\w\\.]+\\@[-\\w\\.]+>/r', 'some<example@exаmple.com>', false},
}
-
+
for _,c in ipairs(cases) do
local r = re.create_cached(c[1])
assert_not_nil(r, "cannot parse " .. c[1])
local res = r:match(c[2])
-
+
assert_equal(res, c[3], string.format("'%s' doesn't match with '%s'",
c[2], c[1]))
end
end)
-
+
test("Regexp capture", function()
local cases = {
- {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
- 'mc-filter4 1120; Body=1 Fuz1=2 Fuz2=3',
+ {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
+ 'mc-filter4 1120; Body=1 Fuz1=2 Fuz2=3',
{'Body=1 Fuz1=2 Fuz2=3', '1', '2', '3'}},
- {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
+ {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
'mc-filter4 1120; Body=1 Fuz1=2', {'Body=1 Fuz1=2', '1', '2'}},
- {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
- 'mc-filter4 1120; Body=1 Fuz1=2 mc-filter4 1120; Body=1 Fuz1=2 Fuz2=3',
+ {'Body=(\\S+)(?: Fuz1=(\\S+))?(?: Fuz2=(\\S+))?',
+ 'mc-filter4 1120; Body=1 Fuz1=2 mc-filter4 1120; Body=1 Fuz1=2 Fuz2=3',
{'Body=1 Fuz1=2', '1', '2'}, {'Body=1 Fuz1=2 Fuz2=3', '1', '2', '3'}},
}
for _,c in ipairs(cases) do
local r = re.create_cached(c[1])
assert_not_nil(r, "cannot parse " .. c[1])
local res = r:search(c[2], false, true)
-
+
assert_not_nil(res, "cannot find pattern")
-
- for k = 3, table.maxn(c) do
+
+ for k = 3, #c do
for n,m in ipairs(c[k]) do
assert_equal(res[k - 2][n], c[k][n], string.format("'%s' doesn't match with '%s'",
c[k][n], res[k - 2][n]))
end
end
end)
-
+
test("Regexp split", function()
local cases = {
{'\\s', 'one', {'one'}}, -- one arg
{'\\s', ' one two ', {'one', 'two'}}, -- multiple delimiters
{'\\s', ' one ', {'one'}}, -- multiple delimiters
{'[:,]', ',,,:::one,two,,', {'one', 'two'}}, -- multiple delimiters
- {'[\\|\\s]', '16265 | 1.1.1.0/22 | TR | ripencc | 2014-02-28',
+ {'[\\|\\s]', '16265 | 1.1.1.0/22 | TR | ripencc | 2014-02-28',
{'16265', '1.1.1.0/22', 'TR', 'ripencc', '2014-02-28'}}, -- practical
{'|', '16265 | 1.1.1.0/22 | TR | ripencc | 2014-02-28', {}} -- bad re
}
-
+
for _,c in ipairs(cases) do
local r = re.create_cached(c[1])
assert_not_nil(r, "cannot parse " .. c[1])
-
+
local res = r:split(c[2])
assert_not_nil(res, "cannot split " .. c[2])
-
+
for i,r in ipairs(c[3]) do
assert_equal(res[i], r)
end
end
end)
-
+
end
)
\ No newline at end of file
["pool_var double"] = {
selector = [[pool_var("int_var", 'double')]],
- expect = {"1"}},
+ expect = {"1.0"}},
["time"] = {
selector = "time",
- expect = {"1537364211"}},
+ expect = {"1537364211.0"}},
-- ["request_header"] = {
-- selector = "request_header(hdr1)",
'<a@example.com><>',
}
+ -- Helper to check if a cdata pointer is NULL (cffi-lua compatibility)
+ local function is_null(ptr)
+ if ptr == nil then return true end
+ -- For cffi-lua, check if pointer equals NULL
+ return ptr == ffi.new('void*')
+ end
+
fun.each(function(case)
test("Parse invalid smtp addr: " .. case, function()
local st = ffi.C.rspamd_email_address_from_smtp(case, #case)
- assert_nil(st, "should not be able to parse " .. case)
+ assert_true(is_null(st), "should not be able to parse " .. case)
end)
end, cases_invalid)
{ "///foo", "/foo" },
}
+ -- Helper to convert cdata numbers to Lua numbers (cffi-lua compatibility)
+ local function cdata_to_number(v)
+ -- Try tonumber first (works in LuaJIT and for small values)
+ local n = tonumber(v)
+ if n then return n end
+ -- For 64-bit integers in cffi-lua, convert via string
+ return tonumber(tostring(v):match("^(%d+)"))
+ end
+
for i, v in ipairs(cases) do
test(string.format("Normalize paths '%s'", v[1]), function()
- local buf = ffi.new("uint8_t[?]", #v[1])
+ local buf = ffi.new("char[?]", #v[1])
local sizbuf = ffi.new("size_t[1]")
ffi.copy(buf, v[1], #v[1])
ffi.C.rspamd_normalize_path_inplace(buf, #v[1], sizbuf)
- local res = ffi.string(buf, tonumber(sizbuf[0]))
+ local res = ffi.string(buf, cdata_to_number(sizbuf[0]))
assert_equal(v[2], res, 'expected ' .. v[2] .. ' but got ' .. res .. ' in path ' .. v[1])
end)
end
void rspamd_fast_utf8_library_init (unsigned flags);
void ottery_rand_bytes(void *buf, size_t n);
double rspamd_get_ticks(int allow);
- size_t rspamd_fast_utf8_validate (const unsigned char *data, size_t len);
- size_t rspamd_fast_utf8_validate_ref (const unsigned char *data, size_t len);
+ size_t rspamd_fast_utf8_validate (const char *data, size_t len);
+ size_t rspamd_fast_utf8_validate_ref (const char *data, size_t len);
char * rspamd_str_make_utf_valid (const char *src, size_t slen, size_t *dstlen, void *);
]]
end)
end
+ -- Helper to convert cdata numbers to Lua numbers (cffi-lua compatibility)
+ local function cdata_to_number(v)
+ -- Try tonumber first (works in LuaJIT and for small values)
+ local n = tonumber(v)
+ if n then return n end
+ -- For 64-bit integers in cffi-lua, convert via string
+ return tonumber(tostring(v):match("^(%d+)"))
+ end
+
-- Enable sse and avx2
ffi.C.rspamd_fast_utf8_library_init(3)
local valid_cases = {
ffi.copy(buf, c)
local ret = ffi.C.rspamd_fast_utf8_validate(buf, #c)
- assert_equal(ret, 0)
+ assert_equal(cdata_to_number(ret), 0)
end)
end
local invalid_cases = {
ffi.copy(buf, c)
local ret = ffi.C.rspamd_fast_utf8_validate(buf, #c)
- assert_not_equal(ret, 0)
+ assert_not_equal(cdata_to_number(ret), 0)
end)
end
t1 = rspamd_get_virtual_ticks();
for (i = 0; i < N; i++) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, function_call);
+ /* In Lua 5.4, lua_resume must be called on a coroutine, not the main thread */
+ lua_State *coro = lua_newthread(L);
+ lua_rawgeti(coro, LUA_REGISTRYINDEX, function_call);
#if LUA_VERSION_NUM < 502
- lua_resume(L, 0);
+ lua_resume(coro, 0);
#elif LUA_VERSION_NUM >= 504
- lua_resume(L, NULL, 0, NULL);
+ int nres;
+ lua_resume(coro, NULL, 0, &nres);
#else
- lua_resume(L, NULL, 0);
+ lua_resume(coro, NULL, 0);
#endif
- lua_pop(L, 1);
+ lua_pop(coro, 1);
+ lua_pop(L, 1); /* pop the coroutine from main state */
}
t2 = rspamd_get_virtual_ticks();
#if LUA_VERSION_NUM < 502
lua_resume(ent->lua_state, 0);
#elif LUA_VERSION_NUM >= 504
- lua_resume(ent->lua_state, NULL, 0, NULL);
+ int nres;
+ lua_resume(ent->lua_state, NULL, 0, &nres);
#else
lua_resume(ent->lua_state, NULL, 0);
#endif
#if LUA_VERSION_NUM < 502
lua_resume(ent->lua_state, 0);
#elif LUA_VERSION_NUM >= 504
- lua_resume(ent->lua_state, NULL, 0, NULL);
+ int nres;
+ lua_resume(ent->lua_state, NULL, 0, &nres);
#else
lua_resume(ent->lua_state, NULL, 0);
#endif