From d15163daab930eb12c4ee8e3183204d050dfea80 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 10 Aug 2008 21:34:17 +0200
Subject: [PATCH] Body: added test regarding empty bodies and fixed testsuite
 to flush the message context when the message is changed.

---
 src/lib-sieve/sieve-message.c      | 28 ++++++++++++++++++++--------
 src/lib-sieve/sieve-message.h      |  2 ++
 src/testsuite/cmd-test-set.c       |  2 +-
 src/testsuite/testsuite-common.c   |  7 ++++++-
 src/testsuite/testsuite-common.h   |  3 ++-
 src/testsuite/testsuite-objects.c  | 14 +++++++++-----
 src/testsuite/testsuite-objects.h  |  5 +++--
 tests/extensions/body/basic.svtest | 30 ++++++++++++++++++++++++++++++
 8 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c
index bc623222f..810c9c74f 100644
--- a/src/lib-sieve/sieve-message.c
+++ b/src/lib-sieve/sieve-message.c
@@ -20,16 +20,13 @@ struct sieve_message_context {
 
 struct sieve_message_context *sieve_message_context_create(void)
 {
-	pool_t pool;
 	struct sieve_message_context *msgctx;
 	
-	pool = pool_alloconly_create("sieve_message_context", 1024);
-	msgctx = p_new(pool, struct sieve_message_context, 1);
-	msgctx->pool = pool;
+	msgctx = i_new(struct sieve_message_context, 1);
 	msgctx->refcount = 1;
-	
-	p_array_init(&msgctx->ext_contexts, pool, 4);
-	
+		
+	sieve_message_context_flush(msgctx);
+
 	return msgctx;
 }
 
@@ -46,10 +43,25 @@ void sieve_message_context_unref(struct sieve_message_context **msgctx)
 		return;
 	
 	pool_unref(&((*msgctx)->pool));
-	
+		
+	i_free(*msgctx);
 	*msgctx = NULL;
 }
 
+void sieve_message_context_flush(struct sieve_message_context *msgctx)
+{
+	pool_t pool;
+
+	if ( msgctx->pool != NULL ) {
+		pool_unref(&msgctx->pool);
+	}
+
+	pool = pool_alloconly_create("sieve_message_context", 1024);
+	msgctx->pool = pool;
+
+	p_array_init(&msgctx->ext_contexts, pool, sieve_extensions_get_count());
+}
+
 void sieve_message_context_extension_set
 (struct sieve_message_context *msgctx, const struct sieve_extension *ext, 
 	void *context)
diff --git a/src/lib-sieve/sieve-message.h b/src/lib-sieve/sieve-message.h
index 4e6e848bf..dff96e8d0 100644
--- a/src/lib-sieve/sieve-message.h
+++ b/src/lib-sieve/sieve-message.h
@@ -9,6 +9,8 @@ struct sieve_message_context *sieve_message_context_create(void);
 void sieve_message_context_ref(struct sieve_message_context *msgctx);
 void sieve_message_context_unref(struct sieve_message_context **msgctx);
 
+void sieve_message_context_flush(struct sieve_message_context *msgctx);
+
 void sieve_message_context_extension_set
 	(struct sieve_message_context *msgctx, const struct sieve_extension *ext, 
 		void *context);
diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c
index a6abbcb8d..63c8f9635 100644
--- a/src/testsuite/cmd-test-set.c
+++ b/src/testsuite/cmd-test-set.c
@@ -149,7 +149,7 @@ static int cmd_test_set_operation_execute
 		return SIEVE_EXEC_FAILURE;
 	}
 		
-	object->set_member(member_id, value);	
+	object->set_member(renv, member_id, value);	
 	return SIEVE_EXEC_OK;
 }
 
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index 297ebf6e5..bd1331944 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -11,10 +11,12 @@
 #include "sieve.h"
 #include "sieve-error-private.h"
 #include "sieve-code.h"
+#include "sieve-message.h"
 #include "sieve-commands.h"
 #include "sieve-extensions.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
+#include "sieve-interpreter.h"
 #include "sieve-dump.h"
 
 #include "testsuite-objects.h"
@@ -114,11 +116,14 @@ void testsuite_message_init(pool_t namespaces_pool, const char *user)
 	envelope_auth = str_new(message_pool, 256);
 }
 
