#include "strescape.h"
#include "ioloop-private.h"
+#include <ctype.h>
+
enum event_code {
EVENT_CODE_ALWAYS_LOG_SOURCE = 'a',
EVENT_CODE_CATEGORY = 'c',
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)
{
/* 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
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;
+ }
}
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)