ncs_leap_startup return code error if the node_id file is missing. The return code error is expected. But in the ticket-3266 support for running agent before opensafd. So the test case SysfIpcTest need to running under opensaf cluster.
In this ticket, I move the unit test run as google-test to the apitest --- opensaf.spec.in | 1 + src/base/Makefile.am | 19 ++- src/base/apitest/Makefile.am | 18 +++ src/base/apitest/basetest.c | 78 +++++++++ src/base/apitest/basetest.h | 28 ++++ src/base/apitest/sysf_ipc_test.c | 265 +++++++++++++++++++++++++++++++ src/base/tests/sysf_ipc_test.cc | 238 --------------------------- 7 files changed, 408 insertions(+), 239 deletions(-) create mode 100644 src/base/apitest/Makefile.am create mode 100644 src/base/apitest/basetest.c create mode 100644 src/base/apitest/basetest.h create mode 100644 src/base/apitest/sysf_ipc_test.c delete mode 100644 src/base/tests/sysf_ipc_test.cc diff --git a/opensaf.spec.in b/opensaf.spec.in index 6c6b61500..703615af0 100644 --- a/opensaf.spec.in +++ b/opensaf.spec.in @@ -1526,6 +1526,7 @@ fi %{_bindir}/logtest %{_bindir}/saflogtest %{_bindir}/logtestfr +%{_bindir}/basetest %{_bindir}/msgtest %{_bindir}/ntftest %{_bindir}/ntf_search_criteria_test.sh diff --git a/src/base/Makefile.am b/src/base/Makefile.am index 5082175cf..367b21910 100644 --- a/src/base/Makefile.am +++ b/src/base/Makefile.am @@ -191,7 +191,6 @@ bin_testleap_LDFLAGS = \ bin_testleap_SOURCES = \ src/base/tests/sa_tmr_test.cc \ - src/base/tests/sysf_ipc_test.cc \ src/base/tests/sysf_tmr_test.cc bin_testleap_LDADD = \ @@ -280,3 +279,21 @@ bin_core_common_test_LDADD = \ $(GTEST_DIR)/lib/libgtest_main.la \ $(GMOCK_DIR)/lib/libgmock.la \ $(GMOCK_DIR)/lib/libgmock_main.la + +bin_PROGRAMS += bin/basetest + +noinst_HEADERS += \ + src/base/apitest/basetest.h + +bin_basetest_CFLAGS = $(AM_CFLAGS) -Wformat=1 + +bin_basetest_CPPFLAGS = $(AM_CPPFLAGS) + +bin_basetest_SOURCES = \ + src/base/apitest/basetest.c \ + src/base/apitest/sysf_ipc_test.c + +bin_basetest_LDADD = \ + lib/libapitest.la \ + lib/libosaf_common.la \ + lib/libopensaf_core.la diff --git a/src/base/apitest/Makefile.am b/src/base/apitest/Makefile.am new file mode 100644 index 000000000..6abef4edb --- /dev/null +++ b/src/base/apitest/Makefile.am @@ -0,0 +1,18 @@ +# -*- OpenSAF -*- +# +# (C) Copyright 2021 The OpenSAF Foundation +# +# This program 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. This file and program are licensed +# under the GNU Lesser General Public License Version 2.1, February 1999. +# The complete license can be accessed from the following location: +# http://opensource.org/licenses/lgpl-license.php +# See the Copying file included with the OpenSAF distribution for full +# licensing terms. +# +# Author(s): Ericsson AB +# + +all: + $(MAKE) -C ../../.. bin/basetest diff --git a/src/base/apitest/basetest.c b/src/base/apitest/basetest.c new file mode 100644 index 000000000..6af7e9329 --- /dev/null +++ b/src/base/apitest/basetest.c @@ -0,0 +1,78 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2021 The OpenSAF Foundation + * + * This program 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. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#include "base/apitest/basetest.h" +#include <unistd.h> + +void usage(const char *progname) +{ + printf("Usage: %s [-h] [--help] [suite [testcase]]\n\n", progname); + printf("OPTIONS:\n"); + printf("\t-h, --help this help\n"); + printf("\tsuite suite for testing. 0 for listing all tests\n"); + printf("\ttestcase test case for testing in specific suite\n"); +} + +int main(int argc, char **argv) +{ + int suite = ALL_SUITES, tcase = ALL_TESTS; + int rc = 0; + int i; + int index = 0; + int failed = 0; + char *endptr; + + srandom(getpid()); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(basename(argv[0])); + return 0; + } else if (index == 0) { + suite = strtol(argv[i], &endptr, 10); + if (endptr && *endptr) { + failed = 1; + } else { + index++; + } + } else if (index == 1) { + tcase = strtol(argv[i], &endptr, 10); + if (endptr && *endptr) { + failed = 1; + } else { + index++; + } + } else { + failed = 1; + } + + if (failed) { + fprintf(stderr, + "Try '%s --help' for more information\n", + argv[0]); + return EXIT_FAILURE; + } + } + + if (suite == 0) { + test_list(); + } else { + rc = test_run(suite, tcase); + } + + return rc; +} diff --git a/src/base/apitest/basetest.h b/src/base/apitest/basetest.h new file mode 100644 index 000000000..9217b36f2 --- /dev/null +++ b/src/base/apitest/basetest.h @@ -0,0 +1,28 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2021 The OpenSAF Foundation + * + * This program 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. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#ifndef BASE_APITEST_BASETEST_H_ +#define BASE_APITEST_BASETEST_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "osaf/apitest/utest.h" +#include "osaf/apitest/util.h" + +#endif // BASE_APITEST_BASETEST_H_ diff --git a/src/base/apitest/sysf_ipc_test.c b/src/base/apitest/sysf_ipc_test.c new file mode 100644 index 000000000..dcdcfce07 --- /dev/null +++ b/src/base/apitest/sysf_ipc_test.c @@ -0,0 +1,265 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2021 The OpenSAF Foundation + * + * This program 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. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#include "base/apitest/basetest.h" +#include "base/ncs_main_papi.h" +#include "base/sysf_ipc.h" +#include <poll.h> +#include <pthread.h> +#include <sched.h> +#include <stdatomic.h> +#include <string.h> +#include <unistd.h> + +atomic_int no_of_msgs_sent; +SYSF_MBX mbox; + +typedef struct message_ { + struct message_ *next; + NCS_IPC_PRIORITY prio; + int seq_no; +} Message; + +static bool mbox_clean(NCSCONTEXT arg, NCSCONTEXT msg) +{ + Message *curr; + + /* clean the entire mailbox */ + for (curr = (Message *)msg; curr;) { + Message *temp = curr; + curr = curr->next; + + free(temp); + } + return true; +} + +static int send_msg(NCS_IPC_PRIORITY prio, int seq_no) +{ + Message *msg = NULL; + + msg = (Message *)calloc(1, sizeof(Message)); + msg->prio = prio; + msg->seq_no = seq_no; + return m_NCS_IPC_SEND(&mbox, msg, prio); +} + +static bool recv_msg(NCS_IPC_PRIORITY prio, int seq_no) +{ + Message *msg; + + bool is_success = false; + + msg = (Message *)(ncs_ipc_non_blk_recv(&mbox)); + if (msg == NULL) { + fprintf(stderr, "ncs_ipc_non_blk_recv failed\n"); + } else { + is_success = msg->prio == prio && msg->seq_no == seq_no; + free(msg); + } + return is_success; +} + +static void *message_sender() +{ + srand(time(NULL)); + + Message *msg = NULL; + for (int i = 0; i < 60; ++i) { + int prio = (random() % 3) + 1; + msg = (Message *)calloc(1, sizeof(Message)); + msg->prio = (NCS_IPC_PRIORITY)prio; + msg->seq_no = i; + + int rc = m_NCS_IPC_SEND(&mbox, msg, msg->prio); + assert(rc == NCSCC_RC_SUCCESS && "m_NCS_IPC_SEND failed"); + + no_of_msgs_sent++; + + sched_yield(); + } + return NULL; +} + +static void *message_receiver() +{ + NCS_SEL_OBJ mbox_fd; + struct pollfd fds; + bool done = false; + Message *msg; + int no_of_msgs_received = 0; + + mbox_fd = ncs_ipc_get_sel_obj(&mbox); + + fds.fd = mbox_fd.rmv_obj; + fds.events = POLLIN; + + while (!done) { + int rc = poll(&fds, 1, -1); + + if (rc == -1) { + if (errno == EINTR) { + continue; + } + assert(rc == 0); + } + + if (fds.revents & POLLIN) { + while ((msg = (Message *)(ncs_ipc_non_blk_recv( + &mbox))) != NULL) { + no_of_msgs_received++; + + if (msg->seq_no == 4711) { + done = true; + } + free(msg); + } + } + } + + rc_validate(no_of_msgs_received, no_of_msgs_sent); + return NULL; +} + +void test_send_receive_message(void) +{ + Message *msg; + int rc = NCSCC_RC_SUCCESS; + + if ((rc = ncs_leap_startup()) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "ncs_leap_startup failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto leap_shutdown; + } + + if ((rc = m_NCS_IPC_CREATE(&mbox)) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_CREATE failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto ipc_release; + } + + if ((rc = m_NCS_IPC_ATTACH(&mbox)) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_ATTACH failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto ipc_detach; + } + + NCS_IPC_PRIORITY prio[] = { + NCS_IPC_PRIORITY_LOW, NCS_IPC_PRIORITY_NORMAL, + NCS_IPC_PRIORITY_HIGH, NCS_IPC_PRIORITY_VERY_HIGH}; + // send messages + for (size_t i = 0; i < 8; i++) { + if ((rc = send_msg(prio[i / 2], i % 2 == 0 ? 1 : 2)) != + NCSCC_RC_SUCCESS) { + test_validate(rc, NCSCC_RC_SUCCESS); + goto tear_down; + } + } + + // receive messages + for (size_t i = 8; i > 0; i--) { + if (!recv_msg(prio[(i - 1) / 2], i % 2 == 0 ? 1 : 2)) { + test_validate(false, true); + goto tear_down; + } + } + + msg = (Message *)(ncs_ipc_non_blk_recv(&mbox)); + bool is_null = msg == NULL ? true : false; + test_validate(is_null, true); + +tear_down: +ipc_detach: + if (m_NCS_IPC_DETACH(&mbox, mbox_clean, 0) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_DETACH failed\n"); + } + +ipc_release: + if (m_NCS_IPC_RELEASE(&mbox, 0) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_RELEASE failed\n"); + } + +leap_shutdown: + ncs_leap_shutdown(); +} + +void test_thread_send_receive_message(void) +{ + pthread_t sndr_thread[5]; + pthread_t msg_receiver; + int rc = NCSCC_RC_SUCCESS; + + if ((rc = ncs_leap_startup()) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "ncs_leap_startup failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto leap_shutdown; + } + + if ((rc = m_NCS_IPC_CREATE(&mbox)) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_CREATE failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto ipc_release; + } + + if ((rc = m_NCS_IPC_ATTACH(&mbox)) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_ATTACH failed\n"); + test_validate(rc, NCSCC_RC_SUCCESS); + goto ipc_detach; + } + + srand(time(NULL)); + assert(!pthread_create(&msg_receiver, NULL, message_receiver, NULL)); + + for (int i = 0; i < 5; ++i) { + assert(!pthread_create(&sndr_thread[i], NULL, message_sender, + NULL)); + } + + for (int i = 0; i < 5; ++i) { + pthread_join(sndr_thread[i], NULL); + } + + sched_yield(); + + no_of_msgs_sent++; + + send_msg(NCS_IPC_PRIORITY_LOW, 4711); + + pthread_join(msg_receiver, NULL); + +ipc_detach: + if (m_NCS_IPC_DETACH(&mbox, mbox_clean, 0) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_DETACH failed\n"); + } + +ipc_release: + if (m_NCS_IPC_RELEASE(&mbox, 0) != NCSCC_RC_SUCCESS) { + fprintf(stderr, "m_NCS_IPC_RELEASE failed\n"); + } + +leap_shutdown: + ncs_leap_shutdown(); +} + +__attribute__((constructor)) static void sysf_ipc_test_constructor(void) +{ + test_suite_add(1, "SysfIpcTest"); + test_case_add(1, test_send_receive_message, + "Tests send and receive messages"); + test_case_add(1, test_thread_send_receive_message, + "Tests threads sending and receiving messages"); +} diff --git a/src/base/tests/sysf_ipc_test.cc b/src/base/tests/sysf_ipc_test.cc deleted file mode 100644 index c6ce83197..000000000 --- a/src/base/tests/sysf_ipc_test.cc +++ /dev/null @@ -1,238 +0,0 @@ -/* -*- OpenSAF -*- - * - * (C) Copyright 2015 The OpenSAF Foundation - * - * This program 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. This file and program are licensed - * under the GNU Lesser General Public License Version 2.1, February 1999. - * The complete license can be accessed from the following location: - * http://opensource.org/licenses/lgpl-license.php - * See the Copying file included with the OpenSAF distribution for full - * licensing terms. - * - * Author(s): Ericsson AB - * - */ - -#include <poll.h> -#include <sched.h> -#include <unistd.h> -#include <atomic> -#include <cstdlib> -#include <ctime> -#include <iostream> -#include <string> -#include <thread> -#include "base/ncs_main_papi.h" -#include "base/sysf_ipc.h" -#include "gtest/gtest.h" - -typedef struct message_ { - struct message_ *next; - NCS_IPC_PRIORITY prio; - int seq_no; -} Message; - -bool mbox_clean(NCSCONTEXT arg, NCSCONTEXT msg) { - Message *curr; - - /* clean the entire mailbox */ - for (curr = (Message *)msg; curr;) { - Message *temp = curr; - curr = curr->next; - - delete temp; - } - return true; -} - -// The fixture for testing c-function sysf_ipc -class SysfIpcTest : public ::testing::Test { - public: - protected: - SysfIpcTest() { - // Setup work can be done here for each test. - no_of_msgs_sent = 0; - } - - virtual ~SysfIpcTest() { - // Cleanup work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - // cppcheck-suppress unusedFunction - virtual void SetUp() { - // Code here will be called immediately after the constructor (right - // before each test). - ncs_leap_startup(); - // see ticket #1629, return code should be ok - // ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - - int rc = m_NCS_IPC_CREATE(&mbox); - ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - - rc = m_NCS_IPC_ATTACH(&mbox); - ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - } - - // cppcheck-suppress unusedFunction - virtual void TearDown() { - // Code here will be called immediately after each test (right - // before the destructor). - int rc = m_NCS_IPC_DETACH(&mbox, mbox_clean, 0); - ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - - rc = m_NCS_IPC_RELEASE(&mbox, 0); - ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - - // see ticket #1629, calling ncs_leap_shutdown causes a segv. - // ncs_leap_shutdown(); - } - - void send_msg(NCS_IPC_PRIORITY prio, int seq_no) { - Message *msg; - - msg = new Message; - msg->prio = prio; - msg->seq_no = seq_no; - int rc = m_NCS_IPC_SEND(&mbox, msg, prio); - ASSERT_EQ(rc, NCSCC_RC_SUCCESS); - } - - void recv_msg(NCS_IPC_PRIORITY prio, int seq_no) { - Message *msg; - - msg = reinterpret_cast<Message *>(ncs_ipc_non_blk_recv(&mbox)); - ASSERT_TRUE(msg != NULL); - ASSERT_EQ(msg->prio, prio); - ASSERT_EQ(msg->seq_no, seq_no); - delete msg; - } - - // - static void MessageReceiver(); - - // - static void MessageSender() { - srand(time(NULL)); - - for (int i = 0; i < 60; ++i) { - Message *msg = new Message; - - int prio = (random() % 3) + 1; - msg->prio = (NCS_IPC_PRIORITY)prio; - msg->seq_no = i; - - int rc = m_NCS_IPC_SEND(&mbox, msg, msg->prio); - EXPECT_EQ(rc, NCSCC_RC_SUCCESS); - - no_of_msgs_sent++; - - sched_yield(); - } - } - - // Objects declared here can be used by all tests in the test case. - - static SYSF_MBX mbox; - static std::atomic<int> no_of_msgs_sent; -}; - -SYSF_MBX SysfIpcTest::mbox{0}; -std::atomic<int> SysfIpcTest::no_of_msgs_sent{0}; - -void SysfIpcTest::MessageReceiver() { - NCS_SEL_OBJ mbox_fd; - pollfd fds; - bool done = false; - Message *msg; - int no_of_msgs_received{0}; - - mbox_fd = ncs_ipc_get_sel_obj(&mbox); - - fds.fd = mbox_fd.rmv_obj; - fds.events = POLLIN; - - while (!done) { - int rc = poll(&fds, 1, -1); - - if (rc == -1) { - if (errno == EINTR) { - continue; - } - ASSERT_EQ(rc, 0); - } - - if (fds.revents & POLLIN) { - while ((msg = reinterpret_cast<Message *>(ncs_ipc_non_blk_recv(&mbox))) != - NULL) { - no_of_msgs_received++; - - if (msg->seq_no == 4711) { - done = true; - } - - delete msg; - } - } - } - - ASSERT_EQ(no_of_msgs_received, no_of_msgs_sent); -} - -// Tests send and receive -TEST_F(SysfIpcTest, TestSendReceiveMessage) { - Message *msg; - - // send messages - send_msg(NCS_IPC_PRIORITY_LOW, 1); - send_msg(NCS_IPC_PRIORITY_LOW, 2); - send_msg(NCS_IPC_PRIORITY_NORMAL, 1); - send_msg(NCS_IPC_PRIORITY_NORMAL, 2); - send_msg(NCS_IPC_PRIORITY_HIGH, 1); - send_msg(NCS_IPC_PRIORITY_HIGH, 2); - send_msg(NCS_IPC_PRIORITY_VERY_HIGH, 1); - send_msg(NCS_IPC_PRIORITY_VERY_HIGH, 2); - - // receive messages - recv_msg(NCS_IPC_PRIORITY_VERY_HIGH, 1); - recv_msg(NCS_IPC_PRIORITY_VERY_HIGH, 2); - recv_msg(NCS_IPC_PRIORITY_HIGH, 1); - recv_msg(NCS_IPC_PRIORITY_HIGH, 2); - recv_msg(NCS_IPC_PRIORITY_NORMAL, 1); - recv_msg(NCS_IPC_PRIORITY_NORMAL, 2); - recv_msg(NCS_IPC_PRIORITY_LOW, 1); - recv_msg(NCS_IPC_PRIORITY_LOW, 2); - - msg = reinterpret_cast<Message *>(ncs_ipc_non_blk_recv(&mbox)); - EXPECT_TRUE(msg == NULL); -} - -// Tests threads sending and receiving messages -TEST_F(SysfIpcTest, TestThreadsSendReceiveMessage) { - std::thread sndr_thread[5]; - srand(time(NULL)); - - std::thread msg_receiver{MessageReceiver}; - - ASSERT_EQ(msg_receiver.joinable(), true); - - for (int i = 0; i < 5; ++i) { - sndr_thread[i] = std::thread{MessageSender}; - } - - for (int i = 0; i < 5; ++i) { - sndr_thread[i].join(); - } - - sched_yield(); - - no_of_msgs_sent++; - - send_msg(NCS_IPC_PRIORITY_LOW, 4711); - - msg_receiver.join(); -} -- 2.25.1 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel