From cf7d2f839f523feeca2d49bcbfec0228e5547d46 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Mon, 25 Aug 2008 17:50:51 +0200
Subject: [PATCH] Testsuite: added support for testing runtime errors.

---
 src/lib-sieve/sieve-interpreter.c             |  1 -
 src/testsuite/Makefile.am                     |  1 +
 src/testsuite/ext-testsuite.c                 |  2 +
 src/testsuite/testsuite-common.c              | 55 +++++++++++-
 src/testsuite/testsuite-common.h              |  4 +
 src/testsuite/testsuite.c                     |  1 +
 src/testsuite/tst-test-execute.c              | 90 +++++++++++++++++++
 .../execute}/errors/action-conflicts.sieve    |  3 -
 .../execute}/errors/action-duplicates.sieve   |  0
 9 files changed, 152 insertions(+), 5 deletions(-)
 create mode 100644 src/testsuite/tst-test-execute.c
 rename {sieve => tests/execute}/errors/action-conflicts.sieve (61%)
 rename {sieve => tests/execute}/errors/action-duplicates.sieve (100%)

diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index a7fb2425e..a730ff6fb 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -445,7 +445,6 @@ int sieve_interpreter_continue
 
 		if ( ret != SIEVE_EXEC_OK ) {
 			sieve_runtime_trace(&interp->runenv, "[[EXECUTION ABORTED]]");
-			ret = -1;
 		}
 	}
 	
diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am
index bcb5c5b8d..d320a3284 100644
--- a/src/testsuite/Makefile.am
+++ b/src/testsuite/Makefile.am
@@ -44,6 +44,7 @@ commands = \
 
 tests = \
 	tst-test-compile.c \
+	tst-test-execute.c \
 	tst-test-error.c
 
 testsuite_SOURCES = \
diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c
index 8978d8620..222b018a8 100644
--- a/src/testsuite/ext-testsuite.c
+++ b/src/testsuite/ext-testsuite.c
@@ -56,6 +56,7 @@ const struct sieve_operation *testsuite_operations[] = {
 	&test_fail_operation, 
 	&test_set_operation,
 	&test_compile_operation,
+	&test_execute_operation,
 	&test_error_operation
 };
 
@@ -110,6 +111,7 @@ static bool ext_testsuite_validator_load(struct sieve_validator *valdtr)
 	sieve_validator_register_command(valdtr, &cmd_test_set);
 
 	sieve_validator_register_command(valdtr, &tst_test_compile);
+	sieve_validator_register_command(valdtr, &tst_test_execute);
 	sieve_validator_register_command(valdtr, &tst_test_error);
 	
 	return testsuite_validator_context_initialize(valdtr);
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index 0b670f4dd..d0a3521e4 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -20,6 +20,7 @@
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-result.h"
 #include "sieve-dump.h"
 
 #include "testsuite-objects.h"
@@ -301,6 +302,8 @@ unsigned int _testsuite_script_error_index = 0;
 static pool_t _testsuite_scriptmsg_pool = NULL;
 ARRAY_DEFINE(_testsuite_script_errors, struct _testsuite_script_message);
 
+struct sieve_binary *_testsuite_compiled_script;
+
 static void _testsuite_script_verror
 (struct sieve_error_handler *ehandler ATTR_UNUSED, const char *location,
     const char *fmt, va_list args)
@@ -376,6 +379,8 @@ static void testsuite_script_init(void)
     sieve_error_handler_accept_infolog(test_script_ehandler, TRUE);
 
 	testsuite_script_clear_messages();
+
+	_testsuite_compiled_script = NULL;
 }
 
 bool testsuite_script_compile(const char *script_path)
@@ -399,14 +404,62 @@ bool testsuite_script_compile(const char *script_path)
     if ( (sbin = sieve_compile(script_path, test_script_ehandler)) == NULL )
         return FALSE;
 
-    sieve_close(&sbin);
+	if ( _testsuite_compiled_script != NULL ) {
+	    sieve_close(&_testsuite_compiled_script);
+	}
+
+	_testsuite_compiled_script = sbin;
+
 	return TRUE;
 }
 
+bool testsuite_script_execute(const struct sieve_runtime_env *renv)
+{
+	struct sieve_script_env scriptenv;
+	struct sieve_result *result;
+	struct sieve_interpreter *interp;
+	int ret;
+
+	if ( _testsuite_compiled_script == NULL ) {
+		sieve_runtime_error(renv, sieve_error_script_location(renv->script,0),
+			"testsuite: no script compiled yet");
+		return FALSE;
+	}
+
+	testsuite_script_clear_messages();
+
+	/* Compose script execution environment */
+	memset(&scriptenv, 0, sizeof(scriptenv));
+	scriptenv.inbox = "INBOX";
+	scriptenv.namespaces = NULL;
+	scriptenv.username = "user";
+	scriptenv.hostname = "host.example.com";
+	scriptenv.postmaster_address = "postmaster@example.com";
+	scriptenv.smtp_open = NULL;
+	scriptenv.smtp_close = NULL;
+	scriptenv.duplicate_mark = NULL;
+	scriptenv.duplicate_check = NULL;
+	
+	result = sieve_result_create(test_script_ehandler);
+
+	/* Execute the script */
+	interp=sieve_interpreter_create(_testsuite_compiled_script, test_script_ehandler, NULL);
+	
+	ret = sieve_interpreter_run(interp, renv->msgdata, &scriptenv, &result);
+
+	sieve_interpreter_free(&interp);
+	
+	return ( ret > 0 );
+}
+
 static void testsuite_script_deinit(void)
 {
 	sieve_error_handler_unref(&test_script_ehandler);
 
+	if ( _testsuite_compiled_script != NULL ) {
+        sieve_close(&_testsuite_compiled_script);
+    }
+
 	pool_unref(&_testsuite_scriptmsg_pool);
 	//str_free(test_script_error_buf);
 }
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index 16eee76c6..4cb1d5a98 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -61,6 +61,7 @@ extern const struct sieve_command cmd_test_set;
  */
 
 extern const struct sieve_command tst_test_compile;
