]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add event_field_clear() to allow clearing parent event's fields
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 16 Aug 2018 09:17:38 +0000 (12:17 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 17 Aug 2018 06:15:09 +0000 (06:15 +0000)
src/lib/Makefile.am
src/lib/event-filter.c
src/lib/lib-event.c
src/lib/lib-event.h
src/lib/test-event-filter.c [new file with mode: 0644]
src/lib/test-lib.inc

index d63a65cdb21cbbaec80763586d9ee64f9d13ea54..648d8dbbb82f8f06d7564da2f08eda1639041ccd 100644 (file)
@@ -338,6 +338,7 @@ test_lib_SOURCES = \
        test-byteorder.c \
        test-crc32.c \
        test-data-stack.c \
+       test-event-filter.c \
        test-failures.c \
        test-file-create-locked.c \
        test-guid.c \
index 76585a4f9adbff06ec6496c7e67e541c09f35a63..37aa3465b8575d03bb43d26e12de9b1ed82483e4 100644 (file)
@@ -450,6 +450,10 @@ event_match_field(struct event *event, const struct event_field *wanted_field)
        }
        switch (field->value_type) {
        case EVENT_FIELD_VALUE_TYPE_STR:
+               if (field->value.str[0] == '\0') {
+                       /* field was removed */
+                       return FALSE;
+               }
                return wildcard_match_icase(field->value.str, wanted_field->value.str);
        case EVENT_FIELD_VALUE_TYPE_INTMAX:
                return field->value.intmax == wanted_field->value.intmax;
index dd331e9040378da91156d64facd63528a239d506..324d71234f2fff0a12329d2cebd9d565958841ac 100644 (file)
@@ -460,6 +460,11 @@ event_add_fields(struct event *event,
        return event;
 }
 
+void event_field_clear(struct event *event, const char *key)
+{
+       event_add_str(event, key, "");
+}
+
 struct event *event_get_parent(struct event *event)
 {
        return event->parent;
index aeb56ac686d78e43a1f5f681bc597b7a5b662d05..e39f6c82884100db61772f5f25caa4240865e098 100644 (file)
@@ -162,7 +162,9 @@ event_add_category(struct event *event, struct event_category *category);
 /* Add key=value field to the event. If a key already exists, it's replaced.
    Child events automatically inherit key=values from their parents at the
    time the event is sent. So changing a key in parent will change the values
-   in the child events as well. Returns the event parameter. */
+   in the child events as well, unless the key has been overwritten in the
+   child event. Setting the value to "" is the same as event_field_clear().
+   Returns the event parameter. */
 struct event *
 event_add_str(struct event *event, const char *key, const char *value);
 struct event *
@@ -178,6 +180,12 @@ event_add_timeval(struct event *event, const char *key,
    terminates with key=NULL. Returns the event parameter. */
 struct event *
 event_add_fields(struct event *event, const struct event_add_field *fields);
+/* Mark a field as nonexistent. If a parent event has the field set, this
+   allows removing it from the child event. Using an event filter with e.g.
+   "key=*" won't match this field anymore, although it's still visible in
+   event_find_field*() and event_get_fields(). This is the same as using
+   event_add_str() with value="". */
+void event_field_clear(struct event *event, const char *key);
 
 /* Returns the parent event, or NULL if it doesn't exist. */
 struct event *event_get_parent(struct event *event);
diff --git a/src/lib/test-event-filter.c b/src/lib/test-event-filter.c
new file mode 100644 (file)
index 0000000..eb9621a
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (c) 2018 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "ioloop.h"
+#include "event-filter.h"
+
+static void test_event_filter_clear_parent_fields(void)
+{
+       struct event_filter *filter;
+       struct event_filter_field filter_fields[] = {
+               { .key = "", .value = "*" },
+               { .key = NULL, .value = NULL }
+       };
+       const struct event_filter_query query = {
+               .fields = filter_fields,
+       };
+       const struct failure_context failure_ctx = {
+               .type = LOG_TYPE_DEBUG
+       };
+       const char *keys[] = { "str", "int" };
+
+       test_begin("event filter: clear parent fields");
+
+       struct event *parent = event_create(NULL);
+       event_add_str(parent, "str", "parent_str");
+       event_add_int(parent, "int", 0);
+
+       struct event *child = event_create(NULL);
+       event_field_clear(child, "str");
+       event_field_clear(child, "int");
+
+       for (unsigned int i = 0; i < N_ELEMENTS(keys); i++) {
+               filter_fields[0].key = keys[i];
+               filter = event_filter_create();
+               event_filter_add(filter, &query);
+
+               test_assert_idx(event_filter_match(filter, parent, &failure_ctx), i);
+               test_assert_idx(!event_filter_match(filter, child, &failure_ctx), i);
+               event_filter_unref(&filter);
+       }
+
+       event_unref(&parent);
+       event_unref(&child);
+       test_end();
+}
+
+void test_event_filter(void)
+{
+       test_event_filter_clear_parent_fields();
+}
index f2b04f2ec3a77db2cc420d9972214a81a38d2ff7..74ea8a692beca3364231c250b4df1899838c211e 100644 (file)
@@ -14,6 +14,7 @@ TEST(test_byteorder)
 TEST(test_crc32)
 TEST(test_data_stack)
 FATAL(fatal_data_stack)
+TEST(test_event_filter)
 TEST(test_failures)
 TEST(test_file_create_locked)
 TEST(test_guid)