1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
7 #include <rte_memory.h>
8 #include <rte_mempool.h>
9 #include <rte_security.h>
10 #include <rte_security_driver.h>
12 /* Before including rte_test.h file you can define
13 * RTE_TEST_TRACE_FAILURE(_file, _line, _func) macro to better trace/debug test
14 * failures. Mostly useful in development phase.
16 #ifndef RTE_TEST_TRACE_FAILURE
17 #define RTE_TEST_TRACE_FAILURE(_file, _line, _func) \
18 RTE_LOG(DEBUG, EAL, "in %s:%d %s\n", _file, _line, _func)
28 * Basic unit tests of the librte_security API.
30 * Structure of the file:
31 * - macros for making tests more readable;
32 * - mockup structures and functions for rte_security_ops;
33 * - test suite and test cases setup and teardown functions;
35 * - declaration of testcases.
42 * Set of macros for making tests easier to read.
46 * Verify condition inside mocked up function.
47 * Mockup function cannot return a test error, so the failure
48 * of assertion increases counter and print logs.
49 * The counter can be verified later to check if test case should fail.
51 * @param fail_counter fail counter
52 * @param cond condition expected to be true
53 * @param msg printf style formatting string for custom message
55 #define MOCK_TEST_ASSERT(fail_counter, cond, msg, ...) do { \
58 RTE_LOG(DEBUG, EAL, "Test assert %s line %d failed: " \
59 msg "\n", __func__, __LINE__, \
61 RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
66 * Verify equality condition inside mocked up function.
67 * Mockup function cannot return a test error, so the failure
68 * of assertion increases counter and print logs.
69 * The counter can be verified later to check if test case should fail.
71 * @param fail_counter fail counter
72 * @param a first value of comparison
73 * @param b second value of comparison
74 * @param msg printf style formatting string for custom message
76 #define MOCK_TEST_ASSERT_EQUAL(fail_counter, a, b, msg, ...) \
77 MOCK_TEST_ASSERT(fail_counter, (a) == (b), msg, ##__VA_ARGS__)
81 * Verify if parameter of the mocked up function matches expected value.
82 * The expected value is stored in data structure in the field matching
85 * @param data structure with expected values
86 * @param parameter name of the parameter (both field and parameter name)
87 * @param spec printf style spec for parameter
89 #define MOCK_TEST_ASSERT_PARAMETER(data, parameter, spec) \
90 MOCK_TEST_ASSERT_EQUAL(data.failed, data.parameter, parameter, \
91 "Expecting parameter %s to be " spec \
92 " but it's " spec, RTE_STR(parameter), \
93 data.parameter, parameter)
96 * Wrap for MOCK_TEST_ASSERT_PARAMETER macro for pointer type parameters.
98 * @param data structure with expected values
99 * @param parameter name of the parameter (both field and parameter name)
101 #define MOCK_TEST_ASSERT_POINTER_PARAMETER(data, parameter) \
102 MOCK_TEST_ASSERT_PARAMETER(data, parameter, "%p")
105 * Verify number of calls of the mocked up function
106 * and check if there were any fails during execution.
107 * The fails statistics inside mocked up functions are collected
108 * as "failed" field in mockup structures.
110 * @param mock_data structure with statistics (called, failed)
111 * @param exp_calls expected number of mockup function calls
113 #define TEST_ASSERT_MOCK_CALLS(mock_data, exp_calls) do { \
114 TEST_ASSERT_EQUAL(exp_calls, mock_data.called, \
115 "Expecting sub op to be called %d times, " \
116 "but it's called %d times", \
117 exp_calls, mock_data.called); \
118 TEST_ASSERT_EQUAL(0, mock_data.failed, \
119 "Expecting sub op asserts not to fail, " \
120 "but they're failed %d times", \
125 * Assert tested function result match expected value
127 * @param f_name name of tested function
128 * @param f_ret value returned by the function
129 * @param exp_ret expected returned value
130 * @param fmt printf style format for returned value
132 #define TEST_ASSERT_MOCK_FUNCTION_CALL_RET(f_name, f_ret, exp_ret, fmt) \
133 TEST_ASSERT_EQUAL(exp_ret, f_ret, "Expecting " RTE_STR(f_name) \
134 " to return " fmt ", but it returned " fmt \
135 "\n", exp_ret, f_ret)
138 * Assert tested function result is not NULL
140 * @param f_name name of tested function
141 * @param f_ret value returned by the function
143 #define TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(f_name, f_ret) \
144 TEST_ASSERT_NOT_NULL(f_ret, "Expecting " RTE_STR(f_name) \
145 " to return not NULL\n")
148 * Verify that sess_cnt counter value matches expected
150 * @param expected_sessions_count expected counter value
152 #define TEST_ASSERT_SESSION_COUNT(expected_sessions_count) do { \
153 struct security_unittest_params *ut_params = &unittest_params; \
154 TEST_ASSERT_EQUAL(expected_sessions_count, \
155 ut_params->ctx.sess_cnt, \
156 "Expecting session counter to be %u," \
157 " but it's %u", expected_sessions_count, \
158 ut_params->ctx.sess_cnt); \
162 * Verify usage of mempool by checking if number of allocated objects matches
163 * expectations. The mempool is used to manage objects for sessions data.
164 * A single object is acquired from mempool during session_create
165 * and put back in session_destroy.
167 * @param expected_mempool_usage expected number of used mempool objects
169 #define TEST_ASSERT_MEMPOOL_USAGE(expected_mempool_usage) do { \
170 struct security_testsuite_params *ts_params = &testsuite_params;\
171 unsigned int mempool_usage; \
172 mempool_usage = rte_mempool_in_use_count( \
173 ts_params->session_mpool); \
174 TEST_ASSERT_EQUAL(expected_mempool_usage, mempool_usage, \
175 "Expecting %u mempool allocations, " \
176 "but there are %u allocated objects", \
177 expected_mempool_usage, mempool_usage); \
182 * Mockup structures and functions for rte_security_ops;
184 * Set of structures for controlling mockup functions calls.
185 * Every mockup function X has its corresponding X_data structure
186 * and an instance of that structure X_exp.
187 * Structure contains parameters that a mockup function is expected
188 * to be called with, a value to return (.ret) and 2 statistics:
189 * .called (number of times the mockup function was called)
190 * and .failed (number of assertion fails during mockup function call).
192 * Mockup functions verify that the parameters they are called with match
193 * expected values. The expected values should be stored in corresponding
194 * structures prior to mockup functions call. Every failure of such
195 * verification increases .failed counter. Every call of mockup function
196 * increases .called counter. Function returns value stored in .ret field
198 * In case of some parameters in some functions the expected value is unknown
199 * and cannot be detrmined prior to call. Such parameters are stored
200 * in structure and can be compared or analyzed later in test case code.
202 * Below structures and functions follow the rules just described.
203 * Additional remarks and exceptions are added in comments.
207 * session_create mockup
209 * Verified parameters: device, conf, mp.
210 * Saved, not verified parameters: sess.
212 static struct mock_session_create_data {
214 struct rte_security_session_conf *conf;
215 struct rte_security_session *sess;
216 struct rte_mempool *mp;
222 } mock_session_create_exp = {NULL, NULL, NULL, NULL, 0, 0, 0};
225 mock_session_create(void *device,
226 struct rte_security_session_conf *conf,
227 struct rte_security_session *sess,
228 struct rte_mempool *mp)
230 mock_session_create_exp.called++;
232 MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, device);
233 MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, conf);
234 MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, mp);
236 mock_session_create_exp.sess = sess;
238 return mock_session_create_exp.ret;
242 * session_destroy mockup
244 * Verified parameters: device, sess.
246 static struct mock_session_destroy_data {
248 struct rte_security_session *sess;
254 } mock_session_destroy_exp = {NULL, NULL, 0, 0, 0};
257 mock_session_destroy(void *device, struct rte_security_session *sess)
259 mock_session_destroy_exp.called++;
261 MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, device);
262 MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, sess);
264 return mock_session_destroy_exp.ret;
270 * is an empty security operations set (all function pointers set to NULL)
272 struct rte_security_ops empty_ops = { NULL };
277 * is a security operations set using mockup functions
279 struct rte_security_ops mock_ops = {
280 .session_create = mock_session_create,
281 .session_destroy = mock_session_destroy,
286 * Test suite and test cases setup and teardown functions.
290 * struct security_testsuite_params defines parameters initialized once
291 * for whole tests suite.
292 * Currently the only stored parameter is session_mpool a mempool created
293 * once in testsuite_setup and released in testsuite_teardown.
294 * The instance of this structure is stored in testsuite_params variable.
296 static struct security_testsuite_params {
297 struct rte_mempool *session_mpool;
298 } testsuite_params = { NULL };
301 * struct security_unittest_params defines parameters initialized
302 * for every test case. The parameters are initialized in ut_setup
303 * and released in ut_teardown.
304 * The instance of this structure is stored in unittest_params variable.
306 static struct security_unittest_params {
307 struct rte_security_ctx ctx;
308 struct rte_security_session_conf conf;
309 struct rte_security_session *sess;
310 } unittest_params = {
319 #define SECURITY_TEST_MEMPOOL_NAME "SecurityTestsMempoolName"
320 #define SECURITY_TEST_MEMPOOL_SIZE 15
321 #define SECURITY_TEST_SESSION_OBJECT_SIZE sizeof(struct rte_security_session)
324 * testsuite_setup initializes whole test suite parameters.
325 * It creates a new mempool used in all test cases
326 * and verifies if it properly created.
329 testsuite_setup(void)
331 struct security_testsuite_params *ts_params = &testsuite_params;
332 ts_params->session_mpool = rte_mempool_create(
333 SECURITY_TEST_MEMPOOL_NAME,
334 SECURITY_TEST_MEMPOOL_SIZE,
335 SECURITY_TEST_SESSION_OBJECT_SIZE,
336 0, 0, NULL, NULL, NULL, NULL,
338 TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
339 "Cannot create mempool %s\n", rte_strerror(rte_errno));
344 * testsuite_teardown releases test suite wide parameters.
347 testsuite_teardown(void)
349 struct security_testsuite_params *ts_params = &testsuite_params;
350 if (ts_params->session_mpool) {
351 rte_mempool_free(ts_params->session_mpool);
352 ts_params->session_mpool = NULL;
357 * ut_setup initializes test case parameters to default values.
358 * It resets also any .called and .failed statistics of mockup functions
364 struct security_unittest_params *ut_params = &unittest_params;
365 ut_params->ctx.device = NULL;
366 ut_params->ctx.ops = &mock_ops;
367 ut_params->ctx.sess_cnt = 0;
368 ut_params->sess = NULL;
370 mock_session_create_exp.called = 0;
371 mock_session_destroy_exp.called = 0;
373 mock_session_create_exp.failed = 0;
374 mock_session_destroy_exp.failed = 0;
380 * destroy_session_with_check is a helper function releasing session
381 * created with rte_security_session_create and stored in test case parameters.
382 * It's used both to release sessions created in test cases' bodies
383 * which are assigned to ut_params->sess
386 destroy_session_with_check(void)
388 struct security_unittest_params *ut_params = &unittest_params;
389 if (ut_params->sess != NULL) {
390 /* Assure that mockup function for destroy operation is set. */
391 ut_params->ctx.ops = &mock_ops;
393 mock_session_destroy_exp.device = NULL;
394 mock_session_destroy_exp.sess = ut_params->sess;
395 mock_session_destroy_exp.ret = 0;
396 mock_session_destroy_exp.called = 0;
397 mock_session_destroy_exp.failed = 0;
399 int ret = rte_security_session_destroy(&ut_params->ctx,
401 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
403 TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 1);
405 ut_params->sess = NULL;
411 * ut_teardown releases test case parameters.
416 destroy_session_with_check();
423 * Each test function is related to a single test case.
424 * They are arranged by tested rte_security API function
425 * and by rte_security execution paths sequence in code.
429 * rte_security_session_create tests
433 * Test execution of rte_security_session_create with NULL instance
436 test_session_create_inv_context(void)
438 struct security_testsuite_params *ts_params = &testsuite_params;
439 struct security_unittest_params *ut_params = &unittest_params;
440 struct rte_security_session *sess;
442 sess = rte_security_session_create(NULL, &ut_params->conf,
443 ts_params->session_mpool);
444 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
446 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
447 TEST_ASSERT_MEMPOOL_USAGE(0);
448 TEST_ASSERT_SESSION_COUNT(0);
454 * Test execution of rte_security_session_create with invalid
455 * security operations structure (NULL)
458 test_session_create_inv_context_ops(void)
460 struct security_testsuite_params *ts_params = &testsuite_params;
461 struct security_unittest_params *ut_params = &unittest_params;
462 struct rte_security_session *sess;
464 ut_params->ctx.ops = NULL;
466 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
467 ts_params->session_mpool);
468 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
470 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
471 TEST_ASSERT_MEMPOOL_USAGE(0);
472 TEST_ASSERT_SESSION_COUNT(0);
478 * Test execution of rte_security_session_create with empty
479 * security operations
482 test_session_create_inv_context_ops_fun(void)
484 struct security_testsuite_params *ts_params = &testsuite_params;
485 struct security_unittest_params *ut_params = &unittest_params;
486 struct rte_security_session *sess;
488 ut_params->ctx.ops = &empty_ops;
490 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
491 ts_params->session_mpool);
492 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
494 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
495 TEST_ASSERT_MEMPOOL_USAGE(0);
496 TEST_ASSERT_SESSION_COUNT(0);
502 * Test execution of rte_security_session_create with NULL conf parameter
505 test_session_create_inv_configuration(void)
507 struct security_testsuite_params *ts_params = &testsuite_params;
508 struct security_unittest_params *ut_params = &unittest_params;
509 struct rte_security_session *sess;
511 sess = rte_security_session_create(&ut_params->ctx, NULL,
512 ts_params->session_mpool);
513 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
515 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
516 TEST_ASSERT_MEMPOOL_USAGE(0);
517 TEST_ASSERT_SESSION_COUNT(0);
523 * Test execution of rte_security_session_create with NULL mp parameter
526 test_session_create_inv_mempool(void)
528 struct security_unittest_params *ut_params = &unittest_params;
529 struct rte_security_session *sess;
531 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
533 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
535 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
536 TEST_ASSERT_MEMPOOL_USAGE(0);
537 TEST_ASSERT_SESSION_COUNT(0);
543 * Test execution of rte_security_session_create in case when mempool
544 * is fully used and no object can be got from it
547 test_session_create_mempool_empty(void)
549 struct security_testsuite_params *ts_params = &testsuite_params;
550 struct security_unittest_params *ut_params = &unittest_params;
551 struct rte_security_session *tmp[SECURITY_TEST_MEMPOOL_SIZE];
552 struct rte_security_session *sess;
554 /* Get all available objects from mempool. */
556 for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i) {
557 ret = rte_mempool_get(ts_params->session_mpool,
559 TEST_ASSERT_EQUAL(0, ret,
560 "Expect getting %d object from mempool"
563 TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
565 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
566 ts_params->session_mpool);
567 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
569 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
570 TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
571 TEST_ASSERT_SESSION_COUNT(0);
573 /* Put objects back to the pool. */
574 for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i)
575 rte_mempool_put(ts_params->session_mpool, (void *)(tmp[i]));
576 TEST_ASSERT_MEMPOOL_USAGE(0);
582 * Test execution of rte_security_session_create when session_create
583 * security operation fails
586 test_session_create_ops_failure(void)
588 struct security_testsuite_params *ts_params = &testsuite_params;
589 struct security_unittest_params *ut_params = &unittest_params;
590 struct rte_security_session *sess;
592 mock_session_create_exp.device = NULL;
593 mock_session_create_exp.conf = &ut_params->conf;
594 mock_session_create_exp.mp = ts_params->session_mpool;
595 mock_session_create_exp.ret = -1; /* Return failure status. */
597 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
598 ts_params->session_mpool);
599 TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
601 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
602 TEST_ASSERT_MEMPOOL_USAGE(0);
603 TEST_ASSERT_SESSION_COUNT(0);
609 * Test execution of rte_security_session_create in successful execution path
612 test_session_create_success(void)
614 struct security_testsuite_params *ts_params = &testsuite_params;
615 struct security_unittest_params *ut_params = &unittest_params;
616 struct rte_security_session *sess;
618 mock_session_create_exp.device = NULL;
619 mock_session_create_exp.conf = &ut_params->conf;
620 mock_session_create_exp.mp = ts_params->session_mpool;
621 mock_session_create_exp.ret = 0; /* Return success status. */
623 sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
624 ts_params->session_mpool);
625 TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(rte_security_session_create,
627 TEST_ASSERT_EQUAL(sess, mock_session_create_exp.sess,
628 "Expecting session_create to be called with %p sess"
629 " parameter, but it's called %p sess parameter",
630 sess, mock_session_create_exp.sess);
631 TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
632 TEST_ASSERT_MEMPOOL_USAGE(1);
633 TEST_ASSERT_SESSION_COUNT(1);
636 * Store created session in test case parameters, so it can be released
637 * after test case in ut_teardown by destroy_session_with_check.
639 ut_params->sess = sess;
646 * Declaration of testcases
648 static struct unit_test_suite security_testsuite = {
649 .suite_name = "generic security",
650 .setup = testsuite_setup,
651 .teardown = testsuite_teardown,
653 TEST_CASE_ST(ut_setup, ut_teardown,
654 test_session_create_inv_context),
655 TEST_CASE_ST(ut_setup, ut_teardown,
656 test_session_create_inv_context_ops),
657 TEST_CASE_ST(ut_setup, ut_teardown,
658 test_session_create_inv_context_ops_fun),
659 TEST_CASE_ST(ut_setup, ut_teardown,
660 test_session_create_inv_configuration),
661 TEST_CASE_ST(ut_setup, ut_teardown,
662 test_session_create_inv_mempool),
663 TEST_CASE_ST(ut_setup, ut_teardown,
664 test_session_create_mempool_empty),
665 TEST_CASE_ST(ut_setup, ut_teardown,
666 test_session_create_ops_failure),
667 TEST_CASE_ST(ut_setup, ut_teardown,
668 test_session_create_success),
670 TEST_CASES_END() /**< NULL terminate unit test array */
677 rte_log_set_global_level(RTE_LOG_DEBUG);
678 rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
680 return unit_test_suite_runner(&security_testsuite);
683 REGISTER_TEST_COMMAND(security_autotest, test_security);