+extern const struct sieve_command tst_test_execute;
 extern const struct sieve_command tst_test_error;
 
 /* 
@@ -73,6 +74,7 @@ enum testsuite_operation_code {
 	TESTSUITE_OPERATION_TEST_FAIL,
 	TESTSUITE_OPERATION_TEST_SET,
 	TESTSUITE_OPERATION_TEST_COMPILE,
+	TESTSUITE_OPERATION_TEST_EXECUTE,
 	TESTSUITE_OPERATION_TEST_ERROR,
 };
 
@@ -81,6 +83,7 @@ extern const struct sieve_operation test_finish_operation;
 extern const struct sieve_operation test_fail_operation;
 extern const struct sieve_operation test_set_operation;
 extern const struct sieve_operation test_compile_operation;
+extern const struct sieve_operation test_execute_operation;
 extern const struct sieve_operation test_error_operation;
 
 /* 
@@ -109,6 +112,7 @@ int testsuite_testcase_result(void);
  */
 
 bool testsuite_script_compile(const char *script_path);
+bool testsuite_script_execute(const struct sieve_runtime_env *renv);
 
 void testsuite_script_get_error_init(void);
 const char *testsuite_script_get_error_next(bool location);
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index eb12d91a6..16cca8dc7 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -66,6 +66,7 @@ static void testsuite_bin_init(void)
 	
 	testsuite_init();
 }
+
 static void testsuite_bin_deinit(void)
 {
 	testsuite_deinit();
diff --git a/src/testsuite/tst-test-execute.c b/src/testsuite/tst-test-execute.c
new file mode 100644
index 000000000..8c45a308a
--- /dev/null
+++ b/src/testsuite/tst-test-execute.c
@@ -0,0 +1,90 @@
+/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#include "sieve-common.h"
+#include "sieve-script.h"
+#include "sieve-commands.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-code.h"
+#include "sieve-binary.h"
+#include "sieve-dump.h"
+#include "sieve.h"
+
+#include "testsuite-common.h"
+
+/*
+ * Test_execute command
+ *
+ * Syntax:   
+ *   test_execute
+ */
+
+static bool tst_test_execute_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
+
+const struct sieve_command tst_test_execute = { 
+	"test_execute", 
+	SCT_TEST, 
+	0, 0, FALSE, FALSE,
+	NULL, NULL, NULL,
+	tst_test_execute_generate, 
+	NULL 
+};
+
+/* 
+ * Operation 
+ */
+
+static int tst_test_execute_operation_execute
+	(const struct sieve_operation *op, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
+
+const struct sieve_operation test_execute_operation = { 
+	"TEST_EXECUTE",
+	&testsuite_extension, 
+	TESTSUITE_OPERATION_TEST_EXECUTE,
+	NULL, 
+	tst_test_execute_operation_execute 
+};
+
+/* 
+ * Code generation 
+ */
+
+static bool tst_test_execute_generate
+(const struct sieve_codegen_env *cgenv, 
+	struct sieve_command_context *tst ATTR_UNUSED)
+{
+	sieve_operation_emit_code(cgenv->sbin, &test_execute_operation);
+
+	return TRUE;
+}
+
+/*
+ * Intepretation
+ */
+
+static int tst_test_execute_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
+	const struct sieve_runtime_env *renv, 
+	sieve_size_t *address ATTR_UNUSED)
+{
+	bool result = TRUE;
+
+	/*
+	 * Perform operation
+	 */
+
+	result = testsuite_script_execute(renv);
+
+	/* Set result */
+	sieve_interpreter_set_test_result(renv->interp, result);
+
+	return SIEVE_EXEC_OK;
+}
+
+
+
+
diff --git a/sieve/errors/action-conflicts.sieve b/tests/execute/errors/action-conflicts.sieve
similarity index 61%
rename from sieve/errors/action-conflicts.sieve
rename to tests/execute/errors/action-conflicts.sieve
index 03949471d..082bdf780 100644
--- a/sieve/errors/action-conflicts.sieve
+++ b/tests/execute/errors/action-conflicts.sieve
@@ -1,8 +1,5 @@
-require "fileinto";
 require "reject";
 require "vacation";
 
-#fileinto "frop";
 reject "No nonsense in my mailbox.";
 vacation "I am gone for a while.";
-redirect "stephan@example.com";
diff --git a/sieve/errors/action-duplicates.sieve b/tests/execute/errors/action-duplicates.sieve
similarity index 100%
rename from sieve/errors/action-duplicates.sieve
rename to tests/execute/errors/action-duplicates.sieve
-- 
GitLab