diff --git a/Makefile.am b/Makefile.am
index 880428c223b140b808bd936734164b4e34a81c3d..8027c8fb250c8d8ee2aa857d043dacca4f08b3a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,8 +39,15 @@ test_unfinished =
 endif
 
 test_cases = \
-	tests/testsuite.svtest\
-	tests/control-structures.svtest \
+	tests/testsuite.svtest \
+	tests/control-if.svtest \
+	tests/control-stop.svtest \
+	tests/test-allof.svtest \
+	tests/test-anyof.svtest \
+	tests/test-exists.svtest \
+	tests/test-header.svtest \
+	tests/test-address.svtest \
+	tests/test-size.svtest \
 	tests/compile/compile.svtest \
 	tests/compile/errors.svtest \
 	tests/compile/warnings.svtest \
@@ -50,15 +57,14 @@ test_cases = \
 	tests/execute/smtp.svtest \
 	tests/execute/mailstore.svtest \
 	tests/execute/examples.svtest \
-	tests/exists.svtest \
-	tests/header.svtest \
-	tests/address.svtest \
-	tests/size.svtest \
 	tests/lexer.svtest \
-	tests/comparators/core.svtest \
+	tests/comparators/i-octet.svtest \
+	tests/comparators/i-ascii-casemap.svtest \
 	tests/match-types/is.svtest \
 	tests/match-types/contains.svtest \
 	tests/match-types/matches.svtest \
+	tests/multiscript/basic.svtest \
+	tests/multiscript/conflicts.svtest \
 	tests/extensions/encoded-character.svtest \
 	tests/extensions/envelope.svtest \
 	tests/extensions/variables/basic.svtest \
@@ -114,7 +120,10 @@ test_cases = \
 	tests/extensions/date/basic.svtest \
 	tests/extensions/date/date-parts.svtest \
 	tests/extensions/date/zones.svtest \
-	tests/multiscript/basic.svtest \
+	tests/extensions/spamvirustest/spamtest.svtest \
+	tests/extensions/spamvirustest/virustest.svtest \
+	tests/extensions/spamvirustest/spamtestplus.svtest \
+	tests/extensions/spamvirustest/errors.svtest \
 	tests/deprecated/notify/basic.svtest \
 	tests/deprecated/notify/mailto.svtest \
 	tests/deprecated/notify/errors.svtest \
@@ -122,10 +131,6 @@ test_cases = \
 	tests/deprecated/notify/denotify.svtest \
 	tests/deprecated/imapflags/execute.svtest \
 	tests/deprecated/imapflags/errors.svtest \
-	tests/extensions/spamvirustest/spamtest.svtest \
-	tests/extensions/spamvirustest/virustest.svtest \
-	tests/extensions/spamvirustest/spamtestplus.svtest \
-	tests/extensions/spamvirustest/errors.svtest \
 	$(test_unfinished)
 
 $(test_cases):
diff --git a/TODO b/TODO
index 4a16162f60d92ccc57a5cca279cea33d3dddbbb3..eed9fa369db24b307d95917a9e3d5d724b64ab75 100644
--- a/TODO
+++ b/TODO
@@ -4,8 +4,6 @@ Current activities:
 	- Avoid reporting user-caused errors to the master log.
 	- Review logging and error handling; add more warning/info/debug messages
 	  where useful.
-* Cleanup the test suite
-	- Cleanup test scripts
 
 Next (in order of descending priority/precedence):
 
@@ -28,11 +26,14 @@ Next (in order of descending priority/precedence):
 	- Implement proper :content "multipart" behavior
 	- Implement proper :content "message/rfc822" behavior
 	- Build test cases for decoding MIME encodings to UTF-8
-* Implement index extension
+* Cleanup the test suite
+	- Restructure test scripts
+	- Add more comment on purpose of tests
 * Build a sieve tool to filter an entire existing mailbox through a Sieve 
   script:
 	- Add commandline options to fully customize execution
 	- Write manual page
+* Implement index extension
 * Update include extension to latest draft (v05 currently):
 	- Implement required ManageSieve behavior (pending IETF discussion)
 * Vacation extension improvements:
@@ -58,7 +59,7 @@ Next (in order of descending priority/precedence):
 * Make testsuite much more exhaustive:
 	- Add support for testing the content of result actions
 	- Test as many error/warning/info conditions as possible. 
-	- Review the specification documents and check whether the given conditions
+	- Review the specification documents and check whether the given requirements
 	  are tested at least once.
 * Fix ManageSieve proxy to recognize response codes from the backend and forward
   them to the user if appropriate/safe.
