tldk_test: Add TLDK unit tests 98/3298/3
authorDaniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Sat, 6 Aug 2016 19:38:27 +0000 (20:38 +0100)
committerMohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Fri, 7 Oct 2016 07:49:12 +0000 (08:49 +0100)
Unit tests for TLDK libtle_udp & libtle_dring libraries

Change-Id: I6818c72ca0260f1af784e758bfe21118c395afcf
Signed-off-by: Karol Latecki <karolx.latecki@intel.com>
Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
17 files changed:
README
test/Makefile
test/gtest/Makefile [new file with mode: 0644]
test/gtest/README [new file with mode: 0644]
test/gtest/main.cpp [new file with mode: 0644]
test/gtest/test_tle_dring.cpp [new file with mode: 0644]
test/gtest/test_tle_dring.h [new file with mode: 0644]
test/gtest/test_tle_udp_ctx.cpp [new file with mode: 0644]
test/gtest/test_tle_udp_ctx.h [new file with mode: 0644]
test/gtest/test_tle_udp_destroy.cpp [new file with mode: 0644]
test/gtest/test_tle_udp_destroy.h [new file with mode: 0644]
test/gtest/test_tle_udp_dev.cpp [new file with mode: 0644]
test/gtest/test_tle_udp_dev.h [new file with mode: 0644]
test/gtest/test_tle_udp_event.cpp [new file with mode: 0644]
test/gtest/test_tle_udp_event.h [new file with mode: 0644]
test/gtest/test_tle_udp_stream.cpp [new file with mode: 0644]
test/gtest/test_tle_udp_stream.h [new file with mode: 0644]

diff --git a/README b/README
index 6d8b7f8..6131a89 100644 (file)
--- a/README
+++ b/README
@@ -34,18 +34,22 @@ TLDK project scope is:
    the resulting host stack easily usable by existing non-vpp aware software.
 
 INSTALLATION GUIDE
-=================
+==================
 
