changeset 6718:4e4a5d6bb2cb HEAD

Added beginnings of unit tests.
author Timo Sirainen <tss@iki.fi>
date Wed, 07 Nov 2007 01:17:26 +0200
parents 02014f5b0068
children 1efa924b134b
files .hgignore configure.in src/tests/Makefile.am src/tests/test-common.c src/tests/test-common.h src/tests/test-lib.c src/tests/test-mail.c
diffstat 7 files changed, 362 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Nov 07 00:40:11 2007 +0200
+++ b/.hgignore	Wed Nov 07 01:17:26 2007 +0200
@@ -67,6 +67,8 @@
 src/plugins/fts-squat/squat-test
 src/pop3-login/pop3-login
 src/pop3/pop3
+src/tests/test-lib
+src/tests/test-mail
 src/util/dovecotpw
 src/util/gdbhelper
 src/util/idxview
--- a/configure.in	Wed Nov 07 00:40:11 2007 +0200
+++ b/configure.in	Wed Nov 07 01:17:26 2007 +0200
@@ -2038,6 +2038,7 @@
 src/master/Makefile
 src/pop3/Makefile
 src/pop3-login/Makefile
+src/tests/Makefile
 src/util/Makefile
 src/plugins/Makefile
 src/plugins/acl/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/Makefile.am	Wed Nov 07 01:17:26 2007 +0200