-void testsuite_message_set(string_t *message)
+void testsuite_message_set
+(const struct sieve_runtime_env *renv, string_t *message)
 {
 	mail_raw_close(_raw_message);
 
 	_testsuite_message_set(message);	
+
+	sieve_message_context_flush(renv->msgctx);
 }
 
 void testsuite_message_deinit(void)
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index 5385b26c8..8bf37ab47 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -12,7 +12,8 @@ extern struct sieve_message_data testsuite_msgdata;
 void testsuite_message_init(pool_t namespaces_pool, const char *user);
 void testsuite_message_deinit(void);
 
-void testsuite_message_set(string_t *message);
+void testsuite_message_set
+	(const struct sieve_runtime_env *renv, string_t *message);
 
 void testsuite_envelope_set_sender(const char *value);
 void testsuite_envelope_set_recipient(const char *value);
diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c
index 88142303a..4e002603f 100644
--- a/src/testsuite/testsuite-objects.c
+++ b/src/testsuite/testsuite-objects.c
@@ -249,11 +249,13 @@ static bool arg_testsuite_object_generate
  * Testsuite core object implementation
  */
  
-static bool tsto_message_set_member(int id, string_t *value);
+static bool tsto_message_set_member
+	(const struct sieve_runtime_env *renv, int id, string_t *value);
 
 static int tsto_envelope_get_member_id(const char *identifier);
 static const char *tsto_envelope_get_member_name(int id);
-static bool tsto_envelope_set_member(int id, string_t *value);
+static bool tsto_envelope_set_member
+	(const struct sieve_runtime_env *renv, int id, string_t *value);
 
 const struct testsuite_object message_testsuite_object = { 
 	SIEVE_OBJECT("message",	&testsuite_object_operand, TESTSUITE_OBJECT_MESSAGE),
@@ -276,11 +278,12 @@ enum testsuite_object_envelope_field {
 	TESTSUITE_OBJECT_ENVELOPE_AUTH_USER
 };
 
-static bool tsto_message_set_member(int id, string_t *value) 
+static bool tsto_message_set_member
+(const struct sieve_runtime_env *renv, int id, string_t *value) 
 {
 	if ( id != -1 ) return FALSE;
 	
-	testsuite_message_set(value);
+	testsuite_message_set(renv, value);
 	
 	return TRUE;
 }
@@ -311,7 +314,8 @@ static const char *tsto_envelope_get_member_name(int id)
 	return NULL;
 }
 
-static bool tsto_envelope_set_member(int id, string_t *value)
+static bool tsto_envelope_set_member
+(const struct sieve_runtime_env *renv ATTR_UNUSED, int id, string_t *value)
 {
 	switch ( id ) {
 	case TESTSUITE_OBJECT_ENVELOPE_FROM: 
diff --git a/src/testsuite/testsuite-objects.h b/src/testsuite/testsuite-objects.h
index 999a0c7fc..0512ea370 100644
--- a/src/testsuite/testsuite-objects.h
+++ b/src/testsuite/testsuite-objects.h
@@ -21,8 +21,9 @@ struct testsuite_object {
 	
 	int (*get_member_id)(const char *identifier);
 	const char *(*get_member_name)(int id);
-	bool (*set_member)(int id, string_t *value);
-	string_t *(*get_member)(int id);
+
+	bool (*set_member)(const struct sieve_runtime_env *renv, int id, string_t *value);
+	string_t *(*get_member)(const struct sieve_runtime_env *renv, int id);
 };
 
 /* Testsuite object registration */
diff --git a/tests/extensions/body/basic.svtest b/tests/extensions/body/basic.svtest
index f9dab31da..da86d488e 100644
--- a/tests/extensions/body/basic.svtest
+++ b/tests/extensions/body/basic.svtest
@@ -63,3 +63,33 @@ test "Defaults" {
 		test_fail "default comparator is not i;ascii-casemap as is required";
 	}
 }
+
+/* No body
+ *
+ *  RFC 5173:
+ *    'If a message consists of a header only, not followed by an empty line, 
+ *     then that set is empty and all "body" tests return false, including 
+ *     those that test for an empty string.  (This is similar to how the 
+ *     "header" test always fails when the named header fields aren't present.)'
+ */
+
+test_set "message" text:
+From: stephan@rename-it.nl
+To: tss@iki.fi
+Subject: No body is here!
+.
+;
+
+test "No body" {
+	if body :raw :contains "" {
+		test_fail "matched against non-existant body (:contains \"\")";
+	}
+
+	if body :raw :is "" {
+		test_fail "matched against non-existant body (:is \"\")";
+	}
+
+	if body :raw :matches "*" {
+		test_fail "matched against non-existant body (:matches \"*\")";
+	}
+}
-- 
GitLab