From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id A402D558D for ; Tue, 2 Aug 2016 22:42:04 +0200 (CEST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP; 02 Aug 2016 13:42:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,462,1464678000"; d="scan'208";a="858502479" Received: from dwdohert-dpdk.ir.intel.com ([163.33.210.152]) by orsmga003.jf.intel.com with ESMTP; 02 Aug 2016 13:42:04 -0700 From: Declan Doherty To: dev@dpdk.org Cc: Declan Doherty Date: Tue, 2 Aug 2016 21:37:49 +0100 Message-Id: <1470170269-20721-5-git-send-email-declan.doherty@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1470170269-20721-1-git-send-email-declan.doherty@intel.com> References: <1470170269-20721-1-git-send-email-declan.doherty@intel.com> Subject: [dpdk-dev] [RFC 4/4] app/test-gtest: example google test application X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Aug 2016 20:42:06 -0000 Adds a new application to demonstrate how google test could be used as a new unit test framework. To compile both ${GTEST_DIR} and ${GMOCK_DIR} the install paths to google test and google mock directories respectively must be defined/exported. Signed-off-by: Declan Doherty --- app/Makefile | 1 + app/test-gtest/Makefile | 67 ++++++++++ app/test-gtest/main.cpp | 20 +++ app/test-gtest/test_mempool.cpp | 281 ++++++++++++++++++++++++++++++++++++++++ config/common_base | 5 + 5 files changed, 374 insertions(+) create mode 100644 app/test-gtest/Makefile create mode 100644 app/test-gtest/main.cpp create mode 100644 app/test-gtest/test_mempool.cpp diff --git a/app/Makefile b/app/Makefile index 30ec292..71cf31e 100644 --- a/app/Makefile +++ b/app/Makefile @@ -38,5 +38,6 @@ DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_test DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += proc_info DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump +DIRS-$(CONFIG_RTE_TEST_GTEST) += test-gtest include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/app/test-gtest/Makefile b/app/test-gtest/Makefile new file mode 100644 index 0000000..66dbe15 --- /dev/null +++ b/app/test-gtest/Makefile @@ -0,0 +1,67 @@ +# BSD LICENSE +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +ifneq ($(MAKECMDGOALS),clean) +ifeq ($(GTEST_DIR),) +$(error "Please define GTEST_DIR environment variable") +endif + +ifeq ($(GMOCK_DIR),) +$(error "Please define GMOCK_DIR environment variable") +endif +endif + +include $(RTE_SDK)/mk/rte.vars.mk + +# binary name +APP = test-gtest + +# all source are stored in SRCS-y +SRCS-y := main.cpp +SRCS-y += test_mempool.cpp + +CFLAGS += -O0 +CFLAGS += $(WERROR_FLAGS) + +CXXFLAGS += -std=c++11 +CXXFLAGS += -I$(GTEST_DIR)/include +CXXFLAGS += -I$(GMOCK_DIR)/include + +LDFLAGS += -lstdc++ +LDFLAGS += -L$(GMOCK_DIR) -lgmock + +# this application needs libraries first +DEPDIRS-y += lib drivers + +include $(RTE_SDK)/mk/rte.app.mk + diff --git a/app/test-gtest/main.cpp b/app/test-gtest/main.cpp new file mode 100644 index 0000000..a221823 --- /dev/null +++ b/app/test-gtest/main.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + /* Initialise DPDK EAL */ + int ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); + argc -= ret; + argv += ret; + + testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/app/test-gtest/test_mempool.cpp b/app/test-gtest/test_mempool.cpp new file mode 100644 index 0000000..4c3f7e2 --- /dev/null +++ b/app/test-gtest/test_mempool.cpp @@ -0,0 +1,281 @@ +#include +#include + +#include + +#include +#include +#include +#include + +class MemoryPool : public ::testing::Test { + +protected: + + virtual void SetUp() { + mp = NULL; + mempool_elements = (rte_lcore_count() * (lcore_cache_size + + RTE_MEMPOOL_CACHE_MAX_SIZE) -1); + } + + virtual void TearDown() { + if (mp) + rte_mempool_free(mp); + + } + + /* + * save the object number in the first 4 bytes of object data. All + * other bytes are set to 0. + */ + static void + obj_initializer_fn(struct rte_mempool *mp, void *arg __rte_unused, + void *obj, unsigned i) + { + uint32_t *objnum = (uint32_t *)obj; + + memset(obj, 0, mp->elt_size); + *objnum = i; + } + + struct rte_mempool *mp; + + static const unsigned element_size = 2048; + static const uint32_t lcore_cache_size = 16; + + unsigned mempool_elements; +}; + +TEST_F(MemoryPool, CreateWithNoCache) +{ + mp = rte_mempool_create("test_nocache", mempool_elements, element_size, + 0, 0, NULL, NULL, obj_initializer_fn, NULL, + SOCKET_ID_ANY, 0); + + ASSERT_NE(mp, (void *)NULL); + + EXPECT_EQ(mp, rte_mempool_lookup("test_nocache")); + EXPECT_EQ(rte_mempool_avail_count(mp), mempool_elements); +} + +TEST_F(MemoryPool, CreateWithCache) +{ + mp = rte_mempool_create("test_cache", mempool_elements, element_size, + RTE_MEMPOOL_CACHE_MAX_SIZE, 0, NULL, NULL, + obj_initializer_fn, NULL, SOCKET_ID_ANY, 0); + + ASSERT_NE(mp, (void *)NULL); + + EXPECT_EQ(mp, rte_mempool_lookup("test_cache")); + EXPECT_EQ(rte_mempool_avail_count(mp), mempool_elements); +} + +TEST_F(MemoryPool, ExceedMaxCacheSize) +{ + mp = rte_mempool_create("test_exceed_max_cache_sz", + mempool_elements, element_size, + RTE_MEMPOOL_CACHE_MAX_SIZE + 1, 0, NULL, NULL, + obj_initializer_fn, NULL, SOCKET_ID_ANY, 0); + + ASSERT_EQ(mp, (void *)NULL); +} + +TEST_F(MemoryPool, MempoolNameCollosion) { + mp = rte_mempool_create("test_name_collosion", mempool_elements, + element_size, RTE_MEMPOOL_CACHE_MAX_SIZE, 0, NULL, NULL, + obj_initializer_fn, NULL, SOCKET_ID_ANY, 0); + + ASSERT_NE(mp, (void *)NULL); + + ASSERT_EQ(rte_mempool_create("test_name_collosion", mempool_elements, + element_size, RTE_MEMPOOL_CACHE_MAX_SIZE, 0, NULL, NULL, + obj_initializer_fn, NULL, SOCKET_ID_ANY, 0), + (struct rte_mempool *)NULL); +} + +TEST_F(MemoryPool, ExternalMemorySize) { + size_t sz; + ssize_t usz; + + uint32_t obj_size = rte_mempool_calc_obj_size(element_size, 0, NULL); + + sz = rte_mempool_xmem_size(mempool_elements, obj_size, + MEMPOOL_PG_SHIFT_MAX); + + usz = rte_mempool_xmem_usage(NULL, mempool_elements, obj_size, 0, 1, + MEMPOOL_PG_SHIFT_MAX); + + EXPECT_EQ(sz, (size_t)usz); +} + + +class MempoolMock { +public: + + MOCK_METHOD2(MempoolInitializerMockFn, + void(struct rte_mempool *, void *)); + + MOCK_METHOD4(MempoolObjInitializerMockFn, + void(struct rte_mempool *, void *arg, void *, unsigned)); + + static MempoolMock *obj; + + static void mempool_initializer_fn(struct rte_mempool *mp, void * arg) + { + obj->MempoolInitializerMockFn(mp, arg); + } + + static void mempool_obj_initializer_fn(struct rte_mempool *mp, + void *arg, void *m_obj, unsigned i) + { + obj->MempoolObjInitializerMockFn(mp, arg, m_obj, i); + } +}; + + +MempoolMock * MempoolMock::obj; + +TEST_F(MemoryPool, MempoolInitialization) +{ + MempoolMock mock; + MempoolMock::obj = &mock; + + + EXPECT_CALL(mock, MempoolInitializerMockFn(::testing::_, ::testing::_)) + .Times(1); + + EXPECT_CALL(mock, MempoolObjInitializerMockFn( + ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(mempool_elements); + + mp = rte_mempool_create("test_nocache", mempool_elements, + element_size, 0, 0, + MempoolMock::mempool_initializer_fn, NULL, + MempoolMock::mempool_obj_initializer_fn, NULL, + SOCKET_ID_ANY, 0); + ASSERT_NE(mp, (void *)NULL); + + EXPECT_EQ(rte_mempool_full(mp), 1); +} + + +class MemoryPoolWithNoCache : public MemoryPool { +protected : + virtual void SetUp() { + mempool_elements = (rte_lcore_count() * (lcore_cache_size + + RTE_MEMPOOL_CACHE_MAX_SIZE) -1); + + objs = (void **)malloc(mempool_elements * sizeof(void *)); + + mp = rte_mempool_create("test_nocache", mempool_elements, + element_size, 0, 0, NULL, NULL, + obj_initializer_fn, NULL, SOCKET_ID_ANY, 0); + ASSERT_NE(mp, (void *)NULL); + + EXPECT_EQ(rte_mempool_full(mp), 1); + + } + + virtual void TearDown() { + if (mp) + rte_mempool_free(mp); + + if (objs) + free(objs); + + } + + void **objs; + int i; +}; + +TEST_F(MemoryPoolWithNoCache, GetOneObjectPutOneObject) +{ + /* Get an object for mempool */ + ASSERT_EQ(rte_mempool_get(mp, &objs[0]), 0); + + /* Verify object count in mempool */ + EXPECT_EQ(rte_mempool_avail_count(mp), mempool_elements -1); + + /* Verify physical address of an object */ + +#ifndef RTE_EXEC_ENV_BSDAPP + /* rte_mem_virt2phy() not supported on BSD */ + EXPECT_EQ(rte_mempool_virt2phy(mp, objs[0]), rte_mem_virt2phy(objs[0])); +#endif + + /* put the object back */ + rte_mempool_put(mp, objs[0]); + + EXPECT_EQ(rte_mempool_avail_count(mp), mempool_elements); +} + +TEST_F(MemoryPoolWithNoCache, GetAllObjectsPutAllObjects) +{ + /* Get all objects from mempool */ + for (i = 0; i < mempool_elements; i++) { + EXPECT_EQ(rte_mempool_get(mp, &objs[i]), 0); + /* Verify physical address of an object */ +#ifndef RTE_EXEC_ENV_BSDAPP + EXPECT_EQ(rte_mempool_virt2phy(mp, objs[i]), + rte_mem_virt2phy(objs[i])); +#endif + } + + /* Verify object count in mempool */ + EXPECT_EQ(rte_mempool_avail_count(mp), 0); + + + /* Put the objects back */ + for (i = 0; i < mempool_elements; i++) { + rte_mempool_put(mp, objs[i]); + } + + EXPECT_EQ(rte_mempool_avail_count(mp), mempool_elements); +} + +TEST_F(MemoryPoolWithNoCache, GetOjectFromEmptyMempool) +{ + void *err_obj = NULL; + + for (i = 0; i < mempool_elements; i++) + EXPECT_EQ(rte_mempool_get(mp, &objs[i]), 0); + + EXPECT_EQ(rte_mempool_empty(mp), 1); + + EXPECT_LT(rte_mempool_get(mp, &err_obj), 0); + EXPECT_EQ(err_obj, (void *)NULL); + + for (i = 0; i < mempool_elements; i++) + rte_mempool_put(mp, objs[i]); + + EXPECT_EQ(rte_mempool_full(mp), 1); + // printf("test_mempool_basic_ex the mempool should be full\n"); +} + + + +class MemoryPoolSingleProducerSingleConsumer : public MemoryPool { +protected: + virtual void SetUp() { + lcore_id = rte_lcore_id(); + + mempool_elements = (rte_lcore_count() * (lcore_cache_size + + RTE_MEMPOOL_CACHE_MAX_SIZE) -1); + + mp = rte_mempool_create("single_producer_consumer", + mempool_elements, element_size, 0, 0, + NULL, NULL, + obj_initializer_fn, NULL, + SOCKET_ID_ANY, + MEMPOOL_F_NO_CACHE_ALIGN | + MEMPOOL_F_SP_PUT | + MEMPOOL_F_SC_GET); + + ASSERT_NE(mp, (void *)NULL); + + EXPECT_EQ(rte_mempool_full(mp), 1); + } + + unsigned lcore_id, lcore_next; +}; diff --git a/config/common_base b/config/common_base index 7830535..6ef4de6 100644 --- a/config/common_base +++ b/config/common_base @@ -579,6 +579,11 @@ CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n # +# Compile the google test unit tests +# +CONFIG_RTE_TEST_GTEST=y + +# # Compile the PMD test application # CONFIG_RTE_TEST_PMD=y -- 2.5.5