diff --git a/tests/address.svtest b/tests/address.svtest
deleted file mode 100644
index 86f75aff49f70b77cd7c539270f9660ee5d298bf..0000000000000000000000000000000000000000
--- a/tests/address.svtest
+++ /dev/null
@@ -1,111 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-/*
- * If an address is not syntactically valid, then it will not be matched
- * by tests specifying ":localpart" or ":domain".
- */
-
-test_set "message" text:
-From: stephan@
-To: @example.org
-Cc: nonsense
-Resent-To:
-Subject: Invalid addresses
-
-Test.
-.
-;
-
-test "Invalid single addresses" {
-	if address :localpart "from" "stephan" {
-		test_fail ":localpart matched invalid address";
-	}	
-
-	if address :domain "to" "example.org" {
-		test_fail ":domain matched invalid address";
-	}	
-
-	if not address :is :all "resent-to" "" {
-		test_fail ":all failed to match empty address";
-	}	
-
-	if not address :is :all "cc" "nonsense" {
-		test_fail ":all failed to match invalid address";
-	}
-}
-
-/*
- * Errors in address lists
- */ 
-
-test_set "message" text:
-From: stephan@
-To: nico@frop.example.com, @example.org
-Cc: stephan@example.org, nonsense
-Subject: Invalid addresses
-
-Test.
-.
-;
-
-test "Invalid address list" {
-	if address :is :localpart "to" "" {
-		test_fail ":localpart matched invalid address";
-	}	
-
-	if address :is :domain "to" "example.org" {
-		test_fail ":domain matched invalid address";
-	}	
-}
-
-/*
- * Undisclosed recipients
- */
-
-test_set "message" text:
-From: stephan@
-To: undisclosed-recipients:;
-Subject: Invalid addresses
-
-Test.
-.
-;
-
-test "Undisclosed recipients" {
-    if address :is :domain "to" "undisclosed-recipients:;" {
-        test_fail ":domain matched group name";
-    }
-
-    if address :is :localpart "to" "undisclosed-recipients:;" {
-        test_fail ":localpart matched group name";
-    }
-}
-
-/*
- * Strange
- */
-
-test_set "message" text:
-From: SPAM@MYDOMAIN
-To: stephan@example.org
-Subject: Spam
-
-Spam!
-.
-;
-
-test "Questionable address" {
-	if address :domain :is "from" "MYDOMAIN" {
-		if address :localpart :is "from" "SPAM" {
-			
-		} elsif header :contains "subject" "Cron" {
-			test_fail "message erroneously recognized as cron";
-		} else {
-			test_fail "message erroneously recognized as normal";
-		}
-	} else {
-		test_fail "message domain not recognized";
-	}
-}
-
-
diff --git a/tests/comparators/core.svtest b/tests/comparators/core.svtest
deleted file mode 100644
index c504d629da8ad66f279304f0c420ae2e030490ee..0000000000000000000000000000000000000000
--- a/tests/comparators/core.svtest
+++ /dev/null
@@ -1,65 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-test_set "message" text:
-From: stephan@example.org
-Cc: frop@example.com
-To: test@dovecot.example.net
-X-A: This is a TEST header
-Subject: Test Message
-
-Test!
-.
-;
-
-# Comparator Tests
-
-test "CMP-octet-CONTAINS" {
-	if not header :contains :comparator "i;octet" "X-A" "TEST" {
-		test_fail "should have matched";
-	}
-}
-
-test "CMP-octet-NOTCONTAINS" {
-	if header :contains :comparator "i;octet" "X-A" "test" {
-		test_fail "should not have matched";
-	}
-}
-
-test "CMP-octet-MATCH" {
-	if not header :matches :comparator "i;octet" "X-A" "This*TEST*r" {
-		test_fail "should have matched";
-	}
-}
-
-test "CMP-octet-NOTMATCH" {
-	if header :matches :comparator "i;octet" "X-A" "ThIs*tEsT*R" {
-		test_fail "should not have matched";
-	}
-}
-
-test "CMP-ascii-casemap-CONTAINS-1" {
-	if not header :contains :comparator "i;ascii-casemap" "X-A" "TEST" {
-		test_fail "should have matched";
-	}
-}
-
-test "CMP-ascii-casemap-CONTAINS-2" {
-	if not header :contains :comparator "i;ascii-casemap" "X-A" "test" {
-		test_fail "should have matched";
-	}
-}
-
-test "CMP-ascii-casemap-MATCH-1" {
-	if not header :matches :comparator "i;ascii-casemap" "X-A" "This*TEST*r" {
-		test_fail "should have matched";
-	}
-}
-
-test "CMP-ascii-casemap-MATCH-2" {
-	if not header :matches :comparator "i;ascii-casemap" "X-A" "ThIs*tEsT*R" {
-		test_fail "should have matched";
-	}
-}
-
-
-
diff --git a/tests/comparators/i-ascii-casemap.svtest b/tests/comparators/i-ascii-casemap.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..0891f3e68b3606e028b1c6f4aefa978166f6f81a
--- /dev/null
+++ b/tests/comparators/i-ascii-casemap.svtest
@@ -0,0 +1,39 @@
+require "vnd.dovecot.testsuite";
+
+test_set "message" text:
+From: stephan@example.org
+Cc: frop@example.com
+To: test@dovecot.example.net
+X-A: This is a TEST header
+Subject: Test Message
+
+Test!
+.
+;
+
+test "i;ascii-casemap :contains (1)" {
+	if not header :contains :comparator "i;ascii-casemap" "X-A" "TEST" {
+		test_fail "should have matched";
+	}
+}
+
+test "i;ascii-casemap :contains (2)" {
+	if not header :contains :comparator "i;ascii-casemap" "X-A" "test" {
+		test_fail "should have matched";
+	}
+}
+
+test "i;ascii-casemap :matches (1)" {
+	if not header :matches :comparator "i;ascii-casemap" "X-A" "This*TEST*r" {
+		test_fail "should have matched";
+	}
+}
+
+test "i;ascii-casemap :matches (2)" {
+	if not header :matches :comparator "i;ascii-casemap" "X-A" "ThIs*tEsT*R" {
+		test_fail "should have matched";
+	}
+}
+
+
+
diff --git a/tests/comparators/i-octet.svtest b/tests/comparators/i-octet.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..b6041bc3a4620ec37bb404452639b4fb444ddf31
--- /dev/null
+++ b/tests/comparators/i-octet.svtest
@@ -0,0 +1,37 @@
+require "vnd.dovecot.testsuite";
+
+test_set "message" text:
+From: stephan@example.org
+Cc: frop@example.com
+To: test@dovecot.example.net
+X-A: This is a TEST header
+Subject: Test Message
+
+Test!
+.
+;
+
+test "i;octet :contains" {
+	if not header :contains :comparator "i;octet" "X-A" "TEST" {
+		test_fail "should have matched";
+	}
+}
+
+test "i;octet not :contains" {
+	if header :contains :comparator "i;octet" "X-A" "test" {
+		test_fail "should not have matched";
+	}
+}
+
+test "i;octet :matches" {
+	if not header :matches :comparator "i;octet" "X-A" "This*TEST*r" {
+		test_fail "should have matched";
+	}
+}
+
+test "i;octet not :matches" {
+	if header :matches :comparator "i;octet" "X-A" "ThIs*tEsT*R" {
+		test_fail "should not have matched";
+	}
+}
+
diff --git a/tests/compile/errors.svtest b/tests/compile/errors.svtest
index 7bbfc6c6c9a0bcdcc242200fe2f2b7dafbc86829..8dc58aeeeb99409f710fe02200b1f2d4f953b138 100644
--- a/tests/compile/errors.svtest
+++ b/tests/compile/errors.svtest
@@ -13,13 +13,13 @@ require "comparator-i;ascii-numeric";
  */
 
 test "Lexer errors (FIXME: count only)" {
-    if test_script_compile "errors/lexer.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/lexer.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "10" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "10" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -27,13 +27,13 @@ test "Lexer errors (FIXME: count only)" {
  */
 
 test "Parser errors (FIXME: count only)" {
-    if test_script_compile "errors/parser.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/parser.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "9" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "9" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -191,13 +191,13 @@ test "Require errors (FIXME: count only)" {
  */
 
 test "Size errors (FIXME: count only)" {
-    if test_script_compile "errors/size.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/size.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";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "7" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -205,13 +205,13 @@ test "Size errors (FIXME: count only)" {
  */
 
 test "Envelope errors (FIXME: count only)" {
-    if test_script_compile "errors/envelope.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/envelope.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -219,13 +219,13 @@ test "Envelope errors (FIXME: count only)" {
  */
 
 test "Stop errors (FIXME: count only)" {
-    if test_script_compile "errors/stop.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/stop.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "9" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "9" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -233,13 +233,13 @@ test "Stop errors (FIXME: count only)" {
  */
 
 test "Keep errors (FIXME: count only)" {
-    if test_script_compile "errors/keep.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/keep.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -247,13 +247,13 @@ test "Keep errors (FIXME: count only)" {
  */
 
 test "ADDRESS-PART errors (FIXME: count only)" {
-    if test_script_compile "errors/address-part.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/address-part.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -261,13 +261,13 @@ test "ADDRESS-PART errors (FIXME: count only)" {
  */
 
 test "MATCH-TYPE errors (FIXME: count only)" {
-    if test_script_compile "errors/match-type.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/match-type.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";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "2" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -275,13 +275,13 @@ test "MATCH-TYPE errors (FIXME: count only)" {
  */
 
 test "Encoded-character errors (FIXME: count only)" {
-    if test_script_compile "errors/encoded-character.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/encoded-character.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -289,28 +289,27 @@ test "Encoded-character errors (FIXME: count only)" {
  */
 
 test "Outgoing address errors (FIXME: count only)" {
-    if test_script_compile "errors/out-address.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/out-address.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "15" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "15" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
-
 /*
  * Tagged argument errors
  */
 
 test "Tagged argument errors (FIXME: count only)" {
-    if test_script_compile "errors/tag.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/tag.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -358,11 +357,11 @@ test "Typos" {
  */
 
 test "Unsupported language features (FIXME: count only)" {
-    if test_script_compile "errors/unsupported.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "errors/unsupported.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "4" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "4" {
+		test_fail "wrong number of errors reported";
+	}
 }
diff --git a/tests/compile/errors/match-type.sieve b/tests/compile/errors/match-type.sieve
index 78bc3ce206e3d02826301afa14c188bdbbe60cb2..d8e16817b43ac5aa9984f61130969a36a0fb40b9 100644
--- a/tests/compile/errors/match-type.sieve
+++ b/tests/compile/errors/match-type.sieve
@@ -1,7 +1,7 @@
 require "comparator-i;ascii-numeric";
 
 if header :contains :comparator "i;ascii-numeric" "from" "friep.example.com" {
-    keep;
+	keep;
 }
 
 keep;
diff --git a/tests/compile/recover.svtest b/tests/compile/recover.svtest
index f6010a0224a6a65d857bf18f6208638adeff1c43..959a602d018b02bae4f85c3c8ed0c5b3baa8d925 100644
--- a/tests/compile/recover.svtest
+++ b/tests/compile/recover.svtest
@@ -14,25 +14,25 @@ require "comparator-i;ascii-numeric";
 /* Missing semicolon */
 
 test "Missing semicolons" {
-    if test_script_compile "recover/commands-semicolon.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "recover/commands-semicolon.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /* End of block recovery*/
 
 test "Missing semicolon at end of block" {
-    if test_script_compile "recover/commands-endblock.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "recover/commands-endblock.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "4" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "4" {
+		test_fail "wrong number of errors reported";
+	}
 }
 
 /*
@@ -40,11 +40,11 @@ test "Missing semicolon at end of block" {
  */
 
 test "Spurious comma at end of test list" {
-    if test_script_compile "recover/tests-endcomma.sieve" {
-        test_fail "compile should have failed.";
-    }
+	if test_script_compile "recover/tests-endcomma.sieve" {
+		test_fail "compile should have failed.";
+	}
 
-    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-        test_fail "wrong number of errors reported";
-    }
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+		test_fail "wrong number of errors reported";
+	}
 }
diff --git a/tests/compile/recover/commands-endblock.sieve b/tests/compile/recover/commands-endblock.sieve
index 2868c54137b28fb2db37225546cf631e4ac9859b..c06e2181799b5bac7db793bd3ecc8952f73677c1 100644
--- a/tests/compile/recover/commands-endblock.sieve
+++ b/tests/compile/recover/commands-endblock.sieve
@@ -1,10 +1,12 @@
 if true {
 	if true {
+		# Missing semicolon
 		keep
 	}
 }
 
 if true {
+	# Erroneous syntax
 	keep,
 	keep
 }
@@ -18,6 +20,7 @@ if true {
 if true {
 	if anyof(true,true,false) {
 		keep;
+		# Missing semicolon
 		discard
 	}
 }
diff --git a/tests/compile/recover/commands-semicolon.sieve b/tests/compile/recover/commands-semicolon.sieve
index 2571038af804c1eff9331d099431920b466f67ca..effb389f0b47a7fee749d4a6d939eeb05e8cc426 100644
--- a/tests/compile/recover/commands-semicolon.sieve
+++ b/tests/compile/recover/commands-semicolon.sieve
@@ -1,7 +1,16 @@
+
 keep;
+
 discard;
+
+# Missing semicolon
 keep
+
 redirect "frop@nl.example.com";
+
 discard;
+
+# Missing semicolon
 keep
+
 redirect "frml@nl.example.com";
diff --git a/tests/compile/recover/tests-endcomma.sieve b/tests/compile/recover/tests-endcomma.sieve
index 6daf117898f288a59dc716907a07947b5216a606..54c93ec257bdeac9e85c86119b090f9f17ee7827 100644
--- a/tests/compile/recover/tests-endcomma.sieve
+++ b/tests/compile/recover/tests-endcomma.sieve
@@ -1,10 +1,17 @@
 if true {
-if true {
-if anyof(true,true,true,) {
-}}}
+	if true {
+		# Spurious comma
+		if anyof(true,true,true,) {
+		}
+	}
+}
 
 if true {
-if anyof(true,true) {
-if anyof(true,true,true,) {
-if anyof(true,true,true) {
-}}}}
+	if anyof(true,true) {
+		# Spurious comma
+		if anyof(true,true,true,) {
+			if anyof(true,true,true) {
+			}
+		}
+	}
+}
diff --git a/tests/compile/warnings.svtest b/tests/compile/warnings.svtest
index 66f26f686e5683665ab517477d404a110f79b868..8261551f0b57f694c1fc3784cf7750f38f674301 100644
--- a/tests/compile/warnings.svtest
+++ b/tests/compile/warnings.svtest
@@ -1,8 +1,8 @@
 require "vnd.dovecot.testsuite";
 
 test "EOF Warnings" {
-    if not test_script_compile "warnings/eof.sieve" {
-        test_fail "compile should have succeeded.";
-    }
+	if not test_script_compile "warnings/eof.sieve" {
+		test_fail "compile should have succeeded.";
+	}
 }
 
diff --git a/tests/compile/warnings/eof.sieve b/tests/compile/warnings/eof.sieve
index e7121495d7de8a2100fa02b71b5ea1fc925ee02b..cf906dc4ce5e56abb2649923f6754d7f1fcd46de 100644
--- a/tests/compile/warnings/eof.sieve
+++ b/tests/compile/warnings/eof.sieve
@@ -1,2 +1,2 @@
 keep;
-# Kept
\ No newline at end of file
+# Final comment without newline
diff --git a/tests/compile/warnings/invalid-headers.sieve b/tests/compile/warnings/invalid-headers.sieve
index d3fc1a38a190abb68b511aea5ab788c8df2608f4..a6b12a83b3582dbcae3fc8375e91e1e9c5dc1553 100644
--- a/tests/compile/warnings/invalid-headers.sieve
+++ b/tests/compile/warnings/invalid-headers.sieve
@@ -1,11 +1,14 @@
+# Header test
 if header "from:" "frop@example.org" {
 	stop;
 }
 
+# Address test
 if address "from:" "frop@example.org" {
 	stop;
 }
 
+# Exists test
 if exists "from:" {
 	stop;
 }
diff --git a/tests/control-if.svtest b/tests/control-if.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..227205908ff54053fd98c88ae11d09efc0ef49bd
--- /dev/null
+++ b/tests/control-if.svtest
@@ -0,0 +1,162 @@
+require "vnd.dovecot.testsuite";
+
+/* 
+ * ## RFC 5228, Section 3.1. Control if (page 21) ## 
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: test@dovecot.example.net
+Cc: friep@example.com
+Subject: Test
+
+Test!
+.
+;
+
+/*
+ * Basic functionality
+ */
+
+/* "The semantics are similar to those of any of the many other
+ *  programming languages these control structures appear in.  When the
+ *  interpreter sees an "if", it evaluates the test associated with it.
+ *  If the test is true, it executes the block associated with it.
+ *
+ *  If the test of the "if" is false, it evaluates the test of the first
+ *  "elsif" (if any).  If the test of "elsif" is true, it runs the
+ *  elsif's block.  An elsif may be followed by an elsif, in which case,
+ *  the interpreter repeats this process until it runs out of elsifs.
+ *
+ *  When the interpreter runs out of elsifs, there may be an "else" case.
+ *  If there is, and none of the if or elsif tests were true, the
+ *  interpreter runs the else's block.
+ *
+ *  This provides a way of performing exactly one of the blocks in the
+ *  chain.
+ * "
+ */
+
+/*
+ * TEST: Basic functionality: if true/false
+ */
+
+test "Basic functionality: if true/false" {
+	/* Static */
+	if true {
+		/* Correct */
+	} else {
+		test_fail "executed wrong alternative for static true";
+	}
+
+	if false {
+		test_fail "executed wrong alternative for static false";
+	} else {
+		/* Correct */
+	}
+
+	/* Dynamic */
+	if exists "to" {
+		/* Correct */
+	} else {
+		test_fail "executed wrong alternative for dynamic true";
+	}
+
+	if exists "flierp" {
+		test_fail "executed wrong alternative for dynamic false";
+	} else {
+		/* Correct */
+	}
+}
+
+/*
+ * TEST: Basic functionality: elseif true/false
+ */
+
+test "Basic functionality: elseif true/false" {
+	/* Static */
+	if false {
+		test_fail "executed wrong alternative for static true (if)";
+	} elsif true {
+		/* Correct */
+	} else {
+		test_fail "executed wrong alternative for static true (else)";	
+	}
+
+	if false {
+		test_fail "executed wrong alternative for static false (if)";
+	} elsif false {
+		test_fail "executed wrong alternative for static false (elsif)";	
+	} else {
+		/* Correct */
+	}
+
+	/* Dynamic */
+	if address :is "from" "tss@example.net" {
+		test_fail "executed wrong alternative for dynamic true (if)";
+	} elsif address :is "from" "stephan@example.org" {
+		/* Correct */
+	} else {
+		test_fail "executed wrong alternative for dynamic true(else)";	
+	}
+
+	if address :is "from" "tss@example.net" {
+		test_fail "executed wrong alternative for dynamic false (if)";
+	} elsif address :is "to" "stephan@example.org" {
+		test_fail "executed wrong alternative for dynamic false (elsif)";	
+	} else {
+		/* Correct */
+	}
+}
+
+/*
+ * TEST: Basic functionality: nesting
+ */
+
+test "Basic functionality: nesting" {
+	/* Static */
+	if true {
+		if true {
+			if false {
+				test_fail "chose wrong static outcome: true->true->false";
+			} else {
+				/* Correct */
+			}
+		} else {
+			test_fail "chose wrong static outcome: true->false";
+		}
+	} elsif true {
+		if false {
+			test_fail "chose wrong static outcome: false->true->false";	
+		} elsif true {
+			test_fail "chose wrong static outcome: false->true->true";
+		}
+	} else {
+		test_fail "chose wrong static outcome: false->false";
+	}
+
+	/* Dynamic */
+
+	if exists "to" {
+		if exists "from" {
+			if exists "friep" {
+				test_fail "chose wrong dynamic outcome: true->true->false";
+			} else {
+				/* Correct */
+			}
+		} else {
+			test_fail "chose wrong dynamic outcome: true->false";
+		}
+	} elsif exists "cc" {
+		if exists "frop" {
+			test_fail "chose wrong dynamic outcome: false->true->false";	
+		} elsif exists "from" {
+			test_fail "chose wrong dynamic outcome: false->true->true";
+		}
+	} else {
+		test_fail "chose wrong dynamic outcome: false->false";
+	}
+}
+
+
+
diff --git a/tests/control-stop.svtest b/tests/control-stop.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..b49199d21833f1ef102292d59fb173c35a707675
--- /dev/null
+++ b/tests/control-stop.svtest
@@ -0,0 +1,29 @@
+require "vnd.dovecot.testsuite";
+
+/*
+ * ## RFC 5228, Section 3.3. Control stop (page 22) ##
+ */
+
+/*
+ * TEST: End processing
+ */
+
+/* "The "stop" action ends all processing.
+ * "
+ */
+
+test "End processing" {
+	stop;
+
+	test_fail "continued after stop";
+}
+
+/*
+ * TEST: Implicit keep
+ */
+
+/* "If the implicit keep has not been cancelled, then it is taken.
+ * "
+ */
+
+/* FIXME */
diff --git a/tests/control-structures.svtest b/tests/control-structures.svtest
deleted file mode 100644
index 7fb2bd5a4ccfbb45e2498045c20aee5fda42a6b1..0000000000000000000000000000000000000000
--- a/tests/control-structures.svtest
+++ /dev/null
@@ -1,149 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-test_set "message" text:
-From: stephan@example.org
-To: test@dovecot.example.net
-Subject: Test
-
-Test!
-.
-;
-
-test "IF-true" {
-	if true {
-	} else {
-		test_fail "executed wrong alternative";
-	}
-}
-
-test "IF-false" {
-	if false {
-		test_fail "executed wrong alternative";
-	}
-}
-
-test "ELSEIF-true" {
-	if false {
-		test_fail "executed wrong alternative (if)";
-	} elsif true {
-	} else {
-		test_fail "executed wrong alternative (else)";	
-	}
-}
-
-test "ELSEIF-false" {
-	if false {
-		test_fail "executed wrong alternative (if)";
-	} elsif false {
-		test_fail "executed wrong alternative (elsif)";	
-	} else {
-	}
-}
-
-test "IF-address-true" {
-	if address :is "from" "stephan@example.org" {
-	} else {
-		test_fail "executed wrong alternative";
-	}
-}
-
-test "IF-address-false" {
-	if address :is "from" "tss@example.net" {
-		test_fail "executed wrong alternative";
-	}
-}
-
-test "ELSEIF-address-true" {
-	if address :is "from" "tss@example.net" {
-		test_fail "executed wrong alternative (if)";
-	} elsif address :is "from" "stephan@example.org" {
-	} else {
-		test_fail "executed wrong alternative (else)";	
-	}
-}
-
-test "ELSEIF-address-false" {
-	if address :is "from" "tss@example.net" {
-		test_fail "executed wrong alternative (if)";
-	} elsif address :is "to" "stephan@example.org" {
-		test_fail "executed wrong alternative (elsif)";	
-	} else {
-	}
-}
-
-test "IF-nesting-static" {
-	if true {
-		if true {
-			if false {
-				test_fail "chose wrong outcome: true->true->false";
-			} else {
-			}
-		} else {
-			test_fail "chose wrong outcome: true->false";
-		}
-	} elsif true {
-		if false {
-			test_fail "chose wrong outcome: false->true->false";	
-		} elsif true {
-			test_fail "chose wrong outcome: false->true->true";
-		}
-	} else {
-		test_fail "chose wrong outcome: false->false";
-	}
-}
-
-test "ALLOF-ANYOF-static" {
-	if allof ( true, true, true, true, anyof (false, false, true, false) ) {
-		if anyof( allof(false, false), allof(false, true), allof(true, false) ) {
-			test_fail "chose wrong outcome: true->true";
-		} elsif allof( anyof(false, true), true, anyof(true, false), anyof(true, true)) {
-			
-		} else {
-			test_fail "chose wrong outcome: true->false->false";			
-		}
-	} else {
-		test_fail "chose wrong outcome: false";
-	}
-}
-
-test "ALLOF-ANYOF-single" {
-	# Static 
-	if not allof ( true ) {
-		test_fail "allof ( true ) evaluates to false";
-	}
-
-	if allof ( false ) {
-		test_fail "allof ( false ) evaluates to true";
-	}
-
-	if not anyof ( true ) {
-		test_fail "anyof ( true ) evaluates to false";
-	}
-
-	if anyof ( false ) {
-		test_fail "anyof ( false ) evaluates to true";
-	}	
-
-	# Dynamic
-	if not allof ( exists "subject" ) {
-        test_fail "allof ( 'true' ) evaluates to false";
-    }
-
-    if allof ( exists "x-nonsense" ) {
-        test_fail "allof ( 'false' ) evaluates to true";
-    }
-
-    if not anyof ( exists "subject" ) {
-        test_fail "anyof ( 'true' ) evaluates to false";
-    }
-
-    if anyof ( exists "x-nonsense" ) {
-        test_fail "anyof ( 'false' ) evaluates to true";
-    }
-}
-
-test "STOP" {
-	stop;
-	test_fail "continued after stop";
-}
-
diff --git a/tests/deprecated/imapflags/execute.svtest b/tests/deprecated/imapflags/execute.svtest
index e6d6576f986496e3dd89e0a72b58a465f8c26c01..ea6657bcdebac217d712df061628801078f9c826 100644
--- a/tests/deprecated/imapflags/execute.svtest
+++ b/tests/deprecated/imapflags/execute.svtest
@@ -15,29 +15,29 @@ Test message.
 ;
 
 test "Mark / Unmark" {
-    if not test_script_compile "execute/mark.sieve" {
-        test_fail "script compile failed";
-    }
+	if not test_script_compile "execute/mark.sieve" {
+		test_fail "script compile failed";
+	}
 
-    if not test_script_run {
-        test_fail "script execute failed";
-    }
+	if not test_script_run {
+		test_fail "script execute failed";
+	}
 
-    if not test_result_execute {
-        test_fail "failed to execute first result";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute first result";
+	}
 
-    test_result_reset;
+	test_result_reset;
 
-    test_message :folder "Marked" 0;
+	test_message :folder "Marked" 0;
 
 	if not hasflag "\\flagged" {
 		test_fail "message not marked";
 	}
 
-    test_result_reset;
+	test_result_reset;
 
-    test_message :folder "Unmarked" 0;
+	test_message :folder "Unmarked" 0;
 
 	if hasflag "\\flagged" {
 		test_fail "message not unmarked";
@@ -46,29 +46,29 @@ test "Mark / Unmark" {
 
 test_result_reset;
 test "Setflag / Addflag / Removeflag" {
-    if not test_script_compile "execute/flags.sieve" {
-        test_fail "script compile failed";
-    }
+	if not test_script_compile "execute/flags.sieve" {
+		test_fail "script compile failed";
+	}
 
-    if not test_script_run {
-        test_fail "script execute failed";
-    }
+	if not test_script_run {
+		test_fail "script execute failed";
+	}
 
-    if not test_result_execute {
-        test_fail "failed to execute first result";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute first result";
+	}
 
-    test_result_reset;
+	test_result_reset;
 
-    test_message :folder "Set" 0;
+	test_message :folder "Set" 0;
 
 	if not hasflag "\\draft" {
 		test_fail "flag not set";
 	}
 
-    test_result_reset;
+	test_result_reset;
 
-    test_message :folder "Add" 0;
+	test_message :folder "Add" 0;
 
 	if not hasflag "\\draft" {
 		test_fail "flag not retained";
@@ -78,9 +78,9 @@ test "Setflag / Addflag / Removeflag" {
 		test_fail "flag not added";
 	}
 
-    test_result_reset;
+	test_result_reset;
 
-    test_message :folder "Remove" 0;
+	test_message :folder "Remove" 0;
 
 	if not hasflag "\\flagged" {
 		test_fail "flag not retained";
diff --git a/tests/deprecated/notify/denotify.svtest b/tests/deprecated/notify/denotify.svtest
index 72b30bb426549ef42d28776e689d5811b325d73b..9f752e12769c9e47abf8c25dfefedbaec261ec84 100644
--- a/tests/deprecated/notify/denotify.svtest
+++ b/tests/deprecated/notify/denotify.svtest
@@ -16,17 +16,17 @@ Klutsefluts.
 ;
 
 test "Denotify All" {
-    notify :options "timo@example.com";
+	notify :options "timo@example.com";
 	notify :options "stephan@dovecot.example.net";
 	notify :options "postmaster@frop.example.org";
 	denotify;
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if test_message :smtp 0 {
-        test_fail "no notifications should have been sent";
+	if test_message :smtp 0 {
+		test_fail "no notifications should have been sent";
 	}
 }
 
@@ -47,7 +47,7 @@ Klutsefluts.
 
 test "Denotify ID First" {
 	/* #1 */
-    notify :options "timo@example.com" :id "aap";
+	notify :options "timo@example.com" :id "aap";
 
 	/* #2 */
 	notify :options "stephan@dovecot.example.net" :id "noot";
@@ -57,28 +57,28 @@ test "Denotify ID First" {
 
 	denotify :is "aap";
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if not test_message :smtp 0 {
-        test_fail "two notifications should have been sent (#2 missing)";
+	if not test_message :smtp 0 {
+		test_fail "two notifications should have been sent (#2 missing)";
 	}
 
 	if not envelope "to" "stephan@dovecot.example.net" {
 		test_fail "message #2 unexpectedly missing from output";
 	}
 
-    if not test_message :smtp 1 {
-        test_fail "two notifications should have been sent (#3 missing)";
+	if not test_message :smtp 1 {
+		test_fail "two notifications should have been sent (#3 missing)";
 	}
 
 	if not envelope "to" "postmaster@frop.example.org" {
 		test_fail "message #3 unexpectedly missing from output";
 	}
 
-    if test_message :smtp 2 {
-        test_fail "too many notifications sent";
+	if test_message :smtp 2 {
+		test_fail "too many notifications sent";
 	}
 }
 
@@ -99,7 +99,7 @@ Klutsefluts.
 
 test "Denotify ID Middle" {
 	/* #1 */
-    notify :options "timo@example.com" :id "aap";
+	notify :options "timo@example.com" :id "aap";
 
 	/* #2 */
 	notify :options "stephan@dovecot.example.net" :id "noot";
@@ -109,28 +109,28 @@ test "Denotify ID Middle" {
 
 	denotify :is "noot";
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if not test_message :smtp 0 {
-        test_fail "two notifications should have been sent (#1 missing)";
+	if not test_message :smtp 0 {
+		test_fail "two notifications should have been sent (#1 missing)";
 	}
 
 	if not envelope "to" "timo@example.com" {
 		test_fail "message #1 unexpectedly missing from output";
 	}
 
-    if not test_message :smtp 1 {
-        test_fail "two notifications should have been sent (#3 missing)";
+	if not test_message :smtp 1 {
+		test_fail "two notifications should have been sent (#3 missing)";
 	}
 
 	if not envelope "to" "postmaster@frop.example.org" {
 		test_fail "message #3 unexpectedly missing from output";
 	}
 
-    if test_message :smtp 2 {
-        test_fail "too many notifications sent";
+	if test_message :smtp 2 {
+		test_fail "too many notifications sent";
 	}
 }
 
@@ -151,7 +151,7 @@ Klutsefluts.
 
 test "Denotify ID Last" {
 	/* #1 */
-    notify :options "timo@example.com" :id "aap";
+	notify :options "timo@example.com" :id "aap";
 
 	/* #2 */
 	notify :options "stephan@dovecot.example.net" :id "noot";
@@ -161,28 +161,28 @@ test "Denotify ID Last" {
 
 	denotify :is "mies";
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if not test_message :smtp 0 {
-        test_fail "two notifications should have been sent (#1 missing)";
+	if not test_message :smtp 0 {
+		test_fail "two notifications should have been sent (#1 missing)";
 	}
 
 	if not envelope "to" "timo@example.com" {
 		test_fail "message #1 unexpectedly missing from output";
 	}
 
-    if not test_message :smtp 1 {
-        test_fail "two notifications should have been sent (#2 missing)";
+	if not test_message :smtp 1 {
+		test_fail "two notifications should have been sent (#2 missing)";
 	}
 
 	if not envelope "to" "stephan@dovecot.example.net" {
 		test_fail "message #2 unexpectedly missing from output";
 	}
 
-    if test_message :smtp 2 {
-        test_fail "too many notifications sent";
+	if test_message :smtp 2 {
+		test_fail "too many notifications sent";
 	}
 }
 
@@ -204,7 +204,7 @@ Klutsefluts.
 
 test "Denotify Matching" {
 	/* #1 */
-    notify :options "timo@example.com" :id "frop";
+	notify :options "timo@example.com" :id "frop";
 
 	/* #2 */
 	notify :options "stephan@dovecot.example.net" :id "noot";
@@ -214,20 +214,20 @@ test "Denotify Matching" {
 
 	denotify :matches "fr*";
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if not test_message :smtp 0 {
-        test_fail "one notification should have been sent";
+	if not test_message :smtp 0 {
+		test_fail "one notification should have been sent";
 	}
 
 	if not envelope "to" "stephan@dovecot.example.net" {
 		test_fail "message #2 unexpectedly missing from output";
 	}
 
-    if test_message :smtp 1 {
-        test_fail "too many notifications sent";
+	if test_message :smtp 1 {
+		test_fail "too many notifications sent";
 	}
 }
 
@@ -249,7 +249,7 @@ Klutsefluts.
 
 test "Denotify Matching Importance" {
 	/* #1 */
-    notify :options "timo@example.com" :id "frop" :low;
+	notify :options "timo@example.com" :id "frop" :low;
 
 	/* #2 */
 	notify :options "stephan@dovecot.example.net" :id "frml" :high;
@@ -259,20 +259,20 @@ test "Denotify Matching Importance" {
 
 	denotify :matches "fr*" :low;
 
-    if not test_result_execute {
-        test_fail "failed to execute notify";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute notify";
+	}
 
-    if not test_message :smtp 0 {
-        test_fail "one notification should have been sent";
+	if not test_message :smtp 0 {
+		test_fail "one notification should have been sent";
 	}
 
 	if not envelope "to" "stephan@dovecot.example.net" {
 		test_fail "message #2 unexpectedly missing from output";
 	}
 
-    if test_message :smtp 1 {
-        test_fail "too many notifications sent";
+	if test_message :smtp 1 {
+		test_fail "too many notifications sent";
 	}
 }
 
diff --git a/tests/execute/smtp.svtest b/tests/execute/smtp.svtest
index 70fb7f5fb876859ce54b39cdff4f1045528856b1..d98b288afc839f6af9e25bf14cf3fe16ca1c58c5 100644
--- a/tests/execute/smtp.svtest
+++ b/tests/execute/smtp.svtest
@@ -17,18 +17,18 @@ test "Redirect" {
 	redirect "cras@example.net";
 
 	if not test_result_execute {
-        test_fail "failed to execute redirect";
-    }
+		test_fail "failed to execute redirect";
+	}
 
-    test_message :smtp 0;
+	test_message :smtp 0;
 
-    if not address :is "to" "tss@example.net" {
-        test_fail "to address incorrect (strange forward)";
-    }
+	if not address :is "to" "tss@example.net" {
+		test_fail "to address incorrect (strange forward)";
+	}
 
-    if not address :is "from" "stephan@example.org" {
-        test_fail "from address incorrect (strange forward)";
-    }
+	if not address :is "from" "stephan@example.org" {
+		test_fail "from address incorrect (strange forward)";
+	}
 
 	if not envelope :is "to" "cras@example.net" {
 		test_fail "envelope recipient incorrect";
@@ -42,20 +42,19 @@ test "Redirect" {
 test_result_reset;
 
 test "Redirect from <>" {
-
 	test_set "envelope.from" "<>";
 
 	redirect "cras@example.net";
 
 	if not test_result_execute {
-        test_fail "failed to execute redirect";
-    }
+		test_fail "failed to execute redirect";
+	}
 
 	if envelope :is "from" "sirius@example.org" {
-        test_fail "envelope sender incorrect (not changed)";
-    }
+		test_fail "envelope sender incorrect (not changed)";
+	}
 
 	if not envelope :is "from" "" {
-        test_fail "envelope sender incorrect";
-    }
+		test_fail "envelope sender incorrect";
+	}
 }
diff --git a/tests/exists.svtest b/tests/exists.svtest
deleted file mode 100644
index 50aedb4226f8a998b3d683b130dc09b3210eb4a6..0000000000000000000000000000000000000000
--- a/tests/exists.svtest
+++ /dev/null
@@ -1,42 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@vestingbar.bl
-Subject: Test message
-X-Spam-Status: Not Spam
-Resent-To: nico@frop.example.com
-
-Test!
-.
-;
-
-test "EXISTS-one" {
-	if not exists "from" {
-		test_fail "exists test missed from header";
-	}
-
-	if exists "x-nonsense" {
-        test_fail "exists test found non-existent header";
-    }
-}
-
-test "EXISTS-two" {
-    if not exists ["from","to"] {
-        test_fail "exists test missed from or to header";
-    }
-
-    if exists ["from","to","x-nonsense"] {
-        test_fail "exists test found non-existent header";
-    }
-}
-
-test "EXISTS-three" {
-    if not exists ["Subject","X-spam-STATUS","resent-to"] {
-        test_fail "exists test missed from or to header";
-    }
-
-    if exists ["x-spam", "sub", "resent"] {
-        test_fail "exists test found non-existent header";
-    }
-}
diff --git a/tests/extensions/encoded-character.svtest b/tests/extensions/encoded-character.svtest
index b05e2e4c6858091331ad717d6755c20919c37cab..5d1e3368ae27a30e4d0e62859aeeab760144873d 100644
--- a/tests/extensions/encoded-character.svtest
+++ b/tests/extensions/encoded-character.svtest
@@ -85,44 +85,44 @@ test "HEX equality braindead" {
 
 test "Syntax errors" {
 	if anyof( not string "$" "${hex:24}", not string "$ " "${hex:24} ", not string " $" " ${hex:24}" ) {
-        test_fail "loose $ handled inappropriately";
-    }
+		test_fail "loose $ handled inappropriately";
+	}
 
 	if anyof( not string "${" "${hex:24}{", not string "a${" "a${hex:24}{", not string "${a" "${hex:24}{a" ) {
-        test_fail "loose ${ handled inappropriately";
-    }
+		test_fail "loose ${ handled inappropriately";
+	}
 
 	if anyof( not string "${}" "${hex:24}{}", not string "b${}" "b${hex:24}{}", not string "${}b" "${hex:24}{}b" ) {
 		test_fail "entirely missing content handled inappropriately";
 	}
-		
+
 	if not string "${:}" "${hex:24}{:}" {
-        test_fail "missing content handled inappropriately";
-    }
-	
+		test_fail "missing content handled inappropriately";
+	}
+
 	if not string "${hex:}" "${hex:24}{hex:}" {
-        test_fail "missing hex content handled inappropriately";
-    }
+		test_fail "missing hex content handled inappropriately";
+	}
 
 	if not string "${unicode:}" "${hex:24}{unicode:}" {
-        test_fail "missing unicode content handled inappropriately";
-    }
+		test_fail "missing unicode content handled inappropriately";
+	}
 
 	if not string "${hex:sss}" "${hex:24}{hex:sss}" {
-        test_fail "erroneous hex content handled inappropriately";
-    }
+		test_fail "erroneous hex content handled inappropriately";
+	}
+
+	if not string "${unicode:ttt}" "${hex:24}{unicode:ttt}" {
+		test_fail "erroneous unicode content handled inappropriately";
+	}
 
-    if not string "${unicode:ttt}" "${hex:24}{unicode:ttt}" {
-        test_fail "erroneous unicode content handled inappropriately";
-    }
-	
 	if not string "${hex:aa aa" "${hex:24}{hex:aa aa" {
-        test_fail "unterminated hex content handled inappropriately";
-    }
+		test_fail "unterminated hex content handled inappropriately";
+	}
 
-    if not string "${unicode: aaaa aaaa" "${hex:24}{unicode: aaaa aaaa" {
-        test_fail "unterminated unicode content handled inappropriately";
-    }
+	if not string "${unicode: aaaa aaaa" "${hex:24}{unicode: aaaa aaaa" {
+		test_fail "unterminated unicode content handled inappropriately";
+	}
 }
 
 /*
diff --git a/tests/extensions/envelope.svtest b/tests/extensions/envelope.svtest
index 19ea5015ce466f373c875906043b0082f92e42c3..8076070672666f2979fa32b46f644e356a3bf2d3 100644
--- a/tests/extensions/envelope.svtest
+++ b/tests/extensions/envelope.svtest
@@ -57,11 +57,11 @@ test "Envelope - from empty" {
 
 	/* Forward path: <> */
 
-    test_set "envelope.to" "<>";
+	test_set "envelope.to" "<>";
 
-    if envelope :all :is "to" "" {
-        test_fail "successfully matched a <> forward path, which is wrong";
-    }
+	if envelope :all :is "to" "" {
+		test_fail "successfully matched a <> forward path, which is wrong";
+	}
 }
 
 /*
@@ -69,7 +69,7 @@ test "Envelope - from empty" {
  */
 
 test "Envelope - invalid paths" {
-    /* Return_path: "hutsefluts" */
+	/* Return_path: "hutsefluts" */
 
 	test_set "envelope.from" "hutsefluts@";
 	test_set "envelope.to" "knurft@";
@@ -79,24 +79,24 @@ test "Envelope - invalid paths" {
 	}
 
 	if envelope :localpart :is "from" "hutsefluts" {
-        test_fail ":localpart address part matched syntactically incorrect reverse path";
-    }
+		test_fail ":localpart address part matched syntactically incorrect reverse path";
+	}
 
 	if envelope :domain :contains "from" "" {
-        test_fail ":domain address part matched syntactically incorrect reverse path";
-    }
+		test_fail ":domain address part matched syntactically incorrect reverse path";
+	}
 
 	if not envelope :all :is "to" "knurft@" {
 		test_fail ":all address part mangled syntactically incorrect forward path";
 	}
 
 	if envelope :localpart :is "to" "knurft" {
-        test_fail ":localpart address part matched syntactically incorrect forward path";
-    }
+		test_fail ":localpart address part matched syntactically incorrect forward path";
+	}
 
 	if envelope :domain :contains "to" "" {
-        test_fail ":domain address part matched syntactically incorrect forward path";
-    }
+		test_fail ":domain address part matched syntactically incorrect forward path";
+	}
 }
 
 /*
@@ -112,33 +112,33 @@ test "Envelope - syntax errors" {
 
 	# Duplicate <
 	test_set "envelope.from" "<<stephan@example.org>";
-    if envelope :all :is "from" "stephan@example.org" {
-        test_fail "failed to recognize syntax error";
-    }
+	if envelope :all :is "from" "stephan@example.org" {
+		test_fail "failed to recognize syntax error (1)";
+	}
 
 	# Spurious >
 	test_set "envelope.from" "stephan@example.org>";
-    if envelope :all :is "from" "stephan@example.org" {
-        test_fail "failed to recognize syntax error";
-    }
+	if envelope :all :is "from" "stephan@example.org" {
+		test_fail "failed to recognize syntax error (2)";
+	}
 
 	# Missing >
 	test_set "envelope.from" "<stephan@example.org";
-    if envelope :all :is "from" "stephan@example.org" {
-        test_fail "failed to recognize syntax error";
-    }
-	
+	if envelope :all :is "from" "stephan@example.org" {
+		test_fail "failed to recognize syntax error (3)";
+	}
+
 	# No @
 	test_set "envelope.from" "<stephan example.org>";
-    if envelope :domain :contains "from" "" {
-        test_fail "failed to recognize syntax error";
-    }
+	if envelope :domain :contains "from" "" {
+		test_fail "failed to recognize syntax error (4)";
+	}
 
 	# Duplicate @
 	test_set "envelope.from" "<stephan@@example.org>";
-    if envelope :domain :contains "from" "" {
-        test_fail "failed to recognize syntax error";
-    }
+	if envelope :domain :contains "from" "" {
+		test_fail "failed to recognize syntax error (5)";
+	}
 }
 
 /*
@@ -150,21 +150,18 @@ test "Envelope - source route" {
 	test_set "envelope.from" "<@cola.example.org:stephan@example.org>";
 	if not envelope :localpart :is "from" "stephan" {
 		test_fail "parsing path with source route (single) failed";
-
 	}
 
 	/* Dual */
 	test_set "envelope.from" "<@cola.example.org,@mx.utwente.nl:stephan@example.org>";
 	if not envelope :localpart :is "from" "stephan" {
 		test_fail "parsing path with source route (dual) failed";
-
 	}
 	
 	/* Multiple */
 	test_set "envelope.from" "<@cola.example.org,@mx.utwente.nl,@smtp.example.net:stephan@example.org>";
 	if not envelope :localpart :is "from" "stephan" {
 		test_fail "parsing path with source route (multiple) failed";
-
 	}
 
 	/* Bare */
@@ -175,9 +172,9 @@ test "Envelope - source route" {
 
 	/* Whitespace */
 	test_set "envelope.from" "   < @ cola . example . org , @ mx . utwente .   nl , 	@ smtp  .  iki  . fi	:   stephan		@     example   .		org >  ";
-    if not envelope :domain :is "from" "example.org" {
-        test_fail "parsing path with source route (whitespace) failed";
-    }
+	if not envelope :domain :is "from" "example.org" {
+		test_fail "parsing path with source route (whitespace) failed";
+	}
 }
 
 test "Envelope - source route errors" {
@@ -234,16 +231,16 @@ test "Envelope - local part only" {
 
 	test_set "envelope.to" "<MAILER-DAEMON>";
 	if not envelope :is "to" "MAILER-DAEMON" {
-        test_fail "failed to parse local_part only path with angle brackets";
-    }
+		test_fail "failed to parse local_part only path with angle brackets";
+	}
 
 	test_set "envelope.to" "<MAILER-DAEMON  >";
 	if not envelope :is "to" "MAILER-DAEMON" {
-        test_fail "failed to parse local_part only path with angle brackets and whitespace";
-    }
+		test_fail "failed to parse local_part only path with angle brackets and whitespace";
+	}
 
 	test_set "envelope.to" "   MAILER-DAEMON   ";
 	if not envelope :is "to" "MAILER-DAEMON" {
-        test_fail "failed to parse local_part only path with whitespace";
-    }
+		test_fail "failed to parse local_part only path with whitespace";
+	}
 }
diff --git a/tests/extensions/imap4flags/basic.svtest b/tests/extensions/imap4flags/basic.svtest
index 874c40de5b4a0895822dc59413f7f720a2aa3966..07b1a3d2d01d5b33b6e8b547991bf717f7624ebf 100644
--- a/tests/extensions/imap4flags/basic.svtest
+++ b/tests/extensions/imap4flags/basic.svtest
@@ -132,8 +132,8 @@ test "Removal: one" {
 	setflag "\\seen";
 
 	if not hasflag "\\seen" {
-        test_fail "hasflag misses set flag";
-    }
+		test_fail "hasflag misses set flag";
+	}
 
 	removeflag "\\seen";
 
@@ -143,15 +143,15 @@ test "Removal: one" {
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "0" {
 		test_fail "flags are still set";
-    }
+	}
 }
 
 test "Removal: first" {
 	setflag "$frop \\seen";
 
 	if not allof ( hasflag "\\seen", hasflag "$frop" ) {
-        test_fail "hasflag misses set flags";
-    }
+		test_fail "hasflag misses set flags";
+	}
 
 	removeflag "$frop";
 
@@ -165,95 +165,95 @@ test "Removal: first" {
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" {
 		test_fail "more than one flag remains set";
-    }
+	}
 }
 
 test "Removal: last" {
-    setflag "\\seen $friep";
+	setflag "\\seen $friep";
 
-    if not allof ( hasflag "\\seen", hasflag "$friep" ) {
-        test_fail "hasflag misses set flags";
-    }
+	if not allof ( hasflag "\\seen", hasflag "$friep" ) {
+		test_fail "hasflag misses set flags";
+	}
 
-    removeflag "$friep";
+	removeflag "$friep";
 
-    if not hasflag "\\seen" {
-        test_fail "wrong flag removed";
-    }
+	if not hasflag "\\seen" {
+		test_fail "wrong flag removed";
+	}
 
-    if hasflag "$friep" {
-        test_fail "flag not removed";
-    }
+	if hasflag "$friep" {
+		test_fail "flag not removed";
+	}
 
-    if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" {
-        test_fail "more than one flag remains set";
-    }
+	if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" {
+		test_fail "more than one flag remains set";
+	}
 }
 
 test "Removal: middle" {
-    setflag "\\seen $friep \\flagged";
+	setflag "\\seen $friep \\flagged";
 
-    if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
-        test_fail "hasflag misses set flags";
-    }
+	if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
+		test_fail "hasflag misses set flags";
+	}
 
-    removeflag "$friep";
+	removeflag "$friep";
 
-    if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
-        test_fail "wrong flag removed";
-    }
+	if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
+		test_fail "wrong flag removed";
+	}
 
-    if hasflag "$friep" {
-        test_fail "flag not removed";
-    }
+	if hasflag "$friep" {
+		test_fail "flag not removed";
+	}
 
-    if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
-        test_fail "more than two flags remain set";
-    }
+	if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
+		test_fail "more than two flags remain set";
+	}
 }
 
 test "Removal: duplicates" {
-    setflag "\\seen $friep $friep \\flagged $friep";
+	setflag "\\seen $friep $friep \\flagged $friep";
 
-    if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
-        test_fail "hasflag misses set flags";
-    }
+	if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
+		test_fail "hasflag misses set flags";
+	}
 
-    removeflag "$friep";
+	removeflag "$friep";
 
-    if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
-        test_fail "wrong flag removed";
-    }
+	if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
+		test_fail "wrong flag removed";
+	}
 
-    if hasflag "$friep" {
-        test_fail "flag not removed";
-    }
+	if hasflag "$friep" {
+		test_fail "flag not removed";
+	}
 
-    if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
-        test_fail "more than two flags remain set";
-    }
+	if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
+		test_fail "more than two flags remain set";
+	}
 }
 
 test "Removal: whitespace" {
-    setflag "   \\seen     $friep      $friep   \\flagged    $friep   ";
+	setflag "   \\seen     $friep      $friep   \\flagged    $friep   ";
 
-    if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
-        test_fail "hasflag misses set flags";
-    }
+	if not allof ( hasflag "\\flagged", hasflag "\\seen", hasflag "$friep" ) {
+		test_fail "hasflag misses set flags";
+	}
 
-    removeflag "$friep";
+	removeflag "$friep";
 
-    if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
-        test_fail "wrong flag removed";
-    }
+	if not allof ( hasflag "\\seen", hasflag "\\flagged" ) {
+		test_fail "wrong flag removed";
+	}
 
-    if hasflag "$friep" {
-        test_fail "flag not removed";
-    }
+	if hasflag "$friep" {
+		test_fail "flag not removed";
+	}
 
-    if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
-        test_fail "more than two flags remain set";
-    }
+	if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
+		test_fail "more than two flags remain set";
+	}
 }
 
 
diff --git a/tests/extensions/imap4flags/flagstore.svtest b/tests/extensions/imap4flags/flagstore.svtest
index 9ede53ea0fa051861b5282a414a2f0c05b2a993e..bf114024c225b571f565f6a4e21087caed1ab263 100644
--- a/tests/extensions/imap4flags/flagstore.svtest
+++ b/tests/extensions/imap4flags/flagstore.svtest
@@ -15,10 +15,10 @@ Test message.
 ;
 
 test "Basic" {
-    if hasflag :comparator "i;ascii-numeric" :count "ge" "1" {
-        test_fail "some flags or keywords are already set";
-    }
-	
+	if hasflag :comparator "i;ascii-numeric" :count "ge" "1" {
+		test_fail "some flags or keywords are already set";
+	}
+
 	setflag "$label1 \\answered";
 
 	fileinto :create "Uninteresting";
@@ -41,11 +41,11 @@ test "Basic" {
 
 	fileinto :flags "\\flagged" "Uninteresting";
 
-    if not test_result_execute {
-        test_fail "failed to execute third result";
-    }
+	if not test_result_execute {
+		test_fail "failed to execute third result";
+	}
 
-    test_result_reset;
+	test_result_reset;
 
 	test_message :folder "Uninteresting" 0;
 
@@ -54,32 +54,32 @@ test "Basic" {
 	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
-        test_fail "invalid number of flags set for first message";
-    }
+		test_fail "invalid number of flags set for first message";
+	}
 
-    test_result_reset;
+	test_result_reset;
 
 	test_message :folder "Uninteresting" 1;
 
-    if not hasflag "\\draft \\seen Junk" {
-        test_fail "flags not stored for second message";
-    }
+	if not hasflag "\\draft \\seen Junk" {
+		test_fail "flags not stored for second message";
+	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "3" {
-        test_fail "invalid number of flags set for second message";
-    }
+		test_fail "invalid number of flags set for second message";
+	}
 
-    test_result_reset;
+	test_result_reset;
 
 	test_message :folder "Uninteresting" 2;
 
-    if not hasflag "\\flagged" {
-        test_fail "flags not stored for third message";
-    }
+	if not hasflag "\\flagged" {
+		test_fail "flags not stored for third message";
+	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" {
-        test_fail "invalid number of flags set for third message";
-    }
+		test_fail "invalid number of flags set for third message";
+	}
 }
 
 test_result_reset;
