static void test_var_expand_builtin(void) { static struct var_expand_test tests[] = { { "%{hostname}", NULL, 1 }, { "%{pid}", NULL, 1 }, { "a%{env:FOO}b", "abaRb", 1 }, { "%50Hv", "1f", 1 }, { "%50Hw", "2e", 1 }, { "%50Nv", "25", 1 }, { "%50Nw", "e", 1 }, { "%{nonexistent}", "UNSUPPORTED_VARIABLE_nonexistent", 0 }, { "%{nonexistent:default}", "UNSUPPORTED_VARIABLE_nonexistent", 0 }, }; static const struct var_expand_table table[] = { { 'v', "value", NULL }, { 'w', "value2", NULL }, { '\0', NULL, NULL } }; string_t *str = t_str_new(128); const char *error; unsigned int i; tests[0].out = my_hostname; tests[1].out = my_pid; env_put("FOO=baR"); test_begin("var_expand - builtin"); for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); test_assert_idx(var_expand(str, tests[i].in, table, &error) == tests[i].ret, i); test_assert_idx(strcmp(tests[i].out, str_c(str)) == 0, i); } test_end(); }
static void test_rfc822_parse_content_param(void) { const char *input = "; key1=value1#$!%&'*+-.^_`{|}~" "; key2=\" \\\"(),/:;<=>?@[\\\\]\""; const struct { const char *key, *value; } output[] = { { "key1", "value1#$!%&'*+-.^_`{|}~" }, { "key2", " \"(),/:;<=>?@[\\]" } }; struct rfc822_parser_context parser; const char *key, *value; unsigned int i = 0; int ret; test_begin("rfc822 parse content param"); rfc822_parser_init(&parser, (const void *)input, strlen(input), NULL); while ((ret = rfc822_parse_content_param(&parser, &key, &value)) > 0 && i < N_ELEMENTS(output)) { test_assert_idx(strcmp(output[i].key, key) == 0, i); test_assert_idx(strcmp(output[i].value, value) == 0, i); i++; } test_assert(ret == 0); test_assert(i == N_ELEMENTS(output)); test_end(); }
void test_str_sanitize(void) { static struct str_sanitize_test tests[] = { { NULL, 2, NULL }, { "", 2, NULL }, { "a", 2, NULL }, { "ab", 2, NULL }, { "abc", 2, "..." }, { "abcd", 3, "..." }, { "abcde", 4, "a..." }, { "с", 10, NULL }, { "с", 1, NULL }, { "\001x\x1fy\x81", 10, "?x?y?" } }; const char *str; unsigned int i; test_begin("str_sanitize"); for (i = 0; i < N_ELEMENTS(tests); i++) { str = str_sanitize(tests[i].str, tests[i].max_len); if (tests[i].sanitized != NULL) test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i); else test_assert_idx(str == tests[i].str, i); } test_end(); }
static void test_rfc822_parse_quoted_string(void) { static const struct { const char *input, *output; int ret; } tests[] = { { "\"", "", -1 }, { "\"\"", "", 0 }, { "\"foo\"", "foo", 0 }, { "\"\"foo", "", 1 }, { "\"\"\"", "", 1 }, { "\"\\\"\"", "\"", 0 }, { "\"\\\\\"", "\\", 0 }, { "\"\\\\foo\\\\foo\\\\\"", "\\foo\\foo\\", 0 } }; struct rfc822_parser_context parser; string_t *str = t_str_new(64); unsigned int i = 0; test_begin("rfc822 parse quoted string"); for (i = 0; i < N_ELEMENTS(tests); i++) { rfc822_parser_init(&parser, (const void *)tests[i].input, strlen(tests[i].input), NULL); test_assert_idx(rfc822_parse_quoted_string(&parser, str) == tests[i].ret, i); test_assert_idx(tests[i].ret < 0 || strcmp(tests[i].output, str_c(str)) == 0, i); str_truncate(str, 0); } test_end(); }
static void test_charset_utf8_common(const char *input_charset) { struct { const char *input; const char *output; enum charset_result result; } tests[] = { { "p\xC3\xA4\xC3", "p\xC3\xA4", CHARSET_RET_INCOMPLETE_INPUT }, { "p\xC3\xA4\xC3""a", "p\xC3\xA4"UNICODE_REPLACEMENT_CHAR_UTF8"a", CHARSET_RET_INVALID_INPUT } }; string_t *src, *str = t_str_new(256); enum charset_result result; unsigned int i; for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); test_assert_idx(charset_to_utf8_str(input_charset, NULL, tests[i].input, str, &result) == 0, i); test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); test_assert_idx(result == tests[i].result, i); } /* check that E2BIG handling works. We assume that iconv() is called with 8192 byte buffer (tmpbuf[8192]) */ src = str_new(default_pool, 16384); for (i = 0; i < 8190; i++) str_append_c(src, 'a' + i % ('z'-'a'+1)); for (i = 0; i < 256; i++) { str_truncate(str, 0); str_append_c(src, 'A' + i % ('Z'-'A'+1)); test_assert_idx(charset_to_utf8_str(input_charset, NULL, str_c(src), str, &result) == 0, i); } str_free(&src); }
static void test_ostream_multiplex_stream_read(struct istream *is) { uint8_t cid; const unsigned char *data; size_t siz,dlen=0,pos=0; if (i_stream_read_more(is, &data, &siz)>0) { /* parse stream */ for(;pos<siz;) { if (dlen > 0) { if (dlen < N_ELEMENTS(msgs)) { test_assert_idx(memcmp(&data[pos], msgs[dlen], dlen)==0, channel_counter[data[0] % 2]); } channel_counter[data[0] % 2]++; pos += dlen; dlen = 0; } else if (dlen == 0) { cid = data[pos] % 2; test_assert_idx(data[pos] < 2, channel_counter[cid]); pos++; dlen = be32_to_cpu_unaligned(&data[pos]); pos += 4; test_assert(dlen > 0 && dlen < N_ELEMENTS(msgs)); } } i_stream_skip(is, siz); } if (channel_counter[0] > 100 && channel_counter[1] > 100) io_loop_stop(current_ioloop); }
static void test_var_get_key_range(void) { static const struct var_get_key_range_test tests[] = { { "", 0, 0 }, { "{", 1, 0 }, { "k", 0, 1 }, { "{key}", 1, 3 }, { "5.5Rk", 4, 1 }, { "5.5R{key}", 5, 3 }, { "{key", 1, 3 }, { "{if;%{if;%{value};eq;value;t;f};eq;t;t;f}", 1, 39 }, }; unsigned int i, idx, size; test_begin("var_get_key_range"); for (i = 0; i < N_ELEMENTS(tests); i++) { var_get_key_range(tests[i].in, &idx, &size); test_assert_idx(tests[i].idx == idx, i); test_assert_idx(tests[i].size == size, i); if (tests[i].size == 1) test_assert_idx(tests[i].in[idx] == var_get_key(tests[i].in), i); } test_end(); }
static void test_rfc822_parse_domain_literal(void) { static const struct { const char *input, *output; int ret; } tests[] = { { "@[", "", -1 }, { "@[foo", "", -1 }, { "@[foo[]", "", -1 }, { "@[foo[]]", "", -1 }, { "@[]", "[]", 0 }, { "@[foo bar]", "[foo bar]", 0 }, { "@[foo\n bar]", "[foo bar]", 0 }, { "@[foo\n\t\t bar]", "[foo\t\t bar]", 0 }, { "@[foo\\\n bar]", "[foo\\ bar]", 0 }, }; struct rfc822_parser_context parser; string_t *str = t_str_new(64); unsigned int i = 0; test_begin("rfc822 parse domain literal"); for (i = 0; i < N_ELEMENTS(tests); i++) { rfc822_parser_init(&parser, (const void *)tests[i].input, strlen(tests[i].input), NULL); test_assert_idx(rfc822_parse_domain(&parser, str) == tests[i].ret, i); test_assert_idx(tests[i].ret < 0 || strcmp(tests[i].output, str_c(str)) == 0, i); rfc822_parser_deinit(&parser); str_truncate(str, 0); } test_end(); }
static void test_server_read_nofd(struct istream *input, unsigned int idx) { const unsigned char *data; size_t size; test_assert_idx(i_stream_read_data(input, &data, &size, 0) == 1, idx); i_stream_skip(input, 1); test_assert_idx(i_stream_unix_get_read_fd(input) == -1, idx); }
void test_str_sanitize(void) { static struct str_sanitize_test tests[] = { { NULL, 2, NULL }, { "", 2, NULL }, { "a", 2, NULL }, { "ab", 2, NULL }, { "abc", 2, "..." }, { "abcd", 3, "..." }, { "abcde", 4, "a..." }, { "\xD1\x81", 1, "..." }, { "\xD1\x81", 2, "\xD1\x81" }, { "\xD1\x81", 3, NULL }, { "\xC3\xA4\xC3\xA4zyxa", 1, "..." }, { "\xC3\xA4\xC3\xA4zyxa", 2, "..." }, { "\xC3\xA4\xC3\xA4zyxa", 3, "..." }, { "\xC3\xA4\xC3\xA4zyxa", 4, "..." }, { "\xC3\xA4\xC3\xA4zyxa", 5, "\xC3\xA4..." }, { "\xC3\xA4\xC3\xA4zyxa", 6, "\xC3\xA4..." }, { "\xC3\xA4\xC3\xA4zyxa", 7, "\xC3\xA4\xC3\xA4..." }, { "\xC3\xA4\xC3\xA4zyxa", 8, "\xC3\xA4\xC3\xA4zyxa" }, { "\001x\x1fy\x81", 10, "?x?y?" } }; const char *str; string_t *str2; unsigned int i; test_begin("str_sanitize"); for (i = 0; i < N_ELEMENTS(tests); i++) { str = str_sanitize(tests[i].str, tests[i].max_len); if (tests[i].sanitized != NULL) test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i); else test_assert_idx(str == tests[i].str, i); } test_end(); test_begin("str_sanitize_append"); str2 = t_str_new(128); for (i = 0; i < N_ELEMENTS(tests); i++) { if (tests[i].str == NULL) continue; str_truncate(str2, 0); str_append(str2, "1234567890"); str_sanitize_append(str2, tests[i].str, tests[i].max_len); test_assert_idx(strncmp(str_c(str2), "1234567890", 10) == 0, i); if (tests[i].sanitized != NULL) test_assert_idx(strcmp(str_c(str2)+10, tests[i].sanitized) == 0, i); else test_assert_idx(strcmp(str_c(str2)+10, tests[i].str) == 0, i); } test_end(); }
static void test_fts_filter_english_possessive(void) { struct fts_filter *norm = NULL; const char *input[] = { "foo'", "foo's", "foo\xC3\xA4's", "foo'S", "foos'S", "foo's's", "foo'ss", "foo\xE2\x80\x99s", "foo\xC3\xA4\xE2\x80\x99s", "foo\xE2\x80\x99S", "foos\xE2\x80\x99S", "foo\xE2\x80\x99s\xE2\x80\x99s", "foo\xE2\x80\x99ss" }; const char *expected_output[] = { "foo'", "foo", "foo\xC3\xA4", "foo", "foos", "foo's", "foo'ss", "foo", "foo\xC3\xA4", "foo", "foos", "foo\xE2\x80\x99s", "foo\xE2\x80\x99ss" }; const char *error = NULL; const char *token = NULL; unsigned int i; test_begin("fts filter english possessive"); test_assert(fts_filter_create(fts_filter_english_possessive, NULL, NULL, NULL, &norm, &error) == 0); for (i = 0; i < N_ELEMENTS(input); i++) { token = input[i]; test_assert_idx(fts_filter_filter(norm, &token, &error) == 1, i); test_assert_idx(null_strcmp(token, expected_output[i]) == 0, i); } fts_filter_unref(&norm); test_assert(norm == NULL); test_end(); }
static void test_write_read_v2(void) { test_begin("test_write_read_v2"); unsigned char payload[IO_BLOCK_SIZE*10]; const unsigned char *ptr; size_t pos = 0, siz; random_fill_weak(payload, IO_BLOCK_SIZE*10); buffer_t *buf = buffer_create_dynamic(default_pool, sizeof(payload)); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "aes-256-gcm-sha256", test_v1_kp.pub, IO_STREAM_ENC_INTEGRITY_AEAD); o_stream_nsend(os_2, payload, sizeof(payload)); test_assert(o_stream_nfinish(os_2) == 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); /* test regression where read fails due to incorrect behaviour when buffer is full before going to decrypt code */ i_stream_set_max_buffer_size(is, 8192); i_stream_read(is); struct istream *is_2 = i_stream_create_decrypt(is, test_v1_kp.priv); size_t offset = 0; test_istream_set_size(is, 0); test_istream_set_allow_eof(is, FALSE); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); }
static void test_load_v2_key(void) { const char *keys[] = { "-----BEGIN PRIVATE KEY-----\n" \ "MGcCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcETTBLAgEBBCC25AkD65uhlZXCAdwN\n" \ "yLJV2ui8A/CUyqyEMrezvwgMO6EkAyIAAybRUR3MsH0+0PQcDwkrXOJ9aePwzTQV\n" \ "DN51+n1JCxbI\n" \ "-----END PRIVATE KEY-----\n", "2\t1.2.840.10045.3.1.7\t0\t0000002100b6e40903eb9ba19595c201dc0dc8b255dae8bc03f094caac8432b7b3bf080c3b\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", "2\t1.2.840.10045.3.1.7\t2\taes-256-ctr\t2b19763d4bbf7754\tsha256\t2048\tc36fa194669a1aec400eae32fbadaa7c58b14f53c464cfbb0a4b61fbe24ab7750637c4025d\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd", "2\t1.2.840.10045.3.1.7\t1\taes-256-ctr\t7c7f1d12a7c011de\tsha256\t2048\tf5d1de11d58a81b141cf038012a618623e9d7b18062deeb3a4e35872c62ca0837db8688370\t021abfbc5bc4f6cf49c40b9fc388c4616ea079941675f477ee4557df1919626d35\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd\tab13d251976dedab546b67354e7678821740dd534b749c2857f66bf62bbaddfd" }; test_begin("test_load_v2_key"); const char *error = NULL; buffer_t *tmp = buffer_create_dynamic(default_pool, 256); struct dcrypt_private_key *priv,*priv2; test_assert_idx(dcrypt_key_load_private(&priv2, DCRYPT_FORMAT_PEM, keys[0], NULL, NULL, &error), 0); test_assert_idx(dcrypt_key_store_private(priv2, DCRYPT_FORMAT_PEM, NULL, tmp, NULL, NULL, &error), 0); test_assert_idx(strcmp(str_c(tmp), keys[0])==0, 0); buffer_set_used_size(tmp, 0); test_assert_idx(dcrypt_key_load_private(&priv, DCRYPT_FORMAT_DOVECOT, keys[1], NULL, NULL, &error), 1); test_assert_idx(dcrypt_key_store_private(priv, DCRYPT_FORMAT_DOVECOT, NULL, tmp, NULL, NULL, &error), 1); test_assert_idx(strcmp(str_c(tmp), keys[1])==0, 1); buffer_set_used_size(tmp, 0); dcrypt_key_free_private(&priv); test_assert_idx(dcrypt_key_load_private(&priv, DCRYPT_FORMAT_DOVECOT, keys[2], "This Is Sparta", NULL, &error), 2); test_assert_idx(dcrypt_key_store_private(priv, DCRYPT_FORMAT_DOVECOT, "aes-256-ctr", tmp, "This Is Sparta", NULL, &error), 2); buffer_set_used_size(tmp, 0); dcrypt_key_free_private(&priv); struct dcrypt_public_key *pub = NULL; dcrypt_key_convert_private_to_public(priv2, &pub); test_assert_idx(dcrypt_key_load_private(&priv, DCRYPT_FORMAT_DOVECOT, keys[3], NULL, priv2, &error), 3); test_assert_idx(dcrypt_key_store_private(priv, DCRYPT_FORMAT_DOVECOT, "ecdh-aes-256-ctr", tmp, NULL, pub, &error), 3); buffer_set_used_size(tmp, 0); dcrypt_key_free_private(&priv2); dcrypt_key_free_private(&priv); dcrypt_key_free_public(&pub); buffer_free(&tmp); if (error != NULL) error = NULL; test_end(); }
static void test_write_read_v1_short(void) { test_begin("test_write_read_v1_short"); unsigned char payload[1]; const unsigned char *ptr; size_t pos = 0, siz; random_fill_weak(payload, 1); buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v2_kp.pub, IO_STREAM_ENC_VERSION_1); o_stream_nsend(os_2, payload, sizeof(payload)); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); test_assert(os_2->stream_errno == 0); test_assert(o_stream_nfinish(os_2) == 0); test_assert(os_2->stream_errno == 0); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, test_v2_kp.priv); size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); }
static void test_mail_html2text(void) { string_t *str = t_str_new(128); struct mail_html2text *ht; unsigned int i, j; test_begin("mail_html2text()"); for (i = 0; i < N_ELEMENTS(tests); i++) { ht = mail_html2text_init(MAIL_HTML2TEXT_FLAG_SKIP_QUOTED); for (j = 0; tests[i].input[j] != '\0'; j++) { unsigned char c = tests[i].input[j]; mail_html2text_more(ht, &c, 1, str); } test_assert_idx(strcmp(str_c(str), tests[i].output) == 0, i); mail_html2text_deinit(&ht); str_truncate(str, 0); } /* test without skipping quoted */ ht = mail_html2text_init(0); mail_html2text_more(ht, (const void *)test_blockquote_input, strlen(test_blockquote_input), str); test_assert(strcmp(str_c(str), test_blockquote_output) == 0); mail_html2text_deinit(&ht); test_end(); }
static void test_message_snippet(void) { string_t *str = t_str_new(128); struct istream *input; unsigned int i; test_begin("message snippet"); for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); input = i_stream_create_from_data(tests[i].input, strlen(tests[i].input)); test_assert_idx(message_snippet_generate(input, tests[i].max_snippet_chars, str) == 0, i); test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); i_stream_destroy(&input); } test_end(); }
static void test_fts_filter_lowercase(void) { struct { const char *input; const char *output; } tests[] = { { "foo", "foo" }, { "FOO", "foo" }, { "fOo", "foo" } }; struct fts_filter *filter; const char *error; const char *token; unsigned int i; test_begin("fts filter lowercase"); test_assert(fts_filter_create(fts_filter_lowercase, NULL, &english_language, NULL, &filter, &error) == 0); for (i = 0; i < N_ELEMENTS(tests); i++) { token = tests[i].input; test_assert_idx(fts_filter_filter(filter, &token, &error) > 0 && strcmp(token, tests[i].output) == 0, 0); } fts_filter_unref(&filter); test_end(); }
static void test_fts_filter_contractions_fr(void) { struct { const char *input; const char *output; } tests[] = { { "foo", "foo" }, { "you're", "you're" }, { "l'homme", "homme" }, { "l\xE2\x80\x99homme", "homme" }, { "aujourd'hui", "aujourd'hui" }, { "qu\xE2\x80\x99il", "il" }, { "qu'il", "il" }, { "du'il", "du'il" }, { "que", "que" }, { "'foobar'", "'foobar'" }, { "foo'bar", "foo'bar" }, { "a'foo", "a'foo" }, { "cu'", "cu'" }, { "qu", "qu" }, { "d", "d" }, { "qu'", NULL }, { "j'adore", "adore" }, { "quelqu'un", "quelqu'un" }, { "l'esprit", "esprit" } }; struct fts_filter *filter; const char *error; const char *token; unsigned int i; int ret; test_begin("fts filter contractions, French"); test_assert(fts_filter_create(fts_filter_contractions, NULL, &french_language, NULL, &filter, &error) == 0); for (i = 0; i < N_ELEMENTS(tests); i++) { token = tests[i].input; ret = fts_filter_filter(filter, &token, &error); test_assert(ret >= 0); if (ret > 0) test_assert_idx(strcmp(token, tests[i].output) == 0, i); else if (ret == 0) test_assert_idx(token == NULL && tests[i].output == NULL, i); } fts_filter_unref(&filter); test_end(); }
static void test_str_truncate(void) { string_t *str = t_str_new(8); int i; test_begin("str_truncate()"); str_append(str, "123456"); for (i = 100; i >= 6; i--) { str_truncate(str, i); test_assert_idx(str_len(str) == 6, i); } for (; i >= 0; i--) { str_truncate(str, i); test_assert_idx(str_len(str) == (unsigned int)i, i); } test_end(); }
void test_json_tree(void) { struct json_tree *tree; struct json_tree_node *root, *node, *node1, *node2; unsigned int i; test_begin("json tree"); tree = json_tree_init(); for (i = 0; i < N_ELEMENTS(test_input); i++) { test_assert_idx(json_tree_append(tree, test_input[i].type, test_input[i].value) == 0, i); } root = json_tree_root(tree); i_assert(root != NULL); test_assert(root->value_type == JSON_TYPE_OBJECT); root = root->value.child; i_assert(root != NULL); for (i = 0; i < 10+2; i += 2) { node = json_tree_find_key(root, test_input[i].value); test_assert(node != NULL && node->value_type == test_input[i+1].type && null_strcmp(node->value.str, test_input[i+1].value) == 0); } node = json_tree_find_key(root, "key-obj"); test_assert(node != NULL); node = json_tree_find_key(root, "key-arr-empty"); test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY && node->value.child == NULL); node = json_tree_find_key(root, "key-arr"); test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY); node = node->value.child; test_assert(node != NULL && node->value_type == JSON_TYPE_STRING && strcmp(node->value.str, "foo") == 0); node = node->next; test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY && node->value.child != NULL && node->value.child->next == NULL && node->value.child->value_type == JSON_TYPE_TRUE); node = node->next; test_assert(node != NULL && node->value_type == JSON_TYPE_OBJECT && node->value.child != NULL && node->value.child->next == NULL && node->value.child->value_type == JSON_TYPE_ARRAY && node->value.child->value.child == NULL); node1 = json_tree_find_child_with(node->parent, "aobj-key", "value1"); node2 = json_tree_find_child_with(node->parent, "aobj-key", "value2"); test_assert(node1 != NULL && node2 != NULL && node1 != node2); test_assert(json_tree_find_child_with(node->parent, "aobj-key", "value3") == NULL); json_tree_deinit(&tree); test_end(); }
static void test_server_read_fd(struct istream *input, int wanted_fd, unsigned int idx) { struct stat st1, st2; const unsigned char *data; size_t size; int recv_fd; test_assert_idx(i_stream_read_data(input, &data, &size, 0) == 1, idx); i_stream_skip(input, 1); test_assert_idx((recv_fd = i_stream_unix_get_read_fd(input)) != -1, idx); if (recv_fd != -1) { if (fstat(recv_fd, &st1) < 0 || fstat(wanted_fd, &st2) < 0) i_fatal("fstat() failed: %m"); test_assert_idx(st1.st_ino == st2.st_ino, idx); i_close_fd(&recv_fd); } }
static void test_rfc822_parse_comment(void) { static const struct { const char *input, *output; int ret; } tests[] = { { "(", "", -1 }, { "(()", "", -1 }, { "()", "", 0 }, { "(())", "()", 0 }, { "(foo ( bar ) baz)", "foo ( bar ) baz", 0 }, { "(foo\t\tbar)", "foo\t\tbar", 0 }, { "(foo\\(bar)", "foo(bar", 0 }, { "(foo\\\\bar)", "foo\\bar", 0 }, { "(foo\\\\\\\\)", "foo\\\\", 0 }, { "(foo\\)bar)", "foo)bar", 0 }, { "(foo\"flop\"\"bar)", "foo\"flop\"\"bar", 0 }, { "(foo\n bar)", "foo bar", 0 }, { "(foo\n\t\t bar)", "foo\t\t bar", 0 }, { "(foo\\\n bar)", "foo\\ bar", 0 }, { "(foo\\\r\n bar)", "foo\\ bar", 0 }, }; struct rfc822_parser_context parser, parser2; string_t *str = t_str_new(64); unsigned int i = 0; test_begin("rfc822 parse comment"); for (i = 0; i < N_ELEMENTS(tests); i++) { rfc822_parser_init(&parser, (const void *)tests[i].input, strlen(tests[i].input), str); rfc822_parser_init(&parser2, (const void *)tests[i].input, strlen(tests[i].input), NULL); test_assert_idx(rfc822_skip_comment(&parser) == tests[i].ret, i); test_assert_idx(rfc822_skip_comment(&parser2) == tests[i].ret, i); test_assert_idx(tests[i].ret < 0 || strcmp(tests[i].output, str_c(str)) == 0, i); rfc822_parser_deinit(&parser); rfc822_parser_deinit(&parser2); str_truncate(str, 0); } test_end(); }
static void test_travel_to_root(void) { int l = path_height(cwd); const char *npath = cwd; for (npath = cwd; l != 0; l--) { const char *error; test_assert_idx(t_normpath_to("../", npath, &npath, &error) == 0, l); } test_assert_strcmp(npath, "/"); }
void test_wildcard_match(void) { unsigned int i; test_begin("wildcard_match()"); for (i = 0; i < N_ELEMENTS(tests); i++) { test_assert_idx(wildcard_match(tests[i].data, tests[i].mask) == tests[i].result, i); } test_end(); }
void test_istream_failure_at(void) { struct istream *input, *data_input; unsigned char test_data[TEST_DATA_LENGTH]; unsigned int i; ssize_t ret; test_begin("istream failure at"); for (i = 0; i < sizeof(test_data); i++) test_data[i] = i; data_input = i_stream_create_from_data(test_data, sizeof(test_data)); for (i = 0; i < TEST_DATA_LENGTH; i++) { i_stream_seek(data_input, 0); input = i_stream_create_failure_at(data_input, i, EIO, TEST_ERRMSG); while ((ret = i_stream_read(input)) > 0) i_stream_skip(input, ret); test_assert_idx(ret == -1 && input->v_offset == i && input->stream_errno == EIO && strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i); i_stream_destroy(&input); } /* shouldn't fail */ i_stream_seek(data_input, 0); input = i_stream_create_failure_at(data_input, TEST_DATA_LENGTH, EIO, TEST_ERRMSG); while ((ret = i_stream_read(input)) > 0) i_stream_skip(input, ret); test_assert(ret == -1 && input->stream_errno == 0); i_stream_destroy(&input); /* fail at EOF */ i_stream_seek(data_input, 0); input = i_stream_create_failure_at_eof(data_input, EIO, TEST_ERRMSG); while ((ret = i_stream_read(input)) > 0) i_stream_skip(input, ret); test_assert_idx(ret == -1 && input->v_offset == TEST_DATA_LENGTH && input->stream_errno == EIO && strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i); i_stream_destroy(&input); i_stream_destroy(&data_input); test_end(); }
static void test_ds_buffers(void) { test_begin("data-stack buffer growth"); T_BEGIN { size_t i; unsigned char *p; size_t left = t_get_bytes_available(); while (left < 10000) { t_malloc_no0(left); /* force a new block */ left = t_get_bytes_available(); } left -= 64; /* make room for the sentry if DEBUG */ p = t_buffer_get(1); p[0] = 1; for (i = 2; i <= left; i++) { /* grow it */ unsigned char *p2 = t_buffer_get(i); test_assert_idx(p == p2, i); p[i-1] = i; test_assert_idx(p[i-2] == (unsigned char)(i-1), i); } /* now fix it permanently */ t_buffer_alloc_last_full(); test_assert(t_get_bytes_available() < 64 + MEM_ALIGN(1)); } T_END; test_end(); test_begin("data-stack buffer interruption"); T_BEGIN { void *b = t_buffer_get(1000); void *a = t_malloc_no0(1); void *b2 = t_buffer_get(1001); test_assert(a == b); /* expected, not guaranteed */ test_assert(b2 != b); } T_END; test_end(); test_begin("data-stack buffer with reallocs"); T_BEGIN { size_t bigleft = t_get_bytes_available(); size_t i; for (i = 1; i < bigleft-64; i += i_rand()%32) T_BEGIN { unsigned char *p, *p2; size_t left; t_malloc_no0(i); left = t_get_bytes_available(); /* The most useful idx for the assert is 'left' */ test_assert_idx(left <= bigleft-i, left); p = t_buffer_get(left/2); p[0] = 'Z'; p[left/2 - 1] = 'Z'; p2 = t_buffer_get(left + left/2); test_assert_idx(p != p2, left); test_assert_idx(p[0] == 'Z', left); test_assert_idx(p[left/2 -1] == 'Z', left); } T_END; } T_END; test_end(); }
static void test_ds_recurse(int depth, int number, size_t size) { int i; char **ps; char tag[2] = { depth+1, '\0' }; int try_fails = 0; data_stack_frame_t t_id = t_push_named("test_ds_recurse[%i]", depth); ps = t_buffer_get(sizeof(char *) * number); i_assert(ps != NULL); t_buffer_alloc(sizeof(char *) * number); for (i = 0; i < number; i++) { ps[i] = t_malloc_no0(size/2); bool re = t_try_realloc(ps[i], size); i_assert(ps[i] != NULL); if (!re) { try_fails++; ps[i] = t_malloc_no0(size); } /* drop our own canaries */ memset(ps[i], tag[0], size); ps[i][size-2] = 0; } /* Do not expect a high failure rate from t_try_realloc */ test_assert_idx(try_fails <= number / 20, depth); /* Now recurse... */ if(depth>0) test_ds_recurse(depth-1, number, size); /* Test our canaries are still intact */ for (i = 0; i < number; i++) { test_assert_idx(strspn(ps[i], tag) == size - 2, i); test_assert_idx(ps[i][size-1] == tag[0], i); } test_assert_idx(t_pop(&t_id), depth); }
static void test_ds_realloc() { test_begin("data-stack realloc"); T_BEGIN { size_t i; unsigned char *p; size_t left = t_get_bytes_available(); while (left < 10000) { t_malloc_no0(left); /* force a new block */ left = t_get_bytes_available(); } left -= 64; /* make room for the sentry if DEBUG */ p = t_malloc_no0(1); p[0] = 1; for (i = 2; i <= left; i++) { /* grow it */ test_assert_idx(t_try_realloc(p, i), i); p[i-1] = i; test_assert_idx(p[i-2] == (unsigned char)(i-1), i); } test_assert(t_get_bytes_available() < 64 + MEM_ALIGN(1)); } T_END; test_end(); }
static void test_mail_search_args_simplify(void) { struct mail_search_args *args; string_t *str = t_str_new(256); const char *error; unsigned int i; test_begin("mail search args simplify"); for (i = 0; i < N_ELEMENTS(tests); i++) { args = test_build_search_args(tests[i].input); mail_search_args_simplify(args); str_truncate(str, 0); test_assert(mail_search_args_to_imap(str, args->args, &error)); test_assert_idx(strcmp(str_c(str), tests[i].output) == 0, i); mail_search_args_unref(&args); } test_end(); }
static void test_charset_iconv(void) { struct { const char *charset; const char *input; const char *output; enum charset_result result; } tests[] = { { "ISO-8859-1", "p\xE4\xE4", "p\xC3\xA4\xC3\xA4", CHARSET_RET_OK }, { "UTF-7", "+AOQA5AD2AOQA9gDkAPYA5AD2AOQA9gDkAPYA5AD2AOQA9gDkAPYA5AD2AOQA9gDkAPYA5AD2AOQA9gDkAPYA5AD2AOQA9gDk", "\xC3\xA4\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4" "\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4" "\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4" "\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4" "\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4", CHARSET_RET_OK } }; string_t *str = t_str_new(128); struct charset_translation *trans; enum charset_result result; size_t pos, left, limit, len; unsigned int i; test_begin("charset iconv"); for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); test_assert_idx(charset_to_utf8_str(tests[i].charset, NULL, tests[i].input, str, &result) == 0, i); test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); test_assert_idx(result == tests[i].result, i); str_truncate(str, 0); test_assert_idx(charset_to_utf8_begin(tests[i].charset, NULL, &trans) == 0, i); len = strlen(tests[i].input); for (pos = 0, limit = 1; limit <= len; pos += left, limit++) { left = limit - pos; result = charset_to_utf8(trans, (const void *)(tests[i].input + pos), &left, str); if (result != CHARSET_RET_INCOMPLETE_INPUT && result != CHARSET_RET_OK) break; } test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); test_assert_idx(result == tests[i].result, i); charset_to_utf8_end(&trans); } /* Use //IGNORE just to force handling to be done by iconv instead of our own UTF-8 routines. */ test_charset_utf8_common("UTF-8//IGNORE"); test_end(); }