Add tests for libipm file descriptor calls
This commit is contained in:
parent
c9adb3a2a6
commit
7a190bf709
@ -11,6 +11,7 @@ enum
|
||||
LIBIPM_VERSION = 2,
|
||||
LIBIPM_HEADER_SIZE = 12,
|
||||
LIBIPM_MAX_MESSAGE_SIZE = 8192,
|
||||
LIBIPM_MAX_FD_PER_MSG = 8,
|
||||
LIBIPM_MAX_PAYLOAD_SIZE = LIBIPM_MAX_MESSAGE_SIZE - LIBIPM_HEADER_SIZE
|
||||
};
|
||||
|
||||
@ -18,6 +19,7 @@ enum
|
||||
extern struct trans *g_t_out; /* Channel for outputting libipm messages */
|
||||
extern struct trans *g_t_in; /* Channel for inputting libipm messages */
|
||||
extern struct trans *g_t_vanilla; /* Non-SCP channel */
|
||||
extern int g_fd; /* An open file descriptor (/dev/zero) */
|
||||
|
||||
extern const char *g_supported_types; /* All recognised type codes */
|
||||
extern const char *g_unimplemented_types; /* recognised, unimplemented codes */
|
||||
@ -42,6 +44,14 @@ check_binary_data_eq(const void *actual_data,
|
||||
const void *expected_data,
|
||||
unsigned int expected_len);
|
||||
|
||||
/**
|
||||
* Check the file descriptor specified is working as /dev/zero
|
||||
*
|
||||
* If it isn't, an exception is raised using ck_* calls
|
||||
*/
|
||||
void
|
||||
check_fd_is_dev_zero(int fd);
|
||||
|
||||
/**
|
||||
* Looks for the specified string in the specified stream
|
||||
* @param s Stream to search
|
||||
@ -54,6 +64,11 @@ check_binary_data_eq(const void *actual_data,
|
||||
int
|
||||
does_stream_contain_string(const struct stream *s, const char *str);
|
||||
|
||||
/**
|
||||
* Returns the number of open file descriptors in the process */
|
||||
unsigned int
|
||||
get_open_fd_count(void);
|
||||
|
||||
Suite *make_suite_test_libipm_send_calls(void);
|
||||
Suite *make_suite_test_libipm_recv_calls(void);
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "libipm.h"
|
||||
@ -17,9 +19,10 @@
|
||||
struct trans *g_t_out = NULL;
|
||||
struct trans *g_t_in = NULL;
|
||||
struct trans *g_t_vanilla = NULL;
|
||||
int g_fd = -1;
|
||||
|
||||
const char *g_supported_types = "ybnqiuxtsdhogB";
|
||||
const char *g_unimplemented_types = "dhog";
|
||||
const char *g_unimplemented_types = "dog";
|
||||
|
||||
/******************************************************************************/
|
||||
static const char *
|
||||
@ -37,6 +40,7 @@ suite_test_libipm_calls_start(void)
|
||||
struct trans *t1 = NULL;
|
||||
struct trans *t2 = NULL;
|
||||
struct trans *t3 = NULL;
|
||||
int fd = -1;
|
||||
int success = 0;
|
||||
|
||||
if ((t1 = trans_create(TRANS_MODE_UNIX, 128, 128)) == NULL)
|
||||
@ -54,6 +58,11 @@ suite_test_libipm_calls_start(void)
|
||||
const char *errstr = g_get_strerror();
|
||||
LOG(LOG_LEVEL_ERROR, "Can't create test transport 3 [%s]", errstr);
|
||||
}
|
||||
else if ((fd = g_file_open("/dev/zero")) < 0)
|
||||
{
|
||||
const char *errstr = g_get_strerror();
|
||||
LOG(LOG_LEVEL_ERROR, "Can't open /dev/zero [%s]", errstr);
|
||||
}
|
||||
else if ((istatus = g_sck_local_socketpair(sck)) < 0)
|
||||
{
|
||||
const char *errstr = g_get_strerror();
|
||||
@ -89,12 +98,17 @@ suite_test_libipm_calls_start(void)
|
||||
g_t_out = t1;
|
||||
g_t_in = t2;
|
||||
g_t_vanilla = t3;
|
||||
g_fd = fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
trans_delete(t1);
|
||||
trans_delete(t2);
|
||||
trans_delete(t3);
|
||||
if (fd >= 0)
|
||||
{
|
||||
g_file_close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +152,20 @@ check_binary_data_eq(const void *actual_data,
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
check_fd_is_dev_zero(int fd)
|
||||
{
|
||||
char buff[1] = { '\001' };
|
||||
int status;
|
||||
status = g_file_read(fd, buff, sizeof(buff));
|
||||
ck_assert_int_eq(status, 1);
|
||||
ck_assert_int_eq(buff[0], '\0');
|
||||
|
||||
status = g_file_write(fd, buff, sizeof(buff));
|
||||
ck_assert_int_eq(status, 1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
@ -162,6 +190,51 @@ does_stream_contain_string(const struct stream *s, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
unsigned int
|
||||
get_open_fd_count(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int rv;
|
||||
|
||||
// What's the max number of file descriptors?
|
||||
struct rlimit nofile;
|
||||
if (getrlimit(RLIMIT_NOFILE, &nofile) < 0)
|
||||
{
|
||||
const char *errstr = g_get_strerror();
|
||||
ck_abort_msg("Can't create socketpair [%s]", errstr);
|
||||
}
|
||||
|
||||
struct pollfd *fds =
|
||||
(struct pollfd *)g_malloc(sizeof(struct pollfd) * nofile.rlim_cur, 0);
|
||||
ck_assert_ptr_nonnull(fds);
|
||||
|
||||
for (i = 0 ; i < nofile.rlim_cur; ++i)
|
||||
{
|
||||
fds[i].fd = i;
|
||||
fds[i].events = 0;
|
||||
fds[i].revents = 0;
|
||||
}
|
||||
|
||||
if (poll(fds, nofile.rlim_cur, 0) < 0)
|
||||
{
|
||||
const char *errstr = g_get_strerror();
|
||||
ck_abort_msg("Can't poll fds [%s]", errstr);
|
||||
}
|
||||
|
||||
rv = nofile.rlim_cur;
|
||||
for (i = 0 ; i < nofile.rlim_cur; ++i)
|
||||
{
|
||||
if (fds[i].revents == POLLNVAL)
|
||||
{
|
||||
--rv;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(fds);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int main (void)
|
||||
|
@ -245,13 +245,14 @@ START_TEST(test_libipm_send_recv_all_test)
|
||||
int64_t x;
|
||||
uint64_t t;
|
||||
char *s;
|
||||
int h = -1;
|
||||
char B[sizeof(bin_out)];
|
||||
char c;
|
||||
|
||||
/* The message is small enough to fit in the socket buffer */
|
||||
status = libipm_msg_out_simple_send(
|
||||
g_t_out, TEST_MESSAGE_NO,
|
||||
"ybnqiuxtsB",
|
||||
"ybnqiuxtshB",
|
||||
TEST_y_VALUE,
|
||||
TEST_b_VALUE,
|
||||
TEST_n_VALUE,
|
||||
@ -261,6 +262,7 @@ START_TEST(test_libipm_send_recv_all_test)
|
||||
TEST_x_VALUE,
|
||||
TEST_t_VALUE,
|
||||
TEST_s_VALUE,
|
||||
g_fd,
|
||||
&binary_desc);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
|
||||
@ -273,8 +275,8 @@ START_TEST(test_libipm_send_recv_all_test)
|
||||
|
||||
status = libipm_msg_in_parse(
|
||||
g_t_in,
|
||||
"ybnqiuxtsB",
|
||||
&y, &b, &n, &q, &i, &u, &x, &t, &s, &binary_desc);
|
||||
"ybnqiuxtshB",
|
||||
&y, &b, &n, &q, &i, &u, &x, &t, &s, &h, &binary_desc);
|
||||
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
ck_assert_int_eq(y, TEST_y_VALUE);
|
||||
@ -287,6 +289,13 @@ START_TEST(test_libipm_send_recv_all_test)
|
||||
ck_assert_int_eq(t, TEST_t_VALUE);
|
||||
check_binary_data_eq(TEST_s_VALUE, sizeof(TEST_s_VALUE) - 1,
|
||||
s, g_strlen(s));
|
||||
/* The file descriptor should not be -1, neither should it be
|
||||
* the value we sent. It should also point to /dev/zero */
|
||||
ck_assert_int_ne(h, -1);
|
||||
ck_assert_int_ne(h, g_fd);
|
||||
check_fd_is_dev_zero(h);
|
||||
g_file_close(h);
|
||||
|
||||
check_binary_data_eq(bin_out, sizeof(bin_out), B, sizeof(B));
|
||||
|
||||
/* Check we're at the end of the message */
|
||||
@ -540,8 +549,62 @@ START_TEST(test_libipm_receive_s_type)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* Checks various receive errors for 's'
|
||||
* Checks various receive errors for 'h'
|
||||
*/
|
||||
START_TEST(test_libipm_receive_h_type)
|
||||
{
|
||||
enum libipm_status status;
|
||||
int istatus;
|
||||
unsigned int i;
|
||||
int fd_count;
|
||||
|
||||
/* Get the number of open file descriptors */
|
||||
int base_fd_count = get_open_fd_count();
|
||||
ck_assert_int_gt(base_fd_count, 0);
|
||||
|
||||
/* Send the max number of copies of the /dev/zero
|
||||
* file descriptor */
|
||||
status = libipm_msg_out_init(g_t_out, TEST_MESSAGE_NO, NULL);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
|
||||
for (i = 0 ; i < LIBIPM_MAX_FD_PER_MSG; ++i)
|
||||
{
|
||||
status = libipm_msg_out_append(g_t_out, "h", g_fd);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
}
|
||||
libipm_msg_out_mark_end(g_t_out);
|
||||
istatus = trans_force_write(g_t_out);
|
||||
ck_assert_int_eq(istatus, 0);
|
||||
|
||||
check_for_incoming_message(TEST_MESSAGE_NO);
|
||||
|
||||
/* Check the number of file descriptors has gone up as expected */
|
||||
fd_count = get_open_fd_count();
|
||||
ck_assert_int_eq(fd_count, base_fd_count + LIBIPM_MAX_FD_PER_MSG);
|
||||
|
||||
/* Check half the descriptors work */
|
||||
for (i = 0 ; i < LIBIPM_MAX_FD_PER_MSG / 2; ++i)
|
||||
{
|
||||
int h = -1;
|
||||
status = libipm_msg_in_parse(g_t_in, "h", &h);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
check_fd_is_dev_zero(h);
|
||||
g_file_close(h);
|
||||
}
|
||||
|
||||
/* Close the message without reading the other descriptors */
|
||||
libipm_msg_in_reset(g_t_in);
|
||||
|
||||
/* Check all the file descriptors we received have been closed */
|
||||
fd_count = get_open_fd_count();
|
||||
ck_assert_int_eq(fd_count, base_fd_count);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/***************************************************************************//**
|
||||
* Checks various receive errors for 'B'
|
||||
*/
|
||||
START_TEST(test_libipm_receive_B_type)
|
||||
{
|
||||
@ -844,6 +907,7 @@ make_suite_test_libipm_recv_calls(void)
|
||||
tcase_add_test(tc, test_libipm_receive_x_type);
|
||||
tcase_add_test(tc, test_libipm_receive_t_type);
|
||||
tcase_add_test(tc, test_libipm_receive_s_type);
|
||||
tcase_add_test(tc, test_libipm_receive_h_type);
|
||||
tcase_add_test(tc, test_libipm_receive_B_type);
|
||||
tcase_add_test(tc, test_libipm_receive_no_type);
|
||||
tcase_add_test(tc, test_libipm_receive_unexpected_type);
|
||||
|
@ -44,7 +44,7 @@
|
||||
static const unsigned char all_test_expected_buff[] =
|
||||
{
|
||||
BITS16_LE(LIBIPM_VERSION),
|
||||
BITS16_LE(73), /* Header : message length */
|
||||
BITS16_LE(74), /* Header : message length */
|
||||
BITS16_LE(LIBIPM_FAC_TEST),
|
||||
BITS16_LE(TEST_MESSAGE_NO),
|
||||
BITS32_LE(0),
|
||||
@ -59,6 +59,7 @@ static const unsigned char all_test_expected_buff[] =
|
||||
't', BITS64_LE(ALL_TEST_t_VALUE),
|
||||
/* String + terminator */
|
||||
's', ALL_TEST_s_VALUE,
|
||||
'h', /* No buffer value is needed for 'h' */
|
||||
/* Fixed size block */
|
||||
'B', BITS16_LE(7) /* length */, ALL_TEST_B_VALUE
|
||||
};
|
||||
@ -154,7 +155,7 @@ START_TEST(test_libipm_append_all_test)
|
||||
|
||||
status = libipm_msg_out_init(
|
||||
g_t_out, TEST_MESSAGE_NO,
|
||||
"ybnqiuxtsB",
|
||||
"ybnqiuxtshB",
|
||||
ALL_TEST_y_VALUE,
|
||||
ALL_TEST_b_VALUE,
|
||||
ALL_TEST_n_VALUE,
|
||||
@ -164,6 +165,7 @@ START_TEST(test_libipm_append_all_test)
|
||||
ALL_TEST_x_VALUE,
|
||||
ALL_TEST_t_VALUE,
|
||||
string,
|
||||
g_fd,
|
||||
&binary_desc);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
|
||||
@ -352,6 +354,30 @@ START_TEST(test_libipm_send_s_type)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/***************************************************************************//**
|
||||
* Checks various send errors for 'h'
|
||||
*/
|
||||
START_TEST(test_libipm_send_h_type)
|
||||
{
|
||||
enum libipm_status status;
|
||||
unsigned int i;
|
||||
|
||||
test_append_at_end_of_message('h', 1);
|
||||
|
||||
status = libipm_msg_out_init(g_t_out, TEST_MESSAGE_NO, NULL);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
|
||||
for (i = 0 ; i < LIBIPM_MAX_FD_PER_MSG; ++i)
|
||||
{
|
||||
status = libipm_msg_out_append(g_t_out, "h", g_fd);
|
||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||
}
|
||||
|
||||
status = libipm_msg_out_append(g_t_out, "h", 1);
|
||||
ck_assert_int_eq(status, E_LI_TOO_MANY_FDS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/***************************************************************************//**
|
||||
* Checks various send errors for 'B'
|
||||
*/
|
||||
@ -496,6 +522,7 @@ make_suite_test_libipm_send_calls(void)
|
||||
tcase_add_test(tc, test_libipm_send_x_type);
|
||||
tcase_add_test(tc, test_libipm_send_t_type);
|
||||
tcase_add_test(tc, test_libipm_send_s_type);
|
||||
tcase_add_test(tc, test_libipm_send_h_type);
|
||||
tcase_add_test(tc, test_libipm_send_B_type);
|
||||
tcase_add_test(tc, test_libipm_send_y_type);
|
||||
tcase_add_test(tc, test_libipm_send_bad_types);
|
||||
|
Loading…
Reference in New Issue
Block a user