@@ -0,0 +1,28 @@
+noinst_PROGRAMS = test-lib test-mail
+
+noinst_LIBRARIES = libtest.a
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib \
+	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-index \
+	-I$(top_srcdir)/src/lib-storage
+
+libtest_a_SOURCES = \
+	test-common.c
+
+test_lib_SOURCES = \
+	test-lib.c
+
+test_lib_LDADD = \
+	libtest.a \
+	../lib/liblib.a
+
+test_mail_SOURCES = \
+	test-mail.c
+
+test_mail_LDADD = \
+	libtest.a \
+	../lib-mail/libmail.a \
+	../lib-charset/libcharset.a \
+	../lib/liblib.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/test-common.c	Wed Nov 07 01:17:26 2007 +0200
@@ -0,0 +1,43 @@
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-common.h"
+
+#include <stdio.h>
+
+#define OUT_NAME_ALIGN 30
+
+static unsigned int failure_count;
+static unsigned int total_count;
+
+void test_out(const char *name, bool success)
+{
+	int i;
+
+	fputs(name, stdout);
+	putchar(' ');
+	for (i = strlen(name) + 1; i < OUT_NAME_ALIGN; i++)
+		putchar('.');
+	fputs(" : ", stdout);
+	if (success)
+		puts("ok");
+	else {
+		puts("FAILED");
+		failure_count++;
+	}
+	total_count++;
+}
+
+void test_init(void)
+{
+	failure_count = 0;
+	total_count = 0;
+
+	lib_init();
+}
+
+int test_deinit(void)
+{
+	printf("%u / %u tests failed\n", failure_count, total_count);
+	return failure_count == 0 ? 0 : 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/test-common.h	Wed Nov 07 01:17:26 2007 +0200
@@ -0,0 +1,9 @@
+#ifndef TEST_COMMON_H
+#define TEST_COMMON_H
+
+void test_out(const char *name, bool success);
+
+void test_init(void);
+int test_deinit(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/test-lib.c	Wed Nov 07 01:17:26 2007 +0200
@@ -0,0 +1,132 @@
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "base64.h"
+#include "bsearch-insert-pos.h"
+#include "test-common.h"
+
+static void test_base64_encode(void)
+{
+	static const char *input[] = {
+		"hello world",
+		"foo barits",
+		"just niin"
+	};
+	static const char *output[] = {
+		"aGVsbG8gd29ybGQ=",
+		"Zm9vIGJhcml0cw==",
+		"anVzdCBuaWlu"
+	};
+	string_t *str;
+	unsigned int i;
+	bool success;
+
+	str = t_str_new(256);
+	for (i = 0; i < N_ELEMENTS(input); i++) {
+		str_truncate(str, 0);
+		base64_encode(input[i], strlen(input[i]), str);
+		success = strcmp(output[i], str_c(str)) == 0;
+		test_out(t_strdup_printf("base64_encode(%d)", i), success);
+	}
+}
+
+struct test_base64_decode_output {
+	const char *text;
+	int ret;
+	unsigned int src_pos;
+};
+
+static void test_base64_decode(void)
+{
+	static const char *input[] = {
+		"\taGVsbG8gd29ybGQ=",
+		"\nZm9v\n \tIGJh  \t\ncml0cw==",
+		"  anVzdCBuaWlu  \n",
+		"aGVsb",
+		"aGVsb!!!!!",
+		"aGVs!!!!!"
+	};
+	static const struct test_base64_decode_output output[] = {
+		{ "hello world", 0, -1 },
+		{ "foo barits", 0, -1 },
+		{ "just niin", 1, -1 },
+		{ "hel", 1, 4 },
+		{ "hel", -1, 4 },
+		{ "hel", -1, 4 }
+	};
+	string_t *str;
+	unsigned int i;
+	size_t src_pos;
+	int ret;
+	bool success;
+
+	str = t_str_new(256);
+	for (i = 0; i < N_ELEMENTS(input); i++) {
+		str_truncate(str, 0);
+
+		src_pos = 0;
+		ret = base64_decode(input[i], strlen(input[i]), &src_pos, str);
+
+		success = output[i].ret == ret &&
+			strcmp(output[i].text, str_c(str)) == 0 &&
+			(src_pos == output[i].src_pos ||
+			 (output[i].src_pos == (unsigned int)-1 &&
+			  src_pos == strlen(input[i])));
+		test_out(t_strdup_printf("base64_decode(%d)", i), success);
+	}
+}
+
+static int cmp_uint(const void *p1, const void *p2)
+{
+	const unsigned int *i1 = p1, *i2 = p2;
+
+	return *i1 - *i2;
+}
+
+static void test_bsearch_insert_pos(void)
+{
+	static const unsigned int input[] = {
+		1, 5, 9, 15, 16, -1,
+		1, 5, 9, 15, 16, 17, -1,
+		-1
+	};
+	static const unsigned int max_key = 18;
+	const unsigned int *cur;
+	unsigned int key, len, i, idx;
+	bool success;
+
+	cur = input;
+	for (i = 0; cur[0] != -1U; i++) {
+		for (len = 0; cur[len] != -1U; len++) ;
+		for (key = 0; key < max_key; key++) {
+			if (bsearch_insert_pos(&key, cur, len, sizeof(*cur),
+					       cmp_uint, &idx))
+				success = cur[idx] == key;
+			else if (idx == 0)
+				success = cur[0] > key;
+			else if (idx == len)
+				success = cur[len-1] < key;
+			else {
+				success = cur[idx-1] < key &&
+					cur[idx+1] > key;
+			}
+			if (!success)
+				break;
+		}
+		cur += len + 1;
+
+		test_out(t_strdup_printf("bsearch_insert_pos(%d,%d)", i, key),
+			 success);
+	}
+}
+
+int main(void)
+{
+	test_init();
+
+	test_base64_encode();
+	test_base64_decode();
+	test_bsearch_insert_pos();
+	return test_deinit();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/test-mail.c	Wed Nov 07 01:17:26 2007 +0200
@@ -0,0 +1,147 @@
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "message-address.h"
+#include "message-date.h"
+#include "test-common.h"
+
+static bool cmp_addr(const struct message_address *a1,
+		     const struct message_address *a2)
+{
+	return null_strcmp(a1->name, a2->name) == 0 &&
+		null_strcmp(a1->route, a2->route) == 0 &&
+		null_strcmp(a1->mailbox, a2->mailbox) == 0 &&
+		null_strcmp(a1->domain, a2->domain) == 0;
+}
+
+static void test_message_address(void)
+{
+	static const char *input[] = {
+		"user@domain",
+		"<user@domain>",
+		"foo bar <user@domain>",
+		"\"foo bar\" <user@domain>",
+		"<@route:user@domain>",
+		"<@route@route2:user@domain>",
+		"hello <@route ,@route2:user@domain>"
+	};
+	static struct message_address group_prefix = {
+		NULL, NULL, NULL, "group", NULL
+	};
+	static struct message_address group_suffix = {
+		NULL, NULL, NULL, NULL, NULL
+	};
+	static struct message_address output[] = {
+		{ NULL, NULL, NULL, "user", "domain" },
+		{ NULL, NULL, NULL, "user", "domain" },
+		{ NULL, "foo bar", NULL, "user", "domain" },
+		{ NULL, "foo bar", NULL, "user", "domain" },
+		{ NULL, NULL, "@route", "user", "domain" },
+		{ NULL, NULL, "@route,@route2", "user", "domain" },
+		{ NULL, "hello", "@route,@route2", "user", "domain" }
+	};
+	struct message_address *addr;
+	string_t *group;
+	unsigned int i;
+	bool success;
+
+	group = t_str_new(256);
+	str_append(group, "group: ");
+
+	for (i = 0; i < N_ELEMENTS(input); i++) {
+		addr = message_address_parse(pool_datastack_create(),
+					     (const unsigned char *)input[i],
+					     strlen(input[i]), -1U, FALSE);
+		success = addr != NULL && addr->next == NULL &&
+			cmp_addr(addr, &output[i]);
+		test_out(t_strdup_printf("message_address_parse(%d)", i),
+			 success);
+
+		if (i != 0) {
+			if ((i % 2) == 0)
+				str_append(group, ",");
+			else
+				str_append(group, " , \n ");
+		}
+		str_append(group, input[i]);
+	}
+	str_append_c(group, ';');
+
+	addr = message_address_parse(pool_datastack_create(), str_data(group),
+				     str_len(group), -1U, FALSE);
+	success = addr != NULL && cmp_addr(addr, &group_prefix);
+	addr = addr->next;
+	for (i = 0; i < N_ELEMENTS(input) && addr != NULL; i++) {
+		if (!cmp_addr(addr, &output[i])) {
+			success = FALSE;
+			break;
+		}
+		addr = addr->next;
+	}
+	if (addr == NULL || addr->next != NULL ||
+	    !cmp_addr(addr, &group_suffix))
+		success = FALSE;
+	test_out("message_address_parse(group)", success);
+}
+
+struct test_message_date_output {
+	time_t time;
+	int tz_offset;
+	bool ret;
+};
+
+static void test_message_date_parse(void)
+{
+	static const char *input[] = {
+#ifdef TIME_T_SIGNED
+		"Thu, 01 Jan 1970 01:59:59 +0200",
+		"Fri, 13 Dec 1901 20:45:52 +0000",
+#endif
+#if TIME_T_MAX_BITS > 31
+		"Sun, 07 Feb 2106 06:28:15 +0000",
+#endif
+		"Wed, 07 Nov 2007 01:07:20 +0200",
+		"Wed, 07 Nov 2007 01:07:20",
+		"Thu, 01 Jan 1970 02:00:00 +0200",
+		"Tue, 19 Jan 2038 03:14:07 +0000",
+		"Tue, 19 Jan 2038"
+	};
+	static struct test_message_date_output output[] = {
+#ifdef TIME_T_SIGNED
+		{ -1, 2*60, TRUE },
+		{ -2147483648, 0, TRUE },
+#endif
+#if TIME_T_MAX_BITS > 31
+		{ 4294967295, 0, TRUE },
+#endif
+		{ 1194390440, 2*60, TRUE },
+		{ 1194397640, 0, TRUE },
+		{ 0, 2*60, TRUE },
+		{ 2147483647, 0, TRUE },
+		{ 0, 0, FALSE }
+	};
+	unsigned int i;
+	bool success;
+	time_t t;
+	int tz;
+	bool ret;
+
+	for (i = 0; i < N_ELEMENTS(input); i++) {
+		ret = message_date_parse((const unsigned char *)input[i],
+					 strlen(input[i]), &t, &tz);
+		success = (!ret && !output[i].ret) ||
+			(ret == output[i].ret && t == output[i].time &&
+			 tz == output[i].tz_offset);
+		test_out(t_strdup_printf("message_date_parse(%d)", i), success);
+	}
+}
+
+int main(void)
+{
+	test_init();
+
+	test_message_address();
+	test_message_date_parse();
+	return test_deinit();
+}