summaryrefslogtreecommitdiffstats
path: root/pigeonhole/tests/extensions/variables
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/tests/extensions/variables')
-rw-r--r--pigeonhole/tests/extensions/variables/basic.svtest223
-rw-r--r--pigeonhole/tests/extensions/variables/errors.svtest34
-rw-r--r--pigeonhole/tests/extensions/variables/errors/limits.sieve287
-rw-r--r--pigeonhole/tests/extensions/variables/errors/namespace.sieve8
-rw-r--r--pigeonhole/tests/extensions/variables/errors/set.sieve19
-rw-r--r--pigeonhole/tests/extensions/variables/limits.svtest435
-rw-r--r--pigeonhole/tests/extensions/variables/match.svtest365
-rw-r--r--pigeonhole/tests/extensions/variables/modifiers.svtest160
-rw-r--r--pigeonhole/tests/extensions/variables/quoting.svtest36
-rw-r--r--pigeonhole/tests/extensions/variables/regex.svtest35
-rw-r--r--pigeonhole/tests/extensions/variables/string.svtest37
11 files changed, 1639 insertions, 0 deletions
diff --git a/pigeonhole/tests/extensions/variables/basic.svtest b/pigeonhole/tests/extensions/variables/basic.svtest
new file mode 100644
index 0000000..f01aeeb
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/basic.svtest
@@ -0,0 +1,223 @@
+require "vnd.dovecot.testsuite";
+require "variables";
+
+test_set "message" text:
+From: stephan@example.org
+To: test@example.com
+Subject: Variables test
+
+Testing variables...
+.
+;
+
+/*
+ * Substitution syntax
+ */
+
+test "Unknown variables" {
+ set "q" "a";
+ set "qw" "bb";
+ set "qwe" "ccc";
+ set "qwer" "dddd";
+ set "qwert" "ccc";
+
+ if anyof (
+ not string "[${qwerty}]" "[]",
+ not string "[${20}]" "[]"
+ ) {
+ test_fail "unknown variable not substituted with empty string";
+ }
+}
+
+test "One pass" {
+ set "something" "value";
+ set "s" "$";
+
+ if string "${s}{something}" "value" {
+ test_fail "somehow variable string is scanned multiple times";
+ }
+
+ if not string :matches "${s}{something}" "?{something}" {
+ test_fail "unexpected result";
+ }
+}
+
+test "Syntax errors" {
+ set "s" "$";
+ set "variable" "nonsense";
+
+ if anyof (
+ not string "$" "${s}",
+ not string "${" "${s}{",
+ not string "${a" "${s}{a",
+ not string "${$}" "${s}{$}",
+ not string "${%%%%}" "${s}{%%%%}",
+ not string "${0.s}" "${s}{0.s}",
+ not string "&%${}!" "&%${s}{}!",
+ not string "${doh!}" "${s}{doh!}" )
+ {
+ test_fail "variables substitution changed substring not matching variable-ref";
+ }
+}
+
+test "RFC syntax examples" {
+ # The variable "company" holds the value "ACME". No other variables
+ # are set.
+ set "company" "ACME";
+
+ # "${full}" => the empty string
+ if not string :is "${full}" "" {
+ test_fail "unknown variable did not yield empty string";
+ }
+
+ # "${company}" => "ACME"
+ if not string :is "${company}" "ACME" {
+ test_fail "assigned variable did not get substituted";
+ }
+
+ # "${BAD${Company}" => "${BADACME"
+ if not string :is "${BAD${Company}" "${BADACME" {
+ test_fail "'BADACME' test did not yield expected result";
+ }
+
+ #"${President, ${Company} Inc.}"
+ # => "${President, ACME Inc.}"
+ if not string "${President, ${Company} Inc.}"
+ "${President, ACME Inc.}" {
+ test_fail "'Company president' test did not yield expected result";
+ }
+}
+
+/*
+ * Variable assignments
+ */
+
+test "Basic assignment" {
+ set "test" "Value";
+
+ if not string :is "${test}" "Value" {
+ test_fail "variable assignment failed";
+ }
+
+ if string :is "${test}" "value" {
+ test_fail "string test failed";
+ }
+}
+
+test "Assignment overwritten" {
+ set "test" "Value";
+ set "test" "More";
+
+ if not string :is "${test}" "More" {
+ test_fail "variable assignment failed";
+ }
+
+ if string :is "${test}" "Value" {
+ test_fail "value not overwritten";
+ }
+
+ if string :is "${test}" "nonsense" {
+ test_fail "string test failed";
+ }
+}
+
+test "Two assignments" {
+ set "test" "Value";
+ set "test2" "More";
+
+ if not string :is "${test}" "Value" {
+ test_fail "variable assignment failed";
+ }
+
+ if string :is "${test}" "More" {
+ test_fail "assignments to different variables overlap";
+ }
+
+ if string :is "${test}" "nonsense" {
+ test_fail "string test failed";
+ }
+}
+
+test "Variables case-insensitive" {
+ set "VeRyElAboRATeVaRIABLeName" "interesting value";
+
+ if not string "${veryelaboratevariablename}" "interesting value" {
+ test_fail "variable names are case sensitive (lower case try)";
+ }
+
+ if not string "${VERYELABORATEVARIABLENAME}" "interesting value" {
+ test_fail "variable names are case sensitive (upper case try)";
+ }
+}
+
+test "RFC set command example" {
+ set "honorific" "Mr";
+ set "first_name" "Wile";
+ set "last_name" "Coyote";
+ set "vacation" text:
+Dear ${HONORIFIC} ${last_name},
+I'm out, please leave a message after the meep.
+.
+;
+ if not string :is :comparator "i;octet" "${VAcaTION}" text:
+Dear Mr Coyote,
+I'm out, please leave a message after the meep.
+.
+ {
+ test_fail "failed to set variable correctly: ${VAcaTION}";
+ }
+}
+
+/*
+ * Variable substitution
+ */
+
+test "Multi-line string substitution" {
+ set "name" "Stephan Bosch";
+ set "address" "stephan@example.org";
+ set "subject" "Test message";
+
+ set "message" text: # Message with substitutions
+From: ${name} <${address}>
+To: Bertus van Asseldonk <b.vanasseldonk@nl.example.com>
+Subject: ${subject}
+
+This is a test message.
+.
+;
+ if not string :is "${message}" text:
+From: Stephan Bosch <stephan@example.org>
+To: Bertus van Asseldonk <b.vanasseldonk@nl.example.com>
+Subject: Test message
+
+This is a test message.
+.
+ {
+ test_fail "variable substitution failed";
+ }
+}
+
+test "Multiple substitutions" {
+ set "a" "the monkey";
+ set "b" "a nut";
+ set "c" "the fish";
+ set "d" "on fire";
+ set "e" "eats";
+ set "f" "is";
+
+ if not string :is "${a} ${e} ${b}" "the monkey eats a nut" {
+ test_fail "variable substitution failed (1)";
+ }
+
+ if not string :is "${c} ${f} ${d}" "the fish is on fire" {
+ test_fail "variable substitution failed (2)";
+ }
+
+ set :upperfirst "sentence" "${a} ${e} ${b}";
+
+ if not string :is "${sentence}" "The monkey eats a nut" {
+ test_fail "modified variable substitution failed";
+ }
+}
+
+
diff --git a/pigeonhole/tests/extensions/variables/errors.svtest b/pigeonhole/tests/extensions/variables/errors.svtest
new file mode 100644
index 0000000..652075f
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/errors.svtest
@@ -0,0 +1,34 @@
+require "vnd.dovecot.testsuite";
+
+require "comparator-i;ascii-numeric";
+require "relational";
+
+test "Invalid namespaces (FIXME: count only)" {
+ if test_script_compile "errors/namespace.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "5" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+test "Invalid set command invocations (FIXME: count only)" {
+ if test_script_compile "errors/set.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "7" {
+ test_fail "wrong number of errors reported";
+ }
+}
+
+test "Limits (FIXME: count only)" {
+ if test_script_compile "errors/limits.sieve" {
+ test_fail "compile should have failed";
+ }
+
+ if not test_error :count "eq" :comparator "i;ascii-numeric" "6" {
+ test_fail "wrong number of errors reported";
+ }
+}
diff --git a/pigeonhole/tests/extensions/variables/errors/limits.sieve b/pigeonhole/tests/extensions/variables/errors/limits.sieve
new file mode 100644
index 0000000..3c9dbbd
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/errors/limits.sieve
@@ -0,0 +1,287 @@
+require "variables";
+
+# Not an error (0)
+set "var123456789012345678901234567890" "value";
+
+# Exceed the maximum variable name length (1)
+set "var123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" "value";
+
+# Must yield unknown namespace error (no limit exceeded) (1)
+set "namespace.sub.sub.variable" "value";
+
+# Must yield unknown namespace error (exceeds element limit) (1)
+set "namespace.sub.sub.sub.variable" "value";
+
+# Not an error (0)
+if string "${32}" "value" {
+ stop;
+}
+
+# Exceed the maximum match value index (1)
+if string "${33}" "value" {
+ stop;
+}
+
+# Exceed the maximum number of declared variables (1!)
+set "var001" "value";
+set "var002" "value";
+set "var003" "value";
+set "var004" "value";
+set "var005" "value";
+set "var006" "value";
+set "var007" "value";
+set "var008" "value";
+set "var009" "value";
+set "var010" "value";
+set "var011" "value";
+set "var012" "value";
+set "var013" "value";
+set "var014" "value";
+set "var015" "value";
+set "var016" "value";
+set "var017" "value";
+set "var018" "value";
+set "var019" "value";
+set "var020" "value";
+set "var021" "value";
+set "var022" "value";
+set "var023" "value";
+set "var024" "value";
+set "var025" "value";
+set "var026" "value";
+set "var027" "value";
+set "var028" "value";
+set "var029" "value";
+set "var030" "value";
+set "var031" "value";
+set "var032" "value";
+set "var033" "value";
+set "var034" "value";
+set "var035" "value";
+set "var036" "value";
+set "var037" "value";
+set "var038" "value";
+set "var039" "value";
+set "var040" "value";
+set "var041" "value";
+set "var042" "value";
+set "var043" "value";
+set "var044" "value";
+set "var045" "value";
+set "var046" "value";
+set "var047" "value";
+set "var048" "value";
+set "var049" "value";
+set "var050" "value";
+set "var051" "value";
+set "var052" "value";
+set "var053" "value";
+set "var054" "value";
+set "var055" "value";
+set "var056" "value";
+set "var057" "value";
+set "var058" "value";
+set "var059" "value";
+set "var060" "value";
+set "var061" "value";
+set "var062" "value";
+set "var063" "value";
+set "var064" "value";
+set "var065" "value";
+set "var066" "value";
+set "var067" "value";
+set "var068" "value";
+set "var069" "value";
+set "var070" "value";
+set "var071" "value";
+set "var072" "value";
+set "var073" "value";
+set "var074" "value";
+set "var075" "value";
+set "var076" "value";
+set "var077" "value";
+set "var078" "value";
+set "var079" "value";
+set "var080" "value";
+set "var081" "value";
+set "var082" "value";
+set "var083" "value";
+set "var084" "value";
+set "var085" "value";
+set "var086" "value";
+set "var087" "value";
+set "var088" "value";
+set "var089" "value";
+set "var090" "value";
+set "var091" "value";
+set "var092" "value";
+set "var093" "value";
+set "var094" "value";
+set "var095" "value";
+set "var096" "value";
+set "var097" "value";
+set "var098" "value";
+set "var099" "value";
+
+set "var100" "value";
+set "var101" "value";
+set "var102" "value";
+set "var103" "value";
+set "var104" "value";
+set "var105" "value";
+set "var106" "value";
+set "var107" "value";
+set "var108" "value";
+set "var109" "value";
+set "var110" "value";
+set "var111" "value";
+set "var112" "value";
+set "var113" "value";
+set "var114" "value";
+set "var115" "value";
+set "var116" "value";
+set "var117" "value";
+set "var118" "value";
+set "var119" "value";
+set "var120" "value";
+set "var121" "value";
+set "var122" "value";
+set "var123" "value";
+set "var124" "value";
+set "var125" "value";
+set "var126" "value";
+set "var127" "value";
+set "var128" "value";
+set "var129" "value";
+set "var130" "value";
+set "var131" "value";
+set "var132" "value";
+set "var133" "value";
+set "var134" "value";
+set "var135" "value";
+set "var136" "value";
+set "var137" "value";
+set "var138" "value";
+set "var139" "value";
+set "var140" "value";
+set "var141" "value";
+set "var142" "value";
+set "var143" "value";
+set "var144" "value";
+set "var145" "value";
+set "var146" "value";
+set "var147" "value";
+set "var148" "value";
+set "var149" "value";
+set "var150" "value";
+set "var151" "value";
+set "var152" "value";
+set "var153" "value";
+set "var154" "value";
+set "var155" "value";
+set "var156" "value";
+set "var157" "value";
+set "var158" "value";
+set "var159" "value";
+set "var160" "value";
+set "var161" "value";
+set "var162" "value";
+set "var163" "value";
+set "var164" "value";
+set "var165" "value";
+set "var166" "value";
+set "var167" "value";
+set "var168" "value";
+set "var169" "value";
+set "var170" "value";
+set "var171" "value";
+set "var172" "value";
+set "var173" "value";
+set "var174" "value";
+set "var175" "value";
+set "var176" "value";
+set "var177" "value";
+set "var178" "value";
+set "var179" "value";
+set "var180" "value";
+set "var181" "value";
+set "var182" "value";
+set "var183" "value";
+set "var184" "value";
+set "var185" "value";
+set "var186" "value";
+set "var187" "value";
+set "var188" "value";
+set "var189" "value";
+set "var190" "value";
+set "var191" "value";
+set "var192" "value";
+set "var193" "value";
+set "var194" "value";
+set "var195" "value";
+set "var196" "value";
+set "var197" "value";
+set "var198" "value";
+set "var199" "value";
+set "var200" "value";
+
+set "var201" "value";
+set "var202" "value";
+set "var203" "value";
+set "var204" "value";
+set "var205" "value";
+set "var206" "value";
+set "var207" "value";
+set "var208" "value";
+set "var209" "value";
+set "var210" "value";
+set "var211" "value";
+set "var212" "value";
+set "var213" "value";
+set "var214" "value";
+set "var215" "value";
+set "var216" "value";
+set "var217" "value";
+set "var218" "value";
+set "var219" "value";
+set "var220" "value";
+set "var221" "value";
+set "var222" "value";
+set "var223" "value";
+set "var224" "value";
+set "var225" "value";
+set "var226" "value";
+set "var227" "value";
+set "var228" "value";
+set "var229" "value";
+set "var230" "value";
+set "var231" "value";
+set "var232" "value";
+set "var233" "value";
+set "var234" "value";
+set "var235" "value";
+set "var236" "value";
+set "var237" "value";
+set "var238" "value";
+set "var239" "value";
+set "var240" "value";
+set "var241" "value";
+set "var242" "value";
+set "var243" "value";
+set "var244" "value";
+set "var245" "value";
+set "var246" "value";
+set "var247" "value";
+set "var248" "value";
+set "var249" "value";
+set "var250" "value";
+set "var251" "value";
+set "var252" "value";
+set "var253" "value";
+set "var254" "value";
+set "var255" "value";
+set "var256" "value";
+set "var257" "value";
+set "var258" "value";
+set "var259" "value";
+set "var260" "value";
diff --git a/pigeonhole/tests/extensions/variables/errors/namespace.sieve b/pigeonhole/tests/extensions/variables/errors/namespace.sieve
new file mode 100644
index 0000000..e11ac6d
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/errors/namespace.sieve
@@ -0,0 +1,8 @@
+require "variables";
+require "fileinto";
+
+set "namespace.frop" "value";
+set "complex.struct.frop" "value";
+
+fileinto "${namespace.frop}";
+fileinto "${complex.struct.frop}";
diff --git a/pigeonhole/tests/extensions/variables/errors/set.sieve b/pigeonhole/tests/extensions/variables/errors/set.sieve
new file mode 100644
index 0000000..07c393a
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/errors/set.sieve
@@ -0,0 +1,19 @@
+require "variables";
+
+# Invalid variable name
+set "${frop}" "frop";
+set "...." "frop";
+set "name." "frop";
+set ".name" "frop";
+
+# Not an error
+set "\n\a\m\e" "frop";
+
+# Trying to assign match variable;
+set "0" "frop";
+
+# Not an error
+set :UPPER "name" "frop";
+
+# Invalid tag
+set :inner "name" "frop";
diff --git a/pigeonhole/tests/extensions/variables/limits.svtest b/pigeonhole/tests/extensions/variables/limits.svtest
new file mode 100644
index 0000000..7397713
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/limits.svtest
@@ -0,0 +1,435 @@
+require "vnd.dovecot.testsuite";
+require "variables";
+require "encoded-character";
+
+/*
+ * Variable size limit
+ */
+
+test_config_set "sieve_variables_max_variable_size" "4000";
+test_config_reload :extension "variables";
+
+set "a" text:
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+.
+;
+
+test "Variable size limit" {
+ set :length "alen" "${a}";
+
+ if not string "${alen}" "4000" {
+ test_fail "variable 'a' not 4000 bytes long (${alen}) [0]";
+ }
+
+ set "a" "${a}b";
+ set :length "alen" "${a}";
+
+ if not string "${alen}" "4000" {
+ test_fail "variable 'a' not 4000 bytes long (${alen}) [1]";
+ }
+
+ set "a" "${a}${a}";
+ set :length "alen" "${a}";
+
+ if not string "${alen}" "4000" {
+ test_fail "variable 'a' not 4000 bytes long (${alen}) [2]";
+ }
+
+ test_config_set "sieve_variables_max_variable_size" "8000";
+ test_config_reload :extension "variables";
+
+ set "a" "${a}${a}";
+ set :length "alen" "${a}";
+
+ if not string "${alen}" "8000" {
+ test_fail "variable 'a' not 8000 bytes long (${alen})";
+ }
+}
+
+/*
+ * Variable size limit UTF-8
+ */
+
+test_config_set "sieve_variables_max_variable_size" "4000";
+test_config_reload :extension "variables";
+
+set "b" text:
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+012345678901234567890123456789012345678901234567
+01234567890123456789012345678901234567890123456
+.
+;
+
+test "Variable size limit UTF-8" {
+ set :length "blen" "${b}";
+
+ if not string "${blen}" "3999" {
+ test_fail "variable 'b' not 3999 bytes long (${blen}) [0]";
+ }
+
+ set "b" "${b}${unicode:4e03}";
+ set :length "blen" "${b}";
+
+ if not string "${blen}" "3999" {
+ test_fail "variable 'b' not 3999 bytes long (${blen}) [1]";
+ }
+
+ set "b" "${b}ccc";
+ set :length "blen" "${b}";
+
+ if not string "${blen}" "4000" {
+ test_fail "variable 'b' not 4000 bytes long (${blen})";
+ }
+}
+
+/*
+ * :quotewildcard variable size limit
+ */
+
+test_config_set "sieve_variables_max_variable_size" "4000";
+test_config_reload :extension "variables";
+
+set "c" text:
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+**************************************
+.
+;
+
+test ":quotewildcard variable size limit" {
+ set :length "clen" "${c}";
+
+ if not string "${clen}" "4000" {
+ test_fail "variable 'c' not 4000 bytes long (${clen}) [0]";
+ }
+
+ set "d" "0${c}";
+ set :quotewildcard "c" "${c}";
+ set :length "clen" "${c}";
+
+ if not string "${clen}" "4000" {
+ test_fail "variable 'c' not 4000 bytes long (${clen}) [1]";
+ }
+
+ set :quotewildcard "d" "${d}";
+ set :length "dlen" "${d}";
+
+ if not string "${dlen}" "3999" {
+ test_fail "variable 'd' not 3999 bytes long (${dlen})";
+ }
+
+ if not string :is text:
+${d}
+.
+text:
+0\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+\*\*\*\*\*\*\*\*\*\*
+.
+ {
+ test_fail "variable 'd' has unexpected value";
+ }
+}
+
diff --git a/pigeonhole/tests/extensions/variables/match.svtest b/pigeonhole/tests/extensions/variables/match.svtest
new file mode 100644
index 0000000..11c0701
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/match.svtest
@@ -0,0 +1,365 @@
+require "vnd.dovecot.testsuite";
+
+require "variables";
+
+/*
+ * RFC compliance
+ */
+
+# Test acceptance of leading zeroes
+test "RFC - leading zeroes" {
+ if not string :matches "frop:frup:frop" "*:*:*" {
+ test_fail "failed to match";
+ }
+
+ if not string :is "${0000002}" "frup" {
+ test_fail "incorrect match value (0000002): ${0000002}";
+ }
+}
+
+# Test non-greedyness
+test "RFC - not greedy" {
+ if not string :matches "frop.......frop.........frop...." "?*frop*" {
+ test_fail "failed to match";
+ }
+
+ if not string :is "${1}${2}${3}" "frop................frop...." {
+ test_fail "incorrect match values: ${1}${2}${3}";
+ }
+}
+
+# Index out of range
+test "RFC - index out of range" {
+ if not string :matches "test" "*" {
+ test_fail "failed to match (impossible)";
+ }
+
+ if not string :is "${2}" "" {
+ test_fail "incorrect match value: '${2}'";
+ }
+}
+
+# Index 0
+test "RFC - index 0" {
+ if not string :matches "a b c d e f g" "? ? ? ? ? ? ?" {
+ test_fail "failed to match";
+ }
+
+ if not string :is "${0}" "a b c d e f g" {
+ test_fail "incorrect match value: ${0}";
+ }
+}
+
+# Test short-circuit
+test "RFC - test short-circuit" {
+ if not anyof (
+ string :matches "a b c d e f g" "? ?",
+ string :matches "puk pok puk pok" "pu*ok",
+ string :matches "snot kip snot" "snot*snot"
+ ) {
+ test_fail "failed to match any";
+ }
+
+ if string :is "${1}" " kip " {
+ test_fail "did not short-circuit test execution or intented test failed.";
+ }
+
+ if not string :is "${1}" "k pok puk p" {
+ test_fail "incorrect match value: ${1}";
+ }
+}
+
+# Test overwriting only on match
+test "RFC - values overwrite" {
+ set "sentence1" "the cat jumps off the table";
+ set "sentence2" "the dog barks at the cat in the alley";
+
+ if not string :matches "${sentence1}" "the * jumps off the *" {
+ test_fail "failed to match first sentence";
+ }
+
+ if not string :is "${1}:${2}" "cat:table" {
+ test_fail "invalid match values";
+ }
+
+ if string :matches "${sentence2}" "the * barks at the * in the store" {
+ test_fail "should not have matched second sentence";
+ }
+
+ if not string :is "${1}:${2}" "cat:table" {
+ test_fail "should have preserved match values";
+ }
+
+ if not string :matches "${sentence2}" "the * barks at the * in the alley" {
+ test_fail "failed to match the second sentence (second time)";
+ }
+
+ if not string :is "${1}:${2}" "dog:cat" {
+ test_fail "should have overwritten match values";
+ }
+}
+
+test "RFC - example" {
+ test_set "message" text:
+Subject: [acme-users] [fwd] version 1.0 is out
+List-Id: Dovecot Mailing List <dovecot@dovecot.example.net>
+To: coyote@ACME.Example.COM
+Fom: stephan@example.org
+
+Test message.
+.
+;
+ if header :matches "List-ID" "*<*@*" {
+ if not string "INBOX.lists.${2}" "INBOX.lists.dovecot" {
+ test_fail "incorrect match value: INBOX.lists.${2}";
+ }
+ } else {
+ test_fail "failed to match list header";
+ }
+
+ # Imagine the header
+ # Subject: [acme-users] [fwd] version 1.0 is out
+ if header :matches "Subject" "[*] *" {
+ # ${1} will hold "acme-users",
+ # ${2} will hold "[fwd] version 1.0 is out"
+
+ if anyof (
+ not string "${1}" "acme-users",
+ not string "${2}" "[fwd] version 1.0 is out"
+ ) {
+ test_fail "invalid match values: ${1} ${2}";
+ }
+ } else {
+ test_fail "failed to match subject";
+ }
+
+ # Imagine the header
+ # To: coyote@ACME.Example.COM
+ if address :matches ["To", "Cc"] ["coyote@**.com",
+ "wile@**.com"] {
+ # ${0} is the matching address
+ # ${1} is always the empty string
+ # ${2} is part of the domain name ("ACME.Example")
+
+ if anyof (
+ not string "${0}" "coyote@ACME.Example.COM",
+ not string "${1}" "",
+ not string "${2}" "ACME.Example"
+ ) {
+ test_fail "invalid match values: ${0}, ${1}, ${2}";
+ }
+ } else {
+ # Control wouldn't reach this block if any match was
+ # successful, so no match variables are set at this
+ # point.
+
+ test_fail "failed to match to address";
+ }
+
+ if anyof (true, address :domain :matches "To" "*.com") {
+ # The second test is never evaluated, so there are
+ # still no match variables set.
+
+ /* FIXME: not compliant */
+ }
+}
+
+/*
+ * Generic tests
+ */
+
+set "match1" "Test of general stupidity";
+
+test "Begin" {
+ if not string :matches "${match1}" "Test of *" {
+ test_fail "should have matched";
+ }
+
+ if not string :is "${1}" "general stupidity" {
+ test_fail "match value incorrect";
+ }
+}
+
+test "Begin no match" {
+ if string :matches "${match1}" "of *" {
+ test_fail "should not have matched";
+ }
+}
+
+set "match2" "toptoptop";
+
+test "End" {
+ if not string :matches "${match2}" "*top" {
+ test_fail "should have matched";
+ }
+
+ if not string :is "${1}" "toptop" {
+ test_fail "match value incorrect";
+ }
+}
+
+set "match3" "ik ben een tukker met grote oren en een lelijke broek.";
+
+test "Multiple" {
+ if not string :matches "${match3}" "ik ben * met * en *." {
+ test_fail "should have matched";
+ }
+
+ set "line" "Hij is ${1} met ${2} en ${3}!";
+
+ if not string :is "${line}"
+ "Hij is een tukker met grote oren en een lelijke broek!" {
+ test_fail "match values incorrect: ${line}";
+ }
+}
+
+set "match4" "beter van niet?";
+
+test "Escape" {
+ if not string :matches "${match4}" "*\\?" {
+ test_fail "should have matched";
+ }
+
+ if not string :is "${1}" "beter van niet" {
+ test_fail "match value incorrect: ${1}";
+ }
+}
+
+set "match5" "The quick brown fox jumps over the lazy dog.";
+
+test "Alphabet ?" {
+ if not string :matches "${match5}" "T?? ????? ????? ?o? ?u??? o?er ?he ???? ?o?." {
+ test_fail "should have matched";
+ }
+
+ set "alphabet" "${22}${8}${6}${25}${2}${13}${26}${1}${5}${15}${7}${21}${16}${12}${10}${17}${3}${9}${18}${20}${4}${19}${11}${14}${24}${23}";
+
+ if not string :is "${alphabet}" "abcdefghijklmnopqrstuvwxyz" {
+ test_fail "match values incorrect: ${alphabet}";
+ }
+
+ if string :matches "${match5}" "T?? ????? ?w??? ?o? ?u??? o?er ?he ???? ?o?." {
+ test_fail "should not have matched";
+ }
+}
+
+set "match6" "zero:one:zero|three;one;zero/five";
+
+test "Words sep ?" {
+
+ if not string :matches "${match6}" "*one?zero?five" {
+ test_fail "should have matched";
+ }
+
+ if not string :is "${1}${2}${3}" "zero:one:zero|three;;/" {
+ test_fail "incorrect match values: ${1} ${2} ${3}";
+ }
+}
+
+set "match7" "frop";
+
+test "Letters begin ?" {
+ if not string :matches "${match7}" "??op" {
+ test_fail "should have matched";
+ }
+
+ set "val" "${0}:${1}:${2}:${3}:";
+
+ if not string :is "${val}" "frop:f:r::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+test "Letters end ?" {
+ if not string :matches "${match7}" "fr??" {
+ test_fail "should have matched";
+ }
+
+ set "val" "${0}:${1}:${2}:${3}:";
+
+ if not string :is "${val}" "frop:o:p::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+set "match8" "klopfropstroptop";
+
+test "Letters words *? - 1" {
+ if not string :matches "${match8}" "*fr??*top" {
+ test_fail "should have matched";
+ }
+
+ set "val" ":${0}:${1}:${2}:${3}:${4}:${5}:";
+
+ if not string :is "${val}" ":klopfropstroptop:klop:o:p:strop::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+test "Letters words *? - 2" {
+ if not string :matches "${match8}" "?*fr??*top" {
+ test_fail "should have matched";
+ }
+
+ set "val" ":${0}:${1}:${2}:${3}:${4}:${5}:${6}:";
+
+ if not string :is "${val}" ":klopfropstroptop:k:lop:o:p:strop::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+test "Letters words *? backtrack" {
+ if not string :matches "${match8}" "*?op" {
+ test_fail "should have matched";
+ }
+
+ set "val" ":${0}:${1}:${2}:${3}:${4}:";
+
+ if not string :is "${val}" ":klopfropstroptop:klopfropstrop:t:::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+test "Letters words *? first" {
+ if not string :matches "${match8}" "*?op*" {
+ test_fail "failed to match";
+ }
+
+ set "val" ":${0}:${1}:${2}:${3}:${4}:";
+
+ if not string :is "${val}" ":klopfropstroptop:k:l:fropstroptop::" {
+ test_fail "incorrect match values: ${val}";
+ }
+}
+
+/*
+ * Specific tests
+ */
+
+test_set "message" text:
+Return-path: <stephan@xi.example.org>
+Envelope-to: stephan@xi.example.org
+Delivery-date: Sun, 01 Feb 2009 11:29:57 +0100
+Received: from stephan by xi.example.org with local (Exim 4.69)
+ (envelope-from <stephan@xi.example.org>)
+ id 1LTZaP-0007h3-2e
+ for stephan@xi.example.org; Sun, 01 Feb 2009 11:29:57 +0100
+From: Dovecot Debian Builder <stephan.example.org@xi.example.org>
+To: stephan@xi.example.org
+Subject: Log for failed build of dovecot_2:1.2.alpha5-0~auto+159 (dist=hardy)
+Message-Id: <E1LTZaP-0007h3-2e@xi.example.org>
+Date: Sun, 01 Feb 2009 11:29:57 +0100
+
+Automatic build of dovecot_1.2.alpha5-0~auto+159 on xi by sbuild/i386 0.57.7
+.
+;
+
+test "Match combined" {
+ if not header :matches "subject" "Log for ?* build of *" {
+ test_fail "failed to match";
+ }
+
+ if not string "${1}${2}" "failed" {
+ test_fail "incorrect match values: ${1}${2}";
+ }
+}
diff --git a/pigeonhole/tests/extensions/variables/modifiers.svtest b/pigeonhole/tests/extensions/variables/modifiers.svtest
new file mode 100644
index 0000000..37068b6
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/modifiers.svtest
@@ -0,0 +1,160 @@
+require "vnd.dovecot.testsuite";
+require "variables";
+require "encoded-character";
+
+/*
+ * Modifiers
+ */
+
+test "Modifier :lower" {
+ set :lower "test" "VaLuE";
+
+ if not string :is "${test}" "value" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifiers :lower :upperfirst" {
+ set :lower :upperfirst "test" "vAlUe";
+
+ if string :is "${test}" "value" {
+ test_fail "modifiers applied with wrong precedence";
+ }
+
+ if not string :is "${test}" "Value" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifiers :upperfirst :lower" {
+ set :upperfirst :lower "test" "vAlUe";
+
+ if string :is "${test}" "value" {
+ test_fail "modifiers applied with wrong precedence";
+ }
+
+ if not string :is "${test}" "Value" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :upper" {
+ set :upper "test" "vAlUe";
+
+ if not string :is "${test}" "VALUE" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifiers :upper :lowerfirst" {
+ set :upper :lowerfirst "test" "VaLuE";
+
+ if string :is "${test}" "VALUE" {
+ test_fail "modifiers applied with wrong precedence";
+ }
+
+ if not string :is "${test}" "vALUE" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifiers :lowerfirst :upper" {
+ set :lowerfirst :upper "test" "VaLuE";
+
+ if string :is "${test}" "VALUE" {
+ test_fail "modifiers applied with wrong precedence";
+ }
+
+ if not string :is "${test}" "vALUE" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :length (empty)" {
+ set :length "test" "";
+
+ if not string :is "${test}" "0" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :length (simple)" {
+ set :length "test" "VaLuE";
+
+ if not string :is "${test}" "5" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :length (elaborate)" {
+ set "a" "abcdefghijklmnopqrstuvwxyz";
+ set "b" "1234567890";
+ set :length "test" " ${a}:${b} ";
+
+ if not string :is "${test}" "40" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :quotewildcard" {
+ set :quotewildcard "test" "^^***??**^^";
+
+ if not string :is "${test}" "^^\\*\\*\\*\\?\\?\\*\\*^^" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "Modifier :length :quotewildcard" {
+ set :length :quotewildcard "test" "^^***??**^^";
+
+ if string :is "${test}" "11" {
+ test_fail "modifiers applied with wrong precedence";
+ }
+
+ if not string :is "${test}" "18" {
+ test_fail "modified variable assignment failed";
+ }
+}
+
+test "RFC examples" {
+ set "a" "juMBlEd lETteRS"; # => "juMBlEd lETteRS"
+ if not string "${a}" "juMBlEd lETteRS" {
+ test_fail "modified assignment failed (1): ${a}";
+ }
+
+ set :length "b" "${a}"; # => "15"
+ if not string "${b}" "15" {
+ test_fail "modified assignment failed (2): ${a}";
+ }
+
+ set :lower "b" "${a}"; # => "jumbled letters"
+ if not string "${b}" "jumbled letters" {
+ test_fail "modified assignment failed (3): ${a}";
+ }
+
+ set :upperfirst "b" "${a}"; # => "JuMBlEd lETteRS"
+ if not string "${b}" "JuMBlEd lETteRS" {
+ test_fail "modified assignment failed (4): ${a}";
+ }
+
+ set :upperfirst :lower "b" "${a}"; # => "Jumbled letters"
+ if not string "${b}" "Jumbled letters" {
+ test_fail "modified assignment failed (5): ${a}";
+ }
+
+ set :quotewildcard "b" "Rock*"; # => "Rock\*"
+ if not string "${b}" "Rock\\*" {
+ test_fail "modified assignment failed (6): ${a}";
+ }
+}
+
+/* RFC mentions `characters' and not octets */
+
+test "Modifier :length utf8" {
+ set "a" "Das ist ${unicode: 00fc}berhaupt nicht m${unicode: 00f6}glich.";
+
+ set :length "b" "${a}";
+ if not string "${b}" "32" {
+ test_fail "incorrect number of unicode characters reported: ${b}/32";
+ }
+}
diff --git a/pigeonhole/tests/extensions/variables/quoting.svtest b/pigeonhole/tests/extensions/variables/quoting.svtest
new file mode 100644
index 0000000..f65e4e4
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/quoting.svtest
@@ -0,0 +1,36 @@
+require "vnd.dovecot.testsuite";
+
+require "variables";
+require "encoded-character";
+
+test "Encodings - RFC examples" {
+ set "s" "$";
+ set "foo" "bar";
+
+ # "${fo\o}" => ${foo} => the expansion of variable foo.
+ if not string :is "${fo\o}" "bar" {
+ test_fail "failed 'the expansion of variable foo (${s}{fo\\o})'";
+ }
+
+ # "${fo\\o}" => ${fo\o} => illegal identifier => left verbatim.
+ if not string :is "${fo\\o}" "${s}{fo\\o}" {
+ test_fail "failed 'illegal identifier => left verbatim'";
+ }
+
+ # "\${foo}" => ${foo} => the expansion of variable foo.
+ if not string "\${foo}" "bar" {
+ test_fail "failed 'the expansion of variable foo (\\${s}{foo})'";
+ }
+
+ # "\\${foo}" => \${foo} => a backslash character followed by the
+ # expansion of variable foo.
+ if not string "\\${foo}" "\\bar" {
+ test_fail "failed 'a backslash character followed by expansion of variable foo";
+ }
+
+ set "name" "Ethelbert";
+ if not string "dear${hex:20 24 7b 4e}ame}" "dear Ethelbert" {
+ test_fail "failed 'dear Ethelbert' example";
+ }
+}
+
diff --git a/pigeonhole/tests/extensions/variables/regex.svtest b/pigeonhole/tests/extensions/variables/regex.svtest
new file mode 100644
index 0000000..04ca00d
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/regex.svtest
@@ -0,0 +1,35 @@
+require "vnd.dovecot.testsuite";
+
+require "regex";
+require "variables";
+
+# Test overwriting only on match
+test "RFC - values overwrite" {
+ set "sentence1" "the cat jumps off the table";
+ set "sentence2" "the dog barks at the cat in the alley";
+
+ if not string :regex "${sentence1}" "the (.*) jumps off the (.*)" {
+ test_fail "failed to match first sentence";
+ }
+
+ if not string :is "${1}:${2}" "cat:table" {
+ test_fail "invalid match values";
+ }
+
+ if string :regex "${sentence2}" "the (.*) barks at the (.*) in the store" {
+ test_fail "should not have matched second sentence";
+ }
+
+ if not string :is "${1}:${2}" "cat:table" {
+ test_fail "should have preserved match values";
+ }
+
+ if not string :regex "${sentence2}" "the (.*) barks at the (.*) in the alley" {
+ test_fail "failed to match the second sentence (second time)";
+ }
+
+ if not string :is "${1}:${2}" "dog:cat" {
+ test_fail "should have overwritten match values";
+ }
+}
+
diff --git a/pigeonhole/tests/extensions/variables/string.svtest b/pigeonhole/tests/extensions/variables/string.svtest
new file mode 100644
index 0000000..d0244e6
--- /dev/null
+++ b/pigeonhole/tests/extensions/variables/string.svtest
@@ -0,0 +1,37 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+require "variables";
+
+test "String - :count" {
+ if not string :count "eq" :comparator "i;ascii-numeric" ["a", "b", "c"] "3" {
+ test_fail "string test failed :count match";
+ }
+}
+
+test "String - :count \"\"" {
+ if not string :count "eq" :comparator "i;ascii-numeric" ["a", "", "c"] "2" {
+ test_fail "string test failed :count match";
+ }
+}
+
+test "RFC example" {
+ set "state" "${state} pending";
+
+ if not string :matches " ${state} " "* pending *" {
+ # the above test always succeeds
+
+ test_fail "test should have matched: \" ${state} \"";
+ }
+}
+
+test "No whitespace stripping" {
+ set "vara" " value ";
+ set "varb" "value";
+
+ if not string :is :comparator "i;octet" "${vara}" " ${varb} " {
+ test_fail "string test seems to have stripped white space";
+ }
+}