Files
FastSync/tests/test_iconv.c
T

171 lines
5.3 KiB
C

#include "test_iconv.h"
#include "charset.h"
#include "protocol.h"
#include "test_utils.h"
#include "utils.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
/* --- CONVERT_SPEC parsing ------------------------------------------------ */
static void test_iconv_spec_parse_split() {
char* local = NULL;
char* remote = NULL;
EXPECT_EQ_INT(charset_spec_parse("utf-8,iso-8859-1", &local, &remote), 0);
EXPECT_EQ_STR(local, "utf-8");
EXPECT_EQ_STR(remote, "iso-8859-1");
free(local);
free(remote);
}
static void test_iconv_spec_parse_single_defaults_to_local() {
char* local = NULL;
char* remote = NULL;
EXPECT_EQ_INT(charset_spec_parse("utf-8", &local, &remote), 0);
EXPECT_EQ_STR(local, "utf-8");
EXPECT_EQ_STR(remote, "utf-8");
free(local);
free(remote);
}
static void test_iconv_spec_parse_garbage() {
char* local = NULL;
char* remote = NULL;
EXPECT_EQ_INT(charset_spec_parse(NULL, &local, &remote), -1);
EXPECT_EQ_INT(charset_spec_parse("", &local, &remote), -1);
EXPECT_EQ_INT(charset_spec_parse(",", &local, &remote), -1);
EXPECT_EQ_INT(charset_spec_parse("utf-8,", &local, &remote), -1);
EXPECT_EQ_INT(charset_spec_parse(",utf-8", &local, &remote), -1);
}
static void test_iconv_spec_valid() {
EXPECT_TRUE(charset_spec_valid(NULL));
EXPECT_TRUE(charset_spec_valid("utf-8"));
EXPECT_TRUE(charset_spec_valid("utf-8,iso-8859-1"));
EXPECT_TRUE(charset_spec_valid("iso-8859-1,ascii"));
EXPECT_FALSE(charset_spec_valid("no-such-charset,utf-8"));
EXPECT_FALSE(charset_spec_valid("utf-8,no-such-charset"));
EXPECT_FALSE(charset_spec_valid(",,,"));
EXPECT_FALSE(charset_spec_valid("utf-8,"));
}
/* --- one-shot conversion ------------------------------------------------ */
static void test_iconv_utf8_to_latin1() {
void* conv = charset_conversion_open("utf-8", "iso-8859-1");
EXPECT_NOT_NULL(conv);
char* out = charset_convert(conv, "caf\xc3\xa9", NULL);
EXPECT_NOT_NULL(out);
EXPECT_EQ_INT(strcmp(out, "caf\xe9"), 0);
free(out);
charset_conversion_close(conv);
}
static void test_iconv_latin1_to_utf8() {
void* conv = charset_conversion_open("iso-8859-1", "utf-8");
EXPECT_NOT_NULL(conv);
char* out = charset_convert(conv, "caf\xe9", NULL);
EXPECT_NOT_NULL(out);
EXPECT_EQ_INT(strcmp(out, "caf\xc3\xa9"), 0);
free(out);
charset_conversion_close(conv);
}
static void test_iconv_invalid_sequence_fails() {
int err = 0;
/* 0xff is not a valid UTF-8 sequence. */
void* conv = charset_conversion_open("utf-8", "ascii");
EXPECT_NOT_NULL(conv);
EXPECT_TRUE(charset_convert(conv, "bad\xff", &err) == NULL);
EXPECT_TRUE(err == EILSEQ || err == EINVAL);
charset_conversion_close(conv);
}
static void test_iconv_unrepresentable_fails() {
/* "caf\xc3\xa9" (UTF-8 for cafe) has no ASCII representation. */
void* conv = charset_conversion_open("utf-8", "ascii");
EXPECT_NOT_NULL(conv);
EXPECT_TRUE(charset_convert(conv, "caf\xc3\xa9", NULL) == NULL);
charset_conversion_close(conv);
}
/* --- process-wide wire conversion ---------------------------------------- */
static void test_iconv_wire_sender_converts_local_to_remote() {
EXPECT_TRUE(charset_wire_init_sender("utf-8,iso-8859-1"));
char* wire = charset_wire_apply("caf\xc3\xa9");
EXPECT_NOT_NULL(wire);
EXPECT_EQ_INT(strcmp(wire, "caf\xe9"), 0);
free(wire);
charset_wire_free();
}
static void test_iconv_wire_receiver_converts_remote_to_local() {
EXPECT_TRUE(charset_wire_init_receiver("utf-8,iso-8859-1", NULL));
char* local = charset_wire_apply("caf\xe9");
EXPECT_NOT_NULL(local);
EXPECT_EQ_INT(strcmp(local, "caf\xc3\xa9"), 0);
free(local);
charset_wire_free();
}
static void test_iconv_wire_disabled_passthrough() {
charset_wire_init_sender(NULL);
EXPECT_FALSE(charset_wire_active());
char* out = charset_wire_apply("plain/name\xff");
EXPECT_NOT_NULL(out);
EXPECT_EQ_INT(strcmp(out, "plain/name\xff"), 0);
free(out);
charset_wire_free();
}
static void test_iconv_wire_str_roundtrip() {
EXPECT_TRUE(charset_wire_init_sender("utf-8,iso-8859-1"));
int p[2];
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);
io_set_fds(p[0], p[1]);
io_set_bwlimit(0);
pid_t pid = fork();
if (pid == 0) {
close(p[1]);
io_set_fds(p[0], p[0]);
charset_wire_free();
charset_wire_init_receiver("utf-8,iso-8859-1", NULL);
char* got = receive_wire_str(p[0]);
bool ok = got != NULL && strcmp(got, "caf\xc3\xa9") == 0;
free(got);
charset_wire_free();
close(p[0]);
_exit(ok ? 0 : 1);
} else {
close(p[0]);
io_set_fds(p[1], p[1]);
bool sent = send_wire_str(p[1], "caf\xc3\xa9");
int status;
waitpid(pid, &status, 0);
close(p[1]);
charset_wire_free();
EXPECT_TRUE(sent);
EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
}
}
void test_iconv() {
test_iconv_spec_parse_split();
test_iconv_spec_parse_single_defaults_to_local();
test_iconv_spec_parse_garbage();
test_iconv_spec_valid();
test_iconv_utf8_to_latin1();
test_iconv_latin1_to_utf8();
test_iconv_invalid_sequence_fails();
test_iconv_unrepresentable_fails();
test_iconv_wire_sender_converts_local_to_remote();
test_iconv_wire_receiver_converts_remote_to_local();
test_iconv_wire_disabled_passthrough();
test_iconv_wire_str_roundtrip();
}