From 7b048e6cbb9165c6b58fb088e511b5b9a595b599 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Mon, 28 Jul 2008 18:44:23 +0200
Subject: [PATCH] Testsuite: completed support for error validation and added
 one test case.

---
 src/lib-sieve/sieve-error.c                   |  10 +-
 src/lib-sieve/sieve-error.h                   |   5 +
 src/testsuite/Makefile.am                     |   3 +-
 .../tests/{ => compile}/errors.svtest         |   4 +-
 .../errors/header.sieve}                      |   0
 src/testsuite/testsuite-common.c              | 135 +++++++++++++++++-
 src/testsuite/testsuite-common.h              |  14 +-
 src/testsuite/testsuite.c                     |  12 +-
 src/testsuite/tst-test-compile.c              |  15 +-
 src/testsuite/tst-test-error.c                |  35 ++++-
 10 files changed, 200 insertions(+), 33 deletions(-)
 rename src/testsuite/tests/{ => compile}/errors.svtest (97%)
 rename src/testsuite/tests/{header-errors.sieve => compile/errors/header.sieve} (100%)

diff --git a/src/lib-sieve/sieve-error.c b/src/lib-sieve/sieve-error.c
index 26161e645..44bb0cc40 100644
--- a/src/lib-sieve/sieve-error.c
+++ b/src/lib-sieve/sieve-error.c
@@ -43,7 +43,8 @@ void sieve_verror
 	}
 
 	if ( sieve_errors_more_allowed(ehandler) ) {
-		ehandler->verror(ehandler, location, fmt, args);
+		if ( ehandler->verror != NULL )
+			ehandler->verror(ehandler, location, fmt, args);
 		ehandler->errors++;
 	}
 }
@@ -60,8 +61,9 @@ void sieve_vwarning
 		else
 			sieve_sys_warning("%s: %s", location, t_strdup_vprintf(fmt, args));
 	}
-		
-	ehandler->vwarning(ehandler, location, fmt, args);
+	
+	if ( ehandler->vwarning != NULL )	
+		ehandler->vwarning(ehandler, location, fmt, args);
 	ehandler->warnings++;
 }
 
@@ -78,7 +80,7 @@ void sieve_vinfo
 			sieve_sys_info("%s: %s", location, t_strdup_vprintf(fmt, args));
 	}
 	
-	if ( ehandler->log_info )	
+	if ( ehandler->log_info && ehandler->vinfo != NULL )	
 		ehandler->vinfo(ehandler, location, fmt, args);
 }
 
diff --git a/src/lib-sieve/sieve-error.h b/src/lib-sieve/sieve-error.h
index a39f6cc25..e3a02ac63 100644
--- a/src/lib-sieve/sieve-error.h
+++ b/src/lib-sieve/sieve-error.h
@@ -125,10 +125,15 @@ void sieve_error_handler_unref(struct sieve_error_handler **ehandler);
  * Error handlers 
  */
 
+/* Write errors to stderr */
 struct sieve_error_handler *sieve_stderr_ehandler_create
 	(unsigned int max_errors);
+
+/* Write errors into a string buffer */
 struct sieve_error_handler *sieve_strbuf_ehandler_create
 	(string_t *strbuf, unsigned int max_errors);
+
+/* Write errors to a logfile */
 struct sieve_error_handler *sieve_logfile_ehandler_create
 	(const char *logfile, unsigned int max_errors);  
 
diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am
index db2cf88cd..3fdd8a331 100644
--- a/src/testsuite/Makefile.am
+++ b/src/testsuite/Makefile.am
@@ -85,7 +85,8 @@ test_cases = \
 	tests/extensions/imapflags/basic.svtest \
 	tests/extensions/imapflags/rfc.svtest \
 	tests/compile/compile.svtest \
-	tests/compile/compile-examples.svtest
+	tests/compile/compile-examples.svtest \
+	tests/compile/errors.svtest 
 
 $(test_cases): 
 	@$(TESTSUITE_BIN) $@
