configure.ac | 1 +
osaf/libs/core/leap/Makefile.am | 2 +-
osaf/libs/core/leap/tests/Makefile.am | 51 +++++
osaf/libs/core/leap/tests/test_sysf_ipc.cc | 273 +++++++++++++++++++++++++++++
4 files changed, 326 insertions(+), 1 deletions(-)
Updated to use c++11 thread support.
Additional unit test program for sysf_ipc as an example on how to write unit
tests on
self contained components in openSAF. This is an exampled that can be extended.
Updated with review comments.
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -704,6 +704,7 @@ AC_CONFIG_FILES([
osaf/libs/core/include/Makefile
osaf/libs/core/common/Makefile
osaf/libs/core/common/include/Makefile
+ osaf/libs/core/leap/tests/Makefile
osaf/libs/core/leap/Makefile
osaf/libs/core/leap/include/Makefile
osaf/libs/core/mbcsv/Makefile
diff --git a/osaf/libs/core/leap/Makefile.am b/osaf/libs/core/leap/Makefile.am
--- a/osaf/libs/core/leap/Makefile.am
+++ b/osaf/libs/core/leap/Makefile.am
@@ -18,7 +18,7 @@ include $(top_srcdir)/Makefile.common
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = include
+SUBDIRS = include tests
noinst_LTLIBRARIES = libleap.la
diff --git a/osaf/libs/core/leap/tests/Makefile.am
b/osaf/libs/core/leap/tests/Makefile.am
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/leap/tests/Makefile.am
@@ -0,0 +1,51 @@
+# -*- 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 $(top_srcdir)/Makefile.common
+
+TESTS = testleap
+
+check_PROGRAMS = testleap
+
+testleap_CXXFLAGS =$(AM_CXXFLAGS)
+
+testleap_CPPFLAGS = \
+ -DSA_CLM_B01=1 \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/osaf/libs/common/amf/include \
+ -I$(top_srcdir)/osaf/libs/common/immsv/include \
+ -I$(top_srcdir)/osaf/tools/saflog/include \
+ -I$(GTEST_DIR)/include
+
+testleap_LDFLAGS = \
+ -lpthread
+
+testleap_SOURCES = \
+ test_sysf_ipc.cc
+
+testleap_LDADD = \
+ $(GTEST_DIR)/lib/libgtest.la \
+ $(GTEST_DIR)/lib/libgtest_main.la \
+ $(top_builddir)/osaf/tools/saflog/src/libsaflog.la \
+ $(top_builddir)/osaf/tools/safimm/src/libimmutil.la \
+ $(top_builddir)/osaf/libs/core/libopensaf_core.la \
+ $(top_builddir)/osaf/libs/common/amf/libamf_common.la \
+ $(top_builddir)/osaf/libs/saf/libSaNtf/libSaNtf.la \
+ $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOi.la \
+ $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOm.la \
+ $(top_builddir)/osaf/libs/saf/libSaClm/libSaClm.la \
+ $(top_builddir)/osaf/libs/saf/libSaLog/libSaLog.la \
+ $(top_builddir)/osaf/libs/agents/infrastructure/rda/librda.la
diff --git a/osaf/libs/core/leap/tests/test_sysf_ipc.cc
b/osaf/libs/core/leap/tests/test_sysf_ipc.cc
new file mode 100755
--- /dev/null
+++ b/osaf/libs/core/leap/tests/test_sysf_ipc.cc
@@ -0,0 +1,273 @@
+/* -*- 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 <iostream>
+#include <string>
+#include <thread>
+#include <mutex>
+#include <sched.h>
+#include <poll.h>
+#include <cstdlib>
+#include <ctime>
+#include <unistd.h>
+#include <signal.h>
+
+#include "sysf_ipc.h"
+
+#include "ncs_main_papi.h"
+#include "gtest/gtest.h"
+
+std::mutex send_ctr_mutex;
+
+typedef struct message_ {
+ struct message_ *next;
+ NCS_IPC_PRIORITY prio;
+ int seq_no;
+} Message;
+
+bool mbox_clean(NCSCONTEXT arg, NCSCONTEXT msg) {
+ Message *curr;
+ Message *temp;
+
+ /* clean the entire mailbox */
+ for (curr = (Message *)msg; curr;) {
+ 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;
+ no_of_msgs_received = 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:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ int rc = ncs_leap_startup();
+ ASSERT_EQ(rc, NCSCC_RC_SUCCESS);
+
+ rc = m_NCS_IPC_CREATE(&mbox);
+ ASSERT_EQ(rc, NCSCC_RC_SUCCESS);
+
+ rc = m_NCS_IPC_ATTACH(&mbox);
+ ASSERT_EQ(rc, NCSCC_RC_SUCCESS);
+ }
+
+ 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);
+ EXPECT_EQ(rc, NCSCC_RC_SUCCESS);
+
+ rc = m_NCS_IPC_RELEASE(&mbox, 0);
+ EXPECT_EQ(rc, NCSCC_RC_SUCCESS);
+
+ 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 sighandler(int signo);
+
+ //
+ static void MessageReceiver();
+
+ //
+ static void MessageSender() {
+ Message *msg;
+ int prio;
+ srand(time(NULL));
+ int rc = NCSCC_RC_SUCCESS;
+
+ for (int i = 0; i < 60; ++i) {
+ msg = new Message;
+
+ prio = (random() % 3) + 1;
+ msg->prio = (NCS_IPC_PRIORITY) prio;
+ msg->seq_no = i;
+
+ rc = m_NCS_IPC_SEND(&mbox, msg, msg->prio);
+ EXPECT_EQ(rc, NCSCC_RC_SUCCESS);
+
+ {
+ std::lock_guard<std::mutex> lck(send_ctr_mutex);
+ no_of_msgs_sent++;
+ }
+
+ sched_yield();
+ }
+ }
+
+ // Objects declared here can be used by all tests in the test case.
+
+ static SYSF_MBX mbox;
+ static uint32_t no_of_msgs_sent;
+ static uint32_t no_of_msgs_received;
+};
+
+SYSF_MBX SysfIpcTest::mbox = 0;
+uint32_t SysfIpcTest::no_of_msgs_sent = 0;
+uint32_t SysfIpcTest::no_of_msgs_received = 0;
+
+void SysfIpcTest::sighandler(int signo) {
+ int rc = m_NCS_IPC_DETACH(&mbox, 0, 0);
+ EXPECT_EQ(rc, NCSCC_RC_SUCCESS);
+}
+
+void SysfIpcTest::MessageReceiver() {
+ NCS_SEL_OBJ mbox_fd;
+ pollfd fds;
+ bool done = false;
+ Message *msg;
+
+ 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;
+ }
+ }
+ }
+
+ {
+ std::lock_guard<std::mutex> lck(send_ctr_mutex);
+ 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));
+
+ //
+ struct sigaction actions;
+ memset(&actions, 0, sizeof(actions));
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ actions.sa_handler = sighandler;
+
+ int rc = sigaction(SIGTERM, &actions, NULL);
+ ASSERT_EQ(rc, 0);
+
+ 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();
+
+ {
+ std::lock_guard<std::mutex> lck(send_ctr_mutex);
+ no_of_msgs_sent++;
+ }
+
+ send_msg(NCS_IPC_PRIORITY_LOW, 4711);
+
+ msg_receiver.join();
+}
------------------------------------------------------------------------------
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741551&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel