[05/13] app/test: introduce librte_security tests

Message ID 20200312151654.7218-6-l.wojciechow@partner.samsung.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series Fixes and unit tests for librte_security |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

Lukasz Wojciechowski March 12, 2020, 3:16 p.m. UTC
  This patch introduces set of unit tests of librte_security API functions.
Tests are added to dpdk-test application and can be run with
"security_autotest" runtime command.

This is the first patch in the series of patches as adding all test cases
for all API functions in a single patch would make it unreadable.

This patch defines structure of the file and necessary test framework
initialization. It also contains first subset of unit tests for
rte_security_session_create API function.

Structure of the tests file is following:
- macros for making tests more readable;
- mockup structures and functions for rte_security_ops;
- test suite and test cases setup and teardown functions;
- tests functions;
- declaration of testcases.

Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
---
 app/test/Makefile        |   2 +
 app/test/meson.build     |   3 +
 app/test/test_security.c | 670 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 675 insertions(+)
 create mode 100644 app/test/test_security.c
  

Comments

Akhil Goyal April 1, 2020, 5:09 p.m. UTC | #1
Hi Lukasz,


> 
> This patch introduces set of unit tests of librte_security API functions.
> Tests are added to dpdk-test application and can be run with
> "security_autotest" runtime command.
> 
> This is the first patch in the series of patches as adding all test cases
> for all API functions in a single patch would make it unreadable.
> 
> This patch defines structure of the file and necessary test framework
> initialization. It also contains first subset of unit tests for
> rte_security_session_create API function.
> 
> Structure of the tests file is following:
> - macros for making tests more readable;
> - mockup structures and functions for rte_security_ops;
> - test suite and test cases setup and teardown functions;
> - tests functions;
> - declaration of testcases.
> 
> Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
> Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
> ---

This patchset has a lot of repeated(for each API) tests just to check the input parameters to
Rte_security APIs. I am not sure what value addition is done to separate out each API as a separate
Negative Test. Instead a single case can be added to test all APIs with inappropriate arguments.
We should add more positive cases with proper session parameters.

Thomas,
Do we allow these type of test cases in other modules?

Regards,
Akhil
  
Thomas Monjalon April 1, 2020, 5:51 p.m. UTC | #2
01/04/2020 19:09, Akhil Goyal:
> Hi Lukasz,
> 
> > This patch introduces set of unit tests of librte_security API functions.
> > Tests are added to dpdk-test application and can be run with
> > "security_autotest" runtime command.
> > 
> > This is the first patch in the series of patches as adding all test cases
> > for all API functions in a single patch would make it unreadable.
> > 
> > This patch defines structure of the file and necessary test framework
> > initialization. It also contains first subset of unit tests for
> > rte_security_session_create API function.
> > 
> > Structure of the tests file is following:
> > - macros for making tests more readable;
> > - mockup structures and functions for rte_security_ops;
> > - test suite and test cases setup and teardown functions;
> > - tests functions;
> > - declaration of testcases.
> > 
> > Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
> > Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
> > ---
> 
> This patchset has a lot of repeated(for each API) tests just to check the input parameters to
> Rte_security APIs. I am not sure what value addition is done to separate out each API as a separate
> Negative Test. Instead a single case can be added to test all APIs with inappropriate arguments.
> We should add more positive cases with proper session parameters.
> 
> Thomas,
> Do we allow these type of test cases in other modules?

I did not review these patches, but I think we can try to compare
with tests done on eventdev library.
It would be interesting to have an opinion from Declan.

These rte_security tests look quite big.
However I don't know what is too big for test code?
Lukasz, please could you explain the initial motivation when writing
these tests? Are you especially interested in rte_security?
Or do you plan to reproduce this effort on other libraries?
  
