diff options
Diffstat (limited to 'test/mi-mctp.c')
-rw-r--r-- | test/mi-mctp.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/test/mi-mctp.c b/test/mi-mctp.c index a831cf7..5b1a154 100644 --- a/test/mi-mctp.c +++ b/test/mi-mctp.c @@ -28,6 +28,8 @@ struct test_peer; typedef int (*rx_test_fn)(struct test_peer *peer, void *buf, size_t len); +typedef int (*poll_test_fn)(struct test_peer *peer, + struct pollfd *fds, nfds_t nfds, int timeout); /* Our fake MCTP "peer". * @@ -58,6 +60,9 @@ static struct test_peer { void *tx_data; int tx_fn_res; + poll_test_fn poll_fn; + void *poll_data; + /* store sd from socket() setup */ int sd; } test_peer; @@ -153,6 +158,14 @@ ssize_t __wrap_recvmsg(int sd, struct msghdr *hdr, int flags) return test_peer.tx_rc ?: (pos - 1); } +int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + if (!test_peer.poll_fn) + return 1; + + return test_peer.poll_fn(&test_peer, fds, nfds, timeout); +} + struct mctp_ioc_tag_ctl; #ifdef SIOCMCTPALLOCTAG @@ -183,6 +196,7 @@ static struct __mi_mctp_socket_ops ops = { __wrap_socket, __wrap_sendmsg, __wrap_recvmsg, + __wrap_poll, test_ioctl_tag, }; @@ -237,6 +251,23 @@ static void test_tx_short(nvme_mi_ep_t ep, struct test_peer *peer) assert(rc != 0); } +static int poll_fn_err(struct test_peer *peer, struct pollfd *fds, + nfds_t nfds, int timeout) +{ + return -1; +} + +static void test_poll_err(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + int rc; + + peer->poll_fn = poll_fn_err; + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc != 0); +} + static void test_read_mi_data(nvme_mi_ep_t ep, struct test_peer *peer) { struct nvme_mi_read_nvm_ss_info ss_info; @@ -331,6 +362,48 @@ static void test_admin_resp_sizes_unaligned(nvme_mi_ep_t ep, struct test_peer *p nvme_mi_close_ctrl(ctrl); } +/* test: timeout value passed to poll */ +static int poll_fn_timeout_value(struct test_peer *peer, struct pollfd *fds, + nfds_t nfds, int timeout) +{ + assert(timeout == 3141); + return 1; +} + +static void test_poll_timeout_value(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + int rc; + + /* empty response data */ + peer->tx_buf_len = 8 + 32; + + peer->poll_fn = poll_fn_timeout_value; + nvme_mi_ep_set_timeout(ep, 3141); + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc == 0); +} + +/* test: poll timeout expiry */ +static int poll_fn_timeout(struct test_peer *peer, struct pollfd *fds, + nfds_t nfds, int timeout) +{ + return 0; +} + +static void test_poll_timeout(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + int rc; + + peer->poll_fn = poll_fn_timeout; + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc != 0); + assert(errno == ETIMEDOUT); +} + /* test: send a More Processing Required response, then the actual response */ struct mpr_tx_info { int msg_no; @@ -402,6 +475,149 @@ static void test_mpr_admin(nvme_mi_ep_t ep, struct test_peer *peer) nvme_mi_close_ctrl(ctrl); } +/* helpers for the MPR + poll tests */ +struct mpr_poll_info { + int poll_no; + uint16_t mprt; + unsigned int timeouts[2]; +}; + +static int poll_fn_mpr_poll(struct test_peer *peer, struct pollfd *fds, + nfds_t nfds, int timeout) +{ + struct mpr_poll_info *info = peer->poll_data; + + switch (info->poll_no) { + case 1: + case 2: + assert(timeout == info->timeouts[info->poll_no - 1]); + break; + default: + assert(0); + } + + info->poll_no++; + return 1; +} + +static int tx_fn_mpr_poll(struct test_peer *peer, void *buf, size_t len) +{ + struct mpr_tx_info *tx_info = peer->tx_data; + struct mpr_poll_info *poll_info = peer->poll_data; + unsigned int mprt; + + memset(peer->tx_buf, 0, sizeof(peer->tx_buf)); + peer->tx_buf[0] = NVME_MI_MSGTYPE_NVME; + peer->tx_buf[1] = test_peer.rx_buf[1] | (NVME_MI_ROR_RSP << 7); + + switch (tx_info->msg_no) { + case 1: + peer->tx_buf[4] = NVME_MI_RESP_MPR; + peer->tx_buf_len = 8; + mprt = poll_info->mprt; + peer->tx_buf[7] = mprt >> 8; + peer->tx_buf[6] = mprt & 0xff; + break; + case 2: + peer->tx_buf[4] = NVME_MI_RESP_SUCCESS; + peer->tx_buf_len = tx_info->final_len; + break; + default: + assert(0); + } + + test_set_tx_mic(peer); + + tx_info->msg_no++; + + return 0; +} + +/* test: correct timeout value used from MPR response */ +static void test_mpr_timeouts(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + struct mpr_poll_info poll_info; + struct mpr_tx_info tx_info; + int rc; + + nvme_mi_ep_set_timeout(ep, 3141); + + tx_info.msg_no = 1; + tx_info.final_len = sizeof(struct nvme_mi_mi_resp_hdr) + sizeof(ss_info); + + poll_info.poll_no = 1; + poll_info.mprt = 1234; + poll_info.timeouts[0] = 3141; + poll_info.timeouts[1] = 1234 * 100; + + peer->tx_fn = tx_fn_mpr_poll; + peer->tx_data = &tx_info; + + peer->poll_fn = poll_fn_mpr_poll; + peer->poll_data = &poll_info; + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc == 0); +} + +/* test: MPR value is limited to the max mpr */ +static void test_mpr_timeout_clamp(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + struct mpr_poll_info poll_info; + struct mpr_tx_info tx_info; + int rc; + + nvme_mi_ep_set_timeout(ep, 3141); + nvme_mi_ep_set_mprt_max(ep, 123400); + + tx_info.msg_no = 1; + tx_info.final_len = sizeof(struct nvme_mi_mi_resp_hdr) + sizeof(ss_info); + + poll_info.poll_no = 1; + poll_info.mprt = 1235; + poll_info.timeouts[0] = 3141; + poll_info.timeouts[1] = 1234 * 100; + + peer->tx_fn = tx_fn_mpr_poll; + peer->tx_data = &tx_info; + + peer->poll_fn = poll_fn_mpr_poll; + peer->poll_data = &poll_info; + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc == 0); +} + +/* test: MPR value of zero doesn't result in poll with zero timeout */ +static void test_mpr_mprt_zero(nvme_mi_ep_t ep, struct test_peer *peer) +{ + struct nvme_mi_read_nvm_ss_info ss_info; + struct mpr_poll_info poll_info; + struct mpr_tx_info tx_info; + int rc; + + nvme_mi_ep_set_timeout(ep, 3141); + nvme_mi_ep_set_mprt_max(ep, 123400); + + tx_info.msg_no = 1; + tx_info.final_len = sizeof(struct nvme_mi_mi_resp_hdr) + sizeof(ss_info); + + poll_info.poll_no = 1; + poll_info.mprt = 0; + poll_info.timeouts[0] = 3141; + poll_info.timeouts[1] = 3141; + + peer->tx_fn = tx_fn_mpr_poll; + peer->tx_data = &tx_info; + + peer->poll_fn = poll_fn_mpr_poll; + peer->poll_data = &poll_info; + + rc = nvme_mi_mi_read_mi_data_subsys(ep, &ss_info); + assert(rc == 0); +} #define DEFINE_TEST(name) { #name, test_ ## name } struct test { @@ -413,12 +629,18 @@ struct test { DEFINE_TEST(tx_err), DEFINE_TEST(tx_short), DEFINE_TEST(read_mi_data), + DEFINE_TEST(poll_err), DEFINE_TEST(mi_resp_err), DEFINE_TEST(admin_resp_err), DEFINE_TEST(admin_resp_sizes), DEFINE_TEST(admin_resp_sizes_unaligned), + DEFINE_TEST(poll_timeout_value), + DEFINE_TEST(poll_timeout), DEFINE_TEST(mpr_mi), DEFINE_TEST(mpr_admin), + DEFINE_TEST(mpr_timeouts), + DEFINE_TEST(mpr_timeout_clamp), + DEFINE_TEST(mpr_mprt_zero), }; static void run_test(struct test *test, FILE *logfd, nvme_mi_ep_t ep, |