diff --git a/src/testsuite/tests/errors.svtest b/src/testsuite/tests/compile/errors.svtest
similarity index 97%
rename from src/testsuite/tests/errors.svtest
rename to src/testsuite/tests/compile/errors.svtest
index 107585bc2..ac841bd80 100644
--- a/src/testsuite/tests/errors.svtest
+++ b/src/testsuite/tests/compile/errors.svtest
@@ -4,7 +4,7 @@ require "relational";
 require "comparator-i;ascii-numeric";
 
 test "Header errors" {
-	if test_compile "header-errors.sieve" {
+	if test_compile "errors/header.sieve" {
 		test_fail "compile should have failed.";
 	}
 
@@ -25,7 +25,7 @@ test "Header errors" {
 	if not test_error :index 3 :matches
 		"unknown tagged argument ':all' * header test *" {
 		test_fail "error 3 is invalid";
-	}
+	}	
 
 	if not test_error :index 4 :matches
 		"*header test * string list * 2 (key list), * number *" {
diff --git a/src/testsuite/tests/header-errors.sieve b/src/testsuite/tests/compile/errors/header.sieve
similarity index 100%
rename from src/testsuite/tests/header-errors.sieve
rename to src/testsuite/tests/compile/errors/header.sieve
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index a17a84393..034829f55 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -8,6 +8,7 @@
 #include "mail-raw.h"
 #include "namespaces.h"
 #include "sieve.h"
+#include "sieve-error-private.h"
 #include "sieve-code.h"
 #include "sieve-commands.h"
 #include "sieve-extensions.h"
@@ -32,6 +33,10 @@ static string_t *test_name;
 unsigned int test_index;
 unsigned int test_failures;
 
+/* Tested script context */
+
+static struct sieve_error_handler *test_script_ehandler;
+
 /* 
  * Testsuite message environment 
  */
@@ -193,7 +198,7 @@ bool testsuite_generator_context_initialize(struct sieve_generator *gentr)
  * Test context
  */
  
-void testsuite_test_context_init(void)
+static void testsuite_test_context_init(void)
 {
 	test_name = str_new(default_pool, 128);
 	test_index = 0;	
@@ -255,7 +260,7 @@ void testsuite_test_succeed(string_t *reason)
 	str_truncate(test_name, 0);
 }
 
-void testsuite_test_context_deinit(void)
+static void testsuite_test_context_deinit(void)
 {
 	//str_free(test_name);
 }
@@ -271,3 +276,129 @@ int testsuite_testcase_result(void)
 	return 0;
 }
 
+/*
+ * Tested script environment
+ */ 
+
+/* Special error handler */
+
+struct _testsuite_script_message {
+	const char *location;
+	const char *message;
+};
+
+unsigned int _testsuite_script_error_index = 0;
+
+static pool_t _testsuite_scriptmsg_pool = NULL;
+ARRAY_DEFINE(_testsuite_script_errors, struct _testsuite_script_message);
+
+static void _testsuite_script_verror
+(struct sieve_error_handler *ehandler ATTR_UNUSED, const char *location,
+    const char *fmt, va_list args)
+{
+	pool_t pool = _testsuite_scriptmsg_pool;
+	struct _testsuite_script_message msg;
+
+	msg.location = p_strdup(pool, location);
+	msg.message = p_strdup_vprintf(pool, fmt, args);
+	
+	array_append(&_testsuite_script_errors, &msg, 1);	
+}
+
+static struct sieve_error_handler *_testsuite_script_ehandler_create(void)
+{
+    pool_t pool;
+    struct sieve_error_handler *ehandler;
+
+    /* Pool is not strictly necessary, but other handler types will need a pool,
+     * so this one will have one too.
+     */
+    pool = pool_alloconly_create
+        ("testsuite_script_error_handler", sizeof(struct sieve_error_handler));
+    ehandler = p_new(pool, struct sieve_error_handler, 1);
+    sieve_error_handler_init(ehandler, pool, 0);
+
+    ehandler->verror = _testsuite_script_verror;
+
+    return ehandler;
+}
+
+static void testsuite_script_clear_messages(void)
+{
+	if ( _testsuite_scriptmsg_pool != NULL ) {
+		if ( array_count(&_testsuite_script_errors) == 0 )
+			return;
+		pool_unref(&_testsuite_scriptmsg_pool);
+	}
+
+	 _testsuite_scriptmsg_pool = pool_alloconly_create
+        ("testsuite_script_messages", 8192);
+	
+	p_array_init(&_testsuite_script_errors, _testsuite_scriptmsg_pool, 128);	
+}
+
+void testsuite_script_get_error_init(void)
+{
+	_testsuite_script_error_index = 0;
+}
+
+const char *testsuite_script_get_error_next(bool location)
+{
+	const struct _testsuite_script_message *msg;
+
+	if ( _testsuite_script_error_index >= array_count(&_testsuite_script_errors) )
+		return NULL;
+
+	msg = array_idx(&_testsuite_script_errors, _testsuite_script_error_index++);
+
+	if ( location ) 
+		return msg->location;
+
+	return msg->message;		
+}
+
+static void testsuite_script_init(void)
+{
+	testsuite_script_clear_messages();
+	
+	test_script_ehandler = _testsuite_script_ehandler_create(); 	
+    sieve_error_handler_accept_infolog(test_script_ehandler, TRUE);
+}
+
+bool testsuite_script_compile(const char *script_path)
+{
+	struct sieve_binary *sbin;
+
+	testsuite_script_clear_messages();
+
+    if ( (sbin = sieve_compile(script_path, test_script_ehandler)) == NULL )
+        return FALSE;
+
+    sieve_close(&sbin);
+	return TRUE;
+}
+
+static void testsuite_script_deinit(void)
+{
+	sieve_error_handler_unref(&test_script_ehandler);
+
+	pool_unref(&_testsuite_scriptmsg_pool);
+	//str_free(test_script_error_buf);
+}
+
+/*
+ * Main testsuite init/deinit
+ */
+
+void testsuite_init(void)
+{
+	testsuite_test_context_init();
+	testsuite_script_init();
+}
+
+void testsuite_deinit(void)
+{
+	testsuite_script_deinit();
+	testsuite_test_context_deinit();
+}
+
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index 9568a0ba1..5385b26c8 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -64,13 +64,23 @@ enum testsuite_operand_code {
 
 /* Test context */
 
-void testsuite_test_context_init(void);
 void testsuite_test_start(string_t *name);
 void testsuite_test_fail(string_t *reason);
 void testsuite_test_succeed(string_t *reason);
-void testsuite_test_context_deinit(void);
 
 void testsuite_testcase_fail(const char *reason);
 int testsuite_testcase_result(void);
 
+/* Tested script environment */
+
+bool testsuite_script_compile(const char *script_path);
+
+void testsuite_script_get_error_init(void);
+const char *testsuite_script_get_error_next(bool location);
+
+/* Testsuite init/deinit */
+
+void testsuite_init(void);
+void testsuite_deinit(void);
+
 #endif /* __TESTSUITE_COMMON_H */
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index d4e7a75d2..99f9fd9a6 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -43,7 +43,7 @@ static void sig_die(int signo, void *context ATTR_UNUSED)
 	exit(1);
 }
 
-static void testsuite_init(void) 
+static void testsuite_bin_init(void) 
 {
 	lib_init();
 	ioloop = io_loop_create();
@@ -59,12 +59,12 @@ static void testsuite_init(void)
 
 	(void) sieve_extension_register(&testsuite_extension);
 	
-	testsuite_test_context_init();
+	testsuite_init();
 }
 
-static void testsuite_deinit(void)
+static void testsuite_bin_deinit(void)
 {
-	testsuite_test_context_deinit();
+	testsuite_deinit();
 	
 	sieve_deinit();
 	
@@ -182,7 +182,7 @@ int main(int argc, char **argv)
 	struct sieve_script_env scriptenv;
 	bool trace = FALSE;
 
-	testsuite_init();
+	testsuite_bin_init();
 
 	/* Parse arguments */
 	scriptfile = dumpfile =  NULL;
@@ -258,7 +258,7 @@ int main(int argc, char **argv)
 	testsuite_message_deinit();
 	namespaces_deinit();
 
-	testsuite_deinit();  
+	testsuite_bin_deinit();  
 
 	return testsuite_testcase_result();
 }
diff --git a/src/testsuite/tst-test-compile.c b/src/testsuite/tst-test-compile.c
index 49a1e5266..79f5bd4a9 100644
--- a/src/testsuite/tst-test-compile.c
+++ b/src/testsuite/tst-test-compile.c
@@ -109,9 +109,6 @@ static int tst_test_compile_operation_execute
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
-	struct sieve_error_handler *ehandler;
-    struct sieve_binary *sbin;
-
 	string_t *script_name;
 	const char *script_path;
 	bool result = TRUE;
@@ -139,17 +136,7 @@ static int tst_test_compile_operation_execute
 
 	/* Attempt script compile */
 
-	ehandler = sieve_stderr_ehandler_create(0);
-    sieve_error_handler_accept_infolog(ehandler, TRUE);
-
-    if ( (sbin = sieve_compile(script_path, ehandler)) == NULL ) {
-        sieve_error_handler_unref(&ehandler);
-		result = FALSE;
-    } else {
-		sieve_close(&sbin);
-	}
-
-    sieve_error_handler_unref(&ehandler);
+	result = testsuite_script_compile(script_path);
 
 	/* Set result */
 	sieve_interpreter_set_test_result(renv->interp, result);
diff --git a/src/testsuite/tst-test-error.c b/src/testsuite/tst-test-error.c
index 77c4524f4..07a881180 100644
--- a/src/testsuite/tst-test-error.c
+++ b/src/testsuite/tst-test-error.c
@@ -214,7 +214,8 @@ static int tst_test_error_operation_execute
 	struct sieve_match_context *mctx;
 	struct sieve_coded_stringlist *key_list;
 	bool matched;
-	int index = 0;
+	const char *error;
+	int cur_index = 0, index = 0;
 	int ret;
 
 	/*
@@ -255,7 +256,37 @@ static int tst_test_error_operation_execute
 	 * Perform operation
 	 */
 	
-	matched = TRUE;
+	sieve_runtime_trace(renv, "TEST_ERROR test (index: %d)", index);
+
+	testsuite_script_get_error_init();
+
+    /* Initialize match */
+    mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list);
+
+    /* Iterate through all errors to match */
+	error = NULL;
+	matched = FALSE;
+	cur_index = 1;
+	ret = 0;
+	while ( result && !matched &&
+		(error=testsuite_script_get_error_next(FALSE)) != NULL ) {
+		
+		if ( index == 0 || index == cur_index ) {
+			if ( (ret=sieve_match_value(mctx, error, strlen(error))) < 0 ) {
+				result = FALSE;
+				break;
+			}
+		}
+
+		matched = ret > 0;
+		cur_index++;
+    }
+
+    /* Finish match */
+    if ( (ret=sieve_match_end(mctx)) < 0 )
+        result = FALSE;
+    else
+        matched = ( ret > 0 || matched );
 
 	/* Set test result for subsequent conditional jump */
     if ( result ) {
-- 
GitLab