]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Test] Functional test for lua_extras two-phase loader 6020/head
authorVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 5 May 2026 19:43:53 +0000 (20:43 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 5 May 2026 19:43:53 +0000 (20:43 +0100)
Adds Functional.Cases.001_Merged.271_Lua_Extras with two cases:

* the deferred-selector regexp fires when the From-domain is present in
  the map captured by the selector factory;
* the same regexp stays silent when the From-domain is absent.

The companion lua_extras_test.lua stages a tree under TMPDIR with maps,
selectors and regexps subdirectories, then calls lua_extras.load_extras
on it. The selector entry is wrapped in lua_extras.deferred so the
factory captures rspamd_maps[name] at registration time, exercising the
maps -> selectors -> regexps phase 2 ordering and the re_selector
auto-binding into the regexp DSL.

Also wires the new lua file into merged.conf alongside selector_test.lua.

test/functional/cases/001_merged/271_lua_extras.robot [new file with mode: 0644]
test/functional/configs/merged.conf
test/functional/lua/lua_extras_test.lua [new file with mode: 0644]
test/functional/messages/lua_extras_in_map.eml [new file with mode: 0644]
test/functional/messages/lua_extras_not_in_map.eml [new file with mode: 0644]

diff --git a/test/functional/cases/001_merged/271_lua_extras.robot b/test/functional/cases/001_merged/271_lua_extras.robot
new file mode 100644 (file)
index 0000000..8f84142
--- /dev/null
@@ -0,0 +1,19 @@
+*** Settings ***
+Library         ${RSPAMD_TESTDIR}/lib/rspamd.py
+Resource        ${RSPAMD_TESTDIR}/lib/rspamd.robot
+Variables       ${RSPAMD_TESTDIR}/lib/vars.py
+
+*** Variables ***
+${MSG_IN_MAP}      ${RSPAMD_TESTDIR}/messages/lua_extras_in_map.eml
+${MSG_NOT_IN_MAP}  ${RSPAMD_TESTDIR}/messages/lua_extras_not_in_map.eml
+
+*** Test Cases ***
+Lua_extras deferred selector fires regexp when From in map
+  Scan File  ${MSG_IN_MAP}
+  ...  Settings={symbols_enabled = [TEST_EXTRAS_LOCAL_FROM]}
+  Expect Symbol  TEST_EXTRAS_LOCAL_FROM
+
+Lua_extras deferred selector silent when From not in map
+  Scan File  ${MSG_NOT_IN_MAP}
+  ...  Settings={symbols_enabled = [TEST_EXTRAS_LOCAL_FROM]}
+  Do Not Expect Symbol  TEST_EXTRAS_LOCAL_FROM
index a2c2963f14b895dcd302aef981b382fdc0c6a645..6e270432a5d6a96be5523efbff2b2b0b99aed2d4 100644 (file)
@@ -25,6 +25,9 @@ lua = "{= env.TESTDIR =}/lua/dns.lua"
 # 270_selector
 lua = "{= env.TESTDIR =}/lua/selector_test.lua"
 
+# 271_lua_extras
+lua = "{= env.TESTDIR =}/lua/lua_extras_test.lua"
+
 # 281_fnames
 lua = "{= env.TESTDIR =}/lua/test_fname.lua"
 
diff --git a/test/functional/lua/lua_extras_test.lua b/test/functional/lua/lua_extras_test.lua
new file mode 100644 (file)
index 0000000..e8421be
--- /dev/null
@@ -0,0 +1,74 @@
+-- Functional test for the structured lua.local.d/{maps,selectors,regexps}
+-- loader (lua_extras). Stages a small tree under TMPDIR and calls
+-- lua_extras.load_extras() to register a map, a deferred selector that
+-- captures rspamd_maps[name] in its factory, and a regexp using that
+-- selector through the regexp DSL. The companion robot test then asserts
+-- the symbol fires only when the From-domain is present in the map.
+
+local lua_extras = require "lua_extras"
+
+local tmpdir = os.getenv('TMPDIR') or '/tmp'
+local base = tmpdir .. '/lua_extras_test'
+
+-- Always start clean
+os.execute('rm -rf "' .. base .. '"')
+os.execute('mkdir -p "' .. base .. '/maps" "' .. base .. '/selectors" "' .. base .. '/regexps"')
+
+local function write_file(path, content)
+  local f = assert(io.open(path, 'w'))
+  f:write(content)
+  f:close()
+end
+
+-- Map data
+local map_list = base .. '/local_domains.list'
+write_file(map_list, 'example.com\nlocal.test\n')
+
+-- Map definition
+write_file(base .. '/maps/test_extras.lua', string.format([[
+return {
+  example_local_domains = {
+    type = 'set',
+    description = 'TEST: local domains',
+    url = '%s',
+  },
+}
+]], map_list))
+
+-- Deferred selector capturing the map ref at registration time. This is the
+-- whole point of the two-phase loader: by the time this factory runs, the
+-- map above has already been registered and rspamd_maps[name] is populated.
+write_file(base .. '/selectors/test_extras.lua', [[
+local lua_extras = require "lua_extras"
+return {
+  test_extras_local_domain = lua_extras.deferred(function()
+    local domains = rspamd_maps.example_local_domains
+    return {
+      description = 'TEST: From-domain when present in example_local_domains map',
+      re_selector = true,
+      get_value = function(task)
+        local from = task:get_from('mime')
+        local dom = from and from[1] and from[1].domain or nil
+        if dom and domains and domains:get_key(dom) then
+          return dom, 'string'
+        end
+        return nil
+      end,
+    }
+  end),
+}
+]])
+
+-- Regexp symbol firing when the deferred selector resolves a non-nil value.
+write_file(base .. '/regexps/test_extras.lua', [[
+return {
+  TEST_EXTRAS_LOCAL_FROM = {
+    re = 'test_extras_local_domain=/.+/{selector}',
+    score = 0.1,
+    description = 'TEST: From present in example_local_domains map',
+  },
+}
+]])
+
+-- Trigger the structured loader on our staged tree.
+lua_extras.load_extras(rspamd_config, base)
diff --git a/test/functional/messages/lua_extras_in_map.eml b/test/functional/messages/lua_extras_in_map.eml
new file mode 100644 (file)
index 0000000..e22132c
--- /dev/null
@@ -0,0 +1,5 @@
+From: alice@example.com
+To: bob@elsewhere.test
+Subject: in map
+
+body
diff --git a/test/functional/messages/lua_extras_not_in_map.eml b/test/functional/messages/lua_extras_not_in_map.eml
new file mode 100644 (file)
index 0000000..866e6bc
--- /dev/null
@@ -0,0 +1,5 @@
+From: alice@unknown.test
+To: bob@elsewhere.test
+Subject: not in map
+
+body