-1. Obtain latest DPDK.
+1. Obtain latest DPDK and build it.
    (refer to http://dpdk.org for information how to download and build it).
 2. Make sure that RTE_SDK and RTE_TARGET DPDK related environment variables
    are setup correctly.
 3. Go to the TLDK root directory and type: 'make all'.
 4. Run sample applications.
 
+For enabling unit tests application using GoogleTest please see:
+./test/gtest/README
+
 As an example:
 export RTE_SDK=/opt/DPDK
 export RTE_TARGET=x86_64-native-linuxapp-gcc
+
 cd tldk
 make all
 ./x86_64-native-linuxapp-gcc/app/udpfwd ...
@@ -65,6 +69,9 @@ $(TLDK_ROOT)
 |      |
 |      +--udpfwd - sample app to demonstrate and test libtle_udp usage
 |            (refer to examples/udpfwd/README for more information)
+|
 +----test - unit-tests
 |      |
-|      +--dring - UT for libtle_dring
+|      +--dring - UT for libtle_dring (standalone app)
+|      |
+|      +--gtest - UT for libtle_dring and libtle_udp (googletest)
index fb446b4..665396f 100644 (file)
@@ -22,5 +22,6 @@ endif
 include $(RTE_SDK)/mk/rte.vars.mk
 
 DIRS-y += dring
+DIRS-y += gtest
 
 include $(TLDK_ROOT)/mk/tle.subdir.mk
diff --git a/test/gtest/Makefile b/test/gtest/Makefile
new file mode 100644 (file)
index 0000000..5f47cc4
--- /dev/null
@@ -0,0 +1,115 @@
+# Copyright (c) 2016 Intel Corporation.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+ifeq ($(GTEST_DIR),)
+all:
+       @echo "GTEST_DIR is not setup properly. Skipping gtest"
+
+%::
+       @echo "GTEST_DIR is not setup properly. Skipping gtest"
+
+else
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CUR_SUBDIR ?= .
+
+# we must create the output dir first and recall the same Makefile
+# from this directory
+ifeq ($(NOT_FIRST_CALL),)
+
+NOT_FIRST_CALL = 1
+export NOT_FIRST_CALL
+
+
+BDIR := $(RTE_OUTPUT)/build/$(CUR_SUBDIR)
+
+all:
+       $(Q)mkdir -p $(BDIR)
+       $(Q)$(MAKE) -C $(BDIR) -f $(RTE_EXTMK) \
+               S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) X=obj
+       $(Q)$(MAKE) -C $(BDIR) -f $(RTE_EXTMK) \
+               S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) X=app
+
+%::
+       $(Q)mkdir -p $(BDIR)
+       $(Q)$(MAKE) -C $(BDIR) -f $(RTE_EXTMK) $@ \
+               S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) X=obj
+       $(Q)$(MAKE) -C $(BDIR) -f $(RTE_EXTMK) $@ \
+               S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) X=app
+else
+
+#
+# building object
+#
+
+ifeq ($(X),obj)
+include $(TLDK_ROOT)/mk/tle.cpp-vars.mk
+
+# binary name
+OBJ = gtest-rfc.o
+
+# all source are stored in SRCS-y
+SRCS-y += main.cpp
+SRCS-y += test_tle_dring.cpp
+SRCS-y += test_tle_udp_ctx.cpp
+SRCS-y += test_tle_udp_dev.cpp
+SRCS-y += test_tle_udp_destroy.cpp
+SRCS-y += test_tle_udp_event.cpp
+SRCS-y += test_tle_udp_stream.cpp
+
+CXXFLAGS += -std=c++11
+CXXFLAGS += -I$(GTEST_DIR)/include
+CXXFLAGS += -I$(GMOCK_DIR)/include
+CXXFLAGS += -I$(TLDK_ROOT)/$(RTE_TARGET)/include
+
+LDFLAGS += -lstdc++
+LDFLAGS += -L$(GMOCK_DIR) -lgmock
+LDLIBS += -ltle_udp -ltle_dring
+
+include $(TLDK_ROOT)/mk/tle.cpp-obj.mk
+endif
+
+#
+# building app
+#
+
+ifeq ($(X),app)
+
+# binary name
+APP = gtest-rfc
+
+# all source are stored in SRCS-y
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+LDLIBS += gtest-rfc.o
+
+LDFLAGS += -lstdc++
+LDFLAGS += -L$(GMOCK_DIR) -lgmock
+LDLIBS += -L$(TLDK_ROOT)/$(RTE_TARGET)/lib
+LDLIBS += -ltle_udp -ltle_dring
+
+include $(TLDK_ROOT)/mk/tle.app.mk
+endif
+
+endif
+endif
diff --git a/test/gtest/README b/test/gtest/README
new file mode 100644 (file)
index 0000000..8d39b6b
--- /dev/null
@@ -0,0 +1,41 @@
+OVERVIEW
+========
+
+This application is a set of API unit tests for libtle_dring and libtle_udp
+libraries, plus a small set of functional tests for RX/TX functions in
+libtle_udp library.
+UT application needs GoogleTest C++ testing framework to compile, please
+follow installation steps below to enable them.
+
+INSTALLATION GUIDE
+==================
+Assumes that user had finished initial installation from TLDK root
+directory README.
+
+1. TLDK unit tests require pcap PMD to be available, enable it in DPDK and
+       rebuild it.
+       (http://dpdk.org/doc/quick-start has information how to do it)
+2. Obtain GoogleTest and build it. Some additional dependencies might be
+       needed.
+       (refer to https://github.com/google/googletest for information how to
+        download and build it)
+3. Make sure that GTEST_DIR and GMOCK_DIR environment variables are set.
+4. Rebuild TLDK.
+
+Example:
+cd dpdk
+make config T=x86_64-native-linuxapp-gcc
+sed -ri 's,(PMD_PCAP=).*,\1y,' build/.config
+make install
+
+git clone https://github.com/google/googletest.git
+cd ../googletest
+export GTEST_DIR=`pwd`/googletest
+export GMOCK_DIR=`pwd`/googlemock
+cmake CMakeLists.txt
+make
+
+cd ../tldk
+make clean
+make all
+./x86_64-native-linuxapp-gcc/app/gtest-rfc --lcores=0
diff --git a/test/gtest/main.cpp b/test/gtest/main.cpp
new file mode 100644 (file)
index 0000000..8c4e2dc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <iostream>
+#include <rte_common.h>
+#include <rte_eal.h>
+
+int main(int argc, char *argv[])
+{
+       /* Initialize GoogleTest&Mock and parse any args */
+       testing::InitGoogleMock(&argc, argv);
+
+       /* Initialize EAL */
+       int ret = rte_eal_init(argc, argv);
+       if (ret < 0)
+               rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
+       argc -= ret;
+       argv += ret;
+
+       return RUN_ALL_TESTS();
+}
diff --git a/test/gtest/test_tle_dring.cpp b/test/gtest/test_tle_dring.cpp
new file mode 100644 (file)
index 0000000..6ab4905
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_dring.h"
+
+TEST_F(dring, test_dring_st)
+{
+       printf("%s started;\n", __func__);
+
+       tle_dring_reset(&dr);
+       r = init_drb_ring(OBJ_NUM);
+
+       ASSERT_NE(r, (void *) NULL) << "Out of memory";
+
+       tle_dring_dump(stdout, 1, &dr);
+
+       memset(&arg, 0, sizeof(arg));
+       arg[0].dr = &dr;
+       arg[0].r = r;
+       arg[0].iter = ITER_NUM;
+       arg[0].enq_type = SINGLE;
+       arg[0].deq_type = SINGLE;
+       rc = test_dring_enq_deq(&arg[0]);
+
+       rc = (rc != 0) ? rc : (arg[0].enq != arg[0].deq);
+       printf("%s finished with status: %s(%d);\n",
+               __func__, strerror(-rc), rc);
+
+       tle_dring_dump(stdout, rc != 0, &dr);
+       fini_drb_ring(r);
+       EXPECT_EQ(rc, 0);
+}
+
+
+TEST_F(dring ,test_dring_mp_mc)
+{
+       rc = test_dring_mt(MULTI, MULTI, MULTI, MULTI);
+       EXPECT_EQ(rc, 0);
+}
+
+TEST_F(dring, test_dring_mp_sc)
+{
+       rc = test_dring_mt(MULTI, SINGLE, MULTI, NONE);
+       EXPECT_EQ(rc, 0);
+}
+
+TEST_F(dring, test_dring_sp_mc)
+{
+       rc = test_dring_mt(SINGLE, MULTI, NONE, MULTI);
+       EXPECT_EQ(rc, 0);
+}
diff --git a/test/gtest/test_tle_dring.h b/test/gtest/test_tle_dring.h
new file mode 100644 (file)
index 0000000..a978bae
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_DRING_H_
+#define TEST_TLE_DRING_H_
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_errno.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_ring.h>
+#include <rte_random.h>
+
+#include <tle_dring.h>
+
+struct dring_arg {
+       struct tle_dring *dr;
+       struct rte_ring *r;
+       uint32_t iter;
+       int32_t enq_type;
+       int32_t deq_type;
+       uint32_t enq;
+       uint32_t deq;
+};
+
+class dring: public ::testing::Test {
+protected:
+
+       virtual void SetUp(void) {};
+       virtual void TearDown(void) {};
+
+       int32_t rc;
+       struct rte_ring *r;
+       struct tle_dring dr;
+       struct dring_arg arg[RTE_MAX_LCORE];
+
+};
+
+#define OBJ_NUM                UINT16_MAX
+#define ITER_NUM       (4 * OBJ_NUM)
+
+enum {
+       NONE,
+       SINGLE,
+       MULTI,
+};
+
+/*
+ * Each enqueued object will contain:
+ * [2-3]B: it's own sequence number.
+ * [0-1]B: next object sequence number, or UINT16_MAX.
+ */
+static void
+test_fill_obj(uintptr_t obj[], uint32_t num)
+{
+       uint32_t i;
+
+       for (i = 0; i != num - 1; i++)
+               obj[i] = i << 16 | (i + 1);
+
+       obj[i] = i << 16 | UINT16_MAX;
+}
+
+static uint32_t
+test_check_obj(uintptr_t obj[], uint32_t num)
+{
+       uint32_t i, h, l, oh, ol;
+
+       h = obj[0] >> 16;
+       l = obj[0] & UINT16_MAX;
+
+       if (h + 1 != l && l != UINT16_MAX)
+               return 0;
+
+       if (l == UINT16_MAX)
+               l = 0;
+
+       for (i = 1; i != num; i++) {
+
+               oh = obj[i] >> 16;
+               ol = obj[i] & UINT16_MAX;
+
+               if (l != oh || (oh + 1 != ol && ol != UINT16_MAX))
+                       return i;
+
+               l = ol;
+               if (l == UINT16_MAX)
+                       l = 0;
+       }
+
+       return num;
+}
+
+/*
+ * free memory allocated for drbs and for the ring itself.
+ */
+static void
+fini_drb_ring(struct rte_ring *r)
+{
+       struct tle_drb *drb;
+
+       /* free drbs. */
+       while (rte_ring_dequeue(r, (void **)&drb) == 0)
+               free(drb);
+
+       /* free ring. */
+       free(r);
+}
+
+static struct rte_ring *
+init_drb_ring(uint32_t num)
+{
+       uint32_t i, k, n;
+       size_t sz, tsz;
+       struct rte_ring *r;
+       struct tle_drb *drb;
+
+       /* allocate and initialise rte_ring. */
+
+       n = rte_align32pow2(num);
+       sz =  sizeof(*r) + n * sizeof(r->ring[0]);
+
+       r = (struct rte_ring *)calloc(1, sz);
+       if (r == NULL) {
+               printf("%s:%d(%u) failed to allocate %zu bytes;\n",
+                       __func__, __LINE__, num, sz);
+               return NULL;
+       }
+
+       rte_ring_init(r, __func__, n, 0);
+
+       /* allocate drbs and put them into the ring. */
+
+       tsz = sz;
+       for (i = 0; i != num; i += k) {
+               k =  rte_rand() % (UINT8_MAX + 1) + 1;
+               k = RTE_MIN(k, num - i);
+               sz = tle_drb_calc_size(k);
+               drb = (struct tle_drb *)calloc(1, sz);
+               if (drb == NULL) {
+                       printf("%s:%d(%u) %u-th iteration: "
+                               "failed to allocate %zu bytes;\n",
+                               __func__, __LINE__, num, i, sz);
+                       fini_drb_ring(r);
+                       return NULL;
+               }
+               drb->size = k;
+               rte_ring_enqueue(r, drb);
+               tsz += sz;
+       }
+
+       printf("%s(%u) total %zu bytes allocated, number of drbs: %u;\n",
+               __func__, num, tsz, rte_ring_count(r));
+       return r;
+}
+
+static int
+test_dring_enqueue(struct tle_dring *dr, struct rte_ring *r, uint32_t num,
+       int32_t type)
+{
+       uint32_t i, j, k, lc, nb;
+       struct tle_drb *drb[num];
+       uintptr_t obj[num];
+
+       lc = rte_lcore_id();
+
+       /* prepare drbs to enqueue up to *num* objects. */
+       for (i = 0, j = 0; i != num; i += k, j++) {
+
+               if (rte_ring_dequeue(r, (void **)&drb[j]) != 0)
+                       break;
+
+               /* udata value for unused drb should be zero. */
+               if (drb[j]->udata != NULL) {
+                       printf("error @ %s:%d(%p, %u) at lcore %u: "
+                               "erroneous drb@%p={udata=%p, size=%u,};\n",
+                               __func__, __LINE__, dr, num, lc, drb[j],
+                               drb[j]->udata, drb[j]->size);
+                       return -EFAULT;
+               }
+
+               /* update udata value with current lcore id. */
+               drb[j]->udata = (void *)(uintptr_t)(lc + 1);
+               k = drb[j]->size;
+               k = RTE_MIN(k, num - i);
+       }
+
+       /* no free drbs left. */
+       if (i == 0)
+               return 0;
+
+       /* fill objects to enqueue. */
+       test_fill_obj(obj, i);
+
+       /* enqueue into the dring. */
+       nb = j;
+       if (type == SINGLE)
+               k = tle_dring_sp_enqueue(dr, (const void **)obj, i, drb, &nb);
+       else if (type == MULTI)
+               k = tle_dring_mp_enqueue(dr, (const void **)obj, i, drb, &nb);
+       else
+               return -EINVAL;
+
+       if (k != i) {
+               printf("%s:%d(%p, %p, %u): failed to enqueue %u objects;\n",
+                       __func__, __LINE__, dr, r, num, i);
+       }
+
+       /* free unused drbs */
+       for (i = j - nb; i != j; i++) {
+               if ((uintptr_t)drb[i]->udata != lc + 1) {
+                       printf("error @ %s:%d(%p, %u) at lcore %u: "
+                               "erroneous drb@%p={udata=%p, size=%u,};\n",
+                               __func__, __LINE__, dr, num, lc, drb[i],
+                               drb[i]->udata, drb[i]->size);
+                       return -EFAULT;
+               }
+               drb[i]->udata = NULL;
+               rte_ring_enqueue(r, drb[i]);
+       }
+
+       return k;
+}
+
+static int
+test_dring_dequeue(struct tle_dring *dr, struct rte_ring *r, uint32_t num,
+       int32_t type)
+{
+       uint32_t i, k, lc, n, t;
+       struct tle_drb *drb[num];
+       uintptr_t obj[num];
+
+       lc = rte_lcore_id();
+       k = num;
+
+       /* dequeue objects. */
+       if (type == SINGLE)
+               n = tle_dring_sc_dequeue(dr, (const void **)obj, num, drb, &k);
+       else if (type == MULTI)
+               n = tle_dring_mc_dequeue(dr, (const void **)obj, num, drb, &k);
+       else
+               return -EINVAL;
+
+       if (n == 0)
+               return 0;
+
+       /* check the data returned. */
+       t = test_check_obj(obj, n);
+       if (t != n) {
+               printf("%s:%d(%p, %u) at lcore %u: invalid dequeued object, "
+                       "n=%u, idx=%u, obj=%#x, prev obj=%#x;\n",
+                       __func__, __LINE__, dr, num, lc, n, t,
+                       (uint32_t)obj[t], (t == 0) ? 0 : (uint32_t)obj[t - 1]);
+               return -EFAULT;
+       }
+
+       /* check and free drbs. */
+       for (i = 0; i != k; i++) {
+               /* udata value for drb in use shouldn't be zero. */
+               if (drb[i]->udata == NULL) {
+                       printf("error @ %s:%d(%p, %u) at lcore %u: "
+                               "erroneous drb@%p={udata=%p, size=%u,};\n",
+                               __func__, __LINE__, dr, num, lc, drb[i],
+                               drb[i]->udata, drb[i]->size);
+                       return -EFAULT;
+               }
+               drb[i]->udata = NULL;
+               rte_ring_enqueue(r, drb[i]);
+       }
+
+       return n;
+}
+
+static int
+test_dring_enq_deq(struct dring_arg *arg)
+{
+       int32_t rc;
+       uint32_t i, lc, n;
+
+       rc = 0;
+       arg->enq = 0;
+       arg->deq = 0;
+       lc = rte_lcore_id();
+
+       for (i = 0; i != arg->iter; i++) {
+
+               /* try to enqueue random number of objects. */
+               if (arg->enq_type != NONE) {
+                       n = rte_rand() % (UINT8_MAX + 1);
+                       rc = test_dring_enqueue(arg->dr, arg->r, n,
+                               arg->enq_type);
+                       if (rc < 0)
+                               break;
+                       arg->enq += rc;
+               }
+
+               /* try to dequeue random number of objects. */
+               if (arg->deq_type != NONE) {
+                       n = rte_rand() % (UINT8_MAX + 1);
+                       rc = test_dring_dequeue(arg->dr, arg->r, n,
+                               arg->deq_type);
+                       if (rc < 0)
+                               break;
+                       arg->deq += rc;
+               }
+       }
+
+       if (rc < 0)
+               return rc;
+
+       /* dequeue remaining objects. */
+       while (arg->deq_type != NONE && arg->enq != arg->deq) {
+
+               /* try to dequeue random number of objects. */
+               n = rte_rand() % (UINT8_MAX + 1) + 1;
+               rc = test_dring_dequeue(arg->dr, arg->r, n, arg->deq_type);
+               if (rc <= 0)
+                       break;
+               arg->deq += rc;
+       }
+
+       printf("%s:%d(lcore=%u, enq_type=%d, deq_type=%d): "
+               "%u objects enqueued, %u objects dequeued\n",
+               __func__, __LINE__, lc, arg->enq_type, arg->deq_type,
+               arg->enq, arg->deq);
+       return 0;
+}
+
+static int
+test_dring_worker(void *arg)
+{
+       struct dring_arg *p;
+
+       p = (struct dring_arg *)arg;
+       return test_dring_enq_deq(p);
+}
+
+/*
+ * enqueue/dequeue by multiple threads.
+ */
+static int
+test_dring_mt(int32_t master_enq_type, int32_t master_deq_type,
+       int32_t slave_enq_type, int32_t slave_deq_type)
+{
+       int32_t rc;
+       uint32_t lc;
+       uint64_t deq, enq;
+       struct rte_ring *r;
+       struct tle_dring dr;
+       struct dring_arg arg[RTE_MAX_LCORE];
+
+       tle_dring_reset(&dr);
+       r = init_drb_ring(OBJ_NUM);
+       if (r == NULL)
+               return -ENOMEM;
+
+       memset(arg, 0, sizeof(arg));
+
+       /* launch on all slaves */
+       RTE_LCORE_FOREACH_SLAVE(lc) {
+               arg[lc].dr = &dr;
+               arg[lc].r = r;
+               arg[lc].iter = ITER_NUM;
+               arg[lc].enq_type = slave_enq_type;
+               arg[lc].deq_type = slave_deq_type;
+               rte_eal_remote_launch(test_dring_worker, &arg[lc], lc);
+       }
+
+       /* launch on master */
+       lc = rte_lcore_id();
+       arg[lc].dr = &dr;
+       arg[lc].r = r;
+       arg[lc].iter = ITER_NUM;
+       arg[lc].enq_type = master_enq_type;
+       arg[lc].deq_type = master_deq_type;
+       rc = test_dring_worker(&arg[lc]);
+       enq = arg[lc].enq;
+       deq = arg[lc].deq;
+
+       /* wait for slaves. */
+       RTE_LCORE_FOREACH_SLAVE(lc) {
+               rc |= rte_eal_wait_lcore(lc);
+               enq += arg[lc].enq;
+               deq += arg[lc].deq;
+       }
+
+       printf("%s:%d: total %" PRIu64 " objects enqueued, %"
+               PRIu64 " objects dequeued\n",
+               __func__, __LINE__, enq, deq);
+
+       rc = (rc != 0) ? rc : (enq != deq);
+       if (rc != 0)
+               tle_dring_dump(stdout, 1, &dr);
+
+       fini_drb_ring(r);
+       return rc;
+}
+
+#endif /* TEST_TLE_DRING_H_ */
diff --git a/test/gtest/test_tle_udp_ctx.cpp b/test/gtest/test_tle_udp_ctx.cpp
new file mode 100644 (file)
index 0000000..0bad39f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_udp_ctx.h"
+
+TEST(udp_ctx, udp_create_null)
+{
+       struct tle_udp_ctx *ctx;
+
+       ctx = tle_udp_create(NULL);
+       ASSERT_EQ(ctx, (struct tle_udp_ctx *) NULL);
+       ASSERT_EQ(rte_errno, EINVAL);
+}
+
+TEST(udp_ctx, udp_create)
+{
+       struct tle_udp_ctx *ctx;
+       struct tle_udp_ctx_param prm;
+
+       memset(&prm, 0, sizeof(prm));
+       prm.socket_id = SOCKET_ID_ANY;
+       prm.max_streams = 0x10;
+       prm.max_stream_rbufs = 0x100;
+       prm.max_stream_sbufs = 0x100;
+
+       ctx = tle_udp_create(&prm);
+       ASSERT_NE(ctx, (void *)NULL);
+
+       tle_udp_destroy(ctx);
+}
diff --git a/test/gtest/test_tle_udp_ctx.h b/test/gtest/test_tle_udp_ctx.h
new file mode 100644 (file)
index 0000000..af02440
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_UDP_CTX_H_
+#define TEST_TLE_UDP_CTX_H_
+
+#include <gtest/gtest.h>
+#include <rte_errno.h>
+#include <tle_udp_impl.h>
+
+#endif /* TEST_TLE_UDP_CTX_H_ */
diff --git a/test/gtest/test_tle_udp_destroy.cpp b/test/gtest/test_tle_udp_destroy.cpp
new file mode 100644 (file)
index 0000000..2244b18
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_udp_destroy.h"
+
+TEST(udp_destroy_null, udp_destroy_null)
+{
+       tle_udp_destroy(NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_destroy, udp_destroy_positive)
+{
+       int rc;
+       tle_udp_destroy(ctx);
+       ASSERT_EQ(rte_errno, 0);
+}
diff --git a/test/gtest/test_tle_udp_destroy.h b/test/gtest/test_tle_udp_destroy.h
new file mode 100644 (file)
index 0000000..d52376e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_UDP_DESTROY_H_
+#define TEST_TLE_UDP_DESTROY_H_
+
+#include <gtest/gtest.h>
+#include <rte_errno.h>
+#include <tle_udp_impl.h>
+
+class udp_destroy : public ::testing::Test {
+
+protected:
+       struct tle_udp_ctx *ctx;
+       struct tle_udp_ctx_param prm;
+
+       virtual void SetUp(void)
+       {
+               rte_errno = 0;
+               memset(&prm, 0, sizeof(prm));
+               prm.socket_id = SOCKET_ID_ANY;
+               prm.max_streams = 0x10;
+               prm.max_stream_rbufs = 0x100;
+               prm.max_stream_sbufs = 0x100;
+
+               ctx = tle_udp_create(&prm);
+               ASSERT_NE(ctx, (void *) NULL);
+       }
+
+       virtual void TearDown(void)
+       {
+       }
+};
+
+#endif /* TEST_TLE_UDP_DESTROY_H_ */
diff --git a/test/gtest/test_tle_udp_dev.cpp b/test/gtest/test_tle_udp_dev.cpp
new file mode 100644 (file)
index 0000000..8efb866
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_udp_dev.h"
+
+TEST_F(udp_dev, udp_dev_add_null_ctx)
+{
+       dev = tle_udp_add_dev(NULL, &dev_prm);
+       EXPECT_EQ(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_dev, udp_dev_add_null_dev_prm)
+{
+       dev = tle_udp_add_dev(ctx, NULL);
+       EXPECT_EQ(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_dev, udp_dev_add_no_addr)
+{
+       memset(&(dev_prm).local_addr4, 0, sizeof(struct in_addr));
+       memset(&(dev_prm).local_addr6, 0, sizeof(struct in6_addr));
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       EXPECT_EQ(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_dev, udp_dev_add_anyaddr)
+{
+       inet_pton(AF_INET, "0.0.0.0", &(dev_prm).local_addr4);
+       inet_pton(AF_INET6, "::0", &(dev_prm).local_addr6);
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       EXPECT_EQ(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_dev, udp_dev_add_only_ipv4)
+{
+       memset(&(dev_prm).local_addr6, 0, sizeof(struct in6_addr));
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_dev, udp_dev_add_only_ipv6)
+{
+       memset(&(dev_prm).local_addr4, 0, sizeof(struct in_addr));
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_dev, udp_dev_add_nonexist_ipv4)
+{
+       memset(&(dev_prm).local_addr4, 0, sizeof(struct in_addr));
+       inet_pton(AF_INET, "10.0.0.1", &(dev_prm).local_addr4);
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_dev, udp_dev_add_positive)
+{
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_dev, udp_dev_del_positive)
+{
+       dev = tle_udp_add_dev(ctx, &dev_prm);
+       ASSERT_NE(dev, (void *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+       ASSERT_EQ(tle_udp_del_dev(dev), 0);
+       EXPECT_EQ(rte_errno, 0);
+}
diff --git a/test/gtest/test_tle_udp_dev.h b/test/gtest/test_tle_udp_dev.h
new file mode 100644 (file)
index 0000000..3ecc5c7
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_UDP_DEV_H_
+#define TEST_TLE_UDP_DEV_H_
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <rte_errno.h>
+#include <tle_udp_impl.h>
+
+#define RX_NO_OFFLOAD 0
+#define TX_NO_OFFLOAD 0
+
+class udp_dev : public ::testing::Test {
+
+public:
+       struct tle_udp_ctx *ctx;
+       struct tle_udp_dev *dev;
+       struct tle_udp_ctx_param prm;
+       struct tle_udp_dev_param dev_prm;
+
+       virtual void SetUp(void)
+       {
+               rte_errno = 0;
+               memset(&prm, 0, sizeof(prm));
+               prm.socket_id = SOCKET_ID_ANY;
+               prm.max_streams = 0x1;
+               prm.max_stream_rbufs = 0x1;
+               prm.max_stream_sbufs = 0x1;
+
+               memset(&dev_prm, 0, sizeof(dev_prm));
+
+               /* Offload irrelevant in these tests, set to 0 */
+               dev_prm.rx_offload = RX_NO_OFFLOAD;
+               dev_prm.tx_offload = TX_NO_OFFLOAD;
+               inet_pton(AF_INET, "192.168.2.1", &(dev_prm).local_addr4);
+               inet_pton(AF_INET6, "fe80::21e:67ff:fec2:2568",
+                               &(dev_prm).local_addr6);
+
+               ctx = tle_udp_create(&prm);
+               ASSERT_NE(ctx, (void *) NULL);
+       }
+
+       virtual void TearDown(void)
+       {
+               tle_udp_destroy(ctx);
+       }
+};
+
+#endif /* TEST_TLE_UDP_DEV_H_ */
diff --git a/test/gtest/test_tle_udp_event.cpp b/test/gtest/test_tle_udp_event.cpp
new file mode 100644 (file)
index 0000000..6d5c548
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_udp_event.h"
+
+TEST_F(udp_evq, udp_evq_create_null)
+{
+       evq = tle_evq_create(NULL);
+       EXPECT_EQ(evq, (struct tle_evq *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_evq, udp_evq_create_invalid_socket)
+{
+       evq_params.socket_id = 999;
+       evq = tle_evq_create(&evq_params);
+       ASSERT_EQ(evq, (struct tle_evq *) NULL);
+}
+
+TEST_F(udp_evq, udp_evq_create_destroy_positive)
+{
+       evq = tle_evq_create(&evq_params);
+       ASSERT_NE(evq, (struct tle_evq *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+       EXPECT_EQ(evq->nb_events, max_events);
+       EXPECT_EQ(evq->nb_free, max_events);
+       tle_evq_destroy(evq);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_event, udp_event_alloc_null)
+{
+       event = tle_event_alloc(NULL, (void *) &fake_data);
+       EXPECT_EQ(event, (struct tle_event *) NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_event, udp_event_free_null)
+{
+       tle_event_free(NULL);
+       EXPECT_EQ(rte_errno, EINVAL);
+}
+
+TEST_F(udp_event, udp_event_alloc_free_positive)
+{
+       event = tle_event_alloc(evq, (void *) &fake_data);
+       ASSERT_NE(event, (struct tle_event *) NULL);
+       EXPECT_EQ(rte_errno, 0);
+       EXPECT_EQ(evq->nb_free, max_events - 1);
+       tle_event_free(event);
+       EXPECT_EQ(rte_errno, 0);
+       EXPECT_EQ(evq->nb_free, max_events);
+}
+
+TEST_F(udp_event, udp_event_alloc_free_max_reached)
+{
+       uint32_t i;
+       struct tle_event *last_event;
+
+       for (i = 1; i <= max_events; i++) {
+               event = tle_event_alloc(evq, (void *) &fake_data);
+               ASSERT_NE(event, (struct tle_event *) NULL);
+               EXPECT_EQ(rte_errno, 0);
+               EXPECT_EQ(evq->nb_free, max_events - i);
+       }
+
+       last_event = tle_event_alloc(evq, (void *) &fake_data);
+       ASSERT_EQ(last_event, (struct tle_event *) NULL);
+       ASSERT_EQ(rte_errno, -ENOMEM);
+
+       for (i = 1; i <= max_events; i++) {
+               tle_event_free(event);
+       }
+       EXPECT_EQ(evq->nb_free, max_events);
+}
+
+TEST_F(udp_event_state, udp_state_default)
+{
+       ASSERT_EQ(event->state, TLE_SEV_IDLE);
+}
+
+TEST_P(udp_event_state_active, udp_state_active)
+{
+       auto states = GetParam();
+
+       tle_event_active(event, states.event_state);
+       ASSERT_EQ(event->state, states.event_state);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+INSTANTIATE_TEST_CASE_P(Default, udp_event_state_active,
+       testing::Values(
+       event_state_active{TLE_SEV_IDLE},
+       event_state_active{TLE_SEV_UP},
+       event_state_active{TLE_SEV_DOWN}
+));
+
+TEST_P(udp_event_state_active_twice, udp_state_active_twice)
+{
+       auto states = GetParam();
+
+       tle_event_active(event, states.first_state);
+       ASSERT_EQ(event->state, states.first_state);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_active(event, states.second_state);
+       ASSERT_EQ(event->state, states.result_state);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+INSTANTIATE_TEST_CASE_P(Default, udp_event_state_active_twice,
+       testing::Values(
+       event_state_active_twice{TLE_SEV_IDLE, TLE_SEV_IDLE, TLE_SEV_IDLE},
+       event_state_active_twice{TLE_SEV_IDLE, TLE_SEV_DOWN, TLE_SEV_DOWN},
+       event_state_active_twice{TLE_SEV_IDLE, TLE_SEV_UP, TLE_SEV_UP},
+       event_state_active_twice{TLE_SEV_DOWN, TLE_SEV_IDLE, TLE_SEV_DOWN},
+       event_state_active_twice{TLE_SEV_DOWN, TLE_SEV_DOWN, TLE_SEV_DOWN},
+       event_state_active_twice{TLE_SEV_UP, TLE_SEV_IDLE, TLE_SEV_UP},
+       event_state_active_twice{TLE_SEV_UP, TLE_SEV_DOWN, TLE_SEV_UP},
+       event_state_active_twice{TLE_SEV_UP, TLE_SEV_UP, TLE_SEV_UP}
+));
+
+TEST_F(udp_event_state, udp_state_raise)
+{
+       tle_event_raise(event);
+       ASSERT_EQ(event->state, TLE_SEV_IDLE);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_active(event, TLE_SEV_DOWN);
+       ASSERT_EQ(event->state, TLE_SEV_DOWN);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_raise(event);
+       ASSERT_EQ(event->state, TLE_SEV_UP);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_F(udp_event_state, udp_state_down)
+{
+       tle_event_down(event);
+       ASSERT_EQ(event->state, TLE_SEV_IDLE);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_active(event, TLE_SEV_UP);
+       ASSERT_EQ(event->state, TLE_SEV_UP);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_down(event);
+       ASSERT_EQ(event->state, TLE_SEV_DOWN);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+TEST_P(udp_event_state_idle, udp_state_idle)
+{
+       auto states = GetParam();
+
+       tle_event_active(event, states.event_state);
+       ASSERT_EQ(event->state, states.event_state);
+       EXPECT_EQ(rte_errno, 0);
+       tle_event_idle(event);
+       ASSERT_EQ(event->state, TLE_SEV_IDLE);
+       EXPECT_EQ(rte_errno, 0);
+}
+
+INSTANTIATE_TEST_CASE_P(Default, udp_event_state_idle,
+       testing::Values(
+       event_state_active{TLE_SEV_IDLE},
+       event_state_active{TLE_SEV_UP},
+       event_state_active{TLE_SEV_DOWN}
+));
+
+TEST_F(udp_event, udp_event_get)
+{
+       uint32_t i;
+       const void **evd;
+
+       evd = (const void **) malloc(max_events * sizeof(void *));
+       for (i = 1; i <= max_events; i++) {
+               event = tle_event_alloc(evq, (void *) &fake_data);
+               EXPECT_NE(event, (struct tle_event *) NULL);
+               tle_event_active(event, TLE_SEV_UP);
+               EXPECT_EQ(event->state, TLE_SEV_UP);
+       }
+       EXPECT_EQ(evq->nb_free, 0);
+       EXPECT_EQ(tle_evq_get(evq, evd, max_events), max_events);
+       free(evd);
+}
diff --git a/test/gtest/test_tle_udp_event.h b/test/gtest/test_tle_udp_event.h
new file mode 100644 (file)
index 0000000..4d66fb6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_UDP_EVENT_H_
+#define TEST_TLE_UDP_EVENT_H_
+
+#include <gtest/gtest.h>
+#include <rte_errno.h>
+#include <tle_udp_impl.h>
+#include <tle_event.h>
+
+struct event_state_active {
+       enum tle_ev_state event_state;
+};
+
+struct event_state_active_twice {
+       enum tle_ev_state first_state;
+       enum tle_ev_state second_state;
+       enum tle_ev_state result_state;
+};
+
+class udp_evq : public ::testing::Test {
+protected:
+
+       /* Can parameterize here for
+        * different socket_id and max_events values
+        */
+       int32_t socket_id;
+       uint32_t max_events;
+       struct tle_evq_param evq_params;
+       struct tle_evq *evq;
+
+       virtual void SetUp(void)
+       {
+               socket_id = SOCKET_ID_ANY;
+               max_events = 10;
+               rte_errno = 0;
+               memset(&evq_params, 0, sizeof(struct tle_evq_param));
+               evq_params.socket_id = socket_id;
+               evq_params.max_events = max_events;
+       }
+
+       virtual void TearDown(void)
+       {
+       }
+};
+
+class udp_event : public ::udp_evq {
+protected:
+
+       int fake_data;
+       struct tle_event *event;
+
+       virtual void SetUp(void)
+       {
+               udp_evq::SetUp();
+               evq = tle_evq_create(&evq_params);
+               ASSERT_NE(evq, (struct tle_evq *) NULL);
+               EXPECT_EQ(rte_errno, 0);
+       }
+
+       virtual void TearDown(void)
+       {
+               tle_evq_destroy(evq);
+       }
+};
+
+class udp_event_state : public ::udp_event {
+protected:
+
+       virtual void SetUp(void)
+       {
+               udp_event::SetUp();
+               event = tle_event_alloc(evq, (void *) &fake_data);
+               ASSERT_NE(event, (struct tle_event *) NULL);
+       }
+
+       virtual void TearDown(void)
+       {
+               tle_event_free(event);
+               udp_event::TearDown();
+       }
+};
+
+struct udp_event_state_active : ::udp_event_state,
+testing::WithParamInterface < event_state_active > {
+       udp_event_state_active() {}
+};
+
+struct udp_event_state_active_twice : ::udp_event_state,
+testing::WithParamInterface < event_state_active_twice > {
+       udp_event_state_active_twice() {}
+};
+
+struct udp_event_state_idle : ::udp_event_state_active {
+};
+
+#endif /* TEST_TLE_UDP_EVENT_H_ */
diff --git a/test/gtest/test_tle_udp_stream.cpp b/test/gtest/test_tle_udp_stream.cpp
new file mode 100644 (file)
index 0000000..9356288
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_tle_udp_stream.h"
+
+TEST_F(test_tle_udp_stream, stream_test_open)
+{
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+       ret = tle_udp_stream_close(stream);
+
+       EXPECT_EQ(ret, 0);
+}
+
+TEST_F(test_tle_udp_stream, stream_test_open_nullctx)
+{
+       stream = tle_udp_stream_open(nullptr,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_EQ(stream, nullptr);
+       EXPECT_EQ(rte_errno, EINVAL);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, EINVAL);
+}
+
+TEST_F(test_tle_udp_stream, stream_test_open_null_stream_prm)
+{
+       stream = tle_udp_stream_open(ctx, nullptr);
+       EXPECT_EQ(stream, nullptr);
+       EXPECT_EQ(rte_errno, EINVAL);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, EINVAL);
+}
+
+
+TEST_F(test_tle_udp_stream, stream_test_open_close_open_close)
+{
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, 0);
+
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param*)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, 0);
+}
+
+TEST_F(test_tle_udp_stream, stream_test_close)
+{
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, 0);
+}
+
+TEST_F(test_tle_udp_stream, stream_test_close_null)
+{
+       ret = tle_udp_stream_close(nullptr);
+       EXPECT_EQ(ret, EINVAL);
+}
+
+
+TEST_F(test_tle_udp_stream, stream_test_close_already)
+{
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_EQ(ret, 0);
+
+       ret = tle_udp_stream_close(stream);
+       EXPECT_NE(ret, 0);
+}
+
+TEST_F(test_tle_udp_stream, stream_get_param)
+{
+       struct tle_udp_stream_param prm;
+
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_get_param(stream,&prm);
+       EXPECT_EQ(ret, 0);
+}
+
+TEST_F(test_tle_udp_stream, stream_get_param_streamnull)
+{
+       struct tle_udp_stream_param prm;
+
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_get_param(nullptr, &prm);
+       EXPECT_EQ(ret, EINVAL);
+}
+
+TEST_F(test_tle_udp_stream, stream_get_param_prmnull)
+{
+       struct tle_udp_stream_param prm;
+
+       stream = tle_udp_stream_open(ctx,
+                       (const struct tle_udp_stream_param *)&stream_prm);
+       EXPECT_NE(stream, nullptr);
+
+       ret = tle_udp_stream_get_param(stream, nullptr);
+       EXPECT_EQ(ret, EINVAL);
+}
+
+
+
diff --git a/test/gtest/test_tle_udp_stream.h b/test/gtest/test_tle_udp_stream.h
new file mode 100644 (file)
index 0000000..a5d166b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016  Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_TLE_UDP_STREAM_H_
+#define TEST_TLE_UDP_STREAM_H_
+#include <iostream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <rte_errno.h>
+
+#include <tle_udp_impl.h>
+#include <tle_event.h>
+
+struct tle_udp_ctx_param ctx_prm_tmpl = {
+       .socket_id = SOCKET_ID_ANY,
+       .max_streams = 0x10,
+       .max_stream_rbufs = 0x100,
+       .max_stream_sbufs = 0x100
+};
+
+struct tle_udp_dev_param dev_prm_tmpl = {
+       .rx_offload = 0x100,
+       .tx_offload = 0x100
+};
+
+class test_tle_udp_stream: public ::testing::Test {
+public:
+       void setup_dev_prm(struct tle_udp_dev_param *,
+                       char const *, char const *);
+       struct tle_udp_ctx *setup_ctx(struct tle_udp_ctx_param *prm);
+       struct tle_udp_dev *setup_dev(struct tle_udp_ctx *ctx,
+                       struct tle_udp_dev_param *dev_prm);
+       struct tle_evq *setup_event();
+
+       virtual void SetUp(void)
+       {
+               char const *ipv4_laddr = "192.168.0.1";
+               char const *ipv4_raddr = "192.168.0.2";
+               char const *ipv6 = "fe80::21e:67ff:fec2:2568";
+
+               ctx = nullptr;
+               dev = nullptr;
+               stream = nullptr;
+               /* Setup Context */
+               ctx = setup_ctx(&ctx_prm_tmpl);
+               /* Setup Dev */
+               memset(&dev_prm, 0, sizeof(dev_prm));
+               setup_dev_prm(&dev_prm, ipv4_laddr, ipv6);
+               dev = setup_dev(ctx, &dev_prm);
+
+               /* Stream Param & Event param */
+               memset(&stream_prm, 0, sizeof(struct tle_udp_stream_param));
+               inet_pton(AF_INET, ipv4_laddr, &stream_prm.local_addr);
+               inet_pton(AF_INET, ipv4_raddr, &stream_prm.remote_addr);
+               stream_prm.local_addr.ss_family = AF_INET;
+               stream_prm.remote_addr.ss_family = AF_INET;
+               stream_prm.recv_ev = tle_event_alloc(setup_event(), nullptr);
+               stream_prm.send_ev = tle_event_alloc(setup_event(), nullptr);
+       }
+
+       virtual void TearDown(void)
+       {
+               ret = 0;
+               tle_udp_stream_close(stream);
+               tle_udp_del_dev(dev);
+               tle_udp_destroy(ctx);
+       }
+
+       int ret;
+       struct tle_udp_ctx *ctx;
+       struct tle_udp_dev *dev;
+       struct tle_udp_stream *stream;
+
+       struct tle_udp_ctx_param ctx_prm;
+       struct tle_udp_dev_param dev_prm;
+       struct tle_udp_stream_param stream_prm;
+};
+
+struct tle_evq *test_tle_udp_stream::setup_event() {
+       int32_t socket_id;
+       uint32_t max_events;
+       struct tle_evq_param evq_params;
+       struct tle_evq *evq;
+
+       socket_id = SOCKET_ID_ANY;
+       max_events = 10;
+       rte_errno = 0;
+       memset(&evq_params, 0, sizeof(struct tle_evq_param));
+       evq_params.socket_id = socket_id;
+       evq_params.max_events = max_events;
+       evq = tle_evq_create(&evq_params);
+       return evq;
+}
+
+struct tle_udp_ctx
+*test_tle_udp_stream::setup_ctx(struct tle_udp_ctx_param *prm) {
+       struct tle_udp_ctx *ctx;
+
+       ctx = tle_udp_create(prm);
+
+       return ctx;
+}
+
+struct tle_udp_dev
+*test_tle_udp_stream::setup_dev(struct tle_udp_ctx *ctx,
+               struct tle_udp_dev_param *dev_prm) {
+
+       struct tle_udp_dev *dev;
+
+       dev = tle_udp_add_dev(ctx, dev_prm);
+
+       return dev;
+}
+
+void test_tle_udp_stream::setup_dev_prm(struct tle_udp_dev_param *dev_prm,
+               char const *ipv4, char const *ipv6) {
+
+       inet_pton(AF_INET, ipv4, &dev_prm->local_addr4);
+       inet_pton(AF_INET6, ipv6, &dev_prm->local_addr6);
+
+}
+
+#endif /* TEST_TLE_UDP_STREAM_H_ */