Skip to content

Commit

Permalink
app/testbbdev: add test application for bbdev
Browse files Browse the repository at this point in the history
- full test suite for bbdev
- test App works seamlessly on all PMDs registered with bbdev
 framework
- a python script is provided to make our life easier
- supports execution of tests by parsing Test Vector files
- test Vectors can be added/deleted/modified with no need for
 re-compilation
- various tests can be executed:
 (a) Throughput test
 (b) Offload latency test
 (c) Operation latency test
 (d) Validation test
 (c) Sanity checks

Signed-off-by: Amr Mokhtar <amr.mokhtar@intel.com>
  • Loading branch information
amr-mokhtar authored and tmonjalo committed Jan 19, 2018
1 parent b8cfe2c commit f714a18
Show file tree
Hide file tree
Showing 16 changed files with 5,742 additions and 0 deletions.
2 changes: 2 additions & 0 deletions MAINTAINERS
Expand Up @@ -270,6 +270,8 @@ F: lib/librte_bbdev/
F: doc/guides/prog_guide/bbdev.rst
F: drivers/bbdev/
F: doc/guides/bbdevs/
F: app/test-bbdev/
F: doc/guides/tools/testbbdev.rst

Crypto API
M: Declan Doherty <declan.doherty@intel.com>
Expand Down
4 changes: 4 additions & 0 deletions app/Makefile
Expand Up @@ -7,6 +7,10 @@ DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd
DIRS-$(CONFIG_RTE_PROC_INFO) += proc_info
DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump

ifeq ($(CONFIG_RTE_LIBRTE_BBDEV),y)
DIRS-$(CONFIG_RTE_TEST_BBDEV) += test-bbdev
endif

ifeq ($(CONFIG_RTE_LIBRTE_CRYPTODEV),y)
DIRS-$(CONFIG_RTE_APP_CRYPTO_PERF) += test-crypto-perf
endif
Expand Down
22 changes: 22 additions & 0 deletions app/test-bbdev/Makefile
@@ -0,0 +1,22 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation

include $(RTE_SDK)/mk/rte.vars.mk

#
# library name
#
APP = testbbdev

CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)

#
# all sources are stored in SRCS-y
#
SRCS-$(CONFIG_RTE_TEST_BBDEV) += main.c
SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev.c
SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev_perf.c
SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev_vector.c

include $(RTE_SDK)/mk/rte.app.mk
325 changes: 325 additions & 0 deletions app/test-bbdev/main.c
@@ -0,0 +1,325 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2017 Intel Corporation
*/

#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include <rte_eal.h>
#include <rte_common.h>
#include <rte_string_fns.h>
#include <rte_cycles.h>
#include <rte_lcore.h>

#include "main.h"

/* Defines how many testcases can be specified as cmdline args */
#define MAX_CMDLINE_TESTCASES 8

static const char tc_sep = ',';

static struct test_params {
struct test_command *test_to_run[MAX_CMDLINE_TESTCASES];
unsigned int num_tests;
unsigned int num_ops;
unsigned int burst_sz;
unsigned int num_lcores;
char test_vector_filename[PATH_MAX];
} test_params;

static struct test_commands_list commands_list =
TAILQ_HEAD_INITIALIZER(commands_list);

void
add_test_command(struct test_command *t)
{
TAILQ_INSERT_TAIL(&commands_list, t, next);
}

int
unit_test_suite_runner(struct unit_test_suite *suite)
{
int test_result = TEST_SUCCESS;
unsigned int total = 0, skipped = 0, succeeded = 0, failed = 0;
uint64_t start, end;

printf(
"\n + ------------------------------------------------------- +\n");
printf(" + Starting Test Suite : %s\n", suite->suite_name);

start = rte_rdtsc_precise();

if (suite->setup) {
test_result = suite->setup();
if (test_result == TEST_FAILED) {
printf(" + Test suite setup %s failed!\n",
suite->suite_name);
printf(
" + ------------------------------------------------------- +\n");
return 1;
}
if (test_result == TEST_SKIPPED) {
printf(" + Test suite setup %s skipped!\n",
suite->suite_name);
printf(
" + ------------------------------------------------------- +\n");
return 0;
}
}

while (suite->unit_test_cases[total].testcase) {
if (suite->unit_test_cases[total].setup)
test_result = suite->unit_test_cases[total].setup();

if (test_result == TEST_SUCCESS)
test_result = suite->unit_test_cases[total].testcase();

if (suite->unit_test_cases[total].teardown)
suite->unit_test_cases[total].teardown();

if (test_result == TEST_SUCCESS) {
succeeded++;
printf(" + TestCase [%2d] : %s passed\n", total,
suite->unit_test_cases[total].name);
} else if (test_result == TEST_SKIPPED) {
skipped++;
printf(" + TestCase [%2d] : %s skipped\n", total,
suite->unit_test_cases[total].name);
} else {
failed++;
printf(" + TestCase [%2d] : %s failed\n", total,
suite->unit_test_cases[total].name);
}

total++;
}

/* Run test suite teardown */
if (suite->teardown)
suite->teardown();

end = rte_rdtsc_precise();

printf(" + ------------------------------------------------------- +\n");
printf(" + Test Suite Summary : %s\n", suite->suite_name);
printf(" + Tests Total : %2d\n", total);
printf(" + Tests Skipped : %2d\n", skipped);
printf(" + Tests Passed : %2d\n", succeeded);
printf(" + Tests Failed : %2d\n", failed);
printf(" + Tests Lasted : %lg ms\n",
((end - start) * 1000) / (double)rte_get_tsc_hz());
printf(" + ------------------------------------------------------- +\n");

return (failed > 0) ? 1 : 0;
}