Lukasz Wojciechowski April 2, 2020, 7:49 p.m. UTC | #3
W dniu 01.04.2020 o 19:51, Thomas Monjalon pisze:
> 01/04/2020 19:09, Akhil Goyal:
>> Hi Lukasz,
>>
>>> This patch introduces set of unit tests of librte_security API functions.
>>> Tests are added to dpdk-test application and can be run with
>>> "security_autotest" runtime command.
>>>
>>> This is the first patch in the series of patches as adding all test cases
>>> for all API functions in a single patch would make it unreadable.
>>>
>>> This patch defines structure of the file and necessary test framework
>>> initialization. It also contains first subset of unit tests for
>>> rte_security_session_create API function.
>>>
>>> Structure of the tests file is following:
>>> - macros for making tests more readable;
>>> - mockup structures and functions for rte_security_ops;
>>> - test suite and test cases setup and teardown functions;
>>> - tests functions;
>>> - declaration of testcases.
>>>
>>> Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
>>> Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
>>> ---
>> This patchset has a lot of repeated(for each API) tests just to check the input parameters to
>> Rte_security APIs. I am not sure what value addition is done to separate out each API as a separate
>> Negative Test. Instead a single case can be added to test all APIs with inappropriate arguments.
>> We should add more positive cases with proper session parameters.
>>
>> Thomas,
>> Do we allow these type of test cases in other modules?
> I did not review these patches, but I think we can try to compare
> with tests done on eventdev library.
> It would be interesting to have an opinion from Declan.
>
> These rte_security tests look quite big.
> However I don't know what is too big for test code?
> Lukasz, please could you explain the initial motivation when writing
> these tests? Are you especially interested in rte_security?
> Or do you plan to reproduce this effort on other libraries?
>
>
Hi Akhil and Thomas,

I've just started using dpdk this year and was writing few small apps to 
get familiar with API.
I noticed few things that can be fixed in the security lib and though 
that they can be fixed easily, so I prepared patches.

After that I searched for some unit tests of the lib to add some tests 
that cover my code. I always try to do so
and when I found no tests for security lib I made some.

I don't know if you need them or is this the right place to put them, 
but I did. And as I made the tests I tried to cover 100% code of 
security lib.

Currently I don't have any plans to add or change anything in 
rte_security. These patches are just a "collateral damage" to my process 
of learning dpdk and a strong believe that if you can share some fixes 
you should do it, because that the open source power.

So it is totaly up to you, what we can do with these patches. I would be 
glad to work on them and change them the way you think they should look 
like, e.g. I can squash all the parameters checks to a single negative 
case as you, Akhil suggested. If you would like to see similar patches 
in other libraries I can help with that in some spare time. I'm the new 
guy here, so please guide me a bit ;)
  
