Files
flexnbd-c/tests/unit/check_readwrite.c

190 lines
4.2 KiB
C
Raw Normal View History

#include "readwrite.h"
#include <check.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stddef.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "util.h"
#include "nbdtypes.h"
2018-02-20 10:05:35 +00:00
int fd_read_request(int, struct nbd_request_raw *);
int fd_write_reply(int, uint64_t, int);
int marker;
2018-02-20 10:05:35 +00:00
void error_marker(void *unused __attribute__ ((unused)),
int fatal __attribute__ ((unused)))
{
2018-02-20 10:05:35 +00:00
marker = 1;
return;
}
struct respond {
2018-02-20 10:05:35 +00:00
int sock_fds[2]; // server end
int do_fail;
pthread_t thread_id;
pthread_attr_t thread_attr;
struct nbd_request received;
};
2018-02-20 10:05:35 +00:00
void *responder(void *respond_uncast)
{
2018-02-20 10:05:35 +00:00
struct respond *resp = (struct respond *) respond_uncast;
int sock_fd = resp->sock_fds[1];
struct nbd_request_raw request_raw;
uint64_t wrong_handle = 0x80;
if (fd_read_request(sock_fd, &request_raw) == -1) {
fprintf(stderr, "Problem with fd_read_request\n");
} else {
nbd_r2h_request(&request_raw, &resp->received);
if (resp->do_fail) {
fd_write_reply(sock_fd, wrong_handle, 0);
} else {
2018-02-20 10:05:35 +00:00
fd_write_reply(sock_fd, resp->received.handle.w, 0);
}
2018-02-20 10:05:35 +00:00
write(sock_fd, "12345678", 8);
}
return NULL;
}
2018-02-20 10:05:35 +00:00
struct respond *respond_create(int do_fail)
{
2018-02-20 10:05:35 +00:00
struct respond *respond =
(struct respond *) calloc(1, sizeof(struct respond));
socketpair(PF_UNIX, SOCK_STREAM, 0, respond->sock_fds);
respond->do_fail = do_fail;
2018-02-20 10:05:35 +00:00
pthread_attr_init(&respond->thread_attr);
pthread_create(&respond->thread_id, &respond->thread_attr, responder,
respond);
2018-02-20 10:05:35 +00:00
return respond;
}
2018-02-20 10:05:35 +00:00
void respond_destroy(struct respond *respond)
{
NULLCHECK(respond);
2018-02-20 10:05:35 +00:00
pthread_join(respond->thread_id, NULL);
pthread_attr_destroy(&respond->thread_attr);
2018-02-20 10:05:35 +00:00
close(respond->sock_fds[0]);
close(respond->sock_fds[1]);
free(respond);
}
2018-02-20 10:05:35 +00:00
void *reader(void *nothing __attribute__ ((unused)))
{
2018-02-20 10:05:35 +00:00
DECLARE_ERROR_CONTEXT(error_context);
error_set_handler((cleanup_handler *) error_marker, error_context);
2018-02-20 10:05:35 +00:00
struct respond *respond = respond_create(1);
int devnull = open("/dev/null", O_WRONLY);
char outbuf[8] = { 0 };
2018-02-20 10:05:35 +00:00
socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1);
2018-02-20 10:05:35 +00:00
return NULL;
}
2018-02-20 10:05:35 +00:00
START_TEST(test_rejects_mismatched_handle)
{
2018-02-20 10:05:35 +00:00
error_init();
pthread_t reader_thread;
2018-02-20 10:05:35 +00:00
log_level = 5;
2018-02-20 10:05:35 +00:00
marker = 0;
pthread_create(&reader_thread, NULL, reader, NULL);
FATAL_UNLESS(0 == pthread_join(reader_thread, NULL),
"pthread_join failed");
log_level = 2;
2018-02-20 10:05:35 +00:00
fail_unless(marker == 1, "Error handler wasn't called");
}
2018-02-20 10:05:35 +00:00
END_TEST START_TEST(test_accepts_matched_handle)
{
2018-02-20 10:05:35 +00:00
struct respond *respond = respond_create(0);
2018-02-20 10:05:35 +00:00
int devnull = open("/dev/null", O_WRONLY);
char outbuf[8] = { 0 };
2018-02-20 10:05:35 +00:00
socket_nbd_read(respond->sock_fds[0], 0, 8, devnull, outbuf, 1);
2018-02-20 10:05:35 +00:00
respond_destroy(respond);
}
2018-02-20 10:05:35 +00:00
END_TEST START_TEST(test_disconnect_doesnt_read_reply)
{
2018-02-20 10:05:35 +00:00
struct respond *respond = respond_create(1);
2018-02-20 10:05:35 +00:00
socket_nbd_disconnect(respond->sock_fds[0]);
2018-02-20 10:05:35 +00:00
respond_destroy(respond);
}
2018-02-20 10:05:35 +00:00
END_TEST Suite * readwrite_suite(void)
{
2018-02-20 10:05:35 +00:00
Suite *s = suite_create("readwrite");
TCase *tc_transfer = tcase_create("entrust");
TCase *tc_disconnect = tcase_create("disconnect");
2018-02-20 10:05:35 +00:00
tcase_add_test(tc_transfer, test_rejects_mismatched_handle);
tcase_add_exit_test(tc_transfer, test_accepts_matched_handle, 0);
2018-02-20 10:05:35 +00:00
/* This test is a little funny. We respond with a dodgy handle
* and check that this *doesn't* cause a message rejection,
* because we want to know that the sender won't even try to
* read the response.
*/
tcase_add_exit_test(tc_disconnect, test_disconnect_doesnt_read_reply,
0);
2018-02-20 10:05:35 +00:00
suite_add_tcase(s, tc_transfer);
suite_add_tcase(s, tc_disconnect);
2018-02-20 10:05:35 +00:00
return s;
}
#ifdef DEBUG
2018-02-20 10:05:35 +00:00
#define LOG_LEVEL 0
#else
2018-02-20 10:05:35 +00:00
#define LOG_LEVEL 2
#endif
int main(void)
{
2018-02-20 10:05:35 +00:00
log_level = LOG_LEVEL;
int number_failed;
Suite *s = readwrite_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
log_level = 0;
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? 0 : 1;
}