@@ -93,10 +93,10 @@ Test message.
 ;
 
 test "Flag changes between stores" {
-    if hasflag :comparator "i;ascii-numeric" :count "ge" "1" {
-        test_fail "some flags or keywords are already set";
-    }
-	
+	if hasflag :comparator "i;ascii-numeric" :count "ge" "1" {
+		test_fail "some flags or keywords are already set";
+	}
+
 	setflag "$label1 \\answered";
 	fileinto :create "FolderA";
 
@@ -117,30 +117,30 @@ test "Flag changes between stores" {
 	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "2" {
-        test_fail "invalid number of flags set for first message";
-    }
+		test_fail "invalid number of flags set for first message";
+	}
 
-    test_result_reset;
+	test_result_reset;
 	test_message :folder "FolderB" 0;
 
-    if not hasflag "$label2" {
-        test_fail "flag not stored for second message";
-    }
+	if not hasflag "$label2" {
+		test_fail "flag not stored for second message";
+	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "1" {
-        test_fail "invalid number of flags set for second message";
-    }
+		test_fail "invalid number of flags set for second message";
+	}
 
-    test_result_reset;
+	test_result_reset;
 	test_message :folder "FolderC" 0;
 
-    if not hasflag "\\seen \\flagged \\draft" {
-        test_fail "flags not stored for third message";
-    }
+	if not hasflag "\\seen \\flagged \\draft" {
+		test_fail "flags not stored for third message";
+	}
 
 	if not hasflag :comparator "i;ascii-numeric" :count "eq" "3" {
-        test_fail "invalid number of flags set for third message";
-    }
+		test_fail "invalid number of flags set for third message";
+	}
 }
 
 
