]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add event_reason_code() for building reason codes easily
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 11 Mar 2021 15:54:18 +0000 (17:54 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 29 Sep 2021 10:09:58 +0000 (10:09 +0000)
src/lib/lib-event.c
src/lib/lib-event.h
src/lib/test-lib-event.c
src/lib/test-lib.inc

index 587fb2b5e3ee5c5b668311c76e50907ccc6d1306..d0afec37402b000a670d983832a926e5b482f57c 100644 (file)
@@ -10,6 +10,8 @@
 #include "strescape.h"
 #include "ioloop-private.h"
 
+#include <ctype.h>
+
 enum event_code {
        EVENT_CODE_ALWAYS_LOG_SOURCE    = 'a',
        EVENT_CODE_CATEGORY             = 'c',
@@ -557,6 +559,65 @@ void event_reason_end(struct event_reason **_reason)
        i_free(reason);
 }
 
+const char *event_reason_code(const char *module, const char *name)
+{
+       return event_reason_code_prefix(module, "", name);
+}
+
+static bool event_reason_code_module_validate(const char *module)
+{
+       const char *p;
+
+       for (p = module; *p != '\0'; p++) {
+               if (*p == ' ' || *p == '-' || *p == ':')
+                       return FALSE;
+               if (i_isupper(*p))
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+const char *event_reason_code_prefix(const char *module,
+                                    const char *name_prefix, const char *name)
+{
+       const char *p;
+
+       i_assert(module[0] != '\0');
+       i_assert(name[0] != '\0');
+
+       if (!event_reason_code_module_validate(module)) {
+               i_panic("event_reason_code_prefix(): "
+                       "Invalid module '%s'", module);
+       }
+       if (!event_reason_code_module_validate(name_prefix)) {
+               i_panic("event_reason_code_prefix(): "
+                       "Invalid name_prefix '%s'", name_prefix);
+       }
+
+       string_t *str = t_str_new(strlen(module) + 1 +
+                                 strlen(name_prefix) + strlen(name));
+       str_append(str, module);
+       str_append_c(str, ':');
+       str_append(str, name_prefix);
+
+       for (p = name; *p != '\0'; p++) {
+               switch (*p) {
+               case ' ':
+               case '-':
+                       str_append_c(str, '_');
+                       break;
+               case ':':
+                       i_panic("event_reason_code_prefix(): "
+                               "name has ':' (%s, %s%s)",
+                               module, name_prefix, name);
+               default:
+                       str_append_c(str, i_tolower(*p));
+                       break;
+               }
+       }
+       return str_c(str);
+}
+
 static struct event *
 event_set_log_prefix(struct event *event, const char *prefix, bool append)
 {
index 82483518df6f6e2b9d06bec25d00c031b2d33f13..9d92901a31e8a445b11cb6db4c735e8bb194c1c9 100644 (file)
@@ -213,6 +213,21 @@ event_reason_begin(const char *reason_code, const char *source_filename,
 /* Finish the reason event. It pops the global event, which means it must be
    at the top of the stack. */
 void event_reason_end(struct event_reason **reason);
+/* Generate a reason code as <module>:<name>. This function does some
+   sanity checks and conversions to make sure the reason codes are reasonable:
+
+   - Assert-crash if module has space, '-', ':' or uppercase characters.
+   - Assert-crash if module is empty
+   - Convert name to lowercase.
+   - Replace all space and '-' in name with '_'.
+   - Assert-crash if name has ':'
+   - assert-crash if name is empty
+*/
+const char *event_reason_code(const char *module, const char *name);
+/* Same as event_reason_code(), but concatenate name_prefix and name.
+   The name_prefix must not contain spaces, '-', ':' or uppercase characters. */
+const char *event_reason_code_prefix(const char *module,
+                                    const char *name_prefix, const char *name);
 
 /* Set the appended log prefix string for this event. All the parent events'
    log prefixes will be concatenated together when logging. The log type
index b0d9532ff450f90781fb82e5330201b8d6fc2fec..cfc410637772ab5689fa5c9a9dd7dce38d724f54 100644 (file)
@@ -29,7 +29,68 @@ static void test_event_strlist(void)
        test_end();
 }
 
+static void test_lib_event_reason_code(void)
+{
+       test_begin("event reason codes");
+       test_assert_strcmp(event_reason_code("foo", "bar"), "foo:bar");
+       test_assert_strcmp(event_reason_code("foo", "B A-r"), "foo:b_a_r");
+       test_assert_strcmp(event_reason_code_prefix("foo", "x", "bar"), "foo:xbar");
+       test_assert_strcmp(event_reason_code_prefix("foo", "", "bar"), "foo:bar");
+       test_end();
+}
+
 void test_lib_event(void)
 {
        test_event_strlist();
+       test_lib_event_reason_code();
+}
+
+enum fatal_test_state fatal_lib_event(unsigned int stage)
+{
+       switch (stage) {
+       case 0:
+               test_begin("event reason codes - asserts");
+               /* module: uppercase */
+               test_expect_fatal_string("Invalid module");
+               (void)event_reason_code("FOO", "bar");
+               return FATAL_TEST_FAILURE;
+       case 1:
+               /* module: space */
+               test_expect_fatal_string("Invalid module");
+               (void)event_reason_code("f oo", "bar");
+               return FATAL_TEST_FAILURE;
+       case 2:
+               /* module: - */
+               test_expect_fatal_string("Invalid module");
+               (void)event_reason_code("f-oo", "bar");
+               return FATAL_TEST_FAILURE;
+       case 3:
+               /* module: empty */
+               test_expect_fatal_string("module[0] != '\\0'");
+               (void)event_reason_code("", "bar");
+               return FATAL_TEST_FAILURE;
+       case 4:
+               /* name_prefix: uppercase */
+               test_expect_fatal_string("Invalid name_prefix");
+               (void)event_reason_code_prefix("module", "FOO", "bar");
+               return FATAL_TEST_FAILURE;
+       case 5:
+               /* name_prefix: space */
+               test_expect_fatal_string("Invalid name_prefix");
+               (void)event_reason_code_prefix("module", "f oo", "bar");
+               return FATAL_TEST_FAILURE;
+       case 6:
+               /* name_prefix: - */
+               test_expect_fatal_string("Invalid name_prefix");
+               (void)event_reason_code_prefix("module", "f-oo", "bar");
+               return FATAL_TEST_FAILURE;
+       case 7:
+               /* name: empty */
+               test_expect_fatal_string("(name[0] != '\\0')");
+               (void)event_reason_code("foo:", "");
+               return FATAL_TEST_FAILURE;
+       default:
+               test_end();
+               return FATAL_TEST_FINISHED;
+       }
 }
index 462c490dff868f421f7fd58e8a6364eef5b446cd..279c2c7859c317d3f227b81b4c3d89c7809ea371 100644 (file)
@@ -23,6 +23,8 @@ TEST(test_env_util)
 FATAL(fatal_env_util)
 TEST(test_event_category_register)
 FATAL(fatal_event_category_register)
+TEST(test_lib_event)
+FATAL(fatal_lib_event)
 TEST(test_event_filter)
 TEST(test_event_filter_expr)
 TEST(test_event_filter_merge)