Test external mail response parsing

This commit is contained in:
Mario Fetka
2026-07-16 16:14:57 +02:00
parent 754b7ccd50
commit 25dab09cff
4 changed files with 84 additions and 13 deletions
+12
View File
@@ -32,3 +32,15 @@ target_link_libraries(bongocollector
)
install(TARGETS bongocollector DESTINATION ${SBIN_INSTALL_DIR})
if(BUILD_TESTING)
add_executable(collector-transport-test
tests/external-transport-test.c
external_transport.c
)
target_include_directories(collector-transport-test PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(collector-transport-test ${CURL_LIBRARIES})
add_test(NAME collector-external-transport COMMAND collector-transport-test)
endif()
+26 -13
View File
@@ -97,12 +97,17 @@ AddId(CollectorRemoteIds *ids, const char *uid, size_t uid_length,
return 0;
}
static int
ParsePop3Ids(char *response, CollectorRemoteIds *ids)
int
CollectorRemoteParsePop3(const char *response, CollectorRemoteIds *ids)
{
char *copy;
char *line;
char *save = NULL;
for (line = strtok_r(response, "\r\n", &save); line != NULL;
int result = 0;
if (response == NULL || ids == NULL) return -1;
copy = strdup(response);
if (copy == NULL) return -1;
for (line = strtok_r(copy, "\r\n", &save); line != NULL;
line = strtok_r(NULL, "\r\n", &save)) {
char *number_end;
char *uid;
@@ -115,19 +120,26 @@ ParsePop3Ids(char *response, CollectorRemoteIds *ids)
uid = number_end;
while (isspace((unsigned char) *uid)) uid++;
if (*uid != '\0' && AddId(ids, uid, strcspn(uid, " \t"),
line, number_length) != 0) return -1;
line, number_length) != 0) {
result = -1;
break;
}
}
return 0;
free(copy);
return result;
}
static int
ParseImapIds(char *response, CollectorRemoteIds *ids)
int
CollectorRemoteParseImap(const char *response, CollectorRemoteIds *ids)
{
char *search = strstr(response, "SEARCH");
char *validity = strstr(response, "UIDVALIDITY");
char *token;
const char *search;
const char *validity;
const char *token;
if (response == NULL || ids == NULL) return -1;
search = strstr(response, "SEARCH");
validity = strstr(response, "UIDVALIDITY");
if (validity != NULL) {
char *end;
const char *end;
validity += strlen("UIDVALIDITY");
while (*validity != '\0' && !isdigit((unsigned char) *validity)) validity++;
end = validity;
@@ -140,7 +152,7 @@ ParseImapIds(char *response, CollectorRemoteIds *ids)
if (search == NULL) return 0;
token = search + strlen("SEARCH");
while (*token != '\0' && *token != '\r' && *token != '\n') {
char *end;
const char *end;
while (isspace((unsigned char) *token)) token++;
if (!isdigit((unsigned char) *token)) break;
end = token;
@@ -425,7 +437,8 @@ CollectorRemoteList(const CollectorExternalAccount *account,
if (response.data == NULL) goto done;
}
result = strcmp(account->inbound_protocol, "imap") == 0 ?
ParseImapIds(response.data, ids) : ParsePop3Ids(response.data, ids);
CollectorRemoteParseImap(response.data, ids) :
CollectorRemoteParsePop3(response.data, ids);
if (result != 0) {
CollectorRemoteIdsFree(ids);
SetError(error, error_size, "too many remote messages or insufficient memory");
@@ -29,4 +29,8 @@ int CollectorRemoteDelete(const CollectorExternalAccount *account,
char *error, size_t error_size);
void CollectorRemoteIdsFree(CollectorRemoteIds *ids);
/* Exposed for protocol parser tests and offline response validation. */
int CollectorRemoteParsePop3(const char *response, CollectorRemoteIds *ids);
int CollectorRemoteParseImap(const char *response, CollectorRemoteIds *ids);
#endif
@@ -0,0 +1,42 @@
#include <stdio.h>
#include <string.h>
#include "external_transport.h"
static int
CheckPop3(void)
{
CollectorRemoteIds ids = {0};
const char response[] = "+OK 2 messages\r\n1 alpha-uid\r\n2 beta-uid\r\n.\r\n";
int failed = CollectorRemoteParsePop3(response, &ids) != 0 ||
ids.count != 2 || strcmp(ids.items[0].locator, "1") != 0 ||
strcmp(ids.items[0].uid, "alpha-uid") != 0 ||
strcmp(ids.items[1].locator, "2") != 0 ||
strcmp(ids.items[1].uid, "beta-uid") != 0;
CollectorRemoteIdsFree(&ids);
return failed;
}
static int
CheckImap(void)
{
CollectorRemoteIds ids = {0};
const char response[] = "* OK [UIDVALIDITY 4242] valid\r\n* SEARCH 7 99 101\r\n";
int failed = CollectorRemoteParseImap(response, &ids) != 0 ||
strcmp(ids.uidvalidity, "4242") != 0 || ids.count != 3 ||
strcmp(ids.items[0].uid, "7") != 0 ||
strcmp(ids.items[1].uid, "99") != 0 ||
strcmp(ids.items[2].locator, "101") != 0;
CollectorRemoteIdsFree(&ids);
return failed;
}
int
main(void)
{
if (CheckPop3() || CheckImap()) {
fprintf(stderr, "external transport parser test failed\n");
return 1;
}
return 0;
}