diff --git a/tests/extensions/imap4flags/flagstring.svtest b/tests/extensions/imap4flags/flagstring.svtest
index 99c0cd209e5530a32311e28e44c195ea00742f26..23b6b3439a33c2707869036ffdbef118911a2ce4 100644
--- a/tests/extensions/imap4flags/flagstring.svtest
+++ b/tests/extensions/imap4flags/flagstring.svtest
@@ -36,46 +36,46 @@ test "Duplicates: setflag" {
 
 test "Duplicates: addflag" {
 	setflag "flags" "";
-    addflag "flags" "\\seen \\seen";
+	addflag "flags" "\\seen \\seen";
 
-    if not string "${flags}" "\\seen" {
-        test_fail "duplicate \\seen flag item not removed (1)";
-    }
+	if not string "${flags}" "\\seen" {
+		test_fail "duplicate \\seen flag item not removed (1)";
+	}
 
 	setflag "flags" "";
-    addflag "flags" "\\seen $frop \\seen";
+	addflag "flags" "\\seen $frop \\seen";
 
-    if not string "${flags}" "\\seen $frop" {
-        test_fail "duplicate \\seen flag item not removed (2)";
-    }
+	if not string "${flags}" "\\seen $frop" {
+		test_fail "duplicate \\seen flag item not removed (2)";
+	}
 
 	setflag "flags" "";
-    addflag "flags" "\\seen $frop $frop \\seen";
+	addflag "flags" "\\seen $frop $frop \\seen";
 
-    if not string "${flags}" "\\seen $frop" {
-        test_fail "duplicate \\seen flag item not removed (3)";
-    }
+	if not string "${flags}" "\\seen $frop" {
+		test_fail "duplicate \\seen flag item not removed (3)";
+	}
 
 	setflag "flags" "";
-    addflag "flags" "$frop \\seen $frop \\seen";
+	addflag "flags" "$frop \\seen $frop \\seen";
 
-    if not string "${flags}" "$frop \\seen" {
-        test_fail "duplicate \\seen flag item not removed (4)";
-    }
+	if not string "${flags}" "$frop \\seen" {
+		test_fail "duplicate \\seen flag item not removed (4)";
+	}
 
 	setflag "flags" "";
-    addflag "flags" "$frop \\seen \\seen \\seen \\seen $frop $frop $frop \\seen";
+	addflag "flags" "$frop \\seen \\seen \\seen \\seen $frop $frop $frop \\seen";
 
-    if not string "${flags}" "$frop \\seen" {
-        test_fail "duplicate \\seen flag item not removed (5)";
-    }
+	if not string "${flags}" "$frop \\seen" {
+		test_fail "duplicate \\seen flag item not removed (5)";
+	}
 
 	setflag "flags" "$frop \\seen";
-    addflag "flags" "\\seen \\seen \\seen $frop $frop $frop \\seen";
+	addflag "flags" "\\seen \\seen \\seen $frop $frop $frop \\seen";
 
-    if not string "${flags}" "$frop \\seen" {
-        test_fail "duplicate \\seen flag item not removed (6)";
-    }
+	if not string "${flags}" "$frop \\seen" {
+		test_fail "duplicate \\seen flag item not removed (6)";
+	}
 }
 
 
diff --git a/tests/extensions/imap4flags/multiscript.svtest b/tests/extensions/imap4flags/multiscript.svtest
index 35fcabc5e4aa7e06790308283f21cce67da42a7f..cdadea62ee85570108a3e6bda0b20fe01cb662bd 100644
--- a/tests/extensions/imap4flags/multiscript.svtest
+++ b/tests/extensions/imap4flags/multiscript.svtest
@@ -41,7 +41,7 @@ test "Internal Flags" {
 	test_message :folder "folder" 0;
 	
 	if not hasflag "\\answered" {
-        	test_fail "\\answered flag not stored for message";
+		test_fail "\\answered flag not stored for message";
 	}
 
 	if not hasflag "$label1" {
diff --git a/tests/extensions/imap4flags/multiscript/group-spam.sieve b/tests/extensions/imap4flags/multiscript/group-spam.sieve
index 700d33de52bd91ed9ed2c95033e220185125040c..92ea3b91be8740beea027fd79b06d517ea252219 100644
--- a/tests/extensions/imap4flags/multiscript/group-spam.sieve
+++ b/tests/extensions/imap4flags/multiscript/group-spam.sieve
@@ -1,14 +1,14 @@
 require ["fileinto", "variables", "envelope"];
 
 if header :contains "X-Group-Mail" ["Yes", "YES", "1"] {
-  if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] {
-        if envelope :matches :localpart "to" "*" {
-		fileinto "group/${1}/SPAM"; stop;
+	if header :contains "X-Spam-Flag" ["Yes", "YES", "1"] {
+		if envelope :matches :localpart "to" "*" {
+			fileinto "group/${1}/SPAM"; stop;
+		}
 	}
-  }
-  if address :is ["To"] "sales@florist.ru" {
-  	fileinto "group/info/Orders";
-  }
-  stop;
+	if address :is ["To"] "sales@florist.ru" {
+		fileinto "group/info/Orders";
+	}
+	stop;
 }
 keep;
diff --git a/tests/extensions/imap4flags/multiscript/sent-store.sieve b/tests/extensions/imap4flags/multiscript/sent-store.sieve
index e5e3906df4b577f4b6160ea32ff7999304443e99..cb21daa56bc2f94ebb1146e277226c34ffed4ffc 100644
--- a/tests/extensions/imap4flags/multiscript/sent-store.sieve
+++ b/tests/extensions/imap4flags/multiscript/sent-store.sieve
@@ -1,7 +1,7 @@
 require ["imap4flags"];
 
 if header :contains "X-Set-Seen" ["Yes", "YES", "1"] {
-  	setflag "\\Seen";
+	setflag "\\Seen";
 }
 
 keep;
diff --git a/tests/extensions/include/included/rfc-ex1-always_allow.sieve b/tests/extensions/include/included/rfc-ex1-always_allow.sieve
index dcb3413afcc3be3c422b7cef36ffd4cd8e119c21..6dc8ddcfa1091d97c725708397415ff9129473e6 100644
--- a/tests/extensions/include/included/rfc-ex1-always_allow.sieve
+++ b/tests/extensions/include/included/rfc-ex1-always_allow.sieve
@@ -1,8 +1,8 @@
 if header :is "From" "boss@example.com"
 {
-     keep;
+	keep;
 }
 elsif header :is "From" "ceo@example.com"
 {
-     keep;
+	keep;
 }
diff --git a/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve b/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve
index 4ccc11d6a657ea6b51438c1397f422a0081eb304..d020972bb51807cbd2ade9457ec5adfd74778d77 100644
--- a/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve
+++ b/tests/extensions/include/included/rfc-ex1-mailing_lists.sieve
@@ -2,9 +2,9 @@ require ["fileinto"];
 
 if header :is "Sender" "owner-ietf-mta-filters@imc.example.com"
 {
-     fileinto "lists.sieve";
+	fileinto "lists.sieve";
 }
 elsif header :is "Sender" "owner-ietf-imapext@imc.example.com"
 {
-     fileinto "lists.imapext";
+	fileinto "lists.imapext";
 }
diff --git a/tests/extensions/regex/match-values.svtest b/tests/extensions/regex/match-values.svtest
index 9b3070eeb72fdd2b0930f7f32a27ffc3651ca613..344c7c95a7393ca05e319e208fffda7b728b9375 100644
--- a/tests/extensions/regex/match-values.svtest
+++ b/tests/extensions/regex/match-values.svtest
@@ -33,6 +33,8 @@ test "Basic match values 1" {
 		if string :is "${4}" "-bounces" {
 			test_fail "fourth match contains third value";
 		}
+	} else {
+		test_fail "failed to match";
 	}
 }
 
@@ -58,6 +60,8 @@ test "Basic match values 2" {
 		if string :is "${5}" "-bounces" {
 			test_fail "fifth match contains fourth value: ${5}";
 		}
+	} else {
+		test_fail "failed to match";
 	}
 }
 
diff --git a/tests/extensions/relational/basic.svtest b/tests/extensions/relational/basic.svtest
index 4bb3fee9da9394e94890c2908e1d684b48fbdd0c..c13681179f27d87c9a7aa976f72d9b5d71a37cf7 100644
--- a/tests/extensions/relational/basic.svtest
+++ b/tests/extensions/relational/basic.svtest
@@ -63,8 +63,8 @@ test "Value \"\" eq 40 (vs)" {
 	}
 
 	if header :value "gt" :comparator "i;ascii-numeric" "x-spam-score" "" {
-        test_fail ":count exceeded empty string with i;ascii-numeric";
-    }
+		test_fail ":count exceeded empty string with i;ascii-numeric";
+	}
 }
 
 /* 
@@ -98,49 +98,49 @@ test "Value 300 le 302" {
 test "Value 302 le 00302" {
 	if not header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "00302" {
 		test_fail "should have matched";
-    }
+	}
 }
 
 test "Value {1000,20} le 300" {
-    if not header :value "le" :comparator "i;ascii-numeric" "x-nonsense" "300" {
-        test_fail "should have matched";
-    }
+	if not header :value "le" :comparator "i;ascii-numeric" "x-nonsense" "300" {
+		test_fail "should have matched";
+	}
 }
 
 test "Value {1000,20} lt 3" {
-    if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" "3" {
-        test_fail "should not have matched";
-    }
+	if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" "3" {
+		test_fail "should not have matched";
+	}
 }
 
 test "Value {1000,20} gt 3000" {
-    if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" "3000" {
-        test_fail "should not have matched";
-    }
+	if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" "3000" {
+		test_fail "should not have matched";
+	}
 }
 
 test "Value {1000,20} gt {3000,30}" {
-    if not header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","30"] {
-        test_fail "should have matched";
-    }
+	if not header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","30"] {
+		test_fail "should have matched";
+	}
 }
 
 test "Value {1000,20} lt {3, 19})" {
-    if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" ["3","19"] {
-        test_fail "should not have matched";
-    }
+	if header :value "lt" :comparator "i;ascii-numeric" "x-nonsense" ["3","19"] {
+		test_fail "should not have matched";
+	}
 }
 
 test "Value {1000,20} gt {3000,1001}" {
-    if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","1001"] {
-        test_fail "should not have matched";
-    }
+	if header :value "gt" :comparator "i;ascii-numeric" "x-nonsense" ["3000","1001"] {
+		test_fail "should not have matched";
+	}
 }
 
 test "Value abcdzyz gt aaaaaaa" {
-    if not header :value "gt" :comparator "i;octet" "x-alpha" "aaaaaaa" {
-        test_fail "should have matched";
-    }
+	if not header :value "gt" :comparator "i;octet" "x-alpha" "aaaaaaa" {
+		test_fail "should have matched";
+	}
 }
 
 /* 
diff --git a/tests/extensions/relational/comparators.svtest b/tests/extensions/relational/comparators.svtest
index d87bbf697168dc28b291e4222c6814c5a2cd0d81..96ab213471faac5282d9d64e788d29be8a39294b 100644
--- a/tests/extensions/relational/comparators.svtest
+++ b/tests/extensions/relational/comparators.svtest
@@ -49,16 +49,16 @@ test "i;octet" {
 	}
 
 	if not string :comparator "i;octet" :value "lt" "abcce" "abcd" {
-        test_fail "not 'abcce' lt 'abcd'";
-    }
+		test_fail "not 'abcce' lt 'abcd'";
+	}
 
-    if not string :comparator "i;octet" :value "gt" "abcd" "abcce" {
-        test_fail "not 'abcd' gt 'abcce'";
-    }
+	if not string :comparator "i;octet" :value "gt" "abcd" "abcce" {
+		test_fail "not 'abcd' gt 'abcce'";
+	}
 
-    if not string :comparator "i;octet" :value "lt" "Z" "b" {
-        test_fail "not 'Z' lt 'b'";
-    }
+	if not string :comparator "i;octet" :value "lt" "Z" "b" {
+		test_fail "not 'Z' lt 'b'";
+	}
 }
 
 /*
@@ -107,16 +107,16 @@ test "i;ascii-casemap" {
 	}
 
 	if not string :comparator "i;ascii-casemap" :value "lt" "abcce" "abcd" {
-        test_fail "not 'abcce' lt 'abcd'";
-    }
+		test_fail "not 'abcce' lt 'abcd'";
+	}
 
-    if not string :comparator "i;ascii-casemap" :value "gt" "abcd" "abcce" {
-        test_fail "not 'abcd' gt 'abcce'";
-    }
+	if not string :comparator "i;ascii-casemap" :value "gt" "abcd" "abcce" {
+		test_fail "not 'abcd' gt 'abcce'";
+	}
 
-    if not string :comparator "i;ascii-casemap" :value "gt" "Z" "b" {
-        test_fail "not 'Z' gt 'b'";
-    }
+	if not string :comparator "i;ascii-casemap" :value "gt" "Z" "b" {
+		test_fail "not 'Z' gt 'b'";
+	}
 }
 
 /*
diff --git a/tests/extensions/spamvirustest/virustest.svtest b/tests/extensions/spamvirustest/virustest.svtest
index ea2d9eaf4a6f4300d6304a8f5ce21ae0ea84e19d..03bb141c75df725713023c4aa80d791a38a3b1a3 100644
--- a/tests/extensions/spamvirustest/virustest.svtest
+++ b/tests/extensions/spamvirustest/virustest.svtest
@@ -109,13 +109,13 @@ test_config_reload :extension "virustest";
 
 test "Text: regex: 1" {
 	if virustest :is "0" {
-        test_fail "virustest not configured or test failed";
-    }
+		test_fail "virustest not configured or test failed";
+	}
 
-    if not virustest :value "eq" "1" {
-        if virustest :matches "*" { }
-        test_fail "wrong virus value produced: ${1}";
-    }
+	if not virustest :value "eq" "1" {
+		if virustest :matches "*" { }
+		test_fail "wrong virus value produced: ${1}";
+	}
 }
 
 test_config_set "sieve_virustest_status_header" "X-Virus-Scan1:Found to be (.+)\.";
@@ -123,13 +123,13 @@ test_config_reload :extension "virustest";
 
 test "Text: regex: 5" {
 	if virustest :is "0" {
-        test_fail "virustest not configured or test failed";
-    }
+		test_fail "virustest not configured or test failed";
+	}
 
-    if not virustest :value "eq" "5" {
-        if virustest :matches "*" { }
-        test_fail "wrong virus value produced: ${1}";
-    }
+	if not virustest :value "eq" "5" {
+		if virustest :matches "*" { }
+		test_fail "wrong virus value produced: ${1}";
+	}
 }
 
 test_config_set "sieve_virustest_status_header" "X-Virus-Scan2:Found to be (.+)\.";
@@ -137,7 +137,7 @@ test_config_reload :extension "virustest";
 
 test "Text: regex: 0" {
 	if not virustest :is "0" {
-        if virustest :matches "*" { }
-        test_fail "wrong virus value produced: ${1}";
-    }
+		if virustest :matches "*" { }
+		test_fail "wrong virus value produced: ${1}";
+	}
 }
diff --git a/tests/extensions/subaddress/basic.svtest b/tests/extensions/subaddress/basic.svtest
index 6311a5af870ac2626962cc0ff752a851894f8690..b74992b98d82b1e5e39b356bc4282f32abc9bc01 100644
--- a/tests/extensions/subaddress/basic.svtest
+++ b/tests/extensions/subaddress/basic.svtest
@@ -56,27 +56,27 @@ test "Address to :detail" {
 
 
 test "Envelope :user" {
-    if not envelope :is :user "to" "friep" {
-        test_fail "wrong user part extracted 1";
-    }
+	if not envelope :is :user "to" "friep" {
+		test_fail "wrong user part extracted 1";
+	}
 
-    if not envelope :comparator "i;ascii-casemap" :is :user "to" "FRIEP" {
-        test_fail "wrong user part extracted";
-    }
+	if not envelope :comparator "i;ascii-casemap" :is :user "to" "FRIEP" {
+		test_fail "wrong user part extracted";
+	}
 
-    if envelope :comparator "i;ascii-casemap" :is :user "to" "FROP" {
-        test_fail "envelope test failed";
-    }
+	if envelope :comparator "i;ascii-casemap" :is :user "to" "FROP" {
+		test_fail "envelope test failed";
+	}
 }
 
 test "Envelope :detail" {
-    if not envelope :comparator "i;ascii-casemap" :contains :detail "from" "QUES" {
-        test_fail "wrong user part extracted";
-    }
+	if not envelope :comparator "i;ascii-casemap" :contains :detail "from" "QUES" {
+		test_fail "wrong user part extracted";
+	}
 
-    if envelope :comparator "i;ascii-casemap" :contains :detail "from" "LIS" {
-        test_fail "address test failed";
-    }
+	if envelope :comparator "i;ascii-casemap" :contains :detail "from" "LIS" {
+		test_fail "address test failed";
+	}
 }
 
 test_set "message" text:
diff --git a/tests/extensions/subaddress/config.svtest b/tests/extensions/subaddress/config.svtest
index d7c1cea463722954a6546898d2e4419491e50402..ed833c3a2abd2fc65bdef3831095da31e2320106 100644
--- a/tests/extensions/subaddress/config.svtest
+++ b/tests/extensions/subaddress/config.svtest
@@ -15,63 +15,63 @@ test_set "envelope.to" "friep++frop@dovecot.example.net";
 test_set "envelope.from" "list--request@lists.dovecot.example.net";
 
 test "Delimiter default" {
-    if not address :is :user "from" "stephan" {
-        test_fail "wrong user part extracted";
-    }
+	if not address :is :user "from" "stephan" {
+		test_fail "wrong user part extracted";
+	}
 
-    if not address :is :detail "from" "sieve" {
-        test_fail "wrong detail part extracted";
-    }
+	if not address :is :detail "from" "sieve" {
+		test_fail "wrong detail part extracted";
+	}
 }
 
 test "Delimiter \"-\"" {
 	test_config_set "recipient_delimiter" "-";
 	test_config_reload :extension "subaddress";
 
-    if not address :is :user "to" "test" {
-        test_fail "wrong user part extracted";
-    }
+	if not address :is :user "to" "test" {
+		test_fail "wrong user part extracted";
+	}
 
-    if not address :is :detail "to" "failed" {
-        test_fail "wrong detail part extracted";
-    }
+	if not address :is :detail "to" "failed" {
+		test_fail "wrong detail part extracted";
+	}
 }
 
 test "Delimiter \"++\"" {
 	test_config_set "recipient_delimiter" "++";
 	test_config_reload :extension "subaddress";
 
-    if not envelope :is :user "to" "friep" {
-        test_fail "wrong user part extracted";
-    }
+	if not envelope :is :user "to" "friep" {
+		test_fail "wrong user part extracted";
+	}
 
-    if not envelope :is :detail "to" "frop" {
-        test_fail "wrong detail part extracted";
-    }
+	if not envelope :is :detail "to" "frop" {
+		test_fail "wrong detail part extracted";
+	}
 }
 
 test "Delimiter \"--\"" {
 	test_config_set "recipient_delimiter" "--";
 	test_config_reload :extension "subaddress";
 
-    if not envelope :is :user "from" "list" {
-        test_fail "wrong user part extracted";
-    }
+	if not envelope :is :user "from" "list" {
+		test_fail "wrong user part extracted";
+	}
 
-    if not envelope :is :detail "from" "request" {
-        test_fail "wrong detail part extracted";
-    }
+	if not envelope :is :detail "from" "request" {
+		test_fail "wrong detail part extracted";
+	}
 }
 
 test "Delimiter \"+-\"" {
 	test_config_set "recipient_delimiter" "+-";
 	test_config_reload :extension "subaddress";
 
-    if envelope :is :user "from" "list" {
-        test_fail "user part extracted";
-    }
+	if envelope :is :user "from" "list" {
+		test_fail "user part extracted";
+	}
 
-    if envelope :is :detail "from" "request" {
-        test_fail "detail part extracted";
-    }
+	if envelope :is :detail "from" "request" {
+		test_fail "detail part extracted";
+	}
 }
diff --git a/tests/extensions/vacation/execute/no-handle.sieve b/tests/extensions/vacation/execute/no-handle.sieve
index 75ecd2e210294e08db0ce4a7b0b0f39e97e4d7d1..13cb16812baa6109bb78670c1da9d21186e6ba18 100644
--- a/tests/extensions/vacation/execute/no-handle.sieve
+++ b/tests/extensions/vacation/execute/no-handle.sieve
@@ -3,5 +3,8 @@ require "variables";
 
 set "reason" "I have a conference in Seattle";
 
-vacation :subject "I am not in: ${reason}" :from "stephan@example.org" "I am gone for today: ${reason}.";
+vacation 
+	:subject "I am not in: ${reason}" 
+	:from "stephan@example.org" 
+	"I am gone for today: ${reason}.";
 
diff --git a/tests/header.svtest b/tests/header.svtest
deleted file mode 100644
index 9d45286cd6ab76568c01f6964f0500ed32bf9fec..0000000000000000000000000000000000000000
--- a/tests/header.svtest
+++ /dev/null
@@ -1,57 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.com
-Subject:         Help        
-X-A:     Text
-X-B: Text            
-X-Multiline: This is a multi-line
- header body, which should be
- unfolded correctly.
-
-Text
-
-.
-;
-
-test "Strip center" {
-	if not header :is "subject" "Help" {
-		test_fail "header test does not strip leading or trailing whitespace";
-	}
-}
-
-test "Strip lead" {
-    if not header :is "x-a" "Text" {
-        test_fail "header test does not strip leading whitespace";
-    }
-}
-
-test "Strip trail" {
-    if not header :is "x-b" "Text" {
-        test_fail "header test does not strip trailing whitespace";
-    }
-}
-
-test "Contains empty - exist" {
-	if not header :contains "subject" "" {
-		test_fail "header test :contains match type fails to match \"\" on existing header";
-	}
-
-	if header :contains "subject" "a" {
-		test_fail "header test :contains match type matches nonsense";
-	}
-}
-
-test "Contains empty - not exist" {
-	if header :contains "x-nonsense" "" {
-		test_fail "header test :contains match type matches \"\" on non-existent header";
-	}
-}
-
-test "Folded - equals" {
-	if not header :is "x-multiline" 
-		"This is a multi-line header body, which should be unfolded correctly." {
-		test_fail "failed to properly unfold folded header.";
-	}
-}
diff --git a/tests/match-types/contains.svtest b/tests/match-types/contains.svtest
index f6bddce5128ba3702976d784099eb24ff40d703d..18bb2166db1068bf6a2983a4eb51f218af5d90b3 100644
--- a/tests/match-types/contains.svtest
+++ b/tests/match-types/contains.svtest
@@ -20,8 +20,8 @@ test "Match empty" {
 	}
 
 	if not header :contains "comment" "" {
-        test_fail "contains tests fails to match \"\" against empty string";
-    }
+		test_fail "contains tests fails to match \"\" against empty string";
+	}
 }
 
 test "Match full" {
diff --git a/tests/multiscript/conflicts.svtest b/tests/multiscript/conflicts.svtest
index 208b666e578b65bd2c39ae76f482fe473262c35b..79b87adec14849848d965141e45677662b578c14 100644
--- a/tests/multiscript/conflicts.svtest
+++ b/tests/multiscript/conflicts.svtest
@@ -42,12 +42,20 @@ test "Graceful Conflicts" {
 	}
 
 	if not test_result_action :index 1 "store" {
+		test_result_print;
 		test_fail "first action is not 'store'";
 	}
 
-	if test_result_action :index 2 "reject" {
-		test_fail "reject action not discarded";
+	if not test_result_action :index 2 "reject" {
+		test_result_print;
+		test_fail "first reject action not retained";
 	}
+
+	if test_result_action :index 3 "reject" {
+		test_result_print;
+		test_fail "second reject action not discarded";
+	}
+
 }
 
 test "Duplicates" {
@@ -81,8 +89,6 @@ test "Duplicates" {
 		test_fail "result execute failed after third script";
 	}
 
-	test_result_print;
-
 	if not test_result_action :index 1 "keep" {
 		test_fail "first action is not 'keep'";
 	}
diff --git a/tests/size.svtest b/tests/size.svtest
deleted file mode 100644
index f16f8fc639391b576dcd8e17e877e76da12fa38f..0000000000000000000000000000000000000000
--- a/tests/size.svtest
+++ /dev/null
@@ -1,29 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.com
-Subject:         Help        
-X-A:     Text
-X-B: Text            
-X-Multiline: This is a multi-line
- header body, which should be
- unfolded correctly.
-
-Text
-
-.
-;
-
-test "Size :under" {
-	if not size :under 1000 {
-		test_fail "size test produced unexpected result";
-	}
-}
-
-test "Size :over" {
-	if not size :over 10 {
-		test_fail "size test produced unexpected result";
-	}
-}
-
diff --git a/tests/test-address.svtest b/tests/test-address.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..28575ce5da1dfc354657179dd791a0b77f5f930f
--- /dev/null
+++ b/tests/test-address.svtest
@@ -0,0 +1,372 @@
+require "vnd.dovecot.testsuite";
+
+/* 
+ * ## RFC 5228, Section 5.1. Test address (page 26) ##
+ */
+
+/*
+ * TEST: Basic functionionality
+ */
+
+/* "The "address" test matches Internet addresses in structured headers
+ *  that contain addresses.  It returns true if any header contains any
+ *  key in the specified part of the address, as modified by the
+ *  comparator and the match keyword.  Whether there are other addresses
+ *  present in the header doesn't affect this test; this test does not
+ *  provide any way to determine whether an address is the only address
+ *  in a header.
+ *
+ *  Like envelope and header, this test returns true if any combination
+ *  of the header-list and key-list arguments match and returns false
+ *  otherwise.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.com
+To: nico@nl.example.com, harry@de.example.com
+cc: Timo <tss(no spam)@fi.iki>
+Subject: Frobnitzm
+
+Test.
+.
+;
+
+test "Basic functionality" {
+	/* Must match */
+	if not address :contains ["to", "from"] "harry" {
+		test_fail "failed to match address (1)";
+	}
+
+	if not address :contains ["to", "from"] "de.example" {
+		test_fail "failed to match address (2)";
+	}
+
+	if not address :matches "to" "*@*.example.com" {
+		test_fail "failed to match address (3)";
+	}
+
+	if not address :is "to" "harry@de.example.com" {
+		test_fail "failed to match address (4)";
+	}
+
+	/* Must not match */
+	if address :is ["to", "from"] "nonsense@example.com" {
+		test_fail "matches erroneous address";
+	}
+
+	/* Match first key */
+	if not address :contains ["to"] ["nico", "fred", "henk"] {
+		test_fail "failed to match first key";
+	}
+
+	/* Match second key */
+	if not address :contains ["to"] ["fred", "nico", "henk"] {
+		test_fail "failed to match second key";
+	}
+
+	/* Match last key */
+	if not address :contains ["to"] ["fred", "henk", "nico"] {
+		test_fail "failed to match last key";
+	}
+
+	/* First header */
+	if not address :contains ["to", "from"] ["fred", "nico", "henk"] {
+		test_fail "failed to match first header";
+	}	
+
+	/* Second header */
+	if not address :contains ["from", "to"] ["fred", "nico", "henk"] {
+		test_fail "failed to match second header";
+	}	
+
+	/* Comment */
+	if not address :is "cc" "tss@fi.iki" {
+		test_fail "failed to ignore comment in address";
+	}
+}
+
+/*
+ * TEST: Case-sensitivity
+ */
+
+/* "Internet email addresses [RFC 2822] have the somewhat awkward characteristic
+ *  that the local-part to the left of the at-sign is considered case sensitive,
+ *  and the domain-part to the right of the at-sign is case insensitive. The 
+ *  "address" command does not deal with this itself, but provides the
+ *  ADDRESS-PART argument for allowing users to deal with it.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.com
+To: Nico@nl.example.com, harry@DE.EXAMPLE.COM
+Subject: Case-sensitivity
+
+Test.
+.
+;
+
+
+test "Case-sensitivity" {
+	/* Default: i;ascii-casemap */
+
+	if not address :is ["to", "from"] "nico@nl.example.com" {
+		test_fail "address comparator is i;octet by default (1)";
+	}
+
+	if not address :is ["to", "from"] "harry@de.example.com" {
+		test_fail "address comparator is i;octet by default (2)";
+	}
+
+	if not address :is ["to", "from"] "STEPHAN@example.com" {
+		test_fail "address comparator is i;octet by default (3)";
+	}
+
+	if not address :is :localpart ["to"] "nico" {
+		test_fail "address comparator is i;octet by default (4)";
+	}
+
+	/* Match case-sensitively */
+
+	if not address :is :comparator "i;octet" ["to"] "Nico@nl.example.com" {
+		test_fail "failed to match case-sensitive address (1)";
+	}
+
+	if not address :is :comparator "i;octet" ["to"] "harry@DE.EXAMPLE.COM" {
+		test_fail "failed to match case-sensitive address (2)";
+	}
+
+	if address :is :comparator "i;octet" ["to"] "harry@de.example.com" {
+		test_fail "failed to notice case difference in address with i;octet (1)";
+	}
+
+	if address :is :comparator "i;octet" ["from"] "STEPHAN@example.com" {
+		test_fail "failed to notice case difference in address with i;octet (2)";
+	}
+
+	if not address :is :localpart :comparator "i;octet" ["to"] "Nico" {
+		test_fail "failed to match case-sensitive localpart";
+	}
+
+	if address :is :localpart :comparator "i;octet" ["to"] "nico" {
+		test_fail "failed to notice case difference in local_part with i;octet";
+	}
+
+	if not address :is :domain :comparator "i;octet" ["to"] "DE.EXAMPLE.COM" {
+		test_fail "failed to match case-sensitive localpart";
+	}
+
+	if address :is :domain :comparator "i;octet" ["to"] "de.example.com" {
+		test_fail "failed to notice case difference in domain with i;octet";
+	}
+}
+
+/*
+ * TEST: Phrase part, comments and group names
+ */
+
+/* "The address primitive never acts on the phrase part of an email
+ *  address or on comments within that address.  It also never acts on
+ *  group names, ...
+ * "
+ */
+
+test_set "message" text:
+From: Stephan Bosch <stephan(the author)@example.com>
+To: Nico Thalens <nico@nl.example.com>, Harry Becker <harry@de.example.com>
+cc: tukkers: henk@tukkerland.ex, theo@tukkerland.ex, frits@tukkerland.ex;
+Subject: Frobnitzm
+
+Test.
+.
+;
+
+test "Phrase part, comments and group names" {
+	if address :contains :all :comparator "i;ascii-casemap"
+		["to","from"] ["Bosch", "Thalens", "Becker"] {
+		test_fail "matched phrase part";
+	}
+
+	if address :contains :all :comparator "i;ascii-casemap" "from" "author" {
+		test_fail "matched comment";
+	}
+
+
+	if address :contains :all :comparator "i;ascii-casemap" ["cc"] ["tukkers"] {
+		test_fail "matched group name";
+	}
+}
+
+
+/*
+ * TEST: Group addresses
+ */
+
+/* "... although it does act on the addresses within the group
+ *  construct.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@friep.frop
+To: undisclosed-recipients:;
+cc: tukkers: henk@tukkerland.ex, theo@tukkerland.ex, frits@tukkerland.ex;
+Subject: Invalid addresses
+
+Test.
+.
+;
+
+test "Group addresses" {
+	if not address :is :domain ["cc"] ["tukkerland.ex"] {
+		test_fail "failed to match group address (1)";
+	}
+
+	if not address :is :localpart ["cc"] ["henk"] {
+		test_fail "failed to match group address (2)";
+	}
+
+	if not address :is :localpart ["cc"] ["theo"] {
+		test_fail "failed to match group address (3)";
+	}
+
+	if not address :is :localpart ["cc"] ["frits"] {
+		test_fail "failed to match group address (4)";
+	}
+}
+
+/*
+ * TEST: Address headers
+ */
+
+/* "Implementations MUST restrict the address test to headers that
+ *  contain addresses, but MUST include at least From, To, Cc, Bcc,
+ *  Sender, Resent-From, and Resent-To, and it SHOULD include any other
+ *  header that utilizes an "address-list" structured header body.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@friep.frop
+To: henk@tukkerland.ex
+CC: ivo@boer.ex
+Bcc: joop@hooibaal.ex
+Sender: s.bosch@friep.frop
+Resent-From: ivo@boer.ex
+Resent-To: idioot@dombo.ex
+Subject: Berichtje
+
+Test.
+.
+;
+
+
+test "Address headers" {
+	if not address "from" "stephan@friep.frop" {
+		test_fail "from header not recognized";
+	}
+
+	if not address "to" "henk@tukkerland.ex" {
+		test_fail "to header not recognized";
+	}
+
+	if not address "cc" "ivo@boer.ex" {
+		test_fail "cc header not recognized";
+	}
+
+	if not address "bcc" "joop@hooibaal.ex" {
+		test_fail "bcc header not recognized";
+	}
+
+	if not address "sender" "s.bosch@friep.frop" {
+		test_fail "sender header not recognized";
+	}
+
+	if not address "resent-from" "ivo@boer.ex" {
+		test_fail "resent-from header not recognized";
+	}	
+
+	if not address "resent-to" "idioot@dombo.ex" {
+		test_fail "resent-to header not recognized";
+	}	
+}	
+
+/* ## RFC 5228, Section 2.7.4. Comparisons against Addresses (page 16) ## */
+
+/*
+ * TEST: Invalid addresses
+ */ 
+
+/* 
+ * "If an address is not syntactically valid, then it will not be matched
+ *  by tests specifying ":localpart" or ":domain".
+ * "
+ */
+
+test_set "message" text:
+From: stephan@
+To: @example.org
+Cc: nonsense
+Resent-To:
+Bcc: nico@frop.example.com, @example.org
+Subject: Invalid addresses
+
+Test.
+.
+;
+
+test "Invalid addresses" {
+	if address :localpart "from" "stephan" {
+		test_fail ":localpart matched invalid address";
+	}	
+
+	if address :domain "to" "example.org" {
+		test_fail ":domain matched invalid address";
+	}	
+
+	if not address :is :all "resent-to" "" {
+		test_fail ":all failed to match empty address";
+	}	
+
+	if not address :is :all "cc" "nonsense" {
+		test_fail ":all failed to match invalid address";
+	}
+
+	if address :is :localpart "bcc" "" {
+		test_fail ":localpart matched invalid address";
+	}
+
+	if address :is :domain "cc" "example.org" {
+		test_fail ":domain matched invalid address";
+	}	
+}
+
+/*
+ * TEST: Default address part
+ */
+
+/* "If an optional address-part is omitted, the default is ":all".
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.com
+To: nico@nl.example.com, harry@de.example.com
+Subject: Frobnitzm
+
+Test.
+.
+;
+
+test "Default address part" {
+	if not address :is :comparator "i;ascii-casemap" "from" "stephan@example.com"
+		{
+		test_fail "invalid default address part (1)";
+	}
+ 	
+	if not address :is :comparator "i;ascii-casemap" "to"
+		["harry@de.example.com"] {
+		test_fail "invalid default address part (2)";
+	}
+}
diff --git a/tests/test-allof.svtest b/tests/test-allof.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..0ff0b588f2bae680e4348e28669e483a30fd6e51
--- /dev/null
+++ b/tests/test-allof.svtest
@@ -0,0 +1,158 @@
+require "vnd.dovecot.testsuite";
+
+/* 
+ * ## RFC 5228, Section 5.2. Test allof (page 27) ## 
+ */
+
+/* "The "allof" test performs a logical AND on the tests supplied to it.
+ *
+ *  Example:  allof (false, false)  =>   false
+ *            allof (false, true)   =>   false
+ *            allof (true,  true)   =>   true
+ *
+ *  The allof test takes as its argument a test-list.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: test@dovecot.example.net
+cc: stephan@idiot.ex
+Subject: Test
+
+Test!
+.
+;
+
+/*
+ * TEST: Basic functionality: static
+ */
+
+test "Basic functionality: static" {
+	if allof ( true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong single outcome: false";
+	}
+
+	if allof ( false ) {
+		test_fail "chose wrong single outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( true, true, true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong all-true outcome: false";
+	}
+
+	if allof ( false, false, false ) {
+		test_fail "chose wrong all-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( true, false, false ) {
+		test_fail "chose wrong first-true outcome: true";
+	} else {
+		/* Correct */
+	}
+	
+	if allof ( false, true, false ) {
+		test_fail "chose wrong second-true outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( false, false, true ) {
+		test_fail "chose wrong last-true outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( false, true, true ) {
+		test_fail "chose wrong first-false outcome: true";
+	} else {
+		/* Correct */
+	}
+	
+	if allof ( true, false, true ) {
+		test_fail "chose wrong second-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( true, true, false ) {
+		test_fail "chose wrong last-false outcome: true";
+	} else {
+		/* Correct */
+	}
+}
+
+/*
+ * TEST: Basic functionality: dynamic
+ */
+
+test "Basic functionality: dynamic" {
+	if allof ( exists "from" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong single outcome: false";
+	}
+
+	if allof ( exists "friep" ) {
+		test_fail "chose wrong single outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( exists "from", exists "to", exists "cc" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong all-true outcome: false";
+	}
+
+	if allof ( exists "friep", exists "frop", exists "frml" ) {
+		test_fail "chose wrong all-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( exists "to", exists "frop", exists "frml" ) {
+		test_fail "chose wrong first-true outcome: true";
+	} else {
+		/* Correct */
+	}
+	
+	if allof ( exists "friep", exists "from", exists "frml" ) {
+		test_fail "chose wrong second-true outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( exists "friep", exists "frop", exists "cc" ) {
+		test_fail "chose wrong last-true outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( exists "friep", exists "from", exists "cc" ) {
+		test_fail "chose wrong first-false outcome: true";
+	} else {
+		/* Correct */
+	}
+	
+	if allof ( exists "to", exists "frop", exists "cc" ) {
+		test_fail "chose wrong second-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if allof ( exists "to", exists "from", exists "frml" ) {
+		test_fail "chose wrong last-false outcome: true";
+	} else {
+		/* Correct */
+	}
+}
+
diff --git a/tests/test-anyof.svtest b/tests/test-anyof.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..3dc174cc08ba7a400a951c8f8ad9ee584d183d89
--- /dev/null
+++ b/tests/test-anyof.svtest
@@ -0,0 +1,156 @@
+require "vnd.dovecot.testsuite";
+
+/* 
+ * ## RFC 5228, Section 5.3. Test anyof (page 27) ## 
+ */
+
+/* "The "anyof" test performs a logical OR on the tests supplied to it.
+ * 
+ *  Example:  anyof (false, false)  =>   false
+ *            anyof (false, true)   =>   true
+ *            anyof (true,  true)   =>   true
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: test@dovecot.example.net
+cc: stephan@idiot.ex
+Subject: Test
+
+Test!
+.
+;
+
+/*
+ * TEST: Basic functionality: static
+ */
+
+test "Basic functionality: static" {
+	if anyof ( true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong single outcome: false";
+	}
+
+	if anyof ( false ) {
+		test_fail "chose wrong single outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if anyof ( true, true, true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong all-true outcome: false";
+	}
+
+	if anyof ( false, false, false ) {
+		test_fail "chose wrong all-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if anyof ( true, false, false ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong first-true outcome: false";
+	}
+	
+	if anyof ( false, true, false ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong second-true outcome: false";
+	}
+
+	if anyof ( false, false, true ) {		
+		/* Correct */
+	} else {
+		test_fail "chose wrong last-true outcome: false";
+	}
+
+	if anyof ( false, true, true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong first-false outcome: false";
+	}
+	
+	if anyof ( true, false, true ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong second-false outcome: false";
+	}
+
+	if anyof ( true, true, false ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong last-false outcome: false";
+	}
+}
+
+/*
+ * TEST: Basic functionality: dynamic
+ */
+
+test "Basic functionality: dynamic" {
+	if anyof ( exists "from" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong single outcome: false";
+	}
+
+	if anyof ( exists "friep" ) {
+		test_fail "chose wrong single outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if anyof ( exists "from", exists "to", exists "cc" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong all-true outcome: false";
+	}
+
+	if anyof ( exists "friep", exists "frop", exists "frml" ) {
+		test_fail "chose wrong all-false outcome: true";
+	} else {
+		/* Correct */
+	}
+
+	if anyof ( exists "to", exists "frop", exists "frml" ) {
+		/* Correct */		
+	} else {
+		test_fail "chose wrong first-true outcome: false";
+	}
+	
+	if anyof ( exists "friep", exists "from", exists "frml" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong second-true outcome: false";
+	}
+
+	if anyof ( exists "friep", exists "frop", exists "cc" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong last-true outcome: false";
+	}
+
+	if anyof ( exists "friep", exists "from", exists "cc" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong first-false outcome: false";
+	}
+	
+	if anyof ( exists "to", exists "frop", exists "cc" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong second-false outcome: false";
+	}
+
+	if anyof ( exists "to", exists "from", exists "frml" ) {
+		/* Correct */
+	} else {
+		test_fail "chose wrong last-false outcome: false";
+	}
+}
+
diff --git a/tests/test-exists.svtest b/tests/test-exists.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..456fefb11630c9b9d251c376d29e5a88cd3c4496
--- /dev/null
+++ b/tests/test-exists.svtest
@@ -0,0 +1,93 @@
+require "vnd.dovecot.testsuite";
+
+/* "The "exists" test is true if the headers listed in the header-names
+ *  argument exist within the message.  All of the headers must exist or
+ *  the test is false.
+ * "
+ */
+ 
+test_set "message" text:
+From: stephan@example.org
+To: nico@vestingbar.bl
+Subject: Test message
+Date: Wed, 29 Jul 2009 18:21:44 +0300
+X-Spam-Status: Not Spam
+Resent-To: nico@frop.example.com
+
+Test!
+.
+;
+
+/*
+ * TEST: One header
+ */
+
+test "One header" {
+	if not exists "from" {
+		test_fail "exists test missed from header";
+	}
+
+	if exists "x-nonsense" {
+		test_fail "exists test found non-existent header";
+	}
+}
+
+/*
+ * TEST: Two headers
+ */
+
+test "Two headers" {
+	if not exists ["from","to"] {
+		test_fail "exists test missed from or to header";
+	}
+
+	if exists ["from","x-nonsense"] {
+		test_fail "exists test found non-existent header (1)";
+	}
+
+	if exists ["x-nonsense","to"] {
+		test_fail "exists test found non-existent header (2)";
+	}
+
+	if exists ["x-nonsense","x-nonsense2"] {
+		test_fail "exists test found non-existent header (3)";
+	}
+}
+
+/*
+ * TEST: Three headers
+ */
+
+test "Three headers" {
+	if not exists ["Subject","date","resent-to"] {
+		test_fail "exists test missed subject, date or resent-to header";
+	}
+
+	if exists ["x-nonsense","date","resent-to"] {
+		test_fail "exists test found non-existent header (1)";
+	}
+
+	if exists ["subject", "x-nonsense","resent-to"] {
+		test_fail "exists test found non-existent header (2)";
+	}
+
+	if exists ["subject","date","x-nonsense"] {
+		test_fail "exists test found non-existent header (3)";
+	}
+
+	if exists ["subject", "x-nonsense","x-nonsense2"] {
+		test_fail "exists test found non-existent header (4)";
+	}
+
+	if exists ["x-nonsense","date","x-nonsense2"] {
+		test_fail "exists test found non-existent header (5)";
+	}
+
+	if exists ["x-nonsense","x-nonsense2","resent-to"] {
+		test_fail "exists test found non-existent header (6)";
+	}
+
+	if exists ["x-nonsense","x-nonsense2","x-nonsense3"] {
+		test_fail "exists test found non-existent header (7)";
+	}
+}
diff --git a/tests/test-header.svtest b/tests/test-header.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..18c676d9d8e3d2ca84e4803034d462e1e0814b4e
--- /dev/null
+++ b/tests/test-header.svtest
@@ -0,0 +1,270 @@
+require "vnd.dovecot.testsuite";
+
+/*
+ * ## RFC 5228, Section 5.7. Test header (page 29) ##
+ */
+
+/*
+ * TEST: Basic functionality
+ */
+
+/* "The "header" test evaluates to true if the value of any of the named
+ *  headers, ignoring leading and trailing whitespace, matches any key.
+ *  The type of match is specified by the optional match argument, which
+ *  defaults to ":is" if not specified, as specified in section 2.6.
+ *
+ *  Like address and envelope, this test returns true if any combination
+ *  of the header-names list and key-list arguments match and returns
+ *  false otherwise.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.com
+To: nico@nl.example.com, harry@de.example.com
+Subject: Frobnitzm
+Comments: This is nonsense.
+Keywords: nonsense, strange, testing
+X-Spam: Yes
+
+Test.
+.
+;
+
+test "Basic functionality" {
+	/* Must match */
+	if not header :contains ["Subject", "Comments"] "Frobnitzm" {
+		test_fail "failed to match header (1)";
+	}
+
+	if not header :contains ["Subject", "Comments"] "nonsense" {
+		test_fail "failed to match header(2)";
+	}
+
+	if not header :matches "Keywords" "*, strange, *" {
+		test_fail "failed to match header (3)";
+	}
+
+	if not header :is "Comments" "This is nonsense." {
+		test_fail "failed to match header (4)";
+	}
+
+	/* Must not match */
+	if header ["subject", "comments", "keywords"] "idiotic" {
+		test_fail "matched nonsense";
+	}
+
+	/* Match first key */
+	if not header :contains ["keywords"] ["strange", "snot", "vreemd"] {
+		test_fail "failed to match first key";
+	}
+
+	/* Match second key */
+	if not header :contains ["keywords"] ["raar", "strange", "vreemd"] {
+		test_fail "failed to match second key";
+	}
+
+	/* Match last key */
+	if not header :contains ["keywords"] ["raar", "snot", "strange"] {
+		test_fail "failed to match last key";
+	}
+
+	/* First header */
+	if not header :contains ["keywords", "subject"]
+		["raar", "strange", "vreemd"] {
+		test_fail "failed to match first header";
+	}	
+
+	/* Second header */
+	if not header :contains ["subject", "keywords"]
+		["raar", "strange", "vreemd"] {
+		test_fail "failed to match second header";
+	}	
+}
+
+/*
+ * TEST: Matching empty key
+ */
+
+/* "If a header listed in the header-names argument exists, it contains
+ *  the empty key ("").  However, if the named header is not present, it
+ *  does not match any key, including the empty key.  So if a message
+ *  contained the header
+ *
+ *          X-Caffeine: C8H10N4O2
+ *
+ *  these tests on that header evaluate as follows:
+ *
+ *          header :is ["X-Caffeine"] [""]         => false
+ *          header :contains ["X-Caffeine"] [""]   => true
+ * "
+ */
+
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+X-Caffeine: C8H10N4O2
+Subject: I need coffee!
+Comments: 
+
+Text
+.
+;
+
+test "Matching empty key" {
+	if header :is "X-Caffeine" "" {
+		test_fail ":is-matched non-empty header with empty string";
+	}
+
+	if not header :contains "X-Caffeine" "" {
+		test_fail "failed to match existing header with empty string";
+	}
+
+	if not header :is "comments" "" {
+		test_fail "failed to match empty header with empty string";
+	}
+
+	if header :contains "X-Nonsense" "" {
+		test_fail ":contains-matched non-existent header with empty string";
+	}
+}
+
+/*
+ * TEST: Ignoring whitespace
+ */
+
+/* "The "header" test evaluates to true if the value of any of the named
+ *  headers, ignoring leading and trailing whitespace, matches any key.
+ *  ...
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+Subject:         Help        
+X-A:     Text
+X-B: Text            
+
+Text
+.
+;
+
+test "Ignoring whitespace" {
+	if not header :is "x-a" "Text" {
+		test_fail "header test does not strip leading whitespace";
+	}
+
+	if not header :is "x-b" "Text" {
+		test_fail "header test does not strip trailing whitespace";
+	}
+
+	if not header :is "subject" "Help" {
+		test_fail "header test does not strip both leading and trailing whitespace";
+	}
+}
+
+/*
+ * TEST: Absent or empty header
+ */
+
+/* "Testing whether a given header is either absent or doesn't contain
+ *  any non-whitespace characters can be done using a negated "header"
+ *  test:
+ *
+ *          not header :matches "Cc" "?*"
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+CC: harry@nonsense.ex
+Subject:      
+Comments:
+
+Text
+.
+;
+
+test "Absent or empty header" {
+	if not header :matches "Cc" "?*" {
+		test_fail "CC header is not absent or empty";
+	}
+
+	if header :matches "Subject" "?*" {
+		test_fail "Subject header is empty, but matched otherwise";
+	}
+
+	if header :matches "Comment" "?*" {
+		test_fail "Comment header is empty, but matched otherwise";
+	}
+} 
+
+/*
+ * ## RFC 5228, Section 2.4.2.2. Headers (page 9)
+ */
+
+/*
+ * TEST: Invalid header name
+ */
+
+/* "A header name never contains a colon.  The "From" header refers to a
+ *  line beginning "From:" (or "From   :", etc.).  No header will match
+ *  the string "From:" due to the trailing colon.
+ *
+ *  Similarly, no header will match a syntactically invalid header name.
+ *  An implementation MUST NOT cause an error for syntactically invalid
+ *  header names in tests.
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+Subject: Valid message
+X-Multiline: This is a multi-line
+ header body, which should be
+ unfolded correctly.
+
+Text
+.
+;
+
+test "Invalid header name" {
+	if header :contains "subject:" "" {
+		test_fail "matched invalid header name";
+	}
+
+	if header :contains "to!" "" {
+		test_fail "matched invalid header name";
+	}
+}
+
+/*
+ * TEST: Folded headers
+ */
+
+/* "Header lines are unfolded as described in [RFC 2822] section 2.2.3.
+ *  ...
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+Subject: Not enough space on a line!        
+X-Multiline: This is a multi-line
+ header body, which should be
+ unfolded correctly.
+
+Text
+.
+;
+
+test "Folded header" {
+	if not header :is "x-multiline" 
+		"This is a multi-line header body, which should be unfolded correctly." {
+		test_fail "failed to properly unfold folded header.";
+	}
+}
diff --git a/tests/test-size.svtest b/tests/test-size.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..dd5cdc4f42e55abd98b645e5166a487033a6ec99
--- /dev/null
+++ b/tests/test-size.svtest
@@ -0,0 +1,74 @@
+require "vnd.dovecot.testsuite";
+
+/*
+ * ## RFC 5228, Section 5.9. Test size (page 29) ##
+ */
+
+/*
+ * TEST: Basic functionality
+ */
+
+/* "The "size" test deals with the size of a message.  It takes either a
+ *  tagged argument of ":over" or ":under", followed by a number
+ *  representing the size of the message.
+ *
+ *  If the argument is ":over", and the size of the message is greater
+ *  than the number provided, the test is true; otherwise, it is false.
+
+ *  If the argument is ":under", and the size of the message is less than
+ *  the number provided, the test is true; otherwise, it is false.
+ * "
+ */
+
+test_set "message" text:
+From: stephan@example.org
+To: nico@frop.example.com
+Subject:         Help        
+X-A:     Text
+X-B: Text            
+X-Multiline: This is a multi-line
+ header body, which should be
+ unfolded correctly.
+
+Text
+
+.
+;
+
+test "Basic functionality" {
+	if not size :under 1000 {
+		test_fail "size test produced unexpected result (1)";
+	}
+
+	if size :under 10 {
+		test_fail "size test produced unexpected result (2)";
+	}
+
+	if not size :over 10 {
+		test_fail "size test produced unexpected result (3)";
+	}
+
+	if size :over 1000 {
+		test_fail "size test produced unexpected result (4)";
+	}
+}
+
+/*
+ * TEST: Exact size
+ */
+
+/* "Note that for a message that is exactly 4,000 octets, the message is
+ *  neither ":over" nor ":under" 4000 octets.
+ * "
+ */
+
+test "Exact size" {
+	if size :under 221 {
+		test_fail "size :under matched exact limit";
+	}
+
+	if size :over 221 {
+		test_fail "size :over matched exact limit";
+	}
+}
+
diff --git a/tests/testsuite.svtest b/tests/testsuite.svtest
index 68633170116549221baf4e02b0261b921aa8550e..3447fd0cbba67ffcfd9a7bdb48ff6e195e1441c5 100644
--- a/tests/testsuite.svtest
+++ b/tests/testsuite.svtest
@@ -39,37 +39,37 @@ test "Envelope Environment" {
 	test_set "envelope.from" "stephan@hutsefluts.example.net";
 
 	if not envelope :is "from" "stephan@hutsefluts.example.net" {
-        test_fail "envelope.from data not set properly (1).";
-    }
+		test_fail "envelope.from data not set properly (1).";
+	}
 
 	test_set "envelope.to" "news@example.org";
 
 	if not envelope :is "to" "news@example.org" {
-        test_fail "envelope.to data not set properly (1).";
-    }
+		test_fail "envelope.to data not set properly (1).";
+	}
 
 	test_set "envelope.auth" "sirius";
 
-    if not envelope :is "auth" "sirius" {
-        test_fail "envelope.auth data not set properly (1).";
-    }
+	if not envelope :is "auth" "sirius" {
+		test_fail "envelope.auth data not set properly (1).";
+	}
 
 	test_set "envelope.from" "stephan@example.org";
 
 	if not envelope :is "from" "stephan@example.org" {
-        test_fail "envelope.from data not reset properly (2).";
-    }
+		test_fail "envelope.from data not reset properly (2).";
+	}
 
 	test_set "envelope.to" "past-news@example.org";
 
 	if not envelope :is "to" "past-news@example.org" {
-        test_fail "envelope.to data not reset properly (2).";
-    }
+		test_fail "envelope.to data not reset properly (2).";
+	}
 
 	test_set "envelope.auth" "zilla";
 
-    if not envelope :is "auth" "zilla" {
-        test_fail "envelope.auth data not reset properly (2).";
-    }
+	if not envelope :is "auth" "zilla" {
+		test_fail "envelope.auth data not reset properly (2).";
+	}
 }