Thomas Monjalon April 2, 2020, 8:51 p.m. UTC | #4
02/04/2020 21:49, Lukasz Wojciechowski:
> 
> W dniu 01.04.2020 o 19:51, Thomas Monjalon pisze:
> > 01/04/2020 19:09, Akhil Goyal:
> >> Hi Lukasz,
> >>
> >>> This patch introduces set of unit tests of librte_security API functions.
> >>> Tests are added to dpdk-test application and can be run with
> >>> "security_autotest" runtime command.
> >>>
> >>> This is the first patch in the series of patches as adding all test cases
> >>> for all API functions in a single patch would make it unreadable.
> >>>
> >>> This patch defines structure of the file and necessary test framework
> >>> initialization. It also contains first subset of unit tests for
> >>> rte_security_session_create API function.
> >>>
> >>> Structure of the tests file is following:
> >>> - macros for making tests more readable;
> >>> - mockup structures and functions for rte_security_ops;
> >>> - test suite and test cases setup and teardown functions;
> >>> - tests functions;
> >>> - declaration of testcases.
> >>>
> >>> Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
> >>> Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
> >>> ---
> >> This patchset has a lot of repeated(for each API) tests just to check the input parameters to
> >> Rte_security APIs. I am not sure what value addition is done to separate out each API as a separate
> >> Negative Test. Instead a single case can be added to test all APIs with inappropriate arguments.
> >> We should add more positive cases with proper session parameters.
> >>
> >> Thomas,
> >> Do we allow these type of test cases in other modules?
> > I did not review these patches, but I think we can try to compare
> > with tests done on eventdev library.
> > It would be interesting to have an opinion from Declan.
> >
> > These rte_security tests look quite big.
> > However I don't know what is too big for test code?
> > Lukasz, please could you explain the initial motivation when writing
> > these tests? Are you especially interested in rte_security?
> > Or do you plan to reproduce this effort on other libraries?
> >
> >
> Hi Akhil and Thomas,
> 
> I've just started using dpdk this year and was writing few small apps to 
> get familiar with API.
> I noticed few things that can be fixed in the security lib and though 
> that they can be fixed easily, so I prepared patches.
> 
> After that I searched for some unit tests of the lib to add some tests 
> that cover my code. I always try to do so
> and when I found no tests for security lib I made some.
> 
> I don't know if you need them or is this the right place to put them, 
> but I did. And as I made the tests I tried to cover 100% code of 
> security lib.
> 
> Currently I don't have any plans to add or change anything in 
> rte_security. These patches are just a "collateral damage" to my process 
> of learning dpdk and a strong believe that if you can share some fixes 
> you should do it, because that the open source power.
> 
> So it is totaly up to you, what we can do with these patches. I would be 
> glad to work on them and change them the way you think they should look 
> like, e.g. I can squash all the parameters checks to a single negative 
> case as you, Akhil suggested. If you would like to see similar patches 
> in other libraries I can help with that in some spare time. I'm the new 
> guy here, so please guide me a bit ;)

Thanks a lot Lukasz.
In general we need more tests in DPDK.

I won't be able to review these patches myself,
so I hope many developers will review and guide you.

My advice is to review at least one or two other patchsets.
Hopefully someone will do the same for you.
If it does not work, please ping Akhil and me.
As a last resort, we could prioritize merging patches of
contributors helping others.
  
Lukasz Wojciechowski April 3, 2020, 7:24 p.m. UTC | #5
Dear Akhil,

W dniu 01.04.2020 o 19:09, Akhil Goyal pisze:
> Hi Lukasz,
>
>
>> This patch introduces set of unit tests of librte_security API functions.
>> Tests are added to dpdk-test application and can be run with
>> "security_autotest" runtime command.
>>
>> This is the first patch in the series of patches as adding all test cases
>> for all API functions in a single patch would make it unreadable.
>>
>> This patch defines structure of the file and necessary test framework
>> initialization. It also contains first subset of unit tests for
>> rte_security_session_create API function.
>>
>> Structure of the tests file is following:
>> - macros for making tests more readable;
>> - mockup structures and functions for rte_security_ops;
>> - test suite and test cases setup and teardown functions;
>> - tests functions;
>> - declaration of testcases.
>>
>> Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
>> Change-Id: I3a4585f56ef1a75b2984fcea3a3e4a30e4c2d8a6
>> ---
> This patchset has a lot of repeated(for each API) tests just to check the input parameters to
> Rte_security APIs. I am not sure what value addition is done to separate out each API as a separate
> Negative Test. Instead a single case can be added to test all APIs with inappropriate arguments.
> We should add more positive cases with proper session parameters.
>
> Thomas,
> Do we allow these type of test cases in other modules?
>
> Regards,
> Akhil
As I already replied to you and Thomas, my primary intention was to make 
fixes to rte_security lib.

And as I did, I wanted to cover them also with unit tests. And as these 
are unit tests, there is plenty of them and all they do is to verify 
input parameters and check if proper functions are running and the code 
exists function in proper places with proper return values. So they 
verify the flow inside each API function. In my opinion it is best to 
have a single testcase to check single function flow with set 
conditions. So if anything fails in the future, you will know exactly 
what and why.

As the unit tests verify flow of the function, usualy they can fail in 
many ways, but the "proper" path to execute a function is only one, so 
there are much less positive testcases. Maybe more positive testcases 
you can see in the last patch containing tests for 
rte_security_capability_get. There are many testcases showing matches of 
capabilities to different patterns.

