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_VERSION = 2,
|
||||||
LIBIPM_HEADER_SIZE = 12,
|
LIBIPM_HEADER_SIZE = 12,
|
||||||
LIBIPM_MAX_MESSAGE_SIZE = 8192,
|
LIBIPM_MAX_MESSAGE_SIZE = 8192,
|
||||||
|
LIBIPM_MAX_FD_PER_MSG = 8,
|
||||||
LIBIPM_MAX_PAYLOAD_SIZE = LIBIPM_MAX_MESSAGE_SIZE - LIBIPM_HEADER_SIZE
|
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_out; /* Channel for outputting libipm messages */
|
||||||
extern struct trans *g_t_in; /* Channel for inputting libipm messages */
|
extern struct trans *g_t_in; /* Channel for inputting libipm messages */
|
||||||
extern struct trans *g_t_vanilla; /* Non-SCP channel */
|
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_supported_types; /* All recognised type codes */
|
||||||
extern const char *g_unimplemented_types; /* recognised, unimplemented 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,
|
const void *expected_data,
|
||||||
unsigned int expected_len);
|
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
|
* Looks for the specified string in the specified stream
|
||||||
* @param s Stream to search
|
* @param s Stream to search
|
||||||
@ -54,6 +64,11 @@ check_binary_data_eq(const void *actual_data,
|
|||||||
int
|
int
|
||||||
does_stream_contain_string(const struct stream *s, const char *str);
|
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_send_calls(void);
|
||||||
Suite *make_suite_test_libipm_recv_calls(void);
|
Suite *make_suite_test_libipm_recv_calls(void);
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "libipm.h"
|
#include "libipm.h"
|
||||||
@ -17,9 +19,10 @@
|
|||||||
struct trans *g_t_out = NULL;
|
struct trans *g_t_out = NULL;
|
||||||
struct trans *g_t_in = NULL;
|
struct trans *g_t_in = NULL;
|
||||||
struct trans *g_t_vanilla = NULL;
|
struct trans *g_t_vanilla = NULL;
|
||||||
|
int g_fd = -1;
|
||||||
|
|
||||||
const char *g_supported_types = "ybnqiuxtsdhogB";
|
const char *g_supported_types = "ybnqiuxtsdhogB";
|
||||||
const char *g_unimplemented_types = "dhog";
|
const char *g_unimplemented_types = "dog";
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
static const char *
|
static const char *
|
||||||
@ -37,6 +40,7 @@ suite_test_libipm_calls_start(void)
|
|||||||
struct trans *t1 = NULL;
|
struct trans *t1 = NULL;
|
||||||
struct trans *t2 = NULL;
|
struct trans *t2 = NULL;
|
||||||
struct trans *t3 = NULL;
|
struct trans *t3 = NULL;
|
||||||
|
int fd = -1;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
if ((t1 = trans_create(TRANS_MODE_UNIX, 128, 128)) == NULL)
|
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();
|
const char *errstr = g_get_strerror();
|
||||||
LOG(LOG_LEVEL_ERROR, "Can't create test transport 3 [%s]", errstr);
|
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)
|
else if ((istatus = g_sck_local_socketpair(sck)) < 0)
|
||||||
{
|
{
|
||||||
const char *errstr = g_get_strerror();
|
const char *errstr = g_get_strerror();
|
||||||
@ -89,12 +98,17 @@ suite_test_libipm_calls_start(void)
|
|||||||
g_t_out = t1;
|
g_t_out = t1;
|
||||||
g_t_in = t2;
|
g_t_in = t2;
|
||||||
g_t_vanilla = t3;
|
g_t_vanilla = t3;
|
||||||
|
g_fd = fd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trans_delete(t1);
|
trans_delete(t1);
|
||||||
trans_delete(t2);
|
trans_delete(t2);
|
||||||
trans_delete(t3);
|
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
|
int
|
||||||
@ -162,6 +190,51 @@ does_stream_contain_string(const struct stream *s, const char *str)
|
|||||||
return 0;
|
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)
|
int main (void)
|
||||||
|
@ -245,13 +245,14 @@ START_TEST(test_libipm_send_recv_all_test)
|
|||||||
int64_t x;
|
int64_t x;
|
||||||
uint64_t t;
|
uint64_t t;
|
||||||
char *s;
|
char *s;
|
||||||
|
int h = -1;
|
||||||
char B[sizeof(bin_out)];
|
char B[sizeof(bin_out)];
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
/* The message is small enough to fit in the socket buffer */
|
/* The message is small enough to fit in the socket buffer */
|
||||||
status = libipm_msg_out_simple_send(
|
status = libipm_msg_out_simple_send(
|
||||||
g_t_out, TEST_MESSAGE_NO,
|
g_t_out, TEST_MESSAGE_NO,
|
||||||
"ybnqiuxtsB",
|
"ybnqiuxtshB",
|
||||||
TEST_y_VALUE,
|
TEST_y_VALUE,
|
||||||
TEST_b_VALUE,
|
TEST_b_VALUE,
|
||||||
TEST_n_VALUE,
|
TEST_n_VALUE,
|
||||||
@ -261,6 +262,7 @@ START_TEST(test_libipm_send_recv_all_test)
|
|||||||
TEST_x_VALUE,
|
TEST_x_VALUE,
|
||||||
TEST_t_VALUE,
|
TEST_t_VALUE,
|
||||||
TEST_s_VALUE,
|
TEST_s_VALUE,
|
||||||
|
g_fd,
|
||||||
&binary_desc);
|
&binary_desc);
|
||||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
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(
|
status = libipm_msg_in_parse(
|
||||||
g_t_in,
|
g_t_in,
|
||||||
"ybnqiuxtsB",
|
"ybnqiuxtshB",
|
||||||
&y, &b, &n, &q, &i, &u, &x, &t, &s, &binary_desc);
|
&y, &b, &n, &q, &i, &u, &x, &t, &s, &h, &binary_desc);
|
||||||
|
|
||||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||||
ck_assert_int_eq(y, TEST_y_VALUE);
|
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);
|
ck_assert_int_eq(t, TEST_t_VALUE);
|
||||||
check_binary_data_eq(TEST_s_VALUE, sizeof(TEST_s_VALUE) - 1,
|
check_binary_data_eq(TEST_s_VALUE, sizeof(TEST_s_VALUE) - 1,
|
||||||
s, g_strlen(s));
|
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_binary_data_eq(bin_out, sizeof(bin_out), B, sizeof(B));
|
||||||
|
|
||||||
/* Check we're at the end of the message */
|
/* Check we're at the end of the message */
|
||||||
@ -540,8 +549,62 @@ START_TEST(test_libipm_receive_s_type)
|
|||||||
}
|
}
|
||||||
END_TEST
|
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)
|
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_x_type);
|
||||||
tcase_add_test(tc, test_libipm_receive_t_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_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_B_type);
|
||||||
tcase_add_test(tc, test_libipm_receive_no_type);
|
tcase_add_test(tc, test_libipm_receive_no_type);
|
||||||
tcase_add_test(tc, test_libipm_receive_unexpected_type);
|
tcase_add_test(tc, test_libipm_receive_unexpected_type);
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
static const unsigned char all_test_expected_buff[] =
|
static const unsigned char all_test_expected_buff[] =
|
||||||
{
|
{
|
||||||
BITS16_LE(LIBIPM_VERSION),
|
BITS16_LE(LIBIPM_VERSION),
|
||||||
BITS16_LE(73), /* Header : message length */
|
BITS16_LE(74), /* Header : message length */
|
||||||
BITS16_LE(LIBIPM_FAC_TEST),
|
BITS16_LE(LIBIPM_FAC_TEST),
|
||||||
BITS16_LE(TEST_MESSAGE_NO),
|
BITS16_LE(TEST_MESSAGE_NO),
|
||||||
BITS32_LE(0),
|
BITS32_LE(0),
|
||||||
@ -59,6 +59,7 @@ static const unsigned char all_test_expected_buff[] =
|
|||||||
't', BITS64_LE(ALL_TEST_t_VALUE),
|
't', BITS64_LE(ALL_TEST_t_VALUE),
|
||||||
/* String + terminator */
|
/* String + terminator */
|
||||||
's', ALL_TEST_s_VALUE,
|
's', ALL_TEST_s_VALUE,
|
||||||
|
'h', /* No buffer value is needed for 'h' */
|
||||||
/* Fixed size block */
|
/* Fixed size block */
|
||||||
'B', BITS16_LE(7) /* length */, ALL_TEST_B_VALUE
|
'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(
|
status = libipm_msg_out_init(
|
||||||
g_t_out, TEST_MESSAGE_NO,
|
g_t_out, TEST_MESSAGE_NO,
|
||||||
"ybnqiuxtsB",
|
"ybnqiuxtshB",
|
||||||
ALL_TEST_y_VALUE,
|
ALL_TEST_y_VALUE,
|
||||||
ALL_TEST_b_VALUE,
|
ALL_TEST_b_VALUE,
|
||||||
ALL_TEST_n_VALUE,
|
ALL_TEST_n_VALUE,
|
||||||
@ -164,6 +165,7 @@ START_TEST(test_libipm_append_all_test)
|
|||||||
ALL_TEST_x_VALUE,
|
ALL_TEST_x_VALUE,
|
||||||
ALL_TEST_t_VALUE,
|
ALL_TEST_t_VALUE,
|
||||||
string,
|
string,
|
||||||
|
g_fd,
|
||||||
&binary_desc);
|
&binary_desc);
|
||||||
ck_assert_int_eq(status, E_LI_SUCCESS);
|
ck_assert_int_eq(status, E_LI_SUCCESS);
|
||||||
|
|
||||||
@ -352,6 +354,30 @@ START_TEST(test_libipm_send_s_type)
|
|||||||
}
|
}
|
||||||
END_TEST
|
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'
|
* 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_x_type);
|
||||||
tcase_add_test(tc, test_libipm_send_t_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_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_B_type);
|
||||||
tcase_add_test(tc, test_libipm_send_y_type);
|
tcase_add_test(tc, test_libipm_send_y_type);
|
||||||
tcase_add_test(tc, test_libipm_send_bad_types);
|
tcase_add_test(tc, test_libipm_send_bad_types);
|
||||||
|
Loading…
Reference in New Issue
Block a user