summaryrefslogtreecommitdiffstats
path: root/src/lib/test-failures.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/test-failures.c')
-rw-r--r--src/lib/test-failures.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/lib/test-failures.c b/src/lib/test-failures.c
new file mode 100644
index 0000000..c76d5b8
--- /dev/null
+++ b/src/lib/test-failures.c
@@ -0,0 +1,176 @@
+/* Copyright (c) 2001-2018 Dovecot authors, see the included COPYING file */
+
+/* Unit tests for failure helpers */
+
+#include "test-lib.h"
+#include "hostpid.h"
+#include "istream.h"
+#include "failures.h"
+
+#include <unistd.h>
+
+static int handlers_set_me;
+
+static void test_failures_handler(const struct failure_context *ctx,
+ const char *format ATTR_UNUSED,
+ va_list args ATTR_UNUSED)
+{
+ handlers_set_me = ctx->type;
+}
+static void test_get_set_handlers(void)
+{
+ failure_callback_t *handlers[4];
+ test_begin("get_handlers");
+ i_get_failure_handlers(handlers, handlers+1, handlers+2, handlers+3);
+ test_end();
+
+ test_begin("set_handlers");
+
+ i_set_debug_handler(&test_failures_handler);
+ i_debug("If you see this debug, something's gone wrong");
+ test_assert(handlers_set_me == LOG_TYPE_DEBUG);
+ i_set_debug_handler(handlers[3]);
+
+ i_set_info_handler(&test_failures_handler);
+ i_info("If you see this info, something's gone wrong");
+ test_assert(handlers_set_me == LOG_TYPE_INFO);
+ i_set_info_handler(handlers[2]);
+
+ i_set_error_handler(&test_failures_handler);
+ i_warning("If you see this warning, something's gone wrong");
+ test_assert(handlers_set_me == LOG_TYPE_WARNING);
+ i_error("If you see this error, something's gone wrong");
+ test_assert(handlers_set_me == LOG_TYPE_ERROR);
+ i_set_error_handler(handlers[1]);
+
+ //i_set_fatal_handler(&test_failures_handler);
+ //i_fatal("If you see this fatal, something's gone wrong");
+ //test_assert(handlers_set_me == LOG_TYPE_FATAL);
+ //i_set_fatal_handler(handlers[0]);
+
+ test_end();
+}
+static void test_expected(void)
+{
+ test_begin("expected messages");
+ test_expect_errors(1);
+ i_warning("deliberate warning - not suppressed");
+ test_expect_no_more_errors();
+ test_end();
+}
+static void test_expected_str(void)
+{
+ test_begin("expected strings in messages");
+ test_expect_error_string("be unhappy");
+ i_error("deliberate error - suppressed - be unhappy if you see this");
+ test_expect_no_more_errors();
+ test_end();
+}
+
+static bool
+internal_line_match(const char *line, const char *prefix, const char *text)
+{
+ if (line == NULL)
+ return FALSE;
+
+ if (line[0] != '\001')
+ return FALSE;
+ uint8_t type = (uint8_t)line[1];
+ if (type != ((LOG_TYPE_DEBUG+1) | 0x80))
+ return FALSE;
+ line += 2;
+
+ if (!str_begins(line, "123 "))
+ return FALSE;
+ line += 4;
+
+ if (!str_begins(line, prefix))
+ return FALSE;
+ line += strlen(prefix);
+
+ return strcmp(line, text) == 0;
+}
+
+static void test_internal_split(void)
+{
+ int fd[2];
+
+ test_begin("splitting long internal log lines");
+
+ char long_log_prefix[PIPE_BUF+1];
+ memset(long_log_prefix, 'X', sizeof(long_log_prefix)-1);
+ long_log_prefix[sizeof(long_log_prefix)-1] = '\0';
+
+#define TEXT10 "tttttttttt"
+#define TEXT128 TEXT10 TEXT10 TEXT10 TEXT10 TEXT10 TEXT10 TEXT10 TEXT10 \
+ TEXT10 TEXT10 TEXT10 TEXT10 "tttttttt"
+
+ char long_lext[PIPE_BUF*2+1];
+ memset(long_lext, 'T', sizeof(long_lext)-1);
+ long_lext[sizeof(long_lext)-1] = '\0';
+
+ if (pipe(fd) < 0)
+ i_fatal("pipe() failed: %m");
+ switch (fork()) {
+ case (pid_t)-1:
+ i_fatal("fork() failed: %m");
+ case 0:
+ /* child - log writer */
+ if (dup2(fd[1], STDERR_FILENO) < 0)
+ i_fatal("dup2() failed: %m");
+ i_close_fd(&fd[0]);
+ i_close_fd(&fd[1]);
+
+ struct failure_context ctx = {
+ .type = LOG_TYPE_DEBUG,
+ .log_prefix = long_log_prefix,
+ };
+
+ i_set_failure_internal();
+ my_pid = "123";
+ i_log_type(&ctx, "little text");
+ i_log_type(&ctx, TEXT128 TEXT128 TEXT128);
+ ctx.log_prefix = "";
+ i_log_type(&ctx, "%s", long_lext);
+ test_exit(0);
+ case 1:
+ /* parent - log reader */
+ i_close_fd(&fd[1]);
+ break;
+ }
+
+ alarm(10);
+ struct istream *input = i_stream_create_fd(fd[0], SIZE_MAX);
+
+ /* long prefix, little text */
+ const char *line = i_stream_read_next_line(input);
+ test_assert(internal_line_match(line, long_log_prefix, "little text"));
+
+ /* long prefix, text split to multiple lines */
+ for (unsigned int i = 0; i < 3; i++) {
+ line = i_stream_read_next_line(input);
+ test_assert(internal_line_match(line, long_log_prefix, TEXT128));
+ }
+
+ /* no prefix, just lots of text */
+ line = i_stream_read_next_line(input);
+ long_lext[PIPE_BUF-7] = '\0';
+ test_assert(internal_line_match(line, "", long_lext));
+ line = i_stream_read_next_line(input);
+ test_assert(internal_line_match(line, "", long_lext));
+ line = i_stream_read_next_line(input);
+ test_assert(internal_line_match(line, "", "TTTTTTTTTTTTTT"));
+
+ i_stream_unref(&input);
+ alarm(0);
+
+ test_end();
+}
+
+void test_failures(void)
+{
+ test_get_set_handlers();
+ test_expected();
+ test_expected_str();
+ test_internal_split();
+}