/*
* Copyright (c) Likewise Software. All rights Reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the license, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Module Name:
*
* test-session.c
*
* Abstract:
*
* Session management unit tests
*
* Authors: Brian Koropoff (bkoropoff@likewisesoftware.com)
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "test-private.h"
typedef struct TrivialHandle
{
int trivial;
} TrivialHandle;
typedef struct TrivialRequest
{
int trivial;
} TrivialRequest;
typedef struct TrivialReply
{
int trivial;
} TrivialReply;
LWMsgTypeSpec trivialhandle_spec[] =
{
LWMSG_HANDLE(TrivialHandle),
LWMSG_TYPE_END
};
LWMsgTypeSpec trivialrequest_spec[] =
{
LWMSG_STRUCT_BEGIN(TrivialRequest),
LWMSG_MEMBER_INT8(TrivialRequest, trivial),
LWMSG_STRUCT_END,
LWMSG_TYPE_END
};
LWMsgTypeSpec trivialreply_spec[] =
{
LWMSG_STRUCT_BEGIN(TrivialReply),
LWMSG_MEMBER_INT8(TrivialReply, trivial),
LWMSG_STRUCT_END,
LWMSG_TYPE_END
};
typedef enum TrivialType
{
TRIVIAL_OPEN,
TRIVIAL_OPEN_SUCCESS,
TRIVIAL_CLOSE,
TRIVIAL_CLOSE_SUCCESS
} TrivialType;
LWMsgProtocolSpec trivialprotocol_spec[] =
{
LWMSG_MESSAGE(TRIVIAL_OPEN, trivialrequest_spec),
LWMSG_MESSAGE(TRIVIAL_OPEN_SUCCESS, trivialhandle_spec),
LWMSG_MESSAGE(TRIVIAL_CLOSE, trivialhandle_spec),
LWMSG_MESSAGE(TRIVIAL_CLOSE_SUCCESS, trivialreply_spec),
LWMSG_PROTOCOL_END
};
static void*
trivial_sender(void* _assocs)
{
LWMsgAssoc** assocs = (LWMsgAssoc**) _assocs;
LWMsgMessage request_msg = LWMSG_MESSAGE_INITIALIZER;
LWMsgMessage reply_msg = LWMSG_MESSAGE_INITIALIZER;
TrivialRequest request;
TrivialHandle* handle;
char smid_str[17];
LWMsgSessionID id;
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_establish(assocs[0]));
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_get_peer_session_id(assocs[0], &id));
lwmsg_session_id_to_string(&id, smid_str);
MU_VERBOSE("Sending first message to peer with session ID %s", smid_str);
request.trivial = 42;
request_msg.tag = TRIVIAL_OPEN;
request_msg.data = &request;
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_send_message_transact(assocs[0], &request_msg, &reply_msg));
MU_ASSERT_EQUAL(MU_TYPE_INTEGER, reply_msg.tag, TRIVIAL_OPEN_SUCCESS);
handle = reply_msg.data;
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_establish(assocs[1]));
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_get_peer_session_id(assocs[1], &id));
lwmsg_session_id_to_string(&id, smid_str);
MU_VERBOSE("Sending second message to peer with session ID %s", smid_str);
request_msg.tag = TRIVIAL_CLOSE;
request_msg.data = handle;
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_send_message_transact(assocs[1], &request_msg, &reply_msg));
MU_ASSERT_EQUAL(MU_TYPE_INTEGER, reply_msg.tag, TRIVIAL_CLOSE_SUCCESS);
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_close(assocs[0]));
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_close(assocs[1]));
lwmsg_assoc_delete(assocs[0]);
lwmsg_assoc_delete(assocs[1]);
return NULL;
}
static void*
trivial_receiver(void* _assocs)
{
LWMsgAssoc** assocs = (LWMsgAssoc**) _assocs;
LWMsgMessage request_msg = LWMSG_MESSAGE_INITIALIZER;
LWMsgMessage reply_msg = LWMSG_MESSAGE_INITIALIZER;
TrivialHandle* handle;
TrivialReply reply;
char smid_str[17];
LWMsgSessionID id;
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_establish(assocs[0]));
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_get_peer_session_id(assocs[0], &id));
lwmsg_session_id_to_string(&id, smid_str);
MU_VERBOSE("Receiving first message from peer with session ID %s", smid_str);
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_recv_message(assocs[0], &request_msg));
MU_ASSERT_EQUAL(MU_TYPE_INTEGER, request_msg.tag, TRIVIAL_OPEN);
handle = malloc(sizeof(*handle));
handle->trivial = 42;
reply_msg.tag = TRIVIAL_OPEN_SUCCESS;
reply_msg.data = handle;
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_register_handle(assocs[0], "TrivialHandle", handle, free));
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_send_message(assocs[0], &reply_msg));
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_establish(assocs[1]));
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_get_peer_session_id(assocs[1], &id));
lwmsg_session_id_to_string(&id, smid_str);
MU_VERBOSE("Receiving second message from peer with session ID %s", smid_str);
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_recv_message(assocs[1], &request_msg));
MU_ASSERT_EQUAL(MU_TYPE_INTEGER, request_msg.tag, TRIVIAL_CLOSE);
MU_ASSERT_EQUAL(MU_TYPE_POINTER, handle, request_msg.data);
reply.trivial = 42;
reply_msg.tag = TRIVIAL_CLOSE_SUCCESS;
reply_msg.data = &reply;
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_send_message(assocs[1], &reply_msg));
MU_TRY_ASSOC(assocs[0], lwmsg_assoc_close(assocs[0]));
MU_TRY_ASSOC(assocs[1], lwmsg_assoc_close(assocs[1]));
lwmsg_assoc_delete(assocs[0]);
lwmsg_assoc_delete(assocs[1]);
return NULL;
}
MU_TEST(session, trivial_send_recv)
{
int err = 0;
int sockets_a[2];
int sockets_b[2];
LWMsgAssoc* send_assocs[2];
LWMsgAssoc* recv_assocs[2];
pthread_t sender;
pthread_t receiver;
LWMsgProtocol* trivial_protocol = NULL;
LWMsgSessionManager* send_manager = NULL;
LWMsgSessionManager* recv_manager = NULL;
MU_TRY(lwmsg_shared_session_manager_new(&send_manager));
MU_TRY(lwmsg_shared_session_manager_new(&recv_manager));
MU_TRY(lwmsg_protocol_new(NULL, &trivial_protocol));
MU_TRY_PROTOCOL(trivial_protocol, lwmsg_protocol_add_protocol_spec(trivial_protocol, trivialprotocol_spec));
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_a))
{
MU_FAILURE("socketpair(): %s", strerror(errno));
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_b))
{
MU_FAILURE("socketpair(): %s", strerror(errno));
}
MU_TRY(lwmsg_connection_new(NULL,
trivial_protocol,
&send_assocs[0]));
MU_TRY(lwmsg_connection_new(NULL,
trivial_protocol,
&send_assocs[1]));
MU_TRY(lwmsg_connection_set_fd(
send_assocs[0],
LWMSG_CONNECTION_MODE_PAIR,
sockets_a[0]));
MU_TRY(lwmsg_connection_set_fd(
send_assocs[1],
LWMSG_CONNECTION_MODE_PAIR,
sockets_b[0]));
MU_TRY(lwmsg_connection_new(NULL,
trivial_protocol,
&recv_assocs[0]));
MU_TRY(lwmsg_connection_new(NULL,
trivial_protocol,
&recv_assocs[1]));
MU_TRY(lwmsg_connection_set_fd(
recv_assocs[0],
LWMSG_CONNECTION_MODE_PAIR,
sockets_a[1]));
MU_TRY(lwmsg_connection_set_fd(
recv_assocs[1],
LWMSG_CONNECTION_MODE_PAIR,
sockets_b[1]));
/* Put send sockets and recv sockets into same session managers */
MU_TRY(lwmsg_assoc_set_session_manager(send_assocs[0], send_manager));
MU_TRY(lwmsg_assoc_set_session_manager(send_assocs[1], send_manager));
MU_TRY(lwmsg_assoc_set_session_manager(recv_assocs[0], recv_manager));
MU_TRY(lwmsg_assoc_set_session_manager(recv_assocs[1], recv_manager));
if ((err = pthread_create(&sender, NULL, trivial_sender, send_assocs)))
{
MU_FAILURE("pthread_create(): %s", strerror(err));
}
if ((err = pthread_create(&receiver, NULL, trivial_receiver, recv_assocs)))
{
MU_FAILURE("pthread_create(): %s", strerror(err));
}
if ((err = pthread_join(sender, NULL)))
{
MU_FAILURE("pthread_join(): %s", strerror(err));
}
if ((err = pthread_join(receiver, NULL)))
{
MU_FAILURE("pthread_join(): %s", strerror(err));
}
}