const char *
get_vector_filename(void)
{
return test_params.test_vector_filename;
}

unsigned int
get_num_ops(void)
{
return test_params.num_ops;
}

unsigned int
get_burst_sz(void)
{
return test_params.burst_sz;
}

unsigned int
get_num_lcores(void)
{
return test_params.num_lcores;
}

static void
print_usage(const char *prog_name)
{
struct test_command *t;

printf("Usage: %s [EAL params] [-- [-n/--num-ops NUM_OPS]\n"
"\t[-b/--burst-size BURST_SIZE]\n"
"\t[-v/--test-vector VECTOR_FILE]\n"
"\t[-c/--test-cases TEST_CASE[,TEST_CASE,...]]]\n",
prog_name);

printf("Available testcases: ");
TAILQ_FOREACH(t, &commands_list, next)
printf("%s ", t->command);
printf("\n");
}

static int
parse_args(int argc, char **argv, struct test_params *tp)
{
int opt, option_index;
unsigned int num_tests = 0;
bool test_cases_present = false;
bool test_vector_present = false;
struct test_command *t;
char *tokens[MAX_CMDLINE_TESTCASES];
int tc, ret;

static struct option lgopts[] = {
{ "num-ops", 1, 0, 'n' },
{ "burst-size", 1, 0, 'b' },
{ "test-cases", 1, 0, 'c' },
{ "test-vector", 1, 0, 'v' },
{ "lcores", 1, 0, 'l' },
{ "help", 0, 0, 'h' },
{ NULL, 0, 0, 0 }
};

while ((opt = getopt_long(argc, argv, "hn:b:c:v:l:", lgopts,
&option_index)) != EOF)
switch (opt) {
case 'n':
TEST_ASSERT(strlen(optarg) > 0,
"Num of operations is not provided");
tp->num_ops = strtol(optarg, NULL, 10);
break;
case 'b':
TEST_ASSERT(strlen(optarg) > 0,
"Burst size is not provided");
tp->burst_sz = strtol(optarg, NULL, 10);
TEST_ASSERT(tp->burst_sz <= MAX_BURST,
"Burst size mustn't be greater than %u",
MAX_BURST);
break;
case 'c':
TEST_ASSERT(test_cases_present == false,
"Test cases provided more than once");
test_cases_present = true;

ret = rte_strsplit(optarg, strlen(optarg),
tokens, MAX_CMDLINE_TESTCASES, tc_sep);

TEST_ASSERT(ret <= MAX_CMDLINE_TESTCASES,
"Too many test cases (max=%d)",
MAX_CMDLINE_TESTCASES);

for (tc = 0; tc < ret; ++tc) {
/* Find matching test case */
TAILQ_FOREACH(t, &commands_list, next)
if (!strcmp(tokens[tc], t->command))
tp->test_to_run[num_tests] = t;

TEST_ASSERT(tp->test_to_run[num_tests] != NULL,
"Unknown test case: %s",
tokens[tc]);
++num_tests;
}
break;
case 'v':
TEST_ASSERT(test_vector_present == false,
"Test vector provided more than once");
test_vector_present = true;

TEST_ASSERT(strlen(optarg) > 0,
"Config file name is null");

strncpy(tp->test_vector_filename, optarg,
sizeof(tp->test_vector_filename));
break;
case 'l':
TEST_ASSERT(strlen(optarg) > 0,
"Num of lcores is not provided");
tp->num_lcores = strtol(optarg, NULL, 10);
TEST_ASSERT(tp->num_lcores <= RTE_MAX_LCORE,
"Num of lcores mustn't be greater than %u",
RTE_MAX_LCORE);
break;
case 'h':
print_usage(argv[0]);
return 0;
default:
printf("ERROR: Unknown option: -%c\n", opt);
return -1;
}

if (tp->num_ops == 0) {
printf(
"WARNING: Num of operations was not provided or was set 0. Set to default (%u)\n",
DEFAULT_OPS);
tp->num_ops = DEFAULT_OPS;
}
if (tp->burst_sz == 0) {
printf(
"WARNING: Burst size was not provided or was set 0. Set to default (%u)\n",
DEFAULT_BURST);
tp->burst_sz = DEFAULT_BURST;
}
if (tp->num_lcores == 0) {
printf(
"WARNING: Num of lcores was not provided or was set 0. Set to value from RTE config (%u)\n",
rte_lcore_count());
tp->num_lcores = rte_lcore_count();
}

TEST_ASSERT(tp->burst_sz <= tp->num_ops,
"Burst size (%u) mustn't be greater than num ops (%u)",
tp->burst_sz, tp->num_ops);

tp->num_tests = num_tests;
return 0;
}

static int
run_all_tests(void)
{
int ret = TEST_SUCCESS;
struct test_command *t;

TAILQ_FOREACH(t, &commands_list, next)
ret |= t->callback();

return ret;
}

static int
run_parsed_tests(struct test_params *tp)
{
int ret = TEST_SUCCESS;
unsigned int i;

for (i = 0; i < tp->num_tests; ++i)
ret |= tp->test_to_run[i]->callback();

return ret;
}

int
main(int argc, char **argv)
{
int ret;

/* Init EAL */
ret = rte_eal_init(argc, argv);
if (ret < 0)
return 1;
argc -= ret;
argv += ret;

/* Parse application arguments (after the EAL ones) */
ret = parse_args(argc, argv, &test_params);
if (ret < 0) {
print_usage(argv[0]);
return 1;
}

rte_log_set_global_level(RTE_LOG_INFO);

/* If no argument provided - run all tests */
if (test_params.num_tests == 0)
return run_all_tests();
else
return run_parsed_tests(&test_params);
}

0 comments on commit f714a18

Please sign in to comment.