osaf/libs/core/leap/tests/Makefile.am | 3 +- osaf/libs/core/leap/tests/sysf_ipc_test.cc | 275 +++++++++------------------- 2 files changed, 90 insertions(+), 188 deletions(-)
As a start, two unit test cases are written. The first unit test case, credit HansN, evaluates "jitter" using sysf_timer as an interval timer. Elapsed times are written to stdout and e.g. gnuplot can be used to display the result. gnuplot> set ylabel "u sec" gnuplot> plot "testleap.log" using 1 with lines. The second unit test case, credit AndersW, creates a large number of sysf timers. diff --git a/osaf/libs/core/leap/tests/Makefile.am b/osaf/libs/core/leap/tests/Makefile.am --- a/osaf/libs/core/leap/tests/Makefile.am +++ b/osaf/libs/core/leap/tests/Makefile.am @@ -34,7 +34,8 @@ testleap_LDFLAGS = \ -lpthread testleap_SOURCES = \ - sysf_ipc_test.cc + sysf_ipc_test.cc \ + sysf_tmr_test.cc testleap_LDADD = \ $(GTEST_DIR)/lib/libgtest.la \ diff --git a/osaf/libs/core/leap/tests/sysf_ipc_test.cc b/osaf/libs/core/leap/tests/sysf_tmr_test.cc old mode 100755 new mode 100644 copy from osaf/libs/core/leap/tests/sysf_ipc_test.cc copy to osaf/libs/core/leap/tests/sysf_tmr_test.cc --- a/osaf/libs/core/leap/tests/sysf_ipc_test.cc +++ b/osaf/libs/core/leap/tests/sysf_tmr_test.cc @@ -1,6 +1,6 @@ /* -*- OpenSAF -*- * - * (C) Copyright 2015 The OpenSAF Foundation + * (C) Copyright 2016 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 @@ -18,53 +18,27 @@ #include <iostream> #include <string> #include <thread> -#include <mutex> -#include <sched.h> -#include <poll.h> -#include <cstdlib> -#include <ctime> -#include <unistd.h> +#include <chrono> +#include <atomic> +#include <random> -#include "sysf_ipc.h" +#include "ncssysf_tmr.h" -#include "ncs_main_papi.h" #include "gtest/gtest.h" -std::mutex send_ctr_mutex; +using namespace std::chrono; -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 { +// The fixture for testing c-function sysf_tmr +class SysfTmrTest : public ::testing::Test { public: protected: - SysfIpcTest() { + SysfTmrTest() : distribution_(1 * 60 * 60 * 100, 2 * 60 * 60 * 100 - 1) { // Setup work can be done here for each test. - no_of_msgs_sent = 0; - no_of_msgs_received = 0; } - virtual ~SysfIpcTest() { + virtual ~SysfTmrTest() { // Cleanup work that doesn't throw exceptions here. } @@ -74,183 +48,110 @@ class SysfIpcTest : public ::testing::Te virtual void SetUp() { // Code here will be called immediately after the constructor (right // before each test). - int rc = ncs_leap_startup(); - // see ticket #1629, return code should be ok - //ASSERT_EQ(rc, NCSCC_RC_SUCCESS); + bool rc = sysfTmrCreate(); + ASSERT_EQ(rc, true); - 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); - 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() { - 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(); - } + bool rc = sysfTmrDestroy(); + ASSERT_EQ(rc, true); } // Objects declared here can be used by all tests in the test case. + static const int max_counter = 100; + static int counter; + static steady_clock::time_point last_time; - static SYSF_MBX mbox; - static uint32_t no_of_msgs_sent; - static uint32_t no_of_msgs_received; + static steady_clock::duration times[max_counter]; + static std::atomic<bool> finished;; + static std::atomic<bool> first_time_through; + void createIntervalTimers(int timeout_in_ms, int no_of_counters); + static void TimerCallback(void* arg); + static void IntervalTimerCallback(void *arg); + std::mt19937 generator_; + std::uniform_int_distribution<uint32_t> distribution_; + tmr_t timers_[1000000]; + static bool expired_; + }; -SYSF_MBX SysfIpcTest::mbox = 0; -uint32_t SysfIpcTest::no_of_msgs_sent = 0; -uint32_t SysfIpcTest::no_of_msgs_received = 0; +int SysfTmrTest::counter {0}; +steady_clock::time_point SysfTmrTest::last_time {}; +steady_clock::duration SysfTmrTest::times[max_counter] {}; +std::atomic<bool> SysfTmrTest::finished {false}; +std::atomic<bool> SysfTmrTest::first_time_through {true}; -void SysfIpcTest::MessageReceiver() { - NCS_SEL_OBJ mbox_fd; - pollfd fds; - bool done = false; - Message *msg; +bool SysfTmrTest::expired_ {false}; - 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); +void SysfTmrTest::IntervalTimerCallback(void *) { + if (counter >= max_counter) { + for (int i = 0; i < max_counter; i++) { + std::cout << duration_cast<microseconds>(times[i]).count() << "\n"; } - - 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; - } - } + finished = true; + return; } - { - std::lock_guard<std::mutex> lck(send_ctr_mutex); - ASSERT_EQ(no_of_msgs_received, no_of_msgs_sent); + auto elapsed = steady_clock::now(); + + if (!first_time_through) { + times[counter] = elapsed - last_time; + ++counter; + } else { + first_time_through = false; } -} -// 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); + last_time = elapsed; } -// Tests threads sending and receiving messages -TEST_F(SysfIpcTest, TestThreadsSendReceiveMessage) { - std::thread sndr_thread[5]; - srand(time(NULL)); - std::thread msg_receiver(MessageReceiver); +void SysfTmrTest::TimerCallback(void*) { + expired_ = true; +} - ASSERT_EQ(msg_receiver.joinable(), true); +void SysfTmrTest::createIntervalTimers(int timeout_in_ms, int no_of_counters) { + for (int i = 1; i <= no_of_counters; i++) { + tmr_t tmr_id = ncs_tmr_alloc((char*) __FILE__, __LINE__); + ASSERT_NE(tmr_id, nullptr); + ncs_tmr_start(tmr_id, (timeout_in_ms * i) / 10, IntervalTimerCallback, 0, (char*) __FILE__, __LINE__); + } +} - for (int i = 0; i < 5; ++i) { - sndr_thread[i] = std::thread(MessageSender); +// Tests sysf_tmr as an interval timer and measure "jitter". Timeout values are written +// to stdout and can be read by e.g. gnuplot +TEST_F(SysfTmrTest, TestIntervalTimer) { + createIntervalTimers(100, max_counter+2); + + while (!finished) { + std::this_thread::yield(); } +} - for (int i = 0; i < 5; ++i) { - sndr_thread[i].join(); +// Test creating a large number of sysf timers +TEST_F(SysfTmrTest, CreateOneMillionTimers) { + expired_ = false; + for (uint32_t i = 0; i != 1000000; ++i) { + tmr_t tmr1 = ncs_tmr_alloc((char*)__FILE__, __LINE__); + ASSERT_NE(tmr1, TMR_T_NULL); + uint32_t timeout = distribution_(generator_); + tmr_t tmr2 = ncs_tmr_start(tmr1, timeout, TimerCallback, nullptr, (char*) __FILE__, __LINE__); + ASSERT_NE(tmr2, TMR_T_NULL); + timers_[i] = tmr2; } - - sched_yield(); - - { - std::lock_guard<std::mutex> lck(send_ctr_mutex); - no_of_msgs_sent++; + for (uint32_t i = 0;;) { + ASSERT_NE(timers_[i], TMR_T_NULL); + ncs_tmr_stop(timers_[i]); + ncs_tmr_free(timers_[i]); + timers_[i] = TMR_T_NULL; + i = (i + 197167) % 1000000; + if (i == 0) break; } - - send_msg(NCS_IPC_PRIORITY_LOW, 4711); - - msg_receiver.join(); -} + for (uint32_t i = 0; i != 1000000; ++i) { + ASSERT_EQ(timers_[i], TMR_T_NULL); + } + EXPECT_EQ(expired_, false); +} \ No newline at end of file ------------------------------------------------------------------------------ Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel