summaryrefslogtreecommitdiffstats
path: root/test/functional/lib/rspamd.robot
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/lib/rspamd.robot')
-rw-r--r--test/functional/lib/rspamd.robot398
1 files changed, 398 insertions, 0 deletions
diff --git a/test/functional/lib/rspamd.robot b/test/functional/lib/rspamd.robot
new file mode 100644
index 0000000..696b5f9
--- /dev/null
+++ b/test/functional/lib/rspamd.robot
@@ -0,0 +1,398 @@
+*** Settings ***
+Library Collections
+Library OperatingSystem
+Library Process
+
+*** Keywords ***
+Check Controller Errors
+ @{result} = HTTP GET ${RSPAMD_LOCAL_ADDR} ${RSPAMD_PORT_CONTROLLER} /errors
+ Should Be Equal As Integers ${result}[0] 200
+ Log ${result}[1]
+
+Check Pidfile
+ [Arguments] ${pidfile} ${timeout}=1 min
+ Wait Until Created ${pidfile} timeout=${timeout}
+ ${size} = Get File Size ${pidfile}
+ Should Not Be Equal As Integers ${size} 0
+
+Check Rspamc
+ [Arguments] ${result} @{args} &{kwargs}
+ IF ${result.rc} != 0
+ Log ${result.stderr}
+ END
+ ${has_rc} = Evaluate 'rc' in $kwargs
+ ${inverse} = Evaluate 'inverse' in $kwargs
+ ${re} = Evaluate 're' in $kwargs
+ ${rc} = Set Variable If ${has_rc} == True ${kwargs}[rc] 0
+ FOR ${i} IN @{args}
+ IF ${re} == True
+ Check Rspamc Match Regexp ${result.stdout} ${i} ${inverse}
+ ELSE
+ Check Rspamc Match String ${result.stdout} ${i} ${inverse}
+ END
+ END
+ IF @{args} == @{EMPTY}
+ Check Rspamc Match Default ${result.stdout} ${inverse}
+ END
+ Should Be Equal As Integers ${result.rc} ${rc}
+
+Check Rspamc Match Default
+ [Arguments] ${subject} ${inverse}
+ IF ${inverse} == False
+ Should Contain ${subject} success = true
+ ELSE
+ Should Not Contain ${subject} success = true
+ END
+
+Check Rspamc Match Regexp
+ [Arguments] ${subject} ${re} ${inverse}
+ IF ${inverse} == False
+ Should Match Regexp ${subject} ${re}
+ ELSE
+ Should Not Match Regexp ${subject} ${re}
+ END
+
+Check Rspamc Match String
+ [Arguments] ${subject} ${str} ${inverse}
+ IF ${inverse} == False
+ Should Contain ${subject} ${str}
+ ELSE
+ Should Not Contain ${subject} ${str}
+ END
+
+Do Not Expect Symbol
+ [Arguments] ${symbol}
+ Dictionary Should Not Contain Key ${SCAN_RESULT}[symbols] ${symbol}
+ ... msg=Symbol ${symbol} was not expected to be found in result
+
+Do Not Expect Symbols
+ [Arguments] @{symbols}
+ FOR ${symbol} IN @{symbols}
+ Dictionary Should Not Contain Key ${SCAN_RESULT}[symbols] ${symbol}
+ ... msg=Symbol ${symbol} was not expected to be found in result
+ END
+
+Expect Action
+ [Arguments] ${action}
+ Should Be Equal ${SCAN_RESULT}[action] ${action}
+
+Expect Email
+ [Arguments] ${email}
+ List Should Contain Value ${SCAN_RESULT}[emails] ${email}
+
+Expect Required Score
+ [Arguments] ${required_score}
+ Should Be Equal As Numbers ${SCAN_RESULT}[required_score] ${required_score}
+
+Expect Required Score To Be Null
+ Should Be Equal ${SCAN_RESULT}[required_score] ${NONE}
+
+Expect Score
+ [Arguments] ${score}
+ Should Be Equal As Numbers ${SCAN_RESULT}[score] ${score}
+
+Expect Symbol
+ [Arguments] ${symbol}
+ Dictionary Should Contain Key ${SCAN_RESULT}[symbols] ${symbol}
+ ... msg=Symbol ${symbol} wasn't found in result
+
+Expect URL
+ [Arguments] ${url}
+ List Should Contain Value ${SCAN_RESULT}[urls] ${url}
+
+Expect Extended URL
+ [Arguments] ${url}
+ ${found_url} = Set Variable ${FALSE}
+ ${url_list} = Convert To List ${SCAN_RESULT}[urls]
+ FOR ${item} IN @{url_list}
+ ${d} = Convert To Dictionary ${item}
+ ${found_url} = Evaluate "${d}[url]" == "${url}"
+ Exit For Loop If ${found_url} == ${TRUE}
+ END
+ Should Be True ${found_url} msg="Expected URL was not found: ${url}"
+
+Expect Symbol With Exact Options
+ [Arguments] ${symbol} @{options}
+ Expect Symbol ${symbol}
+ ${have_options} = Convert To List ${SCAN_RESULT}[symbols][${symbol}][options]
+ Lists Should Be Equal ${have_options} ${options} ignore_order=True
+ ... msg="Symbol ${symbol} has options ${SCAN_RESULT}[symbols][${symbol}][options] but expected ${options}"
+
+Expect Symbol With Option
+ [Arguments] ${symbol} ${option}
+ Expect Symbol ${symbol}
+ ${have_options} = Convert To List ${SCAN_RESULT}[symbols][${symbol}][options]
+ Should Contain ${have_options} ${option}
+ ... msg="Options for symbol ${symbol} ${SCAN_RESULT}[symbols][${symbol}][options] doesn't contain ${option}"
+
+Expect Symbol With Score
+ [Arguments] ${symbol} ${score}
+ Dictionary Should Contain Key ${SCAN_RESULT}[symbols] ${symbol}
+ ... msg=Symbol ${symbol} wasn't found in result
+ Should Be Equal As Numbers ${SCAN_RESULT}[symbols][${symbol}][score] ${score}
+ ... msg="Symbol ${symbol} has score of ${SCAN_RESULT}[symbols][${symbol}][score] but expected ${score}"
+
+Expect Symbols
+ [Arguments] @{symbols}
+ FOR ${symbol} IN @{symbols}
+ Dictionary Should Contain Key ${SCAN_RESULT}[symbols] ${symbol}
+ ... msg=Symbol ${symbol} wasn't found in result
+ END
+
+Expect Symbols With Scores
+ [Arguments] &{symscores}
+ FOR ${key} ${value} IN &{symscores}
+ Dictionary Should Contain Key ${SCAN_RESULT}[symbols] ${key}
+ ... msg=Symbol ${key} wasn't found in result
+ Should Be Equal As Numbers ${SCAN_RESULT}[symbols][${key}][score] ${value}
+ ... msg="Symbol ${key} has score of ${SCAN_RESULT}[symbols][${key}][score] but expected ${value}"
+ END
+
+Expect Symbol With Score And Exact Options
+ [Arguments] ${symbol} ${score} @{options}
+ Expect Symbol With Exact Options ${symbol} @{options}
+ Expect Symbol With Score ${symbol} ${score}
+
+Export Rspamd Variables To Environment
+ &{all_vars} = Get Variables no_decoration=True
+ FOR ${k} ${v} IN &{all_vars}
+ IF '${k}'.startswith("RSPAMD_")
+ Set Environment Variable ${k} ${v}
+ END
+ END
+
+Export Scoped Variables
+ [Arguments] ${scope} &{vars}
+ IF '${scope}' == 'Test'
+ FOR ${k} ${v} IN &{vars}
+ Set Test Variable ${${k}} ${v}
+ END
+ ELSE IF '${scope}' == 'Suite'
+ FOR ${k} ${v} IN &{vars}
+ Set Suite Variable ${${k}} ${v}
+ END
+ ELSE IF '${scope}' == 'Global'
+ FOR ${k} ${v} IN &{vars}
+ Set Global Variable ${${k}} ${v}
+ END
+ ELSE
+ Fail message="Don't know what to do with scope: ${scope}"
+ END
+
+Log does not contain segfault record
+ ${log} = Get File ${RSPAMD_TMPDIR}/rspamd.log encoding_errors=ignore
+ Should not contain ${log} (Segmentation fault) msg=Segmentation fault detected
+
+Redis HSET
+ [Arguments] ${hash} ${key} ${value}
+ ${result} = Run Process redis-cli -h ${RSPAMD_REDIS_ADDR} -p ${RSPAMD_REDIS_PORT}
+ ... HSET ${hash} ${key} ${value}
+ IF ${result.rc} != 0
+ Log ${result.stderr}
+ END
+ Log ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Redis SET
+ [Arguments] ${key} ${value}
+ ${result} = Run Process redis-cli -h ${RSPAMD_REDIS_ADDR} -p ${RSPAMD_REDIS_PORT}
+ ... SET ${key} ${value}
+ IF ${result.rc} != 0
+ Log ${result.stderr}
+ END
+ Log ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Redis Teardown
+ ${redis_pid} = Get Variable Value ${REDIS_PID}
+ Shutdown Process With Children ${redis_pid}
+ Cleanup Temporary Directory ${REDIS_TMPDIR}
+
+Rspamd Setup
+ # Create and chown temporary directory
+ ${RSPAMD_TMPDIR} = Make Temporary Directory
+ Set Directory Ownership ${RSPAMD_TMPDIR} ${RSPAMD_USER} ${RSPAMD_GROUP}
+
+ # Export ${RSPAMD_TMPDIR} to appropriate scope according to ${RSPAMD_SCOPE}
+ Export Scoped Variables ${RSPAMD_SCOPE} RSPAMD_TMPDIR=${RSPAMD_TMPDIR}
+
+ Run Rspamd
+
+Rspamd Redis Setup
+ Run Redis
+ Rspamd Setup
+
+Rspamd Teardown
+ IF '${CONTROLLER_ERRORS}' == 'True'
+ Run Keyword And Warn On Failure Check Controller Errors
+ END
+ Shutdown Process With Children ${RSPAMD_PID}
+ Save Run Results ${RSPAMD_TMPDIR} configdump.stdout configdump.stderr rspamd.stderr rspamd.stdout rspamd.conf rspamd.log redis.log clickhouse-config.xml
+ Log does not contain segfault record
+ Collect Lua Coverage
+ Cleanup Temporary Directory ${RSPAMD_TMPDIR}
+
+Rspamd Redis Teardown
+ Rspamd Teardown
+ Redis Teardown
+
+Run Redis
+ ${RSPAMD_TMPDIR} = Make Temporary Directory
+ ${template} = Get File ${RSPAMD_TESTDIR}/configs/redis-server.conf
+ ${config} = Replace Variables ${template}
+ Create File ${RSPAMD_TMPDIR}/redis-server.conf ${config}
+ Log ${config}
+ ${result} = Run Process redis-server ${RSPAMD_TMPDIR}/redis-server.conf
+ IF ${result.rc} != 0
+ Log ${result.stderr}
+ END
+ Should Be Equal As Integers ${result.rc} 0
+ Wait Until Keyword Succeeds 5x 1 sec Check Pidfile ${RSPAMD_TMPDIR}/redis.pid timeout=0.5s
+ Wait Until Keyword Succeeds 5x 1 sec Redis Check ${RSPAMD_REDIS_ADDR} ${RSPAMD_REDIS_PORT}
+ ${REDIS_PID} = Get File ${RSPAMD_TMPDIR}/redis.pid
+ ${REDIS_PID} = Convert To Number ${REDIS_PID}
+ Export Scoped Variables ${REDIS_SCOPE} REDIS_PID=${REDIS_PID} REDIS_TMPDIR=${RSPAMD_TMPDIR}
+ ${redis_log} = Get File ${RSPAMD_TMPDIR}/redis.log
+ Log ${redis_log}
+
+Run Rspamd
+ Export Rspamd Variables To Environment
+
+ # Dump templated config or errors to log
+ ${result} = Run Process ${RSPAMADM}
+ ... --var\=TMPDIR\=${RSPAMD_TMPDIR}
+ ... --var\=DBDIR\=${RSPAMD_TMPDIR}
+ ... --var\=LOCAL_CONFDIR\=/non-existent
+ ... --var\=CONFDIR\=${RSPAMD_TESTDIR}/../../conf/
+ ... configdump -c ${CONFIG}
+ ... env:RSPAMD_LOCAL_CONFDIR=/non-existent
+ ... env:RSPAMD_TMPDIR=${RSPAMD_TMPDIR}
+ ... env:RSPAMD_CONFDIR=${RSPAMD_TESTDIR}/../../conf/
+ ... env:LD_LIBRARY_PATH=${RSPAMD_TESTDIR}/../../contrib/aho-corasick
+ ... env:RSPAMD_NO_CLEANUP=1
+ ... env:ASAN_OPTIONS=quarantine_size_mb=2048:malloc_context_size=20:fast_unwind_on_malloc=0:log_path=${RSPAMD_TMPDIR}/rspamd-asan
+ # We need to send output to files (or discard output) to avoid hanging Robot
+ ... stdout=${RSPAMD_TMPDIR}/configdump.stdout stderr=${RSPAMD_TMPDIR}/configdump.stderr
+ IF ${result.rc} == 0
+ ${configdump} = Get File ${RSPAMD_TMPDIR}/configdump.stdout encoding_errors=ignore
+ ELSE
+ ${configdump} = Get File ${RSPAMD_TMPDIR}/configdump.stderr encoding_errors=ignore
+ END
+ Log ${configdump}
+
+ # Fix directory ownership (maybe do this somewhere else)
+ Set Directory Ownership ${RSPAMD_TMPDIR} ${RSPAMD_USER} ${RSPAMD_GROUP}
+
+ # Run Rspamd
+ ${result} = Run Process ${RSPAMD} -u ${RSPAMD_USER} -g ${RSPAMD_GROUP}
+ ... -c ${CONFIG}
+ ... --var\=TMPDIR\=${RSPAMD_TMPDIR}
+ ... --var\=DBDIR\=${RSPAMD_TMPDIR}
+ ... --var\=LOCAL_CONFDIR\=/non-existent
+ ... --var\=CONFDIR\=${RSPAMD_TESTDIR}/../../conf/
+ ... env:RSPAMD_LOCAL_CONFDIR=/non-existent
+ ... env:RSPAMD_TMPDIR=${RSPAMD_TMPDIR}
+ ... env:RSPAMD_CONFDIR=${RSPAMD_TESTDIR}/../../conf/
+ ... env:LD_LIBRARY_PATH=${RSPAMD_TESTDIR}/../../contrib/aho-corasick
+ ... env:RSPAMD_NO_CLEANUP=1
+ ... env:ASAN_OPTIONS=quarantine_size_mb=2048:malloc_context_size=20:fast_unwind_on_malloc=0:log_path=${RSPAMD_TMPDIR}/rspamd-asan
+ ... stdout=${RSPAMD_TMPDIR}/rspamd.stdout stderr=${RSPAMD_TMPDIR}/rspamd.stderr
+
+ # Log stdout/stderr
+ ${rspamd_stdout} = Get File ${RSPAMD_TMPDIR}/rspamd.stdout encoding_errors=ignore
+ ${rspamd_stderror} = Get File ${RSPAMD_TMPDIR}/rspamd.stderr encoding_errors=ignore
+ Log ${rspamd_stdout}
+ Log ${rspamd_stderror}
+
+ # Abort if it failed
+ Should Be Equal As Integers ${result.rc} 0
+
+ # Wait for pid file to be written
+ Wait Until Keyword Succeeds 10x 1 sec Check Pidfile ${RSPAMD_TMPDIR}/rspamd.pid timeout=0.5s
+
+ # Confirm worker is reachable
+ Wait Until Keyword Succeeds 5x 1 sec Ping Rspamd ${RSPAMD_LOCAL_ADDR} ${RSPAMD_PORT_NORMAL}
+
+ # Read PID from PIDfile and export it to appropriate scope as ${RSPAMD_PID}
+ ${RSPAMD_PID} = Get File ${RSPAMD_TMPDIR}/rspamd.pid
+ Export Scoped Variables ${RSPAMD_SCOPE} RSPAMD_PID=${RSPAMD_PID}
+
+Run Nginx
+ ${template} = Get File ${RSPAMD_TESTDIR}/configs/nginx.conf
+ ${config} = Replace Variables ${template}
+ Create File ${RSPAMD_TMPDIR}/nginx.conf ${config}
+ Log ${config}
+ ${result} = Run Process nginx -c ${RSPAMD_TMPDIR}/nginx.conf
+ IF ${result.rc} != 0
+ Log ${result.stderr}
+ END
+ Should Be Equal As Integers ${result.rc} 0
+ Wait Until Keyword Succeeds 10x 1 sec Check Pidfile ${RSPAMD_TMPDIR}/nginx.pid timeout=0.5s
+ Wait Until Keyword Succeeds 5x 1 sec TCP Connect ${NGINX_ADDR} ${NGINX_PORT}
+ ${NGINX_PID} = Get File ${RSPAMD_TMPDIR}/nginx.pid
+ IF '${NGINX_SCOPE}' == 'Test'
+ Set Test Variable ${NGINX_PID}
+ ELSE IF '${NGINX_SCOPE}' == 'Suite'
+ Set Suite Variable ${NGINX_PID}
+ END
+ ${nginx_log} = Get File ${RSPAMD_TMPDIR}/nginx.log
+ Log ${nginx_log}
+
+Run Rspamc
+ [Arguments] @{args}
+ ${result} = Run Process ${RSPAMC} -t 60 --header Queue-ID\=${TEST NAME}
+ ... @{args} env:LD_LIBRARY_PATH=${RSPAMD_TESTDIR}/../../contrib/aho-corasick
+ Log ${result.stdout}
+ [Return] ${result}
+
+Scan File By Reference
+ [Arguments] ${filename} &{headers}
+ Set To Dictionary ${headers} File=${filename}
+ ${result} = Scan File /dev/null &{headers}
+ [Return] ${result}
+
+Scan Message With Rspamc
+ [Arguments] ${msg_file} @{vargs}
+ ${result} = Run Rspamc -p -h ${RSPAMD_LOCAL_ADDR}:${RSPAMD_PORT_NORMAL} @{vargs} ${msg_file}
+ [Return] ${result}
+
+Sync Fuzzy Storage
+ [Arguments] @{vargs}
+ ${len} = Get Length ${vargs}
+ IF $len == 0
+ ${result} = Run Process ${RSPAMADM} control -s
+ ... ${RSPAMD_TMPDIR}/rspamd.sock fuzzy_sync
+ ELSE
+ Run Process ${RSPAMADM} control -s ${vargs}[0]/rspamd.sock
+ ... fuzzy_sync
+ END
+ Log ${result.stdout}
+ Sleep 0.1s Try give fuzzy storage time to sync
+
+Run Dummy Http
+ ${fileExists} = File Exists /tmp/dummy_http.pid
+ IF ${fileExists} is True
+ ${http_pid} = Get File /tmp/dummy_http.pid
+ Shutdown Process With Children ${http_pid}
+ END
+ ${result} = Start Process ${RSPAMD_TESTDIR}/util/dummy_http.py -pf /tmp/dummy_http.pid
+ Wait Until Created /tmp/dummy_http.pid timeout=2 second
+
+Run Dummy Https
+ ${fileExists} = File Exists /tmp/dummy_https.pid
+ IF ${fileExists} is True
+ ${http_pid} = Get File /tmp/dummy_https.pid
+ Shutdown Process With Children ${http_pid}
+ END
+ ${result} = Start Process ${RSPAMD_TESTDIR}/util/dummy_http.py
+ ... -c ${RSPAMD_TESTDIR}/util/server.pem -k ${RSPAMD_TESTDIR}/util/server.pem
+ ... -pf /tmp/dummy_https.pid -p 18081
+ Wait Until Created /tmp/dummy_https.pid timeout=2 second
+
+Dummy Http Teardown
+ ${http_pid} = Get File /tmp/dummy_http.pid
+ Shutdown Process With Children ${http_pid}
+
+Dummy Https Teardown
+ ${https_pid} = Get File /tmp/dummy_https.pid
+ Shutdown Process With Children ${https_pid}