#include #include #include #include #include class VNodeOpsWrapper { public: static void* tunnel_new(const char* symbol, unsigned int size) { return rte_ring_create(symbol, size, SOCKET_ID_ANY, RING_F_SC_DEQ | RING_F_SP_ENQ); } static int tunnel_delete(void* ring) { rte_ring_free((struct rte_ring *)ring); return 0; } static int tunnel_enqueue(void* ring, void* objects[], int nr_objects) { struct rte_ring* _ring = (struct rte_ring *)ring; return rte_ring_enqueue_burst(_ring, objects, nr_objects); } static int tunnel_dequeue(void* ring, void* objects[], int nr_max_objects) { struct rte_ring* _ring = (struct rte_ring *)ring; return rte_ring_dequeue_burst(_ring, objects, nr_max_objects); } }; /// 测试用例基类,只提供操作函数的初始化 class TestCaseVNodeBase : public ::testing::Test { protected: struct vnode_ops* vnode_ops_; TestCaseVNodeBase() : vnode_ops_(new struct vnode_ops) { } ~TestCaseVNodeBase() { delete vnode_ops_; } }; /// 测试用例,测试VNode节点的创建和初始化 TEST_F(TestCaseVNodeBase, TestVNodeCreate) { std::string strVNodeSym = "TVNCreate"; struct vnode* node = vnode_create(strVNodeSym.c_str(), vnode_ops_, 512, 8); ASSERT_TRUE(node != NULL); EXPECT_STREQ(node->symbol, strVNodeSym.c_str()); EXPECT_EQ(node->nr_cons, 0); EXPECT_EQ(node->nr_prod, 0); } /// 测试用例,测试VNode的销毁过程 TEST_F(TestCaseVNodeBase, TestVNodeDelete) { std::string strVNodeSym = "TVNDelete"; struct vnode* node = vnode_create(strVNodeSym.c_str(), vnode_ops_, 512, 8); ASSERT_TRUE(node != NULL); EXPECT_STREQ(node->symbol, strVNodeSym.c_str()); EXPECT_EQ(node->nr_cons, 0); EXPECT_EQ(node->nr_prod, 0); int ret = vnode_delete(node, vnode_ops_); EXPECT_EQ(ret, 0); } /// 测试Case,测试VNode的各项操作。VNode的创建在本测试Case中完成。 class TestCaseVNodeOps : public TestCaseVNodeBase { protected: struct vnode* node_; TestCaseVNodeOps() : TestCaseVNodeBase(), node_(NULL) { } virtual void SetUp() { node_ = vnode_create("TVNOps", vnode_ops_, 512, 8); ASSERT_TRUE(node_ != NULL); } virtual void TearDown() { ASSERT_TRUE(node_ != NULL); vnode_delete(node_, vnode_ops_); } }; /// 测试用例,测试VNode创建生产者的过程。 TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteProd) { struct vnode_prod* prod; std::string strProdSym = "VProd1"; prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10); ASSERT_TRUE(prod != NULL); EXPECT_STREQ(prod->symbol, strProdSym.c_str()); vnode_delete_prod(prod, vnode_ops_); } /// 测试用例,测试VNode创建消费者的过程。 TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteCons) { struct vnode_cons* cons; std::string strConsSym = "VCons2"; cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10); ASSERT_TRUE(cons != NULL); EXPECT_STREQ(cons->symbol, strConsSym.c_str()); vnode_delete_cons(cons, vnode_ops_); } /// 测试用例,测试生产者、消费者共同创建过程 TEST_F(TestCaseVNodeOps, TestVNodeProdConsCreate) { struct vnode_prod* prod; std::string strProdSym = "VProd3"; prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10); struct vnode_cons* cons; std::string strConsSym = "VCons4"; cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10); ASSERT_TRUE(prod != NULL); ASSERT_TRUE(cons != NULL); EXPECT_EQ(node_->nr_cons, 1); EXPECT_EQ(node_->nr_prod, 1); vnode_delete_prod(prod, vnode_ops_); vnode_delete_cons(cons, vnode_ops_); } TEST_F(TestCaseVNodeOps, TestVNodeProdConsLookup) { struct vnode_prod* prod; std::string strProdSym = "VProd5"; prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10); struct vnode_cons* cons; std::string strConsSym = "VCons6"; cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10); struct vnode_prod* prod_lookup; prod_lookup = vnode_prod_lookup(node_, strProdSym.c_str()); EXPECT_EQ(prod_lookup, prod); struct vnode_cons* cons_lookup; cons_lookup = vnode_cons_lookup(node_, strConsSym.c_str()); EXPECT_EQ(cons_lookup, cons); prod_lookup = vnode_prod_lookup(node_, ""); EXPECT_TRUE(prod_lookup == NULL); cons_lookup = vnode_cons_lookup(node_, ""); EXPECT_TRUE(cons_lookup == NULL); vnode_delete_prod(prod, vnode_ops_); vnode_delete_cons(cons, vnode_ops_); } class TestCaseVNodeDataOps : public TestCaseVNodeBase { protected: struct vnode* node_; struct vnode_prod* prod_; struct vnode_cons* cons_; void** buff_send_; void** buff_recv_; uint32_t* hash_; unsigned int bufsize_; static struct rte_mempool* pool_; TestCaseVNodeDataOps() : TestCaseVNodeBase(), node_(NULL), prod_(NULL), cons_(NULL), buff_send_(NULL), buff_recv_(NULL), hash_(NULL), bufsize_(128) { } static void SetUpTestCase() { TestCaseVNodeOps::SetUpTestCase(); pool_ = rte_pktmbuf_pool_create("TCVNDataOpsPool", 8192, 512, 0, 512, SOCKET_ID_ANY); ASSERT_TRUE(pool_ != NULL); } static void TearDownTestCase() { TestCaseVNodeOps::TearDownTestCase(); return; } virtual void VNodeCreate() { node_ = vnode_create("TVNOps", vnode_ops_, 512, 0); ASSERT_TRUE(node_ != NULL); } virtual void VNodeProdCreate() { std::string strProdSym = "Prod"; prod_ = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 1); } virtual void VNodeConsCreate() { std::string strConsSym = "Cons"; cons_ = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 1); } virtual void SetUp() { buff_send_ = new void*[bufsize_]; buff_recv_ = new void*[bufsize_]; hash_ = new uint32_t[bufsize_]; VNodeCreate(); VNodeProdCreate(); VNodeConsCreate(); } virtual void TearDown() { vnode_delete_prod(prod_, vnode_ops_); vnode_delete_cons(cons_, vnode_ops_); vnode_delete(node_, vnode_ops_); delete[] buff_send_; delete[] buff_recv_; delete[] hash_; } }; struct rte_mempool* TestCaseVNodeDataOps::pool_; TEST_F(TestCaseVNodeDataOps, TestSimpleEnqueueDequeue) { buff_send_[0] = rte_pktmbuf_alloc(pool_); hash_[0] = 0; ASSERT_TRUE(buff_send_[0] != NULL); vnode_enqueue_burst_with_hash(prod_, vnode_ops_, 0, buff_send_, hash_, 1); int ret = vnode_dequeue_burst(cons_, vnode_ops_, 0, buff_recv_, 128); EXPECT_EQ(ret, 1); EXPECT_EQ(buff_recv_[0], buff_send_[0]); } TEST_F(TestCaseVNodeDataOps, TestMoreEnqueueDequeue) { for (int i = 0; i < 128; i++) { buff_send_[i] = rte_pktmbuf_alloc(pool_); hash_[i] = 1; ASSERT_TRUE(buff_send_[i]); } vnode_enqueue_burst_with_hash(prod_, vnode_ops_, 0, buff_send_, hash_, 128); int ret = vnode_dequeue_burst(cons_, vnode_ops_, 0, buff_recv_, 128); EXPECT_EQ(ret, 128); for (int i = 0; i < 128; i++) { EXPECT_EQ(buff_send_[i], buff_recv_[i]); } } class TestCaseVNodeDataMultiQ : public TestCaseVNodeDataOps { protected: std::string vnode_sym_; std::string prod_sym_; std::string cons_sym_; unsigned int nr_prodq; unsigned int nr_consq; TestCaseVNodeDataMultiQ() : TestCaseVNodeDataOps(), vnode_sym_("VNodeTest"), prod_sym_("Prod"), cons_sym_("Cons"), nr_prodq(4), nr_consq(2) {} static void SetUpTestCase() { pool_ = rte_pktmbuf_pool_create("TCVNDataMultiQPool", 8192, 512, 0, 512, SOCKET_ID_ANY); ASSERT_TRUE(pool_ != NULL); } virtual void VNodeConsCreate() { cons_ = vnode_create_cons(node_, vnode_ops_, prod_sym_.c_str(), nr_consq); ASSERT_TRUE(cons_ != NULL); } virtual void VNodeProdCreate() { prod_ = vnode_create_prod(node_, vnode_ops_, cons_sym_.c_str(), nr_prodq); ASSERT_TRUE(prod_ != NULL); } }; TEST_F(TestCaseVNodeDataMultiQ, TestMultiQRecv) { struct rte_mbuf ** mbufs_a = new rte_mbuf * [bufsize_]; struct rte_mbuf ** mbufs_b = new rte_mbuf * [bufsize_]; for (int i = 0; i < bufsize_; i++) { mbufs_a[i] = rte_pktmbuf_alloc(pool_); mbufs_b[i] = rte_pktmbuf_alloc(pool_); ASSERT_TRUE(mbufs_a[i] != NULL); ASSERT_TRUE(mbufs_b[i] != NULL); } uint32_t * hash0 = new uint32_t[bufsize_]; uint32_t * hash1 = new uint32_t[bufsize_]; for (int i = 0; i < bufsize_; i++) { hash0[i] = 0; hash1[i] = 1; } struct rte_mbuf ** recv_a = new rte_mbuf *[bufsize_]; struct rte_mbuf ** recv_b = new rte_mbuf *[bufsize_]; vnode_enqueue_burst_with_hash(prod_, vnode_ops_, 0, (void **)mbufs_a, hash0, bufsize_); vnode_enqueue_burst_with_hash(prod_, vnode_ops_, 0, (void **)mbufs_b, hash1, bufsize_); int ret1 = vnode_dequeue_burst(cons_, vnode_ops_, 0, (void **)recv_a, bufsize_); EXPECT_EQ(ret1, bufsize_); int ret2 = vnode_dequeue_burst(cons_, vnode_ops_, 1, (void **)recv_b, bufsize_); EXPECT_EQ(ret2, bufsize_); for (int i = 0; i < bufsize_; i++) { EXPECT_EQ(recv_a[i], mbufs_a[i]); EXPECT_EQ(recv_b[i], mbufs_b[i]); } } TEST_F(TestCaseVNodeDataMultiQ, TestMultiQSend) {}