HelenOS sources
This source file includes following definitions.
- PCUT_TEST
- PCUT_TEST
- PCUT_TEST
- PCUT_TEST
- PCUT_TEST
- test_cstate_change
- test_conns_establish
- test_conns_tear_down
#include <errno.h>
#include <inet/endpoint.h>
#include <io/log.h>
#include <pcut/pcut.h>
#include "../conn.h"
#include "../rqueue.h"
#include "../ucall.h"
PCUT_INIT;
PCUT_TEST_SUITE(ucall);
static void test_cstate_change(tcp_conn_t *, void *, tcp_cstate_t);
static void test_conns_establish(tcp_conn_t **, tcp_conn_t **);
static void test_conns_tear_down(tcp_conn_t *, tcp_conn_t *);
static tcp_rqueue_cb_t test_rqueue_cb = {
.seg_received = tcp_as_segment_arrived
};
static tcp_cb_t test_conn_cb = {
.cstate_change = test_cstate_change
};
static tcp_conn_status_t cconn_status;
static tcp_conn_status_t sconn_status;
static FIBRIL_MUTEX_INITIALIZE(cst_lock);
static FIBRIL_CONDVAR_INITIALIZE(cst_cv);
PCUT_TEST_BEFORE
{
errno_t rc;
rc = log_init("test-tcp");
PCUT_ASSERT_ERRNO_VAL(EOK, rc);
rc = tcp_conns_init();
PCUT_ASSERT_ERRNO_VAL(EOK, rc);
tcp_rqueue_init(&test_rqueue_cb);
tcp_rqueue_fibril_start();
tcp_conn_lb = tcp_lb_segment;
}
PCUT_TEST_AFTER
{
tcp_rqueue_fini();
tcp_conns_fini();
}
PCUT_TEST(listen_delete)
{
tcp_conn_t *conn;
inet_ep2_t epp;
tcp_error_t trc;
tcp_conn_status_t cstatus;
inet_ep2_init(&epp);
inet_addr(&epp.local.addr, 127, 0, 0, 1);
epp.local.port = inet_port_user_lo;
conn = NULL;
trc = tcp_uc_open(&epp, ap_passive, tcp_open_nonblock, &conn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
PCUT_ASSERT_NOT_NULL(conn);
tcp_uc_status(conn, &cstatus);
PCUT_ASSERT_INT_EQUALS(st_listen, cstatus.cstate);
trc = tcp_uc_close(conn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
tcp_uc_delete(conn);
}
PCUT_TEST(connect_rst)
{
tcp_conn_t *conn;
inet_ep2_t epp;
tcp_error_t trc;
inet_ep2_init(&epp);
inet_addr(&epp.local.addr, 127, 0, 0, 1);
inet_addr(&epp.remote.addr, 127, 0, 0, 1);
epp.remote.port = inet_port_user_lo;
conn = NULL;
trc = tcp_uc_open(&epp, ap_active, 0, &conn);
PCUT_ASSERT_INT_EQUALS(TCP_ERESET, trc);
PCUT_ASSERT_NULL(conn);
}
PCUT_TEST(conn_establish)
{
tcp_conn_t *cconn, *sconn;
test_conns_establish(&cconn, &sconn);
test_conns_tear_down(cconn, sconn);
}
PCUT_TEST(conn_est_close_seq)
{
tcp_conn_t *cconn, *sconn;
tcp_error_t trc;
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: establish");
test_conns_establish(&cconn, &sconn);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: close cconn");
trc = tcp_uc_close(cconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait cconn = fin-wait-2");
fibril_mutex_lock(&cst_lock);
tcp_uc_status(cconn, &cconn_status);
while (cconn_status.cstate != st_fin_wait_2)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait sconn = close-wait");
fibril_mutex_lock(&cst_lock);
tcp_uc_status(sconn, &sconn_status);
while (sconn_status.cstate != st_close_wait)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: close sconn");
trc = tcp_uc_close(sconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait cconn = time-wait");
fibril_mutex_lock(&cst_lock);
tcp_uc_status(cconn, &cconn_status);
while (cconn_status.cstate != st_time_wait)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait sconn = closed");
fibril_mutex_lock(&cst_lock);
tcp_uc_status(sconn, &sconn_status);
while (sconn_status.cstate != st_closed) {
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: sconn.status == %d", sconn_status.cstate);
fibril_condvar_wait(&cst_cv, &cst_lock);
}
fibril_mutex_unlock(&cst_lock);
log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: tear down");
test_conns_tear_down(cconn, sconn);
}
PCUT_TEST(conn_est_close_simult)
{
tcp_conn_t *cconn, *sconn;
tcp_error_t trc;
test_conns_establish(&cconn, &sconn);
trc = tcp_uc_close(cconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
trc = tcp_uc_close(sconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
fibril_mutex_lock(&cst_lock);
tcp_uc_status(cconn, &cconn_status);
while (cconn_status.cstate != st_time_wait)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
fibril_mutex_lock(&cst_lock);
tcp_uc_status(sconn, &sconn_status);
while (sconn_status.cstate != st_time_wait &&
sconn_status.cstate != st_closed)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
test_conns_tear_down(cconn, sconn);
}
static void test_cstate_change(tcp_conn_t *conn, void *arg,
tcp_cstate_t old_state)
{
tcp_conn_status_t *status = (tcp_conn_status_t *)arg;
fibril_mutex_lock(&cst_lock);
tcp_uc_status(conn, status);
fibril_mutex_unlock(&cst_lock);
fibril_condvar_broadcast(&cst_cv);
}
static void test_conns_establish(tcp_conn_t **rcconn, tcp_conn_t **rsconn)
{
tcp_conn_t *cconn, *sconn;
inet_ep2_t cepp, sepp;
tcp_conn_status_t cstatus;
tcp_error_t trc;
inet_ep2_init(&cepp);
inet_addr(&cepp.local.addr, 127, 0, 0, 1);
inet_addr(&cepp.remote.addr, 127, 0, 0, 1);
cepp.remote.port = inet_port_user_lo;
inet_ep2_init(&sepp);
inet_addr(&sepp.local.addr, 127, 0, 0, 1);
sepp.local.port = inet_port_user_lo;
sconn = NULL;
trc = tcp_uc_open(&sepp, ap_passive, tcp_open_nonblock, &sconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
PCUT_ASSERT_NOT_NULL(sconn);
tcp_uc_set_cb(sconn, &test_conn_cb, &sconn_status);
PCUT_ASSERT_EQUALS(&sconn_status, tcp_uc_get_userptr(sconn));
tcp_uc_status(sconn, &cstatus);
PCUT_ASSERT_INT_EQUALS(st_listen, cstatus.cstate);
cconn = NULL;
trc = tcp_uc_open(&cepp, ap_active, 0, &cconn);
PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
PCUT_ASSERT_NOT_NULL(cconn);
tcp_uc_set_cb(cconn, &test_conn_cb, &cconn_status);
PCUT_ASSERT_EQUALS(&cconn_status, tcp_uc_get_userptr(cconn));
tcp_uc_status(cconn, &cstatus);
PCUT_ASSERT_INT_EQUALS(st_established, cstatus.cstate);
fibril_mutex_lock(&cst_lock);
tcp_uc_status(sconn, &sconn_status);
while (sconn_status.cstate != st_established)
fibril_condvar_wait(&cst_cv, &cst_lock);
fibril_mutex_unlock(&cst_lock);
*rcconn = cconn;
*rsconn = sconn;
}
static void test_conns_tear_down(tcp_conn_t *cconn, tcp_conn_t *sconn)
{
tcp_uc_abort(cconn);
tcp_uc_delete(cconn);
tcp_uc_abort(sconn);
tcp_uc_delete(sconn);
}
PCUT_EXPORT(ucall);
HelenOS homepage, sources at GitHub