summaryrefslogtreecommitdiffstats
path: root/pigeonhole/tests/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /pigeonhole/tests/plugins
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/tests/plugins')
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/addheader6
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/big8
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/cat3
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/cat-stdin3
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/crlf3
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/env3
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/frame7
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/modify8
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/program5
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/replace12
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/sleep103
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/sleep23
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/spamc6
-rwxr-xr-xpigeonhole/tests/plugins/extprograms/bin/stderr20
-rw-r--r--pigeonhole/tests/plugins/extprograms/errors.svtest32
-rw-r--r--pigeonhole/tests/plugins/extprograms/errors/arguments.sieve5
-rw-r--r--pigeonhole/tests/plugins/extprograms/errors/programname.sieve25
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/command.svtest27
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/errors.svtest53
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve38
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve3
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve7
-rw-r--r--pigeonhole/tests/plugins/extprograms/execute/execute.svtest177
-rw-r--r--pigeonhole/tests/plugins/extprograms/filter/command.svtest10
-rw-r--r--pigeonhole/tests/plugins/extprograms/filter/errors.svtest39
-rw-r--r--pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve22
-rw-r--r--pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve3
-rw-r--r--pigeonhole/tests/plugins/extprograms/filter/execute.svtest213
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/command.svtest10
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/errors.svtest94
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve22
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve3
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve3
-rw-r--r--pigeonhole/tests/plugins/extprograms/pipe/execute.svtest56
34 files changed, 932 insertions, 0 deletions
diff --git a/pigeonhole/tests/plugins/extprograms/bin/addheader b/pigeonhole/tests/plugins/extprograms/bin/addheader
new file mode 100755
index 0000000..8f9805a
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/addheader
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo "$1: $2"
+cat
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/big b/pigeonhole/tests/plugins/extprograms/bin/big
new file mode 100755
index 0000000..ce1df51
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/big
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+N="0123456701234567012345670123456701234567012345670123456701234567"
+N="$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N"
+echo -n "$N$N"
+
+exit 0
+
diff --git a/pigeonhole/tests/plugins/extprograms/bin/cat b/pigeonhole/tests/plugins/extprograms/bin/cat
new file mode 100755
index 0000000..02b9858
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/cat
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cat
diff --git a/pigeonhole/tests/plugins/extprograms/bin/cat-stdin b/pigeonhole/tests/plugins/extprograms/bin/cat-stdin
new file mode 100755
index 0000000..781d70b
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/cat-stdin
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cat /dev/stdin
diff --git a/pigeonhole/tests/plugins/extprograms/bin/crlf b/pigeonhole/tests/plugins/extprograms/bin/crlf
new file mode 100755
index 0000000..a0028cf
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/crlf
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+tr -s '\r' '#'
diff --git a/pigeonhole/tests/plugins/extprograms/bin/env b/pigeonhole/tests/plugins/extprograms/bin/env
new file mode 100755
index 0000000..a7b81ac
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/env
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+eval echo -n "\${$1}"
diff --git a/pigeonhole/tests/plugins/extprograms/bin/frame b/pigeonhole/tests/plugins/extprograms/bin/frame
new file mode 100755
index 0000000..225005e
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/frame
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo -n "FRAMED $1{ "
+cat
+echo -n " }"
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/modify b/pigeonhole/tests/plugins/extprograms/bin/modify
new file mode 100755
index 0000000..ce87014
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/modify
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+echo "X-Frop: Extra header"
+cat
+echo
+echo "Extra body content!"
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/program b/pigeonhole/tests/plugins/extprograms/bin/program
new file mode 100755
index 0000000..4b5edbf
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/program
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+cat > /dev/null
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/replace b/pigeonhole/tests/plugins/extprograms/bin/replace
new file mode 100755
index 0000000..b010f06
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/replace
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+cat > /dev/null
+
+echo "From: hatseflat@example.com"
+echo "To: frutsel@example.org"
+echo "Subject: replacement message"
+echo
+echo "Replaced!"
+
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/sleep10 b/pigeonhole/tests/plugins/extprograms/bin/sleep10
new file mode 100755
index 0000000..8c1b96d
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/sleep10
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sleep 10
diff --git a/pigeonhole/tests/plugins/extprograms/bin/sleep2 b/pigeonhole/tests/plugins/extprograms/bin/sleep2
new file mode 100755
index 0000000..a814acd
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/sleep2
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sleep 2
diff --git a/pigeonhole/tests/plugins/extprograms/bin/spamc b/pigeonhole/tests/plugins/extprograms/bin/spamc
new file mode 100755
index 0000000..a3232f4
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/spamc
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo 'X-Spam-Status: Yes, score=66.5/5.0 tests=CONTAINS_LARGE_ROOSTER'
+cat
+
+exit 0
diff --git a/pigeonhole/tests/plugins/extprograms/bin/stderr b/pigeonhole/tests/plugins/extprograms/bin/stderr
new file mode 100755
index 0000000..75b94b0
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/bin/stderr
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+echo "========================================" 1>&2
+echo "Test shell script successfully executed!" 1>&2
+echo 1>&2
+echo "Arguments: $1 $2" 1>&2
+echo 1>&2
+echo "Environment:" 1>&2
+env 1>&2
+echo 1>&2
+echo "Message:" 1>&2
+cat 1>&2
+echo "========================================" 1>&2
+echo 1>&2
+
+echo "Subject: frop!"
+echo "From: stephan@example.org"
+echo "To: tss@example.com"
+echo
+echo "Frop!"
diff --git a/pigeonhole/tests/plugins/extprograms/errors.svtest b/pigeonhole/tests/plugins/extprograms/errors.svtest
new file mode 100644
index 0000000..148f4da
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/errors.svtest
@@ -0,0 +1,32 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+/*
+ * Invalid program names
+ */
+
+test "Invalid Program Names" {
+ if test_script_compile "errors/programname.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "8" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+/*
+ * Invalid arguments
+ */
+
+test "Invalid Arguments" {
+ if test_script_compile "errors/arguments.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "2" {
+ test_fail "wrong number of errors reported";
+ }
+}
diff --git a/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve b/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve
new file mode 100644
index 0000000..04f0aa0
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/errors/arguments.sieve
@@ -0,0 +1,5 @@
+require "vnd.dovecot.pipe";
+
+pipe :args "aaaa
+ aaaa" "frop";
+
diff --git a/pigeonhole/tests/plugins/extprograms/errors/programname.sieve b/pigeonhole/tests/plugins/extprograms/errors/programname.sieve
new file mode 100644
index 0000000..1d2d19c
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/errors/programname.sieve
@@ -0,0 +1,25 @@
+require "variables";
+require "encoded-character";
+require "vnd.dovecot.pipe";
+
+# Slash
+pipe "../frop";
+
+# More slashes
+pipe "../../james/sieve/vacation";
+
+# 0000-001F; [CONTROL CHARACTERS]
+pipe "idiotic${unicode: 001a}";
+
+# 007F; DELETE
+pipe "idiotic${unicode: 007f}";
+
+# 0080-009F; [CONTROL CHARACTERS]
+pipe "idiotic${unicode: 0085}";
+
+# 2028; LINE SEPARATOR
+pipe "idiotic${unicode: 2028}";
+
+# 2029; PARAGRAPH SEPARATOR
+pipe "idiotic${unicode: 2029}";
+
diff --git a/pigeonhole/tests/plugins/extprograms/execute/command.svtest b/pigeonhole/tests/plugins/extprograms/execute/command.svtest
new file mode 100644
index 0000000..92c1fd1
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/command.svtest
@@ -0,0 +1,27 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.execute";
+require "variables";
+
+test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.execute";
+
+test "Basic" {
+ execute "program";
+}
+
+test "Input message" {
+ execute :pipe "program";
+}
+
+test "Input string" {
+ execute :input "DATA" "program";
+}
+
+test "Input variable" {
+ set "DATA" "DATA";
+ execute :input "${DATA}" "program";
+}
+
+test "Output variable" {
+ execute :output "DATA" "program";
+}
diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors.svtest b/pigeonhole/tests/plugins/extprograms/execute/errors.svtest
new file mode 100644
index 0000000..3dd2d5f
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/errors.svtest
@@ -0,0 +1,53 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.execute";
+
+/*
+ * Command syntax
+ */
+
+test "Command syntax" {
+ if test_script_compile "errors/syntax.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "13" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+/*
+ * Variables
+ */
+
+test "Variables" {
+ if test_script_compile "errors/variables.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "2" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+/*
+ * Unknown program
+ */
+
+test "Unknown program" {
+ if not test_script_compile "errors/unknown-program.sieve" {
+ test_fail "compile should have succeeded";
+ }
+
+ if test_script_run {
+ test_fail "execution should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "1" {
+ test_fail "wrong number of errors reported";
+ }
+}
diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve
new file mode 100644
index 0000000..1f4646a
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/errors/syntax.sieve
@@ -0,0 +1,38 @@
+require "vnd.dovecot.execute";
+
+# 1: error: no arguments
+execute;
+
+# 2: error: numeric argument
+execute 1;
+
+# 3: error: tag argument
+execute :frop;
+
+# 4: error: numeric second argument
+execute "sdfd" 1;
+
+# 5: error: stringlist first argument
+execute ["sdfd","werwe"] "sdfs";
+
+# 6: error: too many arguments
+execute "sdfs" "sdfd" "werwe";
+
+# 7: error: inappropriate :copy argument
+execute :copy "234234" ["324234", "23423"];
+
+# 8: error: invalid :input argument; missing parameter
+execute :input "frop";
+
+# 9: error: invalid :input argument; invalid parameter
+execute :input 1 "frop";
+
+# 10: error: invalid :input argument; invalid parameter
+execute :input ["23423","21342"] "frop";
+
+# 11: error: invalid :input argument; invalid parameter
+execute :input :friep "frop";
+
+# 12: error: :output not allowed without variables extension
+execute :output "${frop}" "frop";
+
diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve
new file mode 100644
index 0000000..3a79bb6
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/errors/unknown-program.sieve
@@ -0,0 +1,3 @@
+require "vnd.dovecot.execute";
+
+execute "unknown";
diff --git a/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve b/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve
new file mode 100644
index 0000000..3d0b3e7
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/errors/variables.sieve
@@ -0,0 +1,7 @@
+require "vnd.dovecot.execute";
+require "variables";
+
+# 1: invalid variable name
+execute :output "wqwe-aeqwe" "frop";
+
+
diff --git a/pigeonhole/tests/plugins/extprograms/execute/execute.svtest b/pigeonhole/tests/plugins/extprograms/execute/execute.svtest
new file mode 100644
index 0000000..f16af11
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/execute/execute.svtest
@@ -0,0 +1,177 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.execute";
+require "vnd.dovecot.debug";
+require "variables";
+require "relational";
+require "environment";
+require "encoded-character";
+
+test_set "message" text:
+From: stephan@example.com
+To: pipe@example.net
+Subject: Frop!
+
+Frop!
+.
+;
+
+test_config_set "sieve_execute_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.execute";
+test_result_reset;
+
+test "Execute - bare" {
+ execute "program";
+}
+
+test_result_reset;
+test "Execute - i/-" {
+ execute :input "FROP" "frame";
+}
+
+test_result_reset;
+test "Execute - -/o" {
+ execute :output "out" "frame";
+
+ if not string "${out}" "FRAMED { }" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_result_reset;
+test "Execute - i/o" {
+ execute :input "FROP" :output "out" "frame";
+
+ if not string "${out}" "FRAMED { FROP }" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_result_reset;
+test "Execute - i/o and arguments" {
+ execute :input "FROP" :output "out" "frame" ["FRIEP "];
+
+ if not string "${out}" "FRAMED FRIEP { FROP }" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_result_reset;
+test "Execute - pipe" {
+ execute :pipe :output "msg" "cat";
+
+ if not string :contains "${msg}" "Subject: Frop!" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_result_reset;
+test "Execute - pipe /dev/stdin" {
+ execute :pipe :output "msg" "cat-stdin";
+
+ if not string :contains "${msg}" "Subject: Frop!" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_result_reset;
+test "Execute - env" {
+ test_set "envelope.from" "stephan@sub.example.com";
+ test_set "envelope.to" "stephan@sub.example.net";
+ test_set "envelope.orig_to" "all@sub.example.net";
+
+ execute :output "out" "env" "SENDER";
+ if not string :is "${out}" "stephan@sub.example.com" {
+ test_fail "wrong SENDER env returned: '${out}'";
+ }
+
+ execute :output "out" "env" "RECIPIENT";
+ if not string :is "${out}" "stephan@sub.example.net" {
+ test_fail "wrong RECIPIENT env returned: '${out}'";
+ }
+
+ execute :output "out" "env" "ORIG_RECIPIENT";
+ if not string :is "${out}" "all@sub.example.net" {
+ test_fail "wrong ORIG_RECIPIENT env returned: '${out}'";
+ }
+
+ execute :output "out" "env" "HOST";
+ if not environment :is "host" "${out}" {
+ test_fail "wrong HOST env returned: '${out}'";
+ }
+
+ execute :output "out" "env" "HOME";
+ if string :count "eq" "${out}" "0" {
+ test_fail "empty HOME env returned";
+ }
+
+ execute :output "out" "env" "USER";
+ if string :count "eq" "${out}" "0" {
+ test_fail "empty USER env returned";
+ }
+}
+
+test_result_reset;
+test "Execute - used as test" {
+ if execute :pipe :output "msg" "dog" {
+ test_fail "execute action indicated success with invalid program";
+ }
+
+ if not execute :pipe :output "msg" "cat" {
+ test_fail "execute action indicated failure with valid program";
+ }
+
+ if not string :contains "${msg}" "Subject: Frop!" {
+ test_fail "wrong string returned: ${out}";
+ }
+}
+
+test_config_set "sieve_execute_input_eol" "crlf";
+test_config_reload :extension "vnd.dovecot.execute";
+test_result_reset;
+set "out" "";
+
+test "Execute - CRLF" {
+ execute
+ :input "FROP${hex:0A}FRIEP${hex:0a}"
+ :output "out"
+ "crlf";
+
+ if not string "${out}" "FROP#${hex:0A}FRIEP#${hex:0a}" {
+ test_fail "wrong string returned: '${out}'";
+ }
+}
+
+test_config_set "sieve_execute_input_eol" "lf";
+test_config_reload :extension "vnd.dovecot.execute";
+test_result_reset;
+set "out" "";
+
+test "Execute - LF" {
+ execute
+ :input "FROP${hex:0D 0A}FRIEP${hex:0d 0a}"
+ :output "out"
+ "crlf";
+
+ if not string "${out}" "FROP${hex:0A}FRIEP${hex:0a}" {
+ test_fail "wrong string returned: '${out}'";
+ }
+}
+
+set "D" "0123456701234567012345670123456701234567012345670123456701234567";
+set "D" "${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}${D}";
+set "data" "${D}${D}";
+
+test_config_set "sieve_execute_input_eol" "crlf";
+test_config_reload :extension "vnd.dovecot.execute";
+test_result_reset;
+set "out" "";
+
+test "Execute - big" {
+ execute
+ :output "out"
+ "big";
+
+ if not string "${out}" "${data}" {
+ test_fail "wrong string returned: '${out}'";
+ }
+}
diff --git a/pigeonhole/tests/plugins/extprograms/filter/command.svtest b/pigeonhole/tests/plugins/extprograms/filter/command.svtest
new file mode 100644
index 0000000..50f949a
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/filter/command.svtest
@@ -0,0 +1,10 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.filter";
+require "variables";
+
+test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.filter";
+
+test "Basic" {
+ filter "program";
+}
diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors.svtest b/pigeonhole/tests/plugins/extprograms/filter/errors.svtest
new file mode 100644
index 0000000..1d04ba1
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/filter/errors.svtest
@@ -0,0 +1,39 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+/*
+ * Command syntax
+ */
+
+test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.filter";
+
+test "Command syntax" {
+ if test_script_compile "errors/syntax.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "8" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+/*
+ * Unknown program
+ */
+
+test "Unknown program" {
+ if not test_script_compile "errors/unknown-program.sieve" {
+ test_fail "compile should have succeeded";
+ }
+
+ if test_script_run {
+ test_fail "execution should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "1" {
+ test_fail "wrong number of errors reported";
+ }
+}
diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve
new file mode 100644
index 0000000..00a3a23
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/filter/errors/syntax.sieve
@@ -0,0 +1,22 @@
+require "vnd.dovecot.filter";
+
+# 1: error: no arguments
+filter;
+
+# 2: error: numeric argument
+filter 1;
+
+# 3: error: tag argument
+filter :frop;
+
+# 4: error: numeric second argument
+filter "sdfd" 1;
+
+# 5: error: stringlist first argument
+filter ["sdfd","werwe"] "sdfs";
+
+# 6: error: too many arguments
+filter "sdfd" "werwe" "sdfs";
+
+# 7: error: inappropriate :copy argument
+filter :try :copy "234234" ["324234", "23423"];
diff --git a/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve
new file mode 100644
index 0000000..7e530ee
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/filter/errors/unknown-program.sieve
@@ -0,0 +1,3 @@
+require "vnd.dovecot.filter";
+
+filter "unknown";
diff --git a/pigeonhole/tests/plugins/extprograms/filter/execute.svtest b/pigeonhole/tests/plugins/extprograms/filter/execute.svtest
new file mode 100644
index 0000000..15fab69
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/filter/execute.svtest
@@ -0,0 +1,213 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.filter";
+require "vnd.dovecot.debug";
+require "variables";
+require "editheader";
+require "spamtest";
+require "body";
+require "fileinto";
+require "mailbox";
+
+test_set "message" text:
+From: stephan@example.com
+To: pipe@example.net
+Subject: Frop!
+
+Frop!
+.
+;
+
+test_config_set "sieve_filter_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.filter";
+test_result_reset;
+
+test_result_reset;
+test "Replace" {
+ if header :contains "subject" "replacement" {
+ test_fail "message already replaced";
+ }
+
+ filter "replace";
+
+ if not header :contains "subject" "replacement" {
+ test_fail "message not replaced";
+ }
+}
+
+test_result_reset;
+test "Used as test" {
+ if filter "nonsense" {
+ test_fail "filter action indicated success with invalid program";
+ }
+
+ if not filter "replace" {
+ test_fail "filter action indicated failure with valid program";
+ }
+
+ if not header :contains "subject" "replacement" {
+ test_fail "message not replaced; filter not actually executed";
+ }
+}
+
+test_result_reset;
+test "Modify" {
+ if anyof (
+ body :contains "extra",
+ exists "x-frop") {
+ test_fail "message already modified";
+ }
+
+ if not header "subject" "Frop!" {
+ test_fail "message is wrong";
+ }
+
+ filter "modify";
+
+ if not header "subject" "Frop!" {
+ test_fail "message replaced erroneously";
+ }
+
+ if not header :contains "x-frop" "extra" {
+ test_fail "message header not modified";
+ }
+
+ if not body :contains "Extra" {
+ test_fail "message body not modified";
+ }
+}
+
+test_result_reset;
+test "Editheader" {
+ if anyof ( exists "X-A", exists "X-B", exists "X-C", exists "X-D",
+ exists "X-E") {
+ test_fail "message already modified";
+ }
+
+ addheader "X-A" "1";
+ if not header "X-A" "1" {
+ test_fail "X-A header missing";
+ }
+
+ fileinto :create "A";
+
+ filter "addheader" ["X-B", "2"];
+ if not header "X-B" "2" {
+ test_fail "X-B header missing";
+ }
+
+ fileinto :create "B";
+
+ addheader "X-C" "3";
+ if not header "X-C" "3" {
+ test_fail "X-C header missing";
+ }
+
+ fileinto :create "C";
+
+ filter "addheader" ["X-D", "4"];
+ if not header "X-D" "4" {
+ test_fail "X-D header missing";
+ }
+
+ fileinto :create "D";
+
+ addheader "X-E" "5";
+ if not header "X-E" "5" {
+ test_fail "X-E header missing";
+ }
+
+ fileinto :create "E";
+
+ if not test_result_execute {
+ test_fail "failed to execute result";
+ }
+
+ test_message :folder "A" 0;
+
+ if not header "X-A" "1" {
+ test_fail "X-A header missing";
+ }
+ if anyof (
+ header "X-B" "2", header "X-C" "3",
+ header "X-D" "4", header "X-E" "5") {
+ test_fail "X-B, X-C, X-D or X-E header found";
+ }
+
+ test_message :folder "B" 0;
+
+ if not header "X-B" "2" {
+ test_fail "X-B header missing";
+ }
+ if anyof (
+ header "X-C" "3", header "X-D" "4", header "X-E" "5") {
+ test_fail "X-C, X-D or X-E header found";
+ }
+
+ test_message :folder "C" 0;
+
+ if not header "X-C" "3" {
+ test_fail "X-C header missing";
+ }
+ if anyof (header "X-D" "4", header "X-E" "5") {
+ test_fail "X-D or X-E header found";
+ }
+
+ test_message :folder "D" 0;
+
+ if not header "X-D" "4" {
+ test_fail "X-D header missing";
+ }
+ if anyof (header "X-E" "5") {
+ test_fail "X-E header found";
+ }
+
+ test_message :folder "E" 0;
+
+ if not header "X-A" "1" {
+ test_fail "X-A header missing in final message";
+ }
+ if not header "X-B" "2" {
+ test_fail "X-B header missing in final message";
+ }
+ if not header "X-C" "3" {
+ test_fail "X-C header missing in final message";
+ }
+ if not header "X-D" "4" {
+ test_fail "X-D header missing in final message";
+ }
+ if not header "X-E" "5" {
+ test_fail "X-E header missing in final message";
+ }
+}
+
+test_config_set "sieve_spamtest_status_header"
+ "X-Spam-Status: [^,]*, score=(-?[[:digit:]]+\\.[[:digit:]]).*";
+test_config_set "sieve_spamtest_max_value" "10";
+test_config_set "sieve_spamtest_status_type" "score";
+test_config_reload :extension "spamtest";
+
+test_result_reset;
+test "Spamtest" {
+ if exists "x-spam-status" {
+ test_fail "message already modified";
+ }
+
+ if not header "subject" "Frop!" {
+ test_fail "message is wrong";
+ }
+
+ filter "spamc";
+
+ if not exists "x-spam-status" {
+ test_fail "x-spam-score header not added";
+ }
+
+ if spamtest :is "0" {
+ test_fail "spamtest not configured or test failed";
+ }
+
+ if not spamtest :is "10" {
+ test_fail "spamtest yields incorrect value";
+ }
+}
+
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/command.svtest b/pigeonhole/tests/plugins/extprograms/pipe/command.svtest
new file mode 100644
index 0000000..dabd970
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/command.svtest
@@ -0,0 +1,10 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.pipe";
+
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.pipe";
+
+test "Basic" {
+ pipe "program";
+}
+
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest b/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest
new file mode 100644
index 0000000..af36b91
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/errors.svtest
@@ -0,0 +1,94 @@
+require "vnd.dovecot.testsuite";
+require "variables";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+/*
+ * Command syntax
+ */
+
+test "Command syntax" {
+ if test_script_compile "errors/syntax.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "8" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+/* Unknown program */
+
+test_set "message" text:
+From: stephan@example.com
+To: pipe@example.net
+Subject: Frop!
+
+Frop!
+.
+;
+
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.pipe";
+test_result_reset;
+
+test "Unknown program" {
+ if not test_script_compile "errors/unknown-program.sieve" {
+ test_fail "compile failed";
+ }
+
+ if not test_script_run {
+ test_fail "execute failed";
+ }
+
+ if test_result_execute {
+ test_fail "pipe should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "1" {
+ test_fail "wrong number of errors reported";
+ }
+
+ if not test_error :index 1 :contains "failed to pipe" {
+ test_fail "wrong error reported";
+ }
+}
+
+/* Timeout */
+
+test_set "message" text:
+From: stephan@example.com
+To: pipe@example.net
+Subject: Frop!
+
+Frop!
+.
+;
+
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_set "sieve_pipe_exec_timeout" "1s";
+test_config_reload :extension "vnd.dovecot.pipe";
+test_result_reset;
+
+test "Timeout" {
+ if not test_script_compile "errors/timeout.sieve" {
+ test_fail "compile failed";
+ }
+
+ if not test_script_run {
+ test_fail "execute failed";
+ }
+
+ if test_result_execute {
+ test_fail "pipe should have timed out";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "2" {
+ test_fail "wrong number of errors reported";
+ }
+
+ if not test_error :index 2 :contains "failed to pipe" {
+ test_fail "wrong error reported";
+ }
+}
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve
new file mode 100644
index 0000000..64d5310
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/syntax.sieve
@@ -0,0 +1,22 @@
+require "vnd.dovecot.pipe";
+
+# 1: error: no arguments
+pipe;
+
+# 2: error: numeric argument
+pipe 1;
+
+# 3: error: tag argument
+pipe :frop;
+
+# 4: error: numeric second argument
+pipe "sdfd" 1;
+
+# 5: error: stringlist first argument
+pipe ["sdfd","werwe"] "sdfs";
+
+# 6: error: too many arguments
+pipe "sdfd" "werwe" "sdfs";
+
+# 7: error: inappropriate :copy argument
+pipe :try :copy "234234" ["324234", "23423"];
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve
new file mode 100644
index 0000000..7a940c8
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/timeout.sieve
@@ -0,0 +1,3 @@
+require "vnd.dovecot.pipe";
+
+pipe "sleep10";
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve b/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve
new file mode 100644
index 0000000..fd6338b
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/errors/unknown-program.sieve
@@ -0,0 +1,3 @@
+require "vnd.dovecot.pipe";
+
+pipe "unknown";
diff --git a/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest b/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest
new file mode 100644
index 0000000..34b6798
--- /dev/null
+++ b/pigeonhole/tests/plugins/extprograms/pipe/execute.svtest
@@ -0,0 +1,56 @@
+require "vnd.dovecot.testsuite";
+require "vnd.dovecot.pipe";
+require "vnd.dovecot.debug";
+require "variables";
+
+test_set "message" text:
+From: stephan@example.com
+To: pipe@example.net
+Subject: Frop!
+
+Frop!
+.
+;
+
+/* Basic pipe */
+
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_reload :extension "vnd.dovecot.pipe";
+test_result_reset;
+
+test "Pipe" {
+ pipe "stderr" ["ONE", "TWO"];
+
+ if not test_result_execute {
+ test_fail "failed to pipe message to script";
+ }
+}
+
+/* Timeout */
+
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_set "sieve_pipe_exec_timeout" "3s";
+test_config_reload :extension "vnd.dovecot.pipe";
+test_result_reset;
+
+test "Timeout 3s" {
+ pipe "sleep2";
+
+ if not test_result_execute {
+ test_fail "failed to pipe message to script";
+ }
+}
+
+test_result_reset;
+test_config_set "sieve_pipe_bin_dir" "${tst.path}/../bin";
+test_config_set "sieve_pipe_exec_timeout" "0";
+test_config_reload :extension "vnd.dovecot.pipe";
+test_result_reset;
+
+test "Timeout infinite" {
+ pipe "sleep2";
+
+ if not test_result_execute {
+ test_fail "failed to pipe message to script";
+ }
+}