From 48acc31adebfdd4e4945ee76e1f5259e4b1b6fff Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 1 Jun 2009 01:11:17 -0400 Subject: [PATCH] liblib unit tests are now split to separate files. --HG-- branch : HEAD --- src/lib/Makefile.am | 15 +- src/lib/test-aqueue.c | 71 +++ src/lib/test-array.c | 30 + src/lib/test-base64.c | 110 ++++ src/lib/test-bsearch-insert-pos.c | 48 ++ src/lib/test-buffer.c | 135 +++++ src/lib/test-istream.c | 2 +- src/lib/test-lib.c | 908 +----------------------------- src/lib/test-lib.h | 20 +- src/lib/test-mempool-alloconly.c | 46 ++ src/lib/test-network.c | 53 ++ src/lib/test-primes.c | 24 + src/lib/test-priorityq.c | 101 ++++ src/lib/test-seq-range-array.c | 162 ++++++ src/lib/test-str-find.c | 85 +++ src/lib/test-str-sanitize.c | 40 ++ src/lib/test-utc-mktime.c | 56 ++ 17 files changed, 1000 insertions(+), 906 deletions(-) create mode 100644 src/lib/test-aqueue.c create mode 100644 src/lib/test-array.c create mode 100644 src/lib/test-base64.c create mode 100644 src/lib/test-bsearch-insert-pos.c create mode 100644 src/lib/test-buffer.c create mode 100644 src/lib/test-mempool-alloconly.c create mode 100644 src/lib/test-network.c create mode 100644 src/lib/test-primes.c create mode 100644 src/lib/test-priorityq.c create mode 100644 src/lib/test-seq-range-array.c create mode 100644 src/lib/test-str-find.c create mode 100644 src/lib/test-str-sanitize.c create mode 100644 src/lib/test-utc-mktime.c diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 0453b9a71e..eb40f1c446 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -210,7 +210,20 @@ test_libs = \ test_lib_SOURCES = \ test-lib.c \ - test-istream.c + test-array.c \ + test-aqueue.c \ + test-base64.c \ + test-bsearch-insert-pos.c \ + test-buffer.c \ + test-istream.c \ + test-mempool-alloconly.c \ + test-network.c \ + test-primes.c \ + test-priorityq.c \ + test-seq-range-array.c \ + test-str-find.c \ + test-str-sanitize.c \ + test-utc-mktime.c test_headers = \ test-lib.h diff --git a/src/lib/test-aqueue.c b/src/lib/test-aqueue.c new file mode 100644 index 0000000000..4064349ed5 --- /dev/null +++ b/src/lib/test-aqueue.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "array.h" +#include "aqueue.h" + +static bool aqueue_is_ok(struct aqueue *aqueue, unsigned int deleted_n) +{ + const unsigned int *p; + unsigned int n, i, count; + + count = aqueue_count(aqueue); + for (i = 0, n = 1; i < count; i++, n++) { + p = array_idx_i(aqueue->arr, aqueue_idx(aqueue, i)); + if (i == deleted_n) + n++; + if (*p != n) + return FALSE; + } + return TRUE; +} + +static const unsigned int aqueue_input[] = { 1, 2, 3, 4, 5, 6 }; +static const char *test_aqueue2(unsigned int initial_size) +{ + ARRAY_DEFINE(aqueue_array, unsigned int); + unsigned int i, j, k; + struct aqueue *aqueue; + + for (i = 0; i < N_ELEMENTS(aqueue_input); i++) { + for (k = 0; k < N_ELEMENTS(aqueue_input); k++) { + t_array_init(&aqueue_array, initial_size); + aqueue = aqueue_init(&aqueue_array.arr); + aqueue->head = aqueue->tail = initial_size - 1; + for (j = 0; j < k; j++) { + aqueue_append(aqueue, &aqueue_input[j]); + if (aqueue_count(aqueue) != j + 1) { + return t_strdup_printf("Wrong count after append %u vs %u)", + aqueue_count(aqueue), j + 1); + } + if (!aqueue_is_ok(aqueue, -1U)) + return "Invalid data after append"; + } + + if (k != 0 && i < k) { + aqueue_delete(aqueue, i); + if (aqueue_count(aqueue) != k - 1) + return "Wrong count after delete"; + if (!aqueue_is_ok(aqueue, i)) + return "Invalid data after delete"; + } + } + } + aqueue_clear(aqueue); + if (aqueue_count(aqueue) != 0) + return "aqueue_clear() broken"; + return NULL; +} + +void test_aqueue(void) +{ + unsigned int i; + const char *reason = NULL; + + for (i = 1; i <= N_ELEMENTS(aqueue_input) + 1 && reason == NULL; i++) { + T_BEGIN { + reason = test_aqueue2(i); + } T_END; + } + test_out_reason("aqueue", reason == NULL, reason); +} diff --git a/src/lib/test-array.c b/src/lib/test-array.c new file mode 100644 index 0000000000..419e35dc28 --- /dev/null +++ b/src/lib/test-array.c @@ -0,0 +1,30 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "array.h" + +static void test_array_reverse(void) +{ + ARRAY_DEFINE(intarr, int); + int input[] = { -1234567890, -272585721, 2724859223U, 824725652 }; + const int *output; + unsigned int i, j; + + test_begin("array reverse"); + t_array_init(&intarr, 5); + for (i = 0; i < N_ELEMENTS(input); i++) { + array_clear(&intarr); + array_append(&intarr, input, i); + array_reverse(&intarr); + + output = i == 0 ? NULL : array_idx(&intarr, 0); + for (j = 0; j < i; j++) + test_assert(input[i-j-1] == output[j]); + } + test_end(); +} + +void test_array(void) +{ + test_array_reverse(); +} diff --git a/src/lib/test-base64.c b/src/lib/test-base64.c new file mode 100644 index 0000000000..645c45ca5c --- /dev/null +++ b/src/lib/test-base64.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str.h" +#include "base64.h" + +#include + +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; + + test_begin("base64_encode()"); + 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); + test_assert(strcmp(output[i], str_c(str)) == 0); + } + test_end(); +} + +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; + + test_begin("base64_decode()"); + 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); + + test_assert(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_end(); +} + +static void test_base64_random(void) +{ + string_t *str, *dest; + char buf[10]; + unsigned int i, j, max; + + str = t_str_new(256); + dest = t_str_new(256); + + test_begin("base64 encode/decode with random input"); + for (i = 0; i < 1000; i++) { + max = rand() % sizeof(buf); + for (j = 0; j < max; j++) + buf[j] = rand(); + + str_truncate(str, 0); + str_truncate(dest, 0); + base64_encode(buf, max, str); + base64_decode(str_data(str), str_len(str), NULL, dest); + test_assert(str_len(dest) == max && + memcmp(buf, str_data(dest), max) == 0); + } + test_end(); +} + +void test_base64(void) +{ + test_base64_encode(); + test_base64_decode(); + test_base64_random(); +} diff --git a/src/lib/test-bsearch-insert-pos.c b/src/lib/test-bsearch-insert-pos.c new file mode 100644 index 0000000000..548016f863 --- /dev/null +++ b/src/lib/test-bsearch-insert-pos.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "bsearch-insert-pos.h" + +static int cmp_uint(const void *p1, const void *p2) +{ + const unsigned int *i1 = p1, *i2 = p2; + + return *i1 - *i2; +} + +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); + } +} diff --git a/src/lib/test-buffer.c b/src/lib/test-buffer.c new file mode 100644 index 0000000000..e20b95b6a4 --- /dev/null +++ b/src/lib/test-buffer.c @@ -0,0 +1,135 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "buffer.h" + +#include + +void test_buffer(void) +{ +#define BUF_TEST_SIZE (1024*2) +#define BUF_TEST_COUNT 1000 + buffer_t *buf; + unsigned char *p, testdata[BUF_TEST_SIZE], shadowbuf[BUF_TEST_SIZE]; + unsigned int i, shadowbuf_size; + size_t pos, pos2, size; + int test = -1; + bool zero; + + buf = buffer_create_dynamic(default_pool, 1); + for (i = 0; i < BUF_TEST_SIZE; i++) + testdata[i] = random(); + memset(shadowbuf, 0, sizeof(shadowbuf)); + + srand(1); + shadowbuf_size = 0; + for (i = 0; i < BUF_TEST_COUNT; i++) { + if (buf->used == BUF_TEST_SIZE) { + size = shadowbuf_size = rand() % (buf->used - 1); + buffer_set_used_size(buf, size); + memset(shadowbuf + shadowbuf_size, 0, + BUF_TEST_SIZE - shadowbuf_size); + i_assert(buf->used < BUF_TEST_SIZE); + } + + test = rand() % 6; + zero = rand() % 10 == 0; + switch (test) { + case 0: + pos = rand() % (BUF_TEST_SIZE-1); + size = rand() % (BUF_TEST_SIZE - pos); + if (!zero) { + buffer_write(buf, pos, testdata, size); + memcpy(shadowbuf + pos, testdata, size); + } else { + buffer_write_zero(buf, pos, size); + memset(shadowbuf + pos, 0, size); + } + if (pos + size > shadowbuf_size) + shadowbuf_size = pos + size; + break; + case 1: + size = rand() % (BUF_TEST_SIZE - buf->used); + if (!zero) { + buffer_append(buf, testdata, size); + memcpy(shadowbuf + shadowbuf_size, + testdata, size); + } else { + buffer_append_zero(buf, size); + memset(shadowbuf + shadowbuf_size, 0, size); + } + shadowbuf_size += size; + break; + case 2: + pos = rand() % (BUF_TEST_SIZE-1); + size = rand() % (BUF_TEST_SIZE - I_MAX(buf->used, pos)); + if (!zero) { + buffer_insert(buf, pos, testdata, size); + memmove(shadowbuf + pos + size, + shadowbuf + pos, + BUF_TEST_SIZE - (pos + size)); + memcpy(shadowbuf + pos, testdata, size); + } else { + buffer_insert_zero(buf, pos, size); + memmove(shadowbuf + pos + size, + shadowbuf + pos, + BUF_TEST_SIZE - (pos + size)); + memset(shadowbuf + pos, 0, size); + } + if (pos < shadowbuf_size) + shadowbuf_size += size; + else + shadowbuf_size = pos + size; + break; + case 3: + pos = rand() % (BUF_TEST_SIZE-1); + size = rand() % (BUF_TEST_SIZE - pos); + buffer_delete(buf, pos, size); + if (pos < shadowbuf_size) { + if (pos + size > shadowbuf_size) + size = shadowbuf_size - pos; + memmove(shadowbuf + pos, + shadowbuf + pos + size, + BUF_TEST_SIZE - (pos + size)); + + shadowbuf_size -= size; + memset(shadowbuf + shadowbuf_size, 0, + BUF_TEST_SIZE - shadowbuf_size); + } + break; + case 4: + if (shadowbuf_size == 0) + break; + pos = rand() % (shadowbuf_size-1); /* dest */ + pos2 = rand() % (shadowbuf_size-1); /* source */ + size = rand() % (shadowbuf_size - I_MAX(pos, pos2)); + buffer_copy(buf, pos, buf, pos2, size); + memmove(shadowbuf + pos, + shadowbuf + pos2, size); + if (pos > pos2 && pos + size > shadowbuf_size) + shadowbuf_size = pos + size; + break; + case 5: + pos = rand() % (BUF_TEST_SIZE-1); + size = rand() % (BUF_TEST_SIZE - pos); + p = buffer_get_space_unsafe(buf, pos, size); + memcpy(p, testdata, size); + memcpy(shadowbuf + pos, testdata, size); + if (pos + size > shadowbuf_size) + shadowbuf_size = pos + size; + break; + } + i_assert(shadowbuf_size <= BUF_TEST_SIZE); + + if (buf->used != shadowbuf_size || + memcmp(buf->data, shadowbuf, buf->used) != 0) + break; + } + if (i == BUF_TEST_COUNT) + test_out("buffer", TRUE); + else { + test_out_reason("buffer", FALSE, + t_strdup_printf("round %u test %d failed", i, test)); + } + buffer_free(&buf); +} diff --git a/src/lib/test-istream.c b/src/lib/test-istream.c index 838e062ebb..415569b4ce 100644 --- a/src/lib/test-istream.c +++ b/src/lib/test-istream.c @@ -99,7 +99,7 @@ static void test_istream_crlf(void) test_istream_crlf_input(input[i], i); } -void test_istreams(void) +void test_istream(void) { test_istream_crlf(); } diff --git a/src/lib/test-lib.c b/src/lib/test-lib.c index ea19d241ee..21cd0bbb78 100644 --- a/src/lib/test-lib.c +++ b/src/lib/test-lib.c @@ -1,923 +1,25 @@ /* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ #include "test-lib.h" -#include "array.h" -#include "str.h" -#include "base64.h" -#include "bsearch-insert-pos.h" -#include "aqueue.h" -#include "network.h" -#include "primes.h" -#include "priorityq.h" -#include "seq-range-array.h" -#include "str-find.h" -#include "str-sanitize.h" -#include "utc-mktime.h" - -#include -#include - -static void test_array(void) -{ - ARRAY_DEFINE(intarr, int); - int input[] = { -1234567890, -272585721, 2724859223U, 824725652 }; - const int *output; - unsigned int i, j; - bool success = TRUE; - - t_array_init(&intarr, 5); - for (i = 0; i < N_ELEMENTS(input); i++) { - array_clear(&intarr); - array_append(&intarr, input, i); - array_reverse(&intarr); - - output = i == 0 ? NULL : array_idx(&intarr, 0); - for (j = 0; j < i; j++) { - if (input[i-j-1] != output[j]) { - success = FALSE; - break; - } - } - } - test_out("array_reverse()", success); -} - -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, *dest; - unsigned int i, j, max; - char buf[10]; - bool success; - - str = t_str_new(256); - dest = 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); - } - - for (i = 0; i < 1000; i++) { - max = rand() % sizeof(buf); - for (j = 0; j < max; j++) - buf[j] = rand(); - - str_truncate(str, 0); - str_truncate(dest, 0); - base64_encode(buf, max, str); - base64_decode(str_data(str), str_len(str), NULL, dest); - if (str_len(dest) != max && - memcmp(buf, str_data(dest), max) != 0) - break; - } - test_out("base64 random", 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); - } -} - -static void test_buffer(void) -{ -#define BUF_TEST_SIZE (1024*2) -#define BUF_TEST_COUNT 1000 - buffer_t *buf; - unsigned char *p, testdata[BUF_TEST_SIZE], shadowbuf[BUF_TEST_SIZE]; - unsigned int i, shadowbuf_size; - size_t pos, pos2, size; - int test = -1; - bool zero; - - buf = buffer_create_dynamic(default_pool, 1); - for (i = 0; i < BUF_TEST_SIZE; i++) - testdata[i] = random(); - memset(shadowbuf, 0, sizeof(shadowbuf)); - - srand(1); - shadowbuf_size = 0; - for (i = 0; i < BUF_TEST_COUNT; i++) { - if (buf->used == BUF_TEST_SIZE) { - size = shadowbuf_size = rand() % (buf->used - 1); - buffer_set_used_size(buf, size); - memset(shadowbuf + shadowbuf_size, 0, - BUF_TEST_SIZE - shadowbuf_size); - i_assert(buf->used < BUF_TEST_SIZE); - } - - test = rand() % 6; - zero = rand() % 10 == 0; - switch (test) { - case 0: - pos = rand() % (BUF_TEST_SIZE-1); - size = rand() % (BUF_TEST_SIZE - pos); - if (!zero) { - buffer_write(buf, pos, testdata, size); - memcpy(shadowbuf + pos, testdata, size); - } else { - buffer_write_zero(buf, pos, size); - memset(shadowbuf + pos, 0, size); - } - if (pos + size > shadowbuf_size) - shadowbuf_size = pos + size; - break; - case 1: - size = rand() % (BUF_TEST_SIZE - buf->used); - if (!zero) { - buffer_append(buf, testdata, size); - memcpy(shadowbuf + shadowbuf_size, - testdata, size); - } else { - buffer_append_zero(buf, size); - memset(shadowbuf + shadowbuf_size, 0, size); - } - shadowbuf_size += size; - break; - case 2: - pos = rand() % (BUF_TEST_SIZE-1); - size = rand() % (BUF_TEST_SIZE - I_MAX(buf->used, pos)); - if (!zero) { - buffer_insert(buf, pos, testdata, size); - memmove(shadowbuf + pos + size, - shadowbuf + pos, - BUF_TEST_SIZE - (pos + size)); - memcpy(shadowbuf + pos, testdata, size); - } else { - buffer_insert_zero(buf, pos, size); - memmove(shadowbuf + pos + size, - shadowbuf + pos, - BUF_TEST_SIZE - (pos + size)); - memset(shadowbuf + pos, 0, size); - } - if (pos < shadowbuf_size) - shadowbuf_size += size; - else - shadowbuf_size = pos + size; - break; - case 3: - pos = rand() % (BUF_TEST_SIZE-1); - size = rand() % (BUF_TEST_SIZE - pos); - buffer_delete(buf, pos, size); - if (pos < shadowbuf_size) { - if (pos + size > shadowbuf_size) - size = shadowbuf_size - pos; - memmove(shadowbuf + pos, - shadowbuf + pos + size, - BUF_TEST_SIZE - (pos + size)); - - shadowbuf_size -= size; - memset(shadowbuf + shadowbuf_size, 0, - BUF_TEST_SIZE - shadowbuf_size); - } - break; - case 4: - if (shadowbuf_size == 0) - break; - pos = rand() % (shadowbuf_size-1); /* dest */ - pos2 = rand() % (shadowbuf_size-1); /* source */ - size = rand() % (shadowbuf_size - I_MAX(pos, pos2)); - buffer_copy(buf, pos, buf, pos2, size); - memmove(shadowbuf + pos, - shadowbuf + pos2, size); - if (pos > pos2 && pos + size > shadowbuf_size) - shadowbuf_size = pos + size; - break; - case 5: - pos = rand() % (BUF_TEST_SIZE-1); - size = rand() % (BUF_TEST_SIZE - pos); - p = buffer_get_space_unsafe(buf, pos, size); - memcpy(p, testdata, size); - memcpy(shadowbuf + pos, testdata, size); - if (pos + size > shadowbuf_size) - shadowbuf_size = pos + size; - break; - } - i_assert(shadowbuf_size <= BUF_TEST_SIZE); - - if (buf->used != shadowbuf_size || - memcmp(buf->data, shadowbuf, buf->used) != 0) - break; - } - if (i == BUF_TEST_COUNT) - test_out("buffer", TRUE); - else { - test_out_reason("buffer", FALSE, - t_strdup_printf("round %u test %d failed", i, test)); - } - buffer_free(&buf); -} - -static bool aqueue_is_ok(struct aqueue *aqueue, unsigned int deleted_n) -{ - const unsigned int *p; - unsigned int n, i, count; - - count = aqueue_count(aqueue); - for (i = 0, n = 1; i < count; i++, n++) { - p = array_idx_i(aqueue->arr, aqueue_idx(aqueue, i)); - if (i == deleted_n) - n++; - if (*p != n) - return FALSE; - } - return TRUE; -} - -static const unsigned int aqueue_input[] = { 1, 2, 3, 4, 5, 6 }; -static const char *test_aqueue2(unsigned int initial_size) -{ - ARRAY_DEFINE(aqueue_array, unsigned int); - unsigned int i, j, k; - struct aqueue *aqueue; - - for (i = 0; i < N_ELEMENTS(aqueue_input); i++) { - for (k = 0; k < N_ELEMENTS(aqueue_input); k++) { - t_array_init(&aqueue_array, initial_size); - aqueue = aqueue_init(&aqueue_array.arr); - aqueue->head = aqueue->tail = initial_size - 1; - for (j = 0; j < k; j++) { - aqueue_append(aqueue, &aqueue_input[j]); - if (aqueue_count(aqueue) != j + 1) { - return t_strdup_printf("Wrong count after append %u vs %u)", - aqueue_count(aqueue), j + 1); - } - if (!aqueue_is_ok(aqueue, -1U)) - return "Invalid data after append"; - } - - if (k != 0 && i < k) { - aqueue_delete(aqueue, i); - if (aqueue_count(aqueue) != k - 1) - return "Wrong count after delete"; - if (!aqueue_is_ok(aqueue, i)) - return "Invalid data after delete"; - } - } - } - aqueue_clear(aqueue); - if (aqueue_count(aqueue) != 0) - return "aqueue_clear() broken"; - return NULL; -} - -static void test_aqueue(void) -{ - unsigned int i; - const char *reason = NULL; - - for (i = 1; i <= N_ELEMENTS(aqueue_input) + 1 && reason == NULL; i++) { - T_BEGIN { - reason = test_aqueue2(i); - } T_END; - } - test_out_reason("aqueue", reason == NULL, reason); -} - -static bool mem_has_bytes(const void *mem, size_t size, uint8_t b) -{ - const uint8_t *bytes = mem; - unsigned int i; - - for (i = 0; i < size; i++) { - if (bytes[i] != b) - return FALSE; - } - return TRUE; -} - -static void test_mempool_alloconly(void) -{ -#define PMALLOC_MAX_COUNT 128 - pool_t pool; - unsigned int i, j, k; - void *mem[PMALLOC_MAX_COUNT + 1]; - bool success = TRUE; - - for (i = 0; i < 64; i++) { - for (j = 1; j <= 128; j++) { - pool = pool_alloconly_create(MEMPOOL_GROWING"test", i); - mem[0] = p_malloc(pool, j); - memset(mem[0], j, j); - - for (k = 1; k <= PMALLOC_MAX_COUNT; k++) { - mem[k] = p_malloc(pool, k); - memset(mem[k], k, k); - } - - if (!mem_has_bytes(mem[0], j, j)) - success = FALSE; - for (k = 1; k <= PMALLOC_MAX_COUNT; k++) { - if (!mem_has_bytes(mem[k], k, k)) - success = FALSE; - } - pool_unref(&pool); - } - } - test_out("mempool_alloconly", success); -} - -struct test_net_is_in_network_input { - const char *ip; - const char *net; - unsigned int bits; - bool ret; -}; - -static void test_net_is_in_network(void) -{ - static struct test_net_is_in_network_input input[] = { - { "1.2.3.4", "1.2.3.4", 32, TRUE }, - { "1.2.3.4", "1.2.3.3", 32, FALSE }, - { "1.2.3.4", "1.2.3.5", 32, FALSE }, - { "1.2.3.4", "1.2.2.4", 32, FALSE }, - { "1.2.3.4", "1.1.3.4", 32, FALSE }, - { "1.2.3.4", "0.2.3.4", 32, FALSE }, - { "1.2.3.253", "1.2.3.254", 31, FALSE }, - { "1.2.3.254", "1.2.3.254", 31, TRUE }, - { "1.2.3.255", "1.2.3.254", 31, TRUE }, - { "1.2.3.255", "1.2.3.0", 24, TRUE }, - { "1.2.255.255", "1.2.254.0", 23, TRUE }, - { "255.255.255.255", "128.0.0.0", 1, TRUE }, - { "255.255.255.255", "127.0.0.0", 1, FALSE } -#ifdef HAVE_IPV6 - , - { "1234:5678::abcf", "1234:5678::abce", 127, TRUE }, - { "1234:5678::abcd", "1234:5678::abce", 127, FALSE }, - { "123e::ffff", "123e::0", 15, TRUE }, - { "123d::ffff", "123e::0", 15, FALSE } -#endif - }; - struct ip_addr ip, net_ip; - unsigned int i; - bool success; - - for (i = 0; i < N_ELEMENTS(input); i++) { - net_addr2ip(input[i].ip, &ip); - net_addr2ip(input[i].net, &net_ip); - success = net_is_in_network(&ip, &net_ip, input[i].bits) == - input[i].ret; - test_out(t_strdup_printf("net_is_in_network(%u)", i), success); - } -} - -struct pq_test_item { - struct priorityq_item item; - int num; -}; - -static int cmp_int(const void *p1, const void *p2) -{ - const struct pq_test_item *i1 = p1, *i2 = p2; - - return i1->num - i2->num; -} - -static void test_primes(void) -{ - unsigned int i, j, num; - bool success; - - success = primes_closest(0) > 0; - for (num = 1; num < 1024; num++) { - if (primes_closest(num) < num) - success = FALSE; - } - for (i = 10; i < 32; i++) { - num = (1 << i) - 100; - for (j = 0; j < 200; j++, num++) { - if (primes_closest(num) < num) - success = FALSE; - } - } - test_out("primes_closest()", success); -} - -static void test_priorityq(void) -{ -#define PQ_MAX_ITEMS 100 - static const int input[] = { - 1, 2, 3, 4, 5, 6, 7, 8, -1, - 8, 7, 6, 5, 4, 3, 2, 1, -1, - 8, 7, 5, 6, 1, 3, 4, 2, -1, - -1 - }; - static const int output[] = { - 1, 2, 3, 4, 5, 6, 7, 8 - }; - struct pq_test_item *item, items[PQ_MAX_ITEMS]; - unsigned int i, j; - struct priorityq *pq; - pool_t pool; - int prev; - bool success = TRUE; - - pool = pool_alloconly_create("priorityq items", 1024); - - /* simple tests with popping only */ - for (i = 0; input[i] != -1; i++) { - p_clear(pool); - pq = priorityq_init(cmp_int, 1); - for (j = 0; input[i] != -1; i++, j++) { - if (priorityq_count(pq) != j) - success = FALSE; - item = p_new(pool, struct pq_test_item, 1); - item->num = input[i]; - priorityq_add(pq, &item->item); - } - for (j = 0; j < N_ELEMENTS(output); j++) { - if (priorityq_count(pq) != N_ELEMENTS(output) - j) - success = FALSE; - - item = (struct pq_test_item *)priorityq_peek(pq); - if (output[j] != item->num) - success = FALSE; - item = (struct pq_test_item *)priorityq_pop(pq); - if (output[j] != item->num) - success = FALSE; - } - if (priorityq_count(pq) != 0) - success = FALSE; - if (priorityq_peek(pq) != NULL || priorityq_pop(pq) != NULL) - success = FALSE; - priorityq_deinit(&pq); - } - test_out("priorityq(1)", success); - - /* randomized tests, remove elements */ - success = TRUE; - for (i = 0; i < 100; i++) { - pq = priorityq_init(cmp_int, 1); - for (j = 0; j < PQ_MAX_ITEMS; j++) { - items[j].num = rand(); - priorityq_add(pq, &items[j].item); - } - for (j = 0; j < PQ_MAX_ITEMS; j++) { - if (rand() % 3 == 0) { - priorityq_remove(pq, &items[j].item); - items[j].num = -1; - } - } - prev = 0; - while (priorityq_count(pq) > 0) { - item = (struct pq_test_item *)priorityq_pop(pq); - if (item->num < 0 || prev > item->num) - success = FALSE; - prev = item->num; - item->num = -1; - } - for (j = 0; j < PQ_MAX_ITEMS; j++) { - if (items[j].num != -1) - success = FALSE; - } - priorityq_deinit(&pq); - } - test_out("priorityq(2)", success); - pool_unref(&pool); -} - -static void test_seq_range_array_random(void) -{ -#define SEQ_RANGE_TEST_BUFSIZE 20 -#define SEQ_RANGE_TEST_COUNT 10000 - unsigned char shadowbuf[SEQ_RANGE_TEST_BUFSIZE]; - ARRAY_TYPE(seq_range) range; - const struct seq_range *seqs; - uint32_t seq1, seq2; - unsigned int i, j, ret, ret2, count; - int test = -1; - - ret = ret2 = 0; - i_array_init(&range, 1); - memset(shadowbuf, 0, sizeof(shadowbuf)); - for (i = 0; i < SEQ_RANGE_TEST_COUNT; i++) { - seq1 = rand() % SEQ_RANGE_TEST_BUFSIZE; - seq2 = seq1 + rand() % (SEQ_RANGE_TEST_BUFSIZE - seq1); - test = rand() % 4; - switch (test) { - case 0: - seq_range_array_add(&range, 0, seq1); - shadowbuf[seq1] = 1; - break; - case 1: - seq_range_array_add_range(&range, seq1, seq2); - memset(shadowbuf + seq1, 1, seq2 - seq1 + 1); - break; - case 2: - ret = seq_range_array_remove(&range, seq1) ? 1 : 0; - ret2 = shadowbuf[seq1] != 0 ? 1 : 0; - shadowbuf[seq1] = 0; - break; - case 3: - ret = seq_range_array_remove_range(&range, seq1, seq2); - for (ret2 = 0; seq1 <= seq2; seq1++) { - if (shadowbuf[seq1] != 0) { - ret2++; - shadowbuf[seq1] = 0; - } - } - break; - } - if (ret != ret2) - break; - - seqs = array_get(&range, &count); - for (j = 0, seq1 = 0; j < count; j++) { - if (j > 0 && seqs[j-1].seq2 >= seqs[j].seq1) - goto fail; - for (; seq1 < seqs[j].seq1; seq1++) { - if (shadowbuf[seq1] != 0) - goto fail; - } - for (; seq1 <= seqs[j].seq2; seq1++) { - if (shadowbuf[seq1] == 0) - goto fail; - } - } - i_assert(seq1 <= SEQ_RANGE_TEST_BUFSIZE); - for (; seq1 < SEQ_RANGE_TEST_BUFSIZE; seq1++) { - if (shadowbuf[seq1] != 0) - goto fail; - } - } -fail: - if (i == SEQ_RANGE_TEST_COUNT) - test_out("seq_range_array random", TRUE); - else { - test_out_reason("seq_range_array random", FALSE, - t_strdup_printf("round %u test %d failed", i, test)); - } -} - -static void test_seq_range_array_invert(void) -{ - static const unsigned int input_min = 1, input_max = 5; - static const unsigned int input[] = { - 1, 2, 3, 4, 5, -1U, - 2, 3, 4, -1U, - 1, 2, 4, 5, -1U, - 1, 3, 5, -1U, - 1, -1U, - 5, -1U, - -1U - }; - ARRAY_TYPE(seq_range) range = ARRAY_INIT; - unsigned int i, j, seq, start, num; - bool old_exists, success; - - for (i = num = 0; input[i] != -1U; num++, i++) { - success = TRUE; - start = i; - for (; input[i] != -1U; i++) { - seq_range_array_add(&range, 32, input[i]); - for (j = start; j < i; j++) { - if (!seq_range_exists(&range, input[j])) - success = FALSE; - } - } - - seq_range_array_invert(&range, input_min, input_max); - for (seq = input_min; seq <= input_max; seq++) { - for (j = start; input[j] != -1U; j++) { - if (input[j] == seq) - break; - } - old_exists = input[j] != -1U; - if (seq_range_exists(&range, seq) == old_exists) - success = FALSE; - } - test_out(t_strdup_printf("seq_range_array_invert(%u)", num), - success); - array_free(&range); - } -} - -static void test_seq_range_create(ARRAY_TYPE(seq_range) *array, uint8_t byte) -{ - unsigned int i; - - array_clear(array); - for (i = 0; i < 8; i++) { - if ((byte & (1 << i)) != 0) - seq_range_array_add(array, 0, i + 1); - } -} - -static void test_seq_range_array_have_common(void) -{ - ARRAY_TYPE(seq_range) arr1, arr2; - unsigned int i, j; - bool ret1, ret2, success = TRUE; - - t_array_init(&arr1, 8); - t_array_init(&arr2, 8); - for (i = 0; i < 256; i++) { - test_seq_range_create(&arr1, i); - for (j = 0; j < 256; j++) { - test_seq_range_create(&arr2, j); - ret1 = seq_range_array_have_common(&arr1, &arr2); - ret2 = (i & j) != 0; - if (ret1 != ret2) - success = FALSE; - } - } - test_out("seq_range_array_have_common()", success); -} - -static void test_seq_range_array(void) -{ - test_seq_range_array_invert(); - test_seq_range_array_have_common(); - test_seq_range_array_random(); -} - -static const char *str_find_text = "xababcd"; - -static bool test_str_find_substring(const char *key, int expected_pos) -{ - const unsigned char *text = (const unsigned char *)str_find_text; - const unsigned int text_len = strlen(str_find_text); - struct str_find_context *ctx; - unsigned int i, j, pos, max, offset; - bool ret; - - ctx = str_find_init(pool_datastack_create(), key); - /* divide text into every possible block combination and test that - it matches */ - max = 1 << (text_len-1); - for (i = 0; i < max; i++) { - str_find_reset(ctx); - pos = 0; offset = 0; ret = FALSE; - for (j = 0; j < text_len; j++) { - if ((i & (1 << j)) != 0) { - if (str_find_more(ctx, text+pos, j-pos+1)) { - ret = TRUE; - break; - } - offset += j-pos + 1; - pos = j + 1; - } - } - if (pos != text_len && !ret) { - if (str_find_more(ctx, text+pos, j-pos)) - ret = TRUE; - } - if (expected_pos < 0) { - if (ret) - return FALSE; - } else { - if (!ret) - return FALSE; - - pos = str_find_get_match_end_pos(ctx) + - offset - strlen(key); - if ((int)pos != expected_pos) - return FALSE; - } - } - return TRUE; -} - -struct str_find_input { - const char *str; - int pos; -}; -static void test_str_find(void) -{ - static const char *fail_input[] = { - "xabc", - "xabd", - "abd" - }; - unsigned int idx, len; - const char *key, *p; - unsigned int i; - bool success = TRUE; - - for (idx = 0; idx < strlen(str_find_text); idx++) { - for (len = strlen(str_find_text)-idx; len > 0; len--) { - /* we'll get a search key for all substrings of text */ - T_BEGIN { - key = t_strndup(str_find_text + idx, len); - p = strstr(str_find_text, key); - success = test_str_find_substring(key, p - str_find_text); - } T_END; - if (!success) - break; - } - } - for (i = 0; i < N_ELEMENTS(fail_input) && success; i++) - success = test_str_find_substring(fail_input[i], -1); - test_out("str_find()", success); -} - -struct str_sanitize_input { - const char *str; - unsigned int max_len; -}; -static void test_str_sanitize(void) -{ - static struct str_sanitize_input input[] = { - { NULL, 2 }, - { "", 2 }, - { "a", 2 }, - { "ab", 2 }, - { "abc", 2 }, - { "abcd", 3 }, - { "abcde", 4 } - }; - static const char *output[] = { - NULL, - "", - "a", - "ab", - "...", - "...", - "a..." - }; - const char *str; - unsigned int i; - bool success; - - for (i = 0; i < N_ELEMENTS(input); i++) { - str = str_sanitize(input[i].str, input[i].max_len); - success = null_strcmp(output[i], str) == 0; - test_out(t_strdup_printf("str_sanitize(%d)", i), success); - } -} - -struct test_message_date_output { - time_t time; - int tz_offset; - bool ret; -}; - -struct test_utc_mktime_input { - int year, month, day, hour, min, sec; -}; - -static void test_utc_mktime(void) -{ - static struct test_utc_mktime_input input[] = { -#ifdef TIME_T_SIGNED - { 1969, 12, 31, 23, 59, 59 }, - { 1901, 12, 13, 20, 45, 53 }, -#endif -#if (TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)) - { 2106, 2, 7, 6, 28, 15 }, -#endif - { 2007, 11, 7, 1, 7, 20 }, - { 1970, 1, 1, 0, 0, 0 }, - { 2038, 1, 19, 3, 14, 7 } - }; - static time_t output[] = { -#ifdef TIME_T_SIGNED - -1, - -2147483647, -#endif -#if (TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)) - 4294967295, -#endif - 1194397640, - 0, - 2147483647 - }; - struct tm tm; - unsigned int i; - time_t t; - bool success; - - for (i = 0; i < N_ELEMENTS(input); i++) { - memset(&tm, 0, sizeof(tm)); - tm.tm_year = input[i].year - 1900; - tm.tm_mon = input[i].month - 1; - tm.tm_mday = input[i].day; - tm.tm_hour = input[i].hour; - tm.tm_min = input[i].min; - tm.tm_sec = input[i].sec; - - t = utc_mktime(&tm); - success = t == output[i]; - test_out_reason(t_strdup_printf("utc_mktime(%d)", i), success, - success ? NULL : t_strdup_printf("%ld != %ld", - (long)t, (long)output[i])); - } -} int main(void) { static void (*test_functions[])(void) = { - test_array, test_aqueue, - test_base64_encode, - test_base64_decode, + test_array, + test_base64, test_bsearch_insert_pos, test_buffer, + test_istream, test_mempool_alloconly, - test_net_is_in_network, + test_network, test_primes, test_priorityq, test_seq_range_array, test_str_find, test_str_sanitize, test_utc_mktime, - - test_istreams + NULL }; return test_run(test_functions); } diff --git a/src/lib/test-lib.h b/src/lib/test-lib.h index 6941541862..97c1b9686a 100644 --- a/src/lib/test-lib.h +++ b/src/lib/test-lib.h @@ -1,4 +1,22 @@ +#ifndef TEST_LIB +#define TEST_LIB + #include "lib.h" #include "test-common.h" -void test_istreams(void); +void test_aqueue(void); +void test_array(void); +void test_base64(void); +void test_bsearch_insert_pos(void); +void test_buffer(void); +void test_istream(void); +void test_mempool_alloconly(void); +void test_network(void); +void test_primes(void); +void test_priorityq(void); +void test_seq_range_array(void); +void test_str_find(void); +void test_str_sanitize(void); +void test_utc_mktime(void); + +#endif diff --git a/src/lib/test-mempool-alloconly.c b/src/lib/test-mempool-alloconly.c new file mode 100644 index 0000000000..a03015e91c --- /dev/null +++ b/src/lib/test-mempool-alloconly.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" + +static bool mem_has_bytes(const void *mem, size_t size, uint8_t b) +{ + const uint8_t *bytes = mem; + unsigned int i; + + for (i = 0; i < size; i++) { + if (bytes[i] != b) + return FALSE; + } + return TRUE; +} + +void test_mempool_alloconly(void) +{ +#define PMALLOC_MAX_COUNT 128 + pool_t pool; + unsigned int i, j, k; + void *mem[PMALLOC_MAX_COUNT + 1]; + bool success = TRUE; + + for (i = 0; i < 64; i++) { + for (j = 1; j <= 128; j++) { + pool = pool_alloconly_create(MEMPOOL_GROWING"test", i); + mem[0] = p_malloc(pool, j); + memset(mem[0], j, j); + + for (k = 1; k <= PMALLOC_MAX_COUNT; k++) { + mem[k] = p_malloc(pool, k); + memset(mem[k], k, k); + } + + if (!mem_has_bytes(mem[0], j, j)) + success = FALSE; + for (k = 1; k <= PMALLOC_MAX_COUNT; k++) { + if (!mem_has_bytes(mem[k], k, k)) + success = FALSE; + } + pool_unref(&pool); + } + } + test_out("mempool_alloconly", success); +} diff --git a/src/lib/test-network.c b/src/lib/test-network.c new file mode 100644 index 0000000000..861b0d1d7a --- /dev/null +++ b/src/lib/test-network.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "network.h" + +struct test_net_is_in_network_input { + const char *ip; + const char *net; + unsigned int bits; + bool ret; +}; + +static void test_net_is_in_network(void) +{ + static struct test_net_is_in_network_input input[] = { + { "1.2.3.4", "1.2.3.4", 32, TRUE }, + { "1.2.3.4", "1.2.3.3", 32, FALSE }, + { "1.2.3.4", "1.2.3.5", 32, FALSE }, + { "1.2.3.4", "1.2.2.4", 32, FALSE }, + { "1.2.3.4", "1.1.3.4", 32, FALSE }, + { "1.2.3.4", "0.2.3.4", 32, FALSE }, + { "1.2.3.253", "1.2.3.254", 31, FALSE }, + { "1.2.3.254", "1.2.3.254", 31, TRUE }, + { "1.2.3.255", "1.2.3.254", 31, TRUE }, + { "1.2.3.255", "1.2.3.0", 24, TRUE }, + { "1.2.255.255", "1.2.254.0", 23, TRUE }, + { "255.255.255.255", "128.0.0.0", 1, TRUE }, + { "255.255.255.255", "127.0.0.0", 1, FALSE } +#ifdef HAVE_IPV6 + , + { "1234:5678::abcf", "1234:5678::abce", 127, TRUE }, + { "1234:5678::abcd", "1234:5678::abce", 127, FALSE }, + { "123e::ffff", "123e::0", 15, TRUE }, + { "123d::ffff", "123e::0", 15, FALSE } +#endif + }; + struct ip_addr ip, net_ip; + unsigned int i; + bool success; + + for (i = 0; i < N_ELEMENTS(input); i++) { + net_addr2ip(input[i].ip, &ip); + net_addr2ip(input[i].net, &net_ip); + success = net_is_in_network(&ip, &net_ip, input[i].bits) == + input[i].ret; + test_out(t_strdup_printf("net_is_in_network(%u)", i), success); + } +} + +void test_network(void) +{ + test_net_is_in_network(); +} diff --git a/src/lib/test-primes.c b/src/lib/test-primes.c new file mode 100644 index 0000000000..e4c05a12ff --- /dev/null +++ b/src/lib/test-primes.c @@ -0,0 +1,24 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "primes.h" + +void test_primes(void) +{ + unsigned int i, j, num; + bool success; + + success = primes_closest(0) > 0; + for (num = 1; num < 1024; num++) { + if (primes_closest(num) < num) + success = FALSE; + } + for (i = 10; i < 32; i++) { + num = (1 << i) - 100; + for (j = 0; j < 200; j++, num++) { + if (primes_closest(num) < num) + success = FALSE; + } + } + test_out("primes_closest()", success); +} diff --git a/src/lib/test-priorityq.c b/src/lib/test-priorityq.c new file mode 100644 index 0000000000..686b7acad4 --- /dev/null +++ b/src/lib/test-priorityq.c @@ -0,0 +1,101 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "priorityq.h" + +#include + +struct pq_test_item { + struct priorityq_item item; + int num; +}; + +static int cmp_int(const void *p1, const void *p2) +{ + const struct pq_test_item *i1 = p1, *i2 = p2; + + return i1->num - i2->num; +} + +void test_priorityq(void) +{ +#define PQ_MAX_ITEMS 100 + static const int input[] = { + 1, 2, 3, 4, 5, 6, 7, 8, -1, + 8, 7, 6, 5, 4, 3, 2, 1, -1, + 8, 7, 5, 6, 1, 3, 4, 2, -1, + -1 + }; + static const int output[] = { + 1, 2, 3, 4, 5, 6, 7, 8 + }; + struct pq_test_item *item, items[PQ_MAX_ITEMS]; + unsigned int i, j; + struct priorityq *pq; + pool_t pool; + int prev; + bool success = TRUE; + + pool = pool_alloconly_create("priorityq items", 1024); + + /* simple tests with popping only */ + for (i = 0; input[i] != -1; i++) { + p_clear(pool); + pq = priorityq_init(cmp_int, 1); + for (j = 0; input[i] != -1; i++, j++) { + if (priorityq_count(pq) != j) + success = FALSE; + item = p_new(pool, struct pq_test_item, 1); + item->num = input[i]; + priorityq_add(pq, &item->item); + } + for (j = 0; j < N_ELEMENTS(output); j++) { + if (priorityq_count(pq) != N_ELEMENTS(output) - j) + success = FALSE; + + item = (struct pq_test_item *)priorityq_peek(pq); + if (output[j] != item->num) + success = FALSE; + item = (struct pq_test_item *)priorityq_pop(pq); + if (output[j] != item->num) + success = FALSE; + } + if (priorityq_count(pq) != 0) + success = FALSE; + if (priorityq_peek(pq) != NULL || priorityq_pop(pq) != NULL) + success = FALSE; + priorityq_deinit(&pq); + } + test_out("priorityq(1)", success); + + /* randomized tests, remove elements */ + success = TRUE; + for (i = 0; i < 100; i++) { + pq = priorityq_init(cmp_int, 1); + for (j = 0; j < PQ_MAX_ITEMS; j++) { + items[j].num = rand(); + priorityq_add(pq, &items[j].item); + } + for (j = 0; j < PQ_MAX_ITEMS; j++) { + if (rand() % 3 == 0) { + priorityq_remove(pq, &items[j].item); + items[j].num = -1; + } + } + prev = 0; + while (priorityq_count(pq) > 0) { + item = (struct pq_test_item *)priorityq_pop(pq); + if (item->num < 0 || prev > item->num) + success = FALSE; + prev = item->num; + item->num = -1; + } + for (j = 0; j < PQ_MAX_ITEMS; j++) { + if (items[j].num != -1) + success = FALSE; + } + priorityq_deinit(&pq); + } + test_out("priorityq(2)", success); + pool_unref(&pool); +} diff --git a/src/lib/test-seq-range-array.c b/src/lib/test-seq-range-array.c new file mode 100644 index 0000000000..a6a022a57a --- /dev/null +++ b/src/lib/test-seq-range-array.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "array.h" +#include "seq-range-array.h" + +#include + +static void test_seq_range_array_random(void) +{ +#define SEQ_RANGE_TEST_BUFSIZE 20 +#define SEQ_RANGE_TEST_COUNT 10000 + unsigned char shadowbuf[SEQ_RANGE_TEST_BUFSIZE]; + ARRAY_TYPE(seq_range) range; + const struct seq_range *seqs; + uint32_t seq1, seq2; + unsigned int i, j, ret, ret2, count; + int test = -1; + + ret = ret2 = 0; + i_array_init(&range, 1); + memset(shadowbuf, 0, sizeof(shadowbuf)); + for (i = 0; i < SEQ_RANGE_TEST_COUNT; i++) { + seq1 = rand() % SEQ_RANGE_TEST_BUFSIZE; + seq2 = seq1 + rand() % (SEQ_RANGE_TEST_BUFSIZE - seq1); + test = rand() % 4; + switch (test) { + case 0: + seq_range_array_add(&range, 0, seq1); + shadowbuf[seq1] = 1; + break; + case 1: + seq_range_array_add_range(&range, seq1, seq2); + memset(shadowbuf + seq1, 1, seq2 - seq1 + 1); + break; + case 2: + ret = seq_range_array_remove(&range, seq1) ? 1 : 0; + ret2 = shadowbuf[seq1] != 0 ? 1 : 0; + shadowbuf[seq1] = 0; + break; + case 3: + ret = seq_range_array_remove_range(&range, seq1, seq2); + for (ret2 = 0; seq1 <= seq2; seq1++) { + if (shadowbuf[seq1] != 0) { + ret2++; + shadowbuf[seq1] = 0; + } + } + break; + } + if (ret != ret2) + break; + + seqs = array_get(&range, &count); + for (j = 0, seq1 = 0; j < count; j++) { + if (j > 0 && seqs[j-1].seq2 >= seqs[j].seq1) + goto fail; + for (; seq1 < seqs[j].seq1; seq1++) { + if (shadowbuf[seq1] != 0) + goto fail; + } + for (; seq1 <= seqs[j].seq2; seq1++) { + if (shadowbuf[seq1] == 0) + goto fail; + } + } + i_assert(seq1 <= SEQ_RANGE_TEST_BUFSIZE); + for (; seq1 < SEQ_RANGE_TEST_BUFSIZE; seq1++) { + if (shadowbuf[seq1] != 0) + goto fail; + } + } +fail: + if (i == SEQ_RANGE_TEST_COUNT) + test_out("seq_range_array random", TRUE); + else { + test_out_reason("seq_range_array random", FALSE, + t_strdup_printf("round %u test %d failed", i, test)); + } +} + +static void test_seq_range_array_invert(void) +{ + static const unsigned int input_min = 1, input_max = 5; + static const unsigned int input[] = { + 1, 2, 3, 4, 5, -1U, + 2, 3, 4, -1U, + 1, 2, 4, 5, -1U, + 1, 3, 5, -1U, + 1, -1U, + 5, -1U, + -1U + }; + ARRAY_TYPE(seq_range) range = ARRAY_INIT; + unsigned int i, j, seq, start, num; + bool old_exists, success; + + for (i = num = 0; input[i] != -1U; num++, i++) { + success = TRUE; + start = i; + for (; input[i] != -1U; i++) { + seq_range_array_add(&range, 32, input[i]); + for (j = start; j < i; j++) { + if (!seq_range_exists(&range, input[j])) + success = FALSE; + } + } + + seq_range_array_invert(&range, input_min, input_max); + for (seq = input_min; seq <= input_max; seq++) { + for (j = start; input[j] != -1U; j++) { + if (input[j] == seq) + break; + } + old_exists = input[j] != -1U; + if (seq_range_exists(&range, seq) == old_exists) + success = FALSE; + } + test_out(t_strdup_printf("seq_range_array_invert(%u)", num), + success); + array_free(&range); + } +} + +static void test_seq_range_create(ARRAY_TYPE(seq_range) *array, uint8_t byte) +{ + unsigned int i; + + array_clear(array); + for (i = 0; i < 8; i++) { + if ((byte & (1 << i)) != 0) + seq_range_array_add(array, 0, i + 1); + } +} + +static void test_seq_range_array_have_common(void) +{ + ARRAY_TYPE(seq_range) arr1, arr2; + unsigned int i, j; + bool ret1, ret2, success = TRUE; + + t_array_init(&arr1, 8); + t_array_init(&arr2, 8); + for (i = 0; i < 256; i++) { + test_seq_range_create(&arr1, i); + for (j = 0; j < 256; j++) { + test_seq_range_create(&arr2, j); + ret1 = seq_range_array_have_common(&arr1, &arr2); + ret2 = (i & j) != 0; + if (ret1 != ret2) + success = FALSE; + } + } + test_out("seq_range_array_have_common()", success); +} + +void test_seq_range_array(void) +{ + test_seq_range_array_invert(); + test_seq_range_array_have_common(); + test_seq_range_array_random(); +} diff --git a/src/lib/test-str-find.c b/src/lib/test-str-find.c new file mode 100644 index 0000000000..d3247d284d --- /dev/null +++ b/src/lib/test-str-find.c @@ -0,0 +1,85 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str-find.h" + +static const char *str_find_text = "xababcd"; + +static bool test_str_find_substring(const char *key, int expected_pos) +{ + const unsigned char *text = (const unsigned char *)str_find_text; + const unsigned int text_len = strlen(str_find_text); + struct str_find_context *ctx; + unsigned int i, j, pos, max, offset; + bool ret; + + ctx = str_find_init(pool_datastack_create(), key); + /* divide text into every possible block combination and test that + it matches */ + max = 1 << (text_len-1); + for (i = 0; i < max; i++) { + str_find_reset(ctx); + pos = 0; offset = 0; ret = FALSE; + for (j = 0; j < text_len; j++) { + if ((i & (1 << j)) != 0) { + if (str_find_more(ctx, text+pos, j-pos+1)) { + ret = TRUE; + break; + } + offset += j-pos + 1; + pos = j + 1; + } + } + if (pos != text_len && !ret) { + if (str_find_more(ctx, text+pos, j-pos)) + ret = TRUE; + } + if (expected_pos < 0) { + if (ret) + return FALSE; + } else { + if (!ret) + return FALSE; + + pos = str_find_get_match_end_pos(ctx) + + offset - strlen(key); + if ((int)pos != expected_pos) + return FALSE; + } + } + return TRUE; +} + +struct str_find_input { + const char *str; + int pos; +}; + +void test_str_find(void) +{ + static const char *fail_input[] = { + "xabc", + "xabd", + "abd" + }; + unsigned int idx, len; + const char *key, *p; + unsigned int i; + bool success = TRUE; + + for (idx = 0; idx < strlen(str_find_text); idx++) { + for (len = strlen(str_find_text)-idx; len > 0; len--) { + /* we'll get a search key for all substrings of text */ + T_BEGIN { + key = t_strndup(str_find_text + idx, len); + p = strstr(str_find_text, key); + success = test_str_find_substring(key, p - str_find_text); + } T_END; + if (!success) + break; + } + } + for (i = 0; i < N_ELEMENTS(fail_input) && success; i++) + success = test_str_find_substring(fail_input[i], -1); + test_out("str_find()", success); +} diff --git a/src/lib/test-str-sanitize.c b/src/lib/test-str-sanitize.c new file mode 100644 index 0000000000..8a5033ca4a --- /dev/null +++ b/src/lib/test-str-sanitize.c @@ -0,0 +1,40 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str-sanitize.h" + +struct str_sanitize_input { + const char *str; + unsigned int max_len; +}; + +void test_str_sanitize(void) +{ + static struct str_sanitize_input input[] = { + { NULL, 2 }, + { "", 2 }, + { "a", 2 }, + { "ab", 2 }, + { "abc", 2 }, + { "abcd", 3 }, + { "abcde", 4 } + }; + static const char *output[] = { + NULL, + "", + "a", + "ab", + "...", + "...", + "a..." + }; + const char *str; + unsigned int i; + bool success; + + for (i = 0; i < N_ELEMENTS(input); i++) { + str = str_sanitize(input[i].str, input[i].max_len); + success = null_strcmp(output[i], str) == 0; + test_out(t_strdup_printf("str_sanitize(%d)", i), success); + } +} diff --git a/src/lib/test-utc-mktime.c b/src/lib/test-utc-mktime.c new file mode 100644 index 0000000000..f4aafc071f --- /dev/null +++ b/src/lib/test-utc-mktime.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "utc-mktime.h" + +struct test_utc_mktime_input { + int year, month, day, hour, min, sec; +}; + +void test_utc_mktime(void) +{ + static struct test_utc_mktime_input input[] = { +#ifdef TIME_T_SIGNED + { 1969, 12, 31, 23, 59, 59 }, + { 1901, 12, 13, 20, 45, 53 }, +#endif +#if (TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)) + { 2106, 2, 7, 6, 28, 15 }, +#endif + { 2007, 11, 7, 1, 7, 20 }, + { 1970, 1, 1, 0, 0, 0 }, + { 2038, 1, 19, 3, 14, 7 } + }; + static time_t output[] = { +#ifdef TIME_T_SIGNED + -1, + -2147483647, +#endif +#if (TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)) + 4294967295, +#endif + 1194397640, + 0, + 2147483647 + }; + struct tm tm; + unsigned int i; + time_t t; + bool success; + + for (i = 0; i < N_ELEMENTS(input); i++) { + memset(&tm, 0, sizeof(tm)); + tm.tm_year = input[i].year - 1900; + tm.tm_mon = input[i].month - 1; + tm.tm_mday = input[i].day; + tm.tm_hour = input[i].hour; + tm.tm_min = input[i].min; + tm.tm_sec = input[i].sec; + + t = utc_mktime(&tm); + success = t == output[i]; + test_out_reason(t_strdup_printf("utc_mktime(%d)", i), success, + success ? NULL : t_strdup_printf("%ld != %ld", + (long)t, (long)output[i])); + } +} -- 2.47.3