What you would like to have are functional tests not only for 
librte_security but together with its usage. I agree that would be nice 
to have such tests also, but those wouldn't test rte_security by itself, 
they would test its usage and that's completely different thing and 
that's not what these patches provide.

I'll check more modules to see how the tests look like there and I'll 
take a look at eventdev-tests, that Thomas mentioned.


Best regards

Lukasz
  

Patch

diff --git a/app/test/Makefile b/app/test/Makefile
index 1f080d162..153610a32 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -231,6 +231,8 @@  SRCS-$(CONFIG_RTE_LIBRTE_BPF) += test_bpf.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_RCU) += test_rcu_qsbr.c test_rcu_qsbr_perf.c
 
+SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_security.c
+
 SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c
 SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c
 ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
diff --git a/app/test/meson.build b/app/test/meson.build
index 0a2ce710f..89e4299fd 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -103,6 +103,7 @@  test_sources = files('commands.c',
 	'test_ring_perf.c',
 	'test_rwlock.c',
 	'test_sched.c',
+	'test_security.c',
 	'test_service_cores.c',
 	'test_spinlock.c',
 	'test_stack.c',
@@ -150,6 +151,7 @@  test_deps = ['acl',
 	'reorder',
 	'rib',
 	'ring',
+	'security',
 	'stack',
 	'timer'
 ]
@@ -209,6 +211,7 @@  fast_test_names = [
         'rwlock_rds_wrm_autotest',
         'rwlock_rde_wro_autotest',
         'sched_autotest',
+        'security_autotest',
         'spinlock_autotest',
         'stack_autotest',
         'stack_lf_autotest',
diff --git a/app/test/test_security.c b/app/test/test_security.c
new file mode 100644
index 000000000..885281703
--- /dev/null
+++ b/app/test/test_security.c
@@ -0,0 +1,670 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ */
+
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_security.h>
+#include <rte_security_driver.h>
+
+/* Before including rte_test.h file you can define
+ * RTE_TEST_TRACE_FAILURE(_file, _line, _func) macro to better trace/debug test
+ * failures. Mostly useful in development phase.
+ */
+#ifndef RTE_TEST_TRACE_FAILURE
+#define RTE_TEST_TRACE_FAILURE(_file, _line, _func) \
+	RTE_LOG(DEBUG, EAL, "in %s:%d %s\n", _file, _line, _func)
+#endif
+
+#include <rte_test.h>
+#include "test.h"
+
+/**
+ * Security
+ * =======
+ *
+ * Basic unit tests of the librte_security API.
+ *
+ * Structure of the file:
+ * - macros for making tests more readable;
+ * - mockup structures and functions for rte_security_ops;
+ * - test suite and test cases setup and teardown functions;
+ * - tests functions;
+ * - declaration of testcases.
+ */
+
+
+/**
+ * Macros
+ *
+ * Set of macros for making tests easier to read.
+ */
+
+/**
+ * Verify condition inside mocked up function.
+ * Mockup function cannot return a test error, so the failure
+ * of assertion increases counter and print logs.
+ * The counter can be verified later to check if test case should fail.
+ *
+ * @param   fail_counter	fail counter
+ * @param   cond	condition expected to be true
+ * @param   msg	printf style formatting string for custom message
+ */
+#define MOCK_TEST_ASSERT(fail_counter, cond, msg, ...) do {			\
+	if (!(cond)) {								\
+		fail_counter++;							\
+		RTE_LOG(DEBUG, EAL, "Test assert %s line %d failed: "		\
+				msg "\n", __func__, __LINE__, ##__VA_ARGS__);	\
+		RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__);		\
+	}									\
+} while (0)
+
+/**
+ * Verify equality condition inside mocked up function.
+ * Mockup function cannot return a test error, so the failure
+ * of assertion increases counter and print logs.
+ * The counter can be verified later to check if test case should fail.
+ *
+ * @param   fail_counter	fail counter
+ * @param   a	first value of comparison
+ * @param   b	second value of comparison
+ * @param   msg	printf style formatting string for custom message
+ */
+#define MOCK_TEST_ASSERT_EQUAL(fail_counter, a, b, msg, ...)	\
+	MOCK_TEST_ASSERT(fail_counter, (a) == (b), msg, ##__VA_ARGS__)
+
+
+/**
+ * Verify if parameter of the mocked up function matches expected value.
+ * The expected value is stored in data structure in the field matching
+ * parameter name.
+ *
+ * @param   data	structure with expected values
+ * @param   parameter	name of the parameter (both field and parameter name)
+ * @param   spec	printf style spec for parameter
+ */
+#define MOCK_TEST_ASSERT_PARAMETER(data, parameter, spec)			\
+	MOCK_TEST_ASSERT_EQUAL(data.failed, data.parameter, parameter,		\
+			"Expecting parameter %s to be " spec " but it's " spec,	\
+			RTE_STR(parameter), data.parameter, parameter)
+
+/**
+ * Wrap for MOCK_TEST_ASSERT_PARAMETER macro for pointer type parameters.
+ *
+ * @param   data	structure with expected values
+ * @param   parameter	name of the parameter (both field and parameter name)
+ */
+#define MOCK_TEST_ASSERT_POINTER_PARAMETER(data, parameter)	\
+	MOCK_TEST_ASSERT_PARAMETER(data, parameter, "%p")
+
+/**
+ * Verify number of calls of the mocked up function
+ * and check if there were any fails during execution.
+ * The fails statistics inside mocked up functions are collected
+ * as "failed" field in mockup structures.
+ *
+ * @param   mock_data	structure with statistics (called, failed)
+ * @param   exp_calls	expected number of mockup function calls
+ */
+#define TEST_ASSERT_MOCK_CALLS(mock_data, exp_calls) do {		\
+	TEST_ASSERT_EQUAL(exp_calls, mock_data.called,			\
+			"Expecting sub op to be called %d times, "	\
+			"but it's called %d times",			\
+			exp_calls, mock_data.called);			\
+	TEST_ASSERT_EQUAL(0, mock_data.failed,				\
+			"Expecting sub op asserts not to fail, "	\
+			"but they're failed %d times",			\
+			mock_data.failed);				\
+} while (0)
+
+/**
+ * Assert tested function result match expected value
+ *
+ * @param   f_name	name of tested function
+ * @param   f_ret	value returned by the function
+ * @param   exp_ret	expected returned value
+ */
+#define TEST_ASSERT_MOCK_FUNCTION_CALL_RET(f_name, f_ret, exp_ret,			\
+		ret_spec) do {								\
+	TEST_ASSERT_EQUAL(exp_ret, f_ret, "Expecting " RTE_STR(f_name)			\
+			" to return " ret_spec ", but it returned " ret_spec "\n",	\
+			exp_ret, f_ret);						\
+} while (0)
+
+/**
+ * Assert tested function result is not NULL
+ *
+ * @param   f_name	name of tested function
+ * @param   f_ret	value returned by the function
+ */
+#define TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(f_name, f_ret) do {	\
+	TEST_ASSERT_NOT_NULL(f_ret, "Expecting " RTE_STR(f_name)	\
+			" to return not NULL\n");			\
+} while (0)
+
+/**
+ * Verify that sess_cnt counter value matches expected
+ *
+ * @param   expected_sessions_count	expected counter value
+ */
+#define TEST_ASSERT_SESSION_COUNT(expected_sessions_count) do {			\
+	struct security_unittest_params *ut_params = &unittest_params;		\
+	TEST_ASSERT_EQUAL(expected_sessions_count, ut_params->ctx.sess_cnt,	\
+			"Expecting session counter to be %u but it's %u",	\
+			expected_sessions_count, ut_params->ctx.sess_cnt);	\
+} while (0)
+
+/**
+ * Verify usage of mempool by checking if number of allocated objects matches
+ * expectations. The mempool is used to manage objects for sessions data.
+ * A single object is acquired from mempool during session_create
+ * and put back in session_destroy.
+ *
+ * @param   expected_mempool_usage	expected number of mempool objects in use
+ */
+#define TEST_ASSERT_MEMPOOL_USAGE(expected_mempool_usage) do {			\
+	struct security_testsuite_params *ts_params = &testsuite_params;	\
+	unsigned int mempool_usage;						\
+	mempool_usage = rte_mempool_in_use_count(ts_params->session_mpool);	\
+	TEST_ASSERT_EQUAL(expected_mempool_usage, mempool_usage,		\
+			"Expecting %u mempool allocations, "			\
+			"but there are %u allocated objects",			\
+			expected_mempool_usage, mempool_usage);			\
+} while (0)
+
+
+/**
+ * Mockup structures and functions for rte_security_ops;
+ *
+ * Set of structures for controlling mockup functions calls.
+ * Every mockup function X has its corresponding X_data structure
+ * and an instance of that structure X_exp.
+ * Structure contains parameters that a mockup function is expected
+ * to be called with, a value to return (.ret) and 2 statistics:
+ * .called (number of times the mockup function was called)
+ * and .failed (number of assertion fails during mockup function call).
+ *
+ * Mockup functions verify that the parameters they are called with match
+ * expected values. The expected values should be stored in corresponding
+ * structures prior to mockup functions call. Every failure of such
+ * verification increases .failed counter. Every call of mockup function
+ * increases .called counter. Function returns value stored in .ret field
+ * of the structure.
+ * In case of some parameters in some functions the expected value is unknown
+ * and cannot be detrmined prior to call. Such parameters are stored
+ * in structure and can be compared or analyzed later in test case code.
+ *
+ * Below structures and functions follow the rules just described.
+ * Additional remarks and exceptions are added in comments.
+ */
+
+/**
+ * session_create mockup
+ *
+ * Verified parameters: device, conf, mp.
+ * Saved, not verified parameters: sess.
+ */
+static struct mock_session_create_data {
+	void *device;
+	struct rte_security_session_conf *conf;
+	struct rte_security_session *sess;
+	struct rte_mempool *mp;
+
+	int ret;
+
+	int called;
+	int failed;
+} mock_session_create_exp = {NULL, NULL, NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_create(void *device,
+		struct rte_security_session_conf *conf,
+		struct rte_security_session *sess,
+		struct rte_mempool *mp) {
+	mock_session_create_exp.called++;
+
+	MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, device);
+	MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, conf);
+	MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, mp);
+
+	mock_session_create_exp.sess = sess;
+
+	return mock_session_create_exp.ret;
+}
+
+/**
+ * session_destroy mockup
+ *
+ * Verified parameters: device, sess.
+ */
+static struct mock_session_destroy_data {
+	void *device;
+	struct rte_security_session *sess;
+
+	int ret;
+
+	int called;
+	int failed;
+} mock_session_destroy_exp = {NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_destroy(void *device,
+		struct rte_security_session *sess) {
+	mock_session_destroy_exp.called++;
+
+	MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, device);
+	MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, sess);
+
+	return mock_session_destroy_exp.ret;
+}
+
+/**
+ * empty_ops
+ *
+ * is an empty security operations set (all function pointers set to NULL)
+ */
+struct rte_security_ops empty_ops = { NULL };
+
+/**
+ * mock_ops
+ *
+ * is a security operations set using mockup functions
+ */
+struct rte_security_ops mock_ops = {
+	.session_create = mock_session_create,
+	.session_destroy = mock_session_destroy,
+};
+
+
+/**
+ * Test suite and test cases setup and teardown functions.
+ */
+
+/**
+ * struct security_testsuite_params defines parameters initialized once
+ * for whole tests suite.
+ * Currently the only stored parameter is session_mpool a mempool created
+ * once in testsuite_setup and released in testsuite_teardown.
+ * The instance of this structure is stored in testsuite_params variable.
+ */
+static struct security_testsuite_params {
+	struct rte_mempool *session_mpool;
+} testsuite_params = { NULL };
+
+/**
+ * struct security_unittest_params defines parameters initialized
+ * for every test case. The parameters are initialized in ut_setup
+ * and released in ut_teardown.
+ * The instance of this structure is stored in unittest_params variable.
+ */
+static struct security_unittest_params {
+	struct rte_security_ctx ctx;
+	struct rte_security_session_conf conf;
+	struct rte_security_session *sess;
+} unittest_params = {
+	.ctx = {
+		.device = NULL,
+		.ops = &mock_ops,
+		.sess_cnt = 0,
+	},
+	.sess = NULL,
+};
+
+#define SECURITY_TEST_MEMPOOL_NAME "SecurityTestsMempoolName"
+#define SECURITY_TEST_MEMPOOL_SIZE 15
+#define SECURITY_TEST_SESSION_OBJECT_SIZE sizeof(struct rte_security_session)
+
+/**
+ * testsuite_setup initializes whole test suite parameters.
+ * It creates a new mempool used in all test cases
+ * and verifies if it properly created.
+ */
+static int
+testsuite_setup(void) {
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	ts_params->session_mpool = rte_mempool_create(
+			SECURITY_TEST_MEMPOOL_NAME,
+			SECURITY_TEST_MEMPOOL_SIZE,
+			SECURITY_TEST_SESSION_OBJECT_SIZE,
+			0, 0, NULL, NULL, NULL, NULL,
+			SOCKET_ID_ANY, 0);
+	TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
+			"Cannot create mempool %s\n", rte_strerror(rte_errno));
+	return TEST_SUCCESS;
+}
+
+/**
+ * testsuite_teardown releases test suite wide parameters.
+ */
+static void
+testsuite_teardown(void) {
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	if (ts_params->session_mpool) {
+		rte_mempool_free(ts_params->session_mpool);
+		ts_params->session_mpool = NULL;
+	}
+}
+
+/**
+ * ut_setup initializes test case parameters to default values.
+ * It resets alse any .called and .failed statistics of mockup functions
+ * usage.
+ */
+static int
+ut_setup(void) {
+	struct security_unittest_params *ut_params = &unittest_params;
+	ut_params->ctx.device = NULL;
+	ut_params->ctx.ops = &mock_ops;
+	ut_params->ctx.sess_cnt = 0;
+	ut_params->sess = NULL;
+
+	mock_session_create_exp.called = 0;
+	mock_session_destroy_exp.called = 0;
+
+	mock_session_create_exp.failed = 0;
+	mock_session_destroy_exp.failed = 0;
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * destroy_session_with_check is a helper function releasing session
+ * created with rte_security_session_create and stored in test case parameters.
+ * It's used both to release sessions created in test cases' bodies
+ * which are assigned to ut_params->sess
+ */
+static int
+destroy_session_with_check(void) {
+	struct security_unittest_params *ut_params = &unittest_params;
+	if (ut_params->sess != NULL) {
+		//assure that mockup function for destroy operation is set.
+		ut_params->ctx.ops = &mock_ops;
+
+		mock_session_destroy_exp.device = NULL;
+		mock_session_destroy_exp.sess = ut_params->sess;
+		mock_session_destroy_exp.ret = 0;
+		mock_session_destroy_exp.called = 0;
+		mock_session_destroy_exp.failed = 0;
+
+		int ret = rte_security_session_destroy(&ut_params->ctx,
+				ut_params->sess);
+		TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+				ret, 0, "%d");
+		TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 1);
+
+		ut_params->sess = NULL;
+	}
+	return TEST_SUCCESS;
+}
+
+/**
+ * ut_teardown releases test case parameters.
+ */
+static void
+ut_teardown(void) {
+	destroy_session_with_check();
+}
+
+
+/**
+ * Test functions
+ *
+ * Each test function is related to a single test case.
+ * They are arranged by tested rte_security API function
+ * and by rte_security execution paths sequence in code.
+ */
+
+/**
+ * rte_security_session_create tests
+ */
+
+/**
+ * Test execution of rte_security_session_create with NULL instance
+ */
+static int
+test_rte_security_session_create_inv_param_context(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	sess = rte_security_session_create(NULL, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_rte_security_session_create_inv_param_context_ops(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	ut_params->ctx.ops = NULL;
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with empty
+ * security operations
+ */
+static int
+test_rte_security_session_create_inv_param_context_ops_fun(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	ut_params->ctx.ops = &empty_ops;
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with NULL conf parameter
+ */
+static int
+test_rte_security_session_create_inv_param_configuration(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	sess = rte_security_session_create(&ut_params->ctx, NULL,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with NULL mp parameter
+ */
+static int
+test_rte_security_session_create_inv_param_mempool(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			NULL);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create in case when mempool
+ * is fully used and no object can be got from it
+ */
+static int
+test_rte_security_session_create_mempool_empty(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *tmp[SECURITY_TEST_MEMPOOL_SIZE];
+	struct rte_security_session *sess;
+
+	// Get all available objects from mempool
+	int i, ret;
+	for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i) {
+		ret = rte_mempool_get(ts_params->session_mpool, (void **)(&tmp[i]));
+		TEST_ASSERT_EQUAL(0, ret,
+				"Expect getting %d object from mempool to succeed", i);
+	}
+	TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+	TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	// Put objects back to the pool.
+	for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i) {
+		rte_mempool_put(ts_params->session_mpool, (void *)(tmp[i]));
+	}
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create when session_create
+ * security operation fails
+ */
+static int
+test_rte_security_session_create_ops_failure(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	mock_session_create_exp.device = NULL;
+	mock_session_create_exp.conf = &ut_params->conf;
+	mock_session_create_exp.mp = ts_params->session_mpool;
+	mock_session_create_exp.ret = -1;	// return failure status
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+			sess, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
+	TEST_ASSERT_MEMPOOL_USAGE(0);
+	TEST_ASSERT_SESSION_COUNT(0);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create in successful execution path
+ */
+static int
+test_rte_security_session_create_success(void)
+{
+	struct security_testsuite_params *ts_params = &testsuite_params;
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_session *sess;
+
+	mock_session_create_exp.device = NULL;
+	mock_session_create_exp.conf = &ut_params->conf;
+	mock_session_create_exp.mp = ts_params->session_mpool;
+	mock_session_create_exp.ret = 0;	// return success status
+
+	sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+			ts_params->session_mpool);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(rte_security_session_create, sess);
+	TEST_ASSERT_EQUAL(sess, mock_session_create_exp.sess,
+			"Expecting session_create to be called with %p sess parameter, "
+			"but it's called %p sess parameter",
+			sess, mock_session_create_exp.sess);
+	TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
+	TEST_ASSERT_MEMPOOL_USAGE(1);
+	TEST_ASSERT_SESSION_COUNT(1);
+
+	// Store created session in test case parameters, so it can be released
+	// after test case in ut_teardown by destroy_session_with_check.
+	ut_params->sess = sess;
+
+	return TEST_SUCCESS;
+}
+
+
+/**
+ * Declaration of testcases
+ */
+static struct unit_test_suite security_testsuite  = {
+	.suite_name = "generic security",
+	.setup = testsuite_setup,
+	.teardown = testsuite_teardown,
+	.unit_test_cases = {
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_inv_param_context),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_inv_param_context_ops),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_inv_param_context_ops_fun),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_inv_param_configuration),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_inv_param_mempool),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_mempool_empty),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_ops_failure),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_rte_security_session_create_success),
+
+		TEST_CASES_END() /**< NULL terminate unit test array */
+	}
+};
+
+static int
+test_security(void)
+{
+	rte_log_set_global_level(RTE_LOG_DEBUG);
+	rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
+
+	return unit_test_suite_runner(&security_testsuite);
+}
+
+REGISTER_TEST_COMMAND(security_autotest, test_security);