static void test_fd_passing_server(struct pomp_ctx *ctx, enum pomp_event event, struct pomp_conn *conn, const struct pomp_msg *msg, void *userdata) { static int fds[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}}; int res = 0; struct test_data *data = userdata; TEST_IPC_LOG("%s : event=%d(%s) conn=%p msg=%p", __func__, event, pomp_event_str(event), conn, msg); switch (event) { case POMP_EVENT_CONNECTED: /* Create 3 pairs of pipes */ res = pipe(fds[0]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = pipe(fds[1]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = pipe(fds[2]); TEST_IPC_CHECK_EQUAL(data, res, 0); /* Send read sides to client */ res = pomp_conn_send(conn, 1, "%s%x%s%x%s%x", "pipe0", fds[0][0], "pipe1", fds[1][0], "pipe2", fds[2][0]); TEST_IPC_CHECK_EQUAL(data, res, 0); /* write some data on pipes */ res = (int)write(fds[0][1], "pipe0", 5); TEST_IPC_CHECK_EQUAL(data, res, 5); res = (int)write(fds[1][1], "pipe1", 5); TEST_IPC_CHECK_EQUAL(data, res, 5); res = (int)write(fds[2][1], "pipe2", 5); TEST_IPC_CHECK_EQUAL(data, res, 5); break; case POMP_EVENT_DISCONNECTED: /* Close all pipes */ res = close(fds[0][0]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = close(fds[0][1]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = close(fds[1][0]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = close(fds[1][1]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = close(fds[2][0]); TEST_IPC_CHECK_EQUAL(data, res, 0); res = close(fds[2][1]); TEST_IPC_CHECK_EQUAL(data, res, 0); data->stop = 1; break; case POMP_EVENT_MSG: break; default: break; } }
static void test_event_cb_t(struct pomp_ctx *ctx, enum pomp_event event, struct pomp_conn *conn, const struct pomp_msg *msg, void *userdata) { int fd; int res = 0; struct test_data *data = userdata; const char *eventstr = pomp_event_str(event); const struct sockaddr *addr = NULL; uint32_t addrlen = 0; const struct pomp_cred *cred = NULL; int isunix = 0; switch (event) { case POMP_EVENT_CONNECTED: data->connection++; /* Invalid get fd (NULL param) */ fd = pomp_conn_get_fd(NULL); CU_ASSERT_EQUAL(fd, -EINVAL); fd = pomp_conn_get_fd(conn); CU_ASSERT_TRUE(fd >= 0); addr = pomp_conn_get_local_addr(conn, &addrlen); CU_ASSERT_TRUE(addr != NULL); addr = pomp_conn_get_peer_addr(conn, &addrlen); CU_ASSERT_TRUE(addr != NULL); isunix = addr->sa_family == AF_UNIX; /* Invalid get addr (NULL param) */ addr = pomp_conn_get_local_addr(NULL, &addrlen); CU_ASSERT_TRUE(addr == NULL); addr = pomp_conn_get_local_addr(conn, NULL); CU_ASSERT_TRUE(addr == NULL); addr = pomp_conn_get_peer_addr(NULL, &addrlen); CU_ASSERT_TRUE(addr == NULL); addr = pomp_conn_get_peer_addr(conn, NULL); CU_ASSERT_TRUE(addr == NULL); if (!isunix) { /* Invalid get credentials (bad type or NULL param) */ cred = pomp_conn_get_peer_cred(conn); CU_ASSERT_TRUE(cred == NULL); cred = pomp_conn_get_peer_cred(NULL); CU_ASSERT_TRUE(cred == NULL); } else { cred = pomp_conn_get_peer_cred(conn); CU_ASSERT_TRUE(cred != NULL); } break; case POMP_EVENT_DISCONNECTED: data->disconnection++; break; case POMP_EVENT_MSG: data->msg++; if (pomp_msg_get_id(msg) == 1) { res = pomp_conn_send(conn, 2, "%s", eventstr); CU_ASSERT_EQUAL(res, 0); } if (data->isdgram) { res = pomp_conn_disconnect(conn); CU_ASSERT_EQUAL(res, -ENOTCONN); /* Internal function invalid arguments checks */ res = pomp_conn_send_msg_to(NULL, msg, NULL, 0); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_conn_send_msg_to(conn, NULL, NULL, 0); CU_ASSERT_EQUAL(res, -EINVAL); } else { /* Internal function invalid arguments checks */ res = pomp_conn_send_msg(NULL, msg); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_conn_send_msg(conn, NULL); CU_ASSERT_EQUAL(res, -EINVAL); } /* Internal function invalid arguments checks */ res = pomp_ctx_notify_event(NULL, POMP_EVENT_CONNECTED, conn); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_notify_event(ctx, POMP_EVENT_MSG, conn); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_notify_event(ctx, POMP_EVENT_CONNECTED, NULL); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_notify_msg(NULL, conn, msg); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_notify_msg(ctx, NULL, msg); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_notify_msg(ctx, conn, NULL); CU_ASSERT_EQUAL(res, -EINVAL); break; default: CU_ASSERT_TRUE_FATAL(0); break; } }
static void test_ctx(const struct sockaddr *addr1, uint32_t addrlen1, const struct sockaddr *addr2, uint32_t addrlen2, int isdgram, int israw, int withsockcb, int withsendcb) { int res = 0; struct test_data data; struct pomp_loop *loop = NULL; struct pomp_conn *conn = NULL; struct pomp_msg *msg = NULL; int fd = -1; uint32_t i = 0, j = 0; struct pomp_buffer *buf = NULL; memset(&data, 0, sizeof(data)); data.isdgram = isdgram; data.israw = israw; data.srv.addr = addr1; data.srv.addrlen = addrlen1; data.cli.addr = addr2; data.cli.addrlen = addrlen2; msg = pomp_msg_new(); CU_ASSERT_PTR_NOT_NULL_FATAL(msg); /* Create context */ data.srv.ctx = pomp_ctx_new(&test_event_cb_t, &data); CU_ASSERT_PTR_NOT_NULL_FATAL(data.srv.ctx); if (israw) { res = pomp_ctx_set_raw(data.srv.ctx, &test_ctx_raw_cb); CU_ASSERT_EQUAL(res, 0); } if (withsockcb) { res = pomp_ctx_set_socket_cb(data.srv.ctx, &test_ctx_socket_cb); CU_ASSERT_EQUAL(res, 0); } if (withsendcb) { res = pomp_ctx_set_send_cb(data.srv.ctx, &test_ctx_send_cb); CU_ASSERT_EQUAL(res, 0); } /* Create context without callback */ data.cli.ctx = pomp_ctx_new(NULL, &data); CU_ASSERT_PTR_NOT_NULL_FATAL(data.cli.ctx); res = pomp_ctx_destroy(data.cli.ctx); CU_ASSERT_EQUAL(res, 0); /* Invalid create (NULL 3nd arg) */ data.cli.ctx = pomp_ctx_new_with_loop(NULL, &data, NULL); CU_ASSERT_PTR_NULL(data.cli.ctx); data.cli.ctx = pomp_ctx_new_with_loop(&test_event_cb_t, &data, NULL); CU_ASSERT_PTR_NULL(data.cli.ctx); /* Create 2nd context */ data.cli.ctx = pomp_ctx_new(&test_event_cb_t, &data); CU_ASSERT_PTR_NOT_NULL_FATAL(data.cli.ctx); if (israw) { res = pomp_ctx_set_raw(data.cli.ctx, &test_ctx_raw_cb); CU_ASSERT_EQUAL(res, 0); } if (withsockcb) { res = pomp_ctx_set_socket_cb(data.cli.ctx, &test_ctx_socket_cb); CU_ASSERT_EQUAL(res, 0); } if (withsendcb) { res = pomp_ctx_set_send_cb(data.cli.ctx, &test_ctx_send_cb); CU_ASSERT_EQUAL(res, 0); } if (!isdgram) { /* Invalid start server (NULL param) */ res = pomp_ctx_listen(NULL, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_listen(data.srv.ctx, NULL, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); /* Start as server 1st context */ res = pomp_ctx_listen(data.srv.ctx, addr1, addrlen1); CU_ASSERT_EQUAL(res, 0); /* Invalid start server (busy) */ res = pomp_ctx_listen(data.srv.ctx, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EBUSY); } else { /* Invalid bind (NULL param) */ res = pomp_ctx_bind(NULL, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_bind(data.srv.ctx, NULL, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); /* Bind 1st context */ res = pomp_ctx_bind(data.srv.ctx, addr1, addrlen1); CU_ASSERT_EQUAL(res, 0); /* Invalid bind (busy) */ res = pomp_ctx_bind(data.srv.ctx, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EBUSY); } if (!isdgram) { /* Invalid start client (NULL param) */ res = pomp_ctx_connect(NULL, addr2, addrlen2); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_connect(data.cli.ctx, NULL, addrlen2); CU_ASSERT_EQUAL(res, -EINVAL); /* Start as client 2nd context */ res = pomp_ctx_connect(data.cli.ctx, addr2, addrlen2); CU_ASSERT_EQUAL(res, 0); /* Invalid start client (busy) */ res = pomp_ctx_connect(data.cli.ctx, addr2, addrlen2); CU_ASSERT_EQUAL(res, -EBUSY); } else { /* Invalid bind (NULL param) */ res = pomp_ctx_bind(NULL, addr2, addrlen2); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_bind(data.cli.ctx, NULL, addrlen2); CU_ASSERT_EQUAL(res, -EINVAL); /* Bind 2nd context */ res = pomp_ctx_bind(data.cli.ctx, addr2, addrlen2); CU_ASSERT_EQUAL(res, 0); /* Invalid bind (busy) */ res = pomp_ctx_bind(data.cli.ctx, addr2, addrlen2); CU_ASSERT_EQUAL(res, -EBUSY); } /* Invalid set raw */ res = pomp_ctx_set_raw(NULL, &test_ctx_raw_cb); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_raw(data.srv.ctx, NULL); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_raw(data.srv.ctx, &test_ctx_raw_cb); CU_ASSERT_EQUAL(res, -EBUSY); /* Invalid set socket cb */ res = pomp_ctx_set_socket_cb(NULL, &test_ctx_socket_cb); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_socket_cb(data.srv.ctx, NULL); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_socket_cb(data.srv.ctx, &test_ctx_socket_cb); CU_ASSERT_EQUAL(res, -EBUSY); /* Invalid set send cb */ res = pomp_ctx_set_send_cb(NULL, &test_ctx_send_cb); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_send_cb(data.srv.ctx, NULL); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_set_send_cb(data.srv.ctx, &test_ctx_send_cb); CU_ASSERT_EQUAL(res, -EBUSY); /* Invalid get loop (NULL param) */ loop = pomp_ctx_get_loop(NULL); CU_ASSERT_PTR_NULL(loop); /* Invalid get fd (NULL param) */ fd = pomp_ctx_get_fd(NULL); CU_ASSERT_EQUAL(fd, -EINVAL); /* Get loop and fd */ loop = pomp_ctx_get_loop(data.srv.ctx); CU_ASSERT_PTR_NOT_NULL(loop); fd = pomp_ctx_get_fd(data.srv.ctx); #ifdef POMP_HAVE_LOOP_EPOLL CU_ASSERT_TRUE(fd >= 0); #else CU_ASSERT_EQUAL(fd, -ENOSYS); #endif /* Invalid process fd (NULL param) */ res = pomp_ctx_process_fd(NULL); CU_ASSERT_EQUAL(res, -EINVAL); /* Keepalive settings */ if (!isdgram) { /* TODO: check that it actually does something */ res = pomp_ctx_setup_keepalive(data.srv.ctx, 0, 0, 0, 0); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_setup_keepalive(data.srv.ctx, 1, 5, 2, 1); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_setup_keepalive(NULL, 0, 0, 0, 0); CU_ASSERT_EQUAL(res, -EINVAL); } /* Run contexts (they shall connect each other) */ run_ctx(data.srv.ctx, data.cli.ctx, 100); if (!isdgram) { CU_ASSERT_EQUAL(data.connection, 2); /* Get remote connections */ conn = pomp_ctx_get_next_conn(data.srv.ctx, NULL); CU_ASSERT_PTR_NOT_NULL(conn); conn = pomp_ctx_get_next_conn(data.srv.ctx, conn); CU_ASSERT_PTR_NULL(conn); conn = pomp_ctx_get_conn(data.cli.ctx); CU_ASSERT_PTR_NOT_NULL(conn); /* Invalid get remote connections */ conn = pomp_ctx_get_next_conn(data.cli.ctx, NULL); CU_ASSERT_PTR_NULL(conn); conn = pomp_ctx_get_conn(data.srv.ctx); CU_ASSERT_PTR_NULL(conn); conn = pomp_ctx_get_next_conn(NULL, NULL); CU_ASSERT_PTR_NULL(conn); conn = pomp_ctx_get_conn(NULL); CU_ASSERT_PTR_NULL(conn); } /* Exchange some message */ if (!isdgram) { if (!israw) { res = pomp_ctx_send(data.srv.ctx, 1, "%s", "hello1->2"); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_send(data.cli.ctx, 1, "%s", "hello2->1"); CU_ASSERT_EQUAL(res, 0); /* Invalid send (NULL param) */ res = pomp_ctx_send(NULL, 1, "%s", "hello1->2"); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_msg(data.srv.ctx, NULL); CU_ASSERT_EQUAL(res, -EINVAL); /* Invalid send (bad format) */ res = pomp_ctx_send(data.srv.ctx, 1, "%o", 1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_conn_send(pomp_ctx_get_conn(data.cli.ctx), 1, "%o", 1); CU_ASSERT_EQUAL(res, -EINVAL); /* Invalid send to (bad type) */ res = pomp_ctx_send_msg_to(data.cli.ctx, msg, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); } else { buf = pomp_buffer_new(32); CU_ASSERT_PTR_NOT_NULL_FATAL(buf); memcpy(buf->data, "Hello World !!!", 15); buf->len = 15; res = pomp_ctx_send_raw_buf(data.srv.ctx, buf); data.datasent += 15; CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_send_raw_buf(data.cli.ctx, buf); data.datasent += 15; CU_ASSERT_EQUAL(res, 0); /* Invalid send (NULL param) */ res = pomp_ctx_send_raw_buf(NULL, buf); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_raw_buf(data.srv.ctx, NULL); CU_ASSERT_EQUAL(res, -EINVAL); pomp_buffer_unref(buf); buf = NULL; } } else { if (!israw) { res = pomp_msg_clear(msg); CU_ASSERT_EQUAL(res, 0); res = pomp_msg_write(msg, 1, "%s", "hello1->2"); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_send_msg_to(data.srv.ctx, msg, addr2, addrlen2); CU_ASSERT_EQUAL(res, 0); res = pomp_msg_clear(msg); CU_ASSERT_EQUAL(res, 0); res = pomp_msg_write(msg, 1, "%s", "hello2->1"); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_send_msg_to(data.cli.ctx, msg, addr1, addrlen1); CU_ASSERT_EQUAL(res, 0); /* Invalid send (not connected) */ res = pomp_ctx_send_msg(data.cli.ctx, msg); CU_ASSERT_EQUAL(res, -ENOTCONN); /* Invalid send to (NULL param) */ res = pomp_ctx_send_msg_to(NULL, msg, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_msg_to(data.cli.ctx, NULL, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_msg_to(data.cli.ctx, msg, NULL, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); } else { buf = pomp_buffer_new(32); CU_ASSERT_PTR_NOT_NULL_FATAL(buf); memcpy(buf->data, "Hello World !!!", 15); buf->len = 15; res = pomp_ctx_send_raw_buf_to(data.srv.ctx, buf, addr2, addrlen2); CU_ASSERT_EQUAL(res, 0); data.datasent += 15; res = pomp_ctx_send_raw_buf_to(data.cli.ctx, buf, addr1, addrlen1); CU_ASSERT_EQUAL(res, 0); data.datasent += 15; /* Invalid send (not connected) */ res = pomp_ctx_send_raw_buf(data.cli.ctx, buf); CU_ASSERT_EQUAL(res, -ENOTCONN); /* Invalid send to (NULL param) */ res = pomp_ctx_send_raw_buf_to(NULL, buf, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_raw_buf_to(data.cli.ctx, NULL, addr1, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); res = pomp_ctx_send_raw_buf_to(data.cli.ctx, buf, NULL, addrlen1); CU_ASSERT_EQUAL(res, -EINVAL); pomp_buffer_unref(buf); buf = NULL; } } /* Check no send callback directly called by the sending function. */ CU_ASSERT_EQUAL(data.sendcount, 0); /* Run contexts (they shall have answered each other) */ run_ctx(data.srv.ctx, data.cli.ctx, 100); if (!israw) { CU_ASSERT_EQUAL(data.msg, 4); if (withsendcb) CU_ASSERT_EQUAL(data.sendcount, 4); } else { if (data.isdgram) CU_ASSERT_EQUAL(data.buf, 2); CU_ASSERT_EQUAL(data.dataread, data.datasent); if (withsendcb) CU_ASSERT_EQUAL(data.sendcount, 2); } /* Dummy run */ res = pomp_ctx_wait_and_process(data.srv.ctx, 100); CU_ASSERT_EQUAL(res, -ETIMEDOUT); res = pomp_ctx_wait_and_process(NULL, 100); CU_ASSERT_EQUAL(res, -EINVAL); /* Wakeup */ res = pomp_ctx_wakeup(data.srv.ctx); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_wait_and_process(data.srv.ctx, 100); CU_ASSERT_EQUAL(res, 0); /* Invalid wakeup (NULL param) */ res = pomp_ctx_wakeup(NULL); CU_ASSERT_EQUAL(res, -EINVAL); /* Overflow server by writing on client side without running loop */ if (!isdgram) { for (i = 0; i < 1024; i++) { if (buf == NULL) buf = pomp_buffer_new(1024); CU_ASSERT_PTR_NOT_NULL_FATAL(buf); for (j = 0; j < 1024; j++) buf->data[j] = rand() % 255; buf->len = 1024; if (!israw) { res = pomp_ctx_send(data.cli.ctx, 3, "%p%u", buf->data, 1024); CU_ASSERT_EQUAL(res, 0); } else { res = pomp_ctx_send_raw_buf(data.cli.ctx, buf); CU_ASSERT_EQUAL(res, 0); } if (buf->refcount > 1) { pomp_buffer_unref(buf); buf = NULL; } } if (buf != NULL) { pomp_buffer_unref(buf); buf = NULL; } /* Run contexts (to unlock writes) */ run_ctx(data.srv.ctx, data.cli.ctx, 100); if (!israw) CU_ASSERT_EQUAL(data.msg, 4 + 1024); } /* Recursive send */ if (withsendcb) { /* reset counts */ data.buf = 0; data.msg = 0; data.sendcount = 0; data.datasent = 0; data.dataread = 0; /* Enable recursive send. */ data.srv.recurs_send_enabled = 1; send_msg(&data, &data.srv, &data.cli, "srv_to_cli"); /* Check no send callback directly called by the sending function. */ CU_ASSERT_EQUAL(data.sendcount, 0); run_ctx(data.srv.ctx, data.cli.ctx, 100); if (!israw) { CU_ASSERT_EQUAL(data.msg, 2); CU_ASSERT_EQUAL(data.sendcount, 2); } else { if (data.isdgram) CU_ASSERT_EQUAL(data.buf, 2); CU_ASSERT_EQUAL(data.dataread, data.datasent); CU_ASSERT_EQUAL(data.sendcount, 2); } /* Check client recursive send during server disconnection */ data.cli.recurs_send_enabled = 1; send_msg(&data, &data.cli, &data.srv, "cli_to_srv"); } /* Disconnect client from server */ if (!isdgram) { if (withsendcb) { /* Check recursive write during disconnection */ data.srv.recurs_send_enabled = 1; data.isdisconnecting = 1; } res = pomp_conn_disconnect(pomp_ctx_get_next_conn(data.srv.ctx, NULL)); CU_ASSERT_EQUAL(res, 0); /* Check recursive send callback by disconnection */ if (withsendcb) CU_ASSERT_EQUAL(data.sendcount, 2); } /* Run contexts (they shall disconnect each other) */ run_ctx(data.srv.ctx, data.cli.ctx, 100); pomp_ctx_process_fd(data.cli.ctx); if (!isdgram) { CU_ASSERT_EQUAL(data.disconnection, 2); if (!israw) { /* Invalid send (client not connected) */ res = pomp_ctx_send(data.cli.ctx, 1, "%s", "hello2->1"); CU_ASSERT_EQUAL(res, -ENOTCONN); } else { /* TODO */ } } /* Invalid destroy (NULL param) */ res = pomp_ctx_destroy(NULL); CU_ASSERT_EQUAL(res, -EINVAL); /* Invalid destroy (busy) */ res = pomp_ctx_destroy(data.srv.ctx); CU_ASSERT_EQUAL(res, -EBUSY); /* Stop server */ res = pomp_ctx_stop(data.srv.ctx); CU_ASSERT_EQUAL(res, 0); /* Stop client */ res = pomp_ctx_stop(data.cli.ctx); CU_ASSERT_EQUAL(res, 0); /* Invalid stop (NULL param) */ res = pomp_ctx_stop(NULL); CU_ASSERT_EQUAL(res, -EINVAL); /* Stop when already done */ res = pomp_ctx_stop(data.srv.ctx); CU_ASSERT_EQUAL(res, 0); /* Destroy contexts */ res = pomp_ctx_destroy(data.srv.ctx); CU_ASSERT_EQUAL(res, 0); res = pomp_ctx_destroy(data.cli.ctx); CU_ASSERT_EQUAL(res, 0); res = pomp_msg_destroy(msg); CU_ASSERT_EQUAL(res, 0); }