From 5e293402f6a34721c68709dde185b1d5578cb74f Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Tue, 27 May 2008 17:47:24 +0200 Subject: [PATCH] Testsuite: added support for test object members. --- src/testsuite/cmd-test-set.c | 14 ++- src/testsuite/ext-testsuite.c | 6 +- src/testsuite/tests/testsuite.sieve | 2 + src/testsuite/testsuite-common.c | 15 ++++ src/testsuite/testsuite-common.h | 4 + src/testsuite/testsuite-objects.c | 135 ++++++++++++++++++++++++++-- src/testsuite/testsuite-objects.h | 5 ++ 7 files changed, 167 insertions(+), 14 deletions(-) diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index 8dc5a9529..7506177db 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -144,10 +144,12 @@ static bool cmd_test_set_operation_execute { const struct testsuite_object *object; string_t *value; + int member_id; t_push(); - if ( (object=testsuite_object_read(renv->sbin, address)) == NULL ) { + if ( (object=testsuite_object_read_member(renv->sbin, address, &member_id)) + == NULL ) { t_pop(); return FALSE; } @@ -157,9 +159,15 @@ static bool cmd_test_set_operation_execute return FALSE; } - printf(">> TEST SET %s = \"%s\"\n", object->identifier, str_c(value)); + printf(">> TEST SET %s = \"%s\"\n", + testsuite_object_member_name(object, member_id), str_c(value)); - object->set_member(-1, value); + if ( object->set_member == NULL ) { + t_pop(); + return FALSE; + } + + object->set_member(member_id, value); t_pop(); diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c index 2608e4d86..11100afe0 100644 --- a/src/testsuite/ext-testsuite.c +++ b/src/testsuite/ext-testsuite.c @@ -7,9 +7,9 @@ * Implementation: skeleton * Status: under development * Purpose: This custom extension is used to add sieve commands that act - * on the test suite. This provides the ability to specify and change the input - * message inside the script and to fail validation, code generation and - * particularly execution based on predicates. + * on the test suite. This provides the ability to specify and change the + * input message inside the script and to fail validation, code generation and + * execution based on predicates. */ #include <stdio.h> diff --git a/src/testsuite/tests/testsuite.sieve b/src/testsuite/tests/testsuite.sieve index a5f350c2c..6a260b4c6 100644 --- a/src/testsuite/tests/testsuite.sieve +++ b/src/testsuite/tests/testsuite.sieve @@ -8,6 +8,7 @@ Subject: Frop! Frop! . ; +test_set "envelope.from" "stephan@rename-it.nl"; if not header :contains "from" "rename-it.nl" { discard; @@ -22,6 +23,7 @@ Subject: Friep! Friep! . ; +test_set "envelope.from" "stephan@rename-it.nl"; if not header :is "from" "nico@vestingbar.nl" { discard; diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index ff3e2317a..b03846b65 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -102,6 +102,21 @@ void testsuite_message_deinit(void) mail_raw_deinit(); } +void testsuite_envelope_set_sender(const char *value) +{ + testsuite_msgdata.return_path = value; +} + +void testsuite_envelope_set_recipient(const char *value) +{ + testsuite_msgdata.to_address = value; +} + +void testsuite_envelope_set_auth_user(const char *value) +{ + testsuite_msgdata.auth_user = value; +} + /* * Validator context */ diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h index 0cac40c8b..d2e62e931 100644 --- a/src/testsuite/testsuite-common.h +++ b/src/testsuite/testsuite-common.h @@ -14,6 +14,10 @@ void testsuite_message_deinit(void); void testsuite_message_set(string_t *message); +void testsuite_envelope_set_sender(const char *value); +void testsuite_envelope_set_recipient(const char *value); +void testsuite_envelope_set_auth_user(const char *value); + /* Testsuite validator context */ struct testsuite_validator_context { diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c index 5ddf0fda4..d4dda7b91 100644 --- a/src/testsuite/testsuite-objects.c +++ b/src/testsuite/testsuite-objects.c @@ -131,10 +131,15 @@ const struct sieve_operand testsuite_object_operand = { }; static void testsuite_object_emit - (struct sieve_binary *sbin, const struct testsuite_object *obj, int ext_id) +(struct sieve_binary *sbin, const struct testsuite_object *obj, int ext_id, + int member_id) { (void) sieve_operand_emit_code(sbin, obj->operand, ext_id); (void) sieve_binary_emit_byte(sbin, obj->code); + + if ( obj->get_member_id != NULL ) { + (void) sieve_binary_emit_byte(sbin, (unsigned char) member_id); + } } const struct testsuite_object *testsuite_object_read @@ -159,18 +164,55 @@ const struct testsuite_object *testsuite_object_read (struct testsuite_object, intf->testsuite_objects, obj_code); } +const struct testsuite_object *testsuite_object_read_member +(struct sieve_binary *sbin, sieve_size_t *address, int *member_id) +{ + const struct testsuite_object *object; + + if ( (object = testsuite_object_read(sbin, address)) == NULL ) + return NULL; + + *member_id = -1; + if ( object->get_member_id != NULL ) { + if ( !sieve_binary_read_code(sbin, address, member_id) ) + return NULL; + } + + return object; +} + +const char *testsuite_object_member_name +(const struct testsuite_object *object, int member_id) +{ + const char *member = NULL; + + if ( object->get_member_id != NULL ) { + if ( object->get_member_name != NULL ) + member = object->get_member_name(member_id); + } else + return object->identifier; + + if ( member == NULL ) + return t_strdup_printf("%s.%d", object->identifier, member_id); + + return t_strdup_printf("%s.%s", object->identifier, member); +} + bool testsuite_object_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { const struct testsuite_object *object; + int member_id; sieve_code_mark(denv); - if ( (object = testsuite_object_read(denv->sbin, address)) == NULL ) + if ( (object = testsuite_object_read_member(denv->sbin, address, &member_id)) + == NULL ) return FALSE; - sieve_code_dumpf(denv, "TESTSUITE_OBJECT: %s", object->identifier); - + sieve_code_dumpf(denv, "TESTSUITE_OBJECT: %s", + testsuite_object_member_name(object, member_id)); + return TRUE; } @@ -188,6 +230,7 @@ const struct sieve_argument testsuite_object_argument = struct testsuite_object_argctx { const struct testsuite_object *object; int ext_id; + int member; }; bool testsuite_object_argument_activate @@ -196,9 +239,20 @@ bool testsuite_object_argument_activate { const char *objname = sieve_ast_argument_strc(arg); const struct testsuite_object *object; - int ext_id; + int ext_id, member_id; + const char *member; struct testsuite_object_argctx *ctx; + /* Parse the object specifier */ + + member = strchr(objname, '.'); + if ( member != NULL ) { + objname = t_strdup_until(objname, member); + member++; + } + + /* Find the object */ + object = testsuite_object_find(valdtr, objname, &ext_id); if ( object == NULL ) { sieve_command_validate_error(valdtr, cmd, @@ -206,9 +260,24 @@ bool testsuite_object_argument_activate return FALSE; } + /* Find the object member */ + + member_id = -1; + if ( member != NULL ) { + if ( object->get_member_id == NULL || + (member_id=object->get_member_id(member)) == -1 ) { + sieve_command_validate_error(valdtr, cmd, + "member '%s' does not exist for testsuite object '%s'", member, objname); + return FALSE; + } + } + + /* Assign argument context */ + ctx = p_new(sieve_command_pool(cmd), struct testsuite_object_argctx, 1); ctx->object = object; ctx->ext_id = ext_id; + ctx->member = member_id; arg->argument = &testsuite_object_argument; arg->context = (void *) ctx; @@ -224,7 +293,7 @@ static bool arg_testsuite_object_generate struct testsuite_object_argctx *ctx = (struct testsuite_object_argctx *) arg->context; - testsuite_object_emit(sbin, ctx->object, ctx->ext_id); + testsuite_object_emit(sbin, ctx->object, ctx->ext_id, ctx->member); return TRUE; } @@ -235,18 +304,28 @@ static bool arg_testsuite_object_generate static bool tsto_message_set_member(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); + + const struct testsuite_object message_testsuite_object = { "message", TESTSUITE_OBJECT_MESSAGE, &testsuite_object_operand, - NULL, tsto_message_set_member, NULL + NULL, NULL, + tsto_message_set_member, + NULL }; const struct testsuite_object envelope_testsuite_object = { "envelope", TESTSUITE_OBJECT_ENVELOPE, &testsuite_object_operand, - NULL, NULL, NULL + tsto_envelope_get_member_id, + tsto_envelope_get_member_name, + tsto_envelope_set_member, + NULL }; static bool tsto_message_set_member(int id, string_t *value) @@ -257,3 +336,43 @@ static bool tsto_message_set_member(int id, string_t *value) return TRUE; } + +static int tsto_envelope_get_member_id(const char *identifier) +{ + if ( strcasecmp(identifier, "from") == 0 ) + return 0; + if ( strcasecmp(identifier, "to") == 0 ) + return 1; + if ( strcasecmp(identifier, "auth") == 0 ) + return 2; + + return -1; +} + +static const char *tsto_envelope_get_member_name(int id) +{ + switch ( id ) { + case 0: return "from"; + case 1: return "to"; + case 2: return "auth"; + } + + return NULL; +} + +static bool tsto_envelope_set_member(int id, string_t *value) +{ + switch ( id ) { + case 0: + testsuite_envelope_set_sender(str_c(value)); + return TRUE; + case 1: + testsuite_envelope_set_recipient(str_c(value)); + return TRUE; + case 2: + testsuite_envelope_set_auth_user(str_c(value)); + return TRUE; + } + + return FALSE; +} diff --git a/src/testsuite/testsuite-objects.h b/src/testsuite/testsuite-objects.h index a8e2b97d1..6719afd18 100644 --- a/src/testsuite/testsuite-objects.h +++ b/src/testsuite/testsuite-objects.h @@ -19,6 +19,7 @@ struct testsuite_object { const struct sieve_operand *operand; 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); }; @@ -43,6 +44,10 @@ bool testsuite_object_argument_activate const struct testsuite_object *testsuite_object_read (struct sieve_binary *sbin, sieve_size_t *address); +const struct testsuite_object *testsuite_object_read_member + (struct sieve_binary *sbin, sieve_size_t *address, int *member_id); +const char *testsuite_object_member_name + (const struct testsuite_object *object, int member_id); bool testsuite_object_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address); -- GitLab