[v3,1/3] test/dma: use unit test framework
Checks
Commit Message
Use unit test framework to execute DMA tests.
Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Suggested-by: Chengwen Feng <fengchengwen@huawei.com>
---
app/test/test_dmadev.c | 240 ++++++++++++++++++++++++++++---------
app/test/test_dmadev_api.c | 89 ++++----------
2 files changed, 212 insertions(+), 117 deletions(-)
Comments
Hi Gowrishankar,
Thanks for your works.
On 2023/11/3 23:38, Gowrishankar Muthukrishnan wrote:
> Use unit test framework to execute DMA tests.
>
> Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
> Suggested-by: Chengwen Feng <fengchengwen@huawei.com>
> ---
> app/test/test_dmadev.c | 240 ++++++++++++++++++++++++++++---------
> app/test/test_dmadev_api.c | 89 ++++----------
> 2 files changed, 212 insertions(+), 117 deletions(-)
>
> diff --git a/app/test/test_dmadev.c b/app/test/test_dmadev.c
> index 216f84b6bb..780941fc1e 100644
> --- a/app/test/test_dmadev.c
> +++ b/app/test/test_dmadev.c
> @@ -22,7 +22,9 @@
> #define COPY_LEN 1024
>
> static struct rte_mempool *pool;
> +static int16_t test_dev_id;
> static uint16_t id_count;
> +static int vchan;
>
> enum {
> TEST_PARAM_REMOTE_ADDR = 0,
> @@ -61,13 +63,35 @@ print_err(const char *func, int lineno, const char *format, ...)
> va_end(ap);
> }
>
> +struct runtest_param {
> + const char *printable;
> + int (*test_fn)(int16_t dev_id, uint16_t vchan);
> + int iterations;
> + int16_t dev_id;
> + uint16_t vchan;
> + bool check_err_stats;
> +};
> +
> static int
> -runtest(const char *printable, int (*test_fn)(int16_t dev_id, uint16_t vchan), int iterations,
> - int16_t dev_id, uint16_t vchan, bool check_err_stats)
> +runtest(const void *args)
> {
> + int (*test_fn)(int16_t dev_id, uint16_t vchan);
> + const struct runtest_param *param = args;
> struct rte_dma_stats stats;
> + const char *printable;
> + bool check_err_stats;
> + int iterations;
> + int16_t dev_id;
> + uint16_t vchan;
> int i;
>
> + printable = param->printable;
> + iterations = param->iterations;
> + dev_id = param->dev_id;
> + vchan = param->vchan;
> + check_err_stats = param->check_err_stats;
> + test_fn = param->test_fn;
> +
> rte_dma_stats_reset(dev_id, vchan);
> printf("DMA Dev %d: Running %s Tests %s\n", dev_id, printable,
> check_err_stats ? " " : "(errors expected)");
> @@ -918,9 +942,21 @@ test_m2d_auto_free(int16_t dev_id, uint16_t vchan)
> }
>
> static int
> -test_dmadev_instance(int16_t dev_id)
> +test_dmadev_burst_setup(void)
> {
> -#define CHECK_ERRS true
> + if (rte_dma_burst_capacity(test_dev_id, vchan) < 64) {
> + printf("DMA Dev %u: insufficient burst capacity (64 required), skipping tests\n",
> + test_dev_id);
> + return TEST_SKIPPED;
> + }
> +
> + return TEST_SUCCESS;
> +}
> +
> +static int
> +test_dmadev_setup(void)
> +{
> + int16_t dev_id = test_dev_id;
> struct rte_dma_stats stats;
> struct rte_dma_info info;
> const struct rte_dma_conf conf = { .nb_vchans = 1};
> @@ -928,16 +964,12 @@ test_dmadev_instance(int16_t dev_id)
> .direction = RTE_DMA_DIR_MEM_TO_MEM,
> .nb_desc = TEST_RINGSIZE,
> };
> - const int vchan = 0;
> int ret;
>
> ret = rte_dma_info_get(dev_id, &info);
> if (ret != 0)
> ERR_RETURN("Error with rte_dma_info_get()\n");
>
> - printf("\n### Test dmadev instance %u [%s]\n",
> - dev_id, info.dev_name);
> -
> if (info.max_vchans < 1)
> ERR_RETURN("Error, no channels available on device id %u\n", dev_id);
>
> @@ -976,20 +1008,123 @@ test_dmadev_instance(int16_t dev_id)
> if (pool == NULL)
> ERR_RETURN("Error with mempool creation\n");
>
> + return 0;
> +}
> +
> +static void
> +test_dmadev_teardown(void)
> +{
> + rte_mempool_free(pool);
> + rte_dma_stop(test_dev_id);
> + rte_dma_stats_reset(test_dev_id, vchan);
> + test_dev_id = -EINVAL;
> +}
> +
> +static int
> +test_dmadev_instance(int16_t dev_id)
> +{
> +#define CHECK_ERRS true
suggest rm this define
> + enum {
> + TEST_COPY = 0,
> + TEST_START,
> + TEST_BURST,
> + TEST_ERR,
> + TEST_FILL,
> + TEST_M2D,
> + TEST_END
> + };
> +
> + struct runtest_param param[TEST_END];
> + struct rte_dma_info dev_info;
> + struct unit_test_suite *ts;
> + struct unit_test_case *tc;
> + int ret;
> +
> + if (rte_dma_info_get(dev_id, &dev_info) < 0)
> + return TEST_SKIPPED;
> +
> + test_dev_id = dev_id;
> + vchan = 0;
> +
> + ts = calloc(1, sizeof(struct unit_test_suite)
> + + sizeof(struct unit_test_case) * (TEST_END + 1));
> +
> + ts->suite_name = "DMA dev instance testsuite";
> + ts->setup = test_dmadev_setup;
> + ts->teardown = test_dmadev_teardown;
> +
> + param[TEST_COPY].printable = "copy";
> + param[TEST_COPY].test_fn = test_enqueue_copies;
> + param[TEST_COPY].iterations = 640;
> + param[TEST_COPY].dev_id = dev_id;
> + param[TEST_COPY].vchan = vchan;
> + param[TEST_COPY].check_err_stats = CHECK_ERRS;
> +
> + param[TEST_START].printable = "stop-start";
> + param[TEST_START].test_fn = test_stop_start;
> + param[TEST_START].iterations = 1;
> + param[TEST_START].dev_id = dev_id;
> + param[TEST_START].vchan = vchan;
> + param[TEST_START].check_err_stats = CHECK_ERRS;
> +
> + param[TEST_BURST].printable = "burst capacity";
> + param[TEST_BURST].test_fn = test_burst_capacity;
> + param[TEST_BURST].iterations = 1;
> + param[TEST_BURST].dev_id = dev_id;
> + param[TEST_BURST].vchan = vchan;
> + param[TEST_BURST].check_err_stats = CHECK_ERRS;
> +
> + param[TEST_ERR].printable = "error handling";
> + param[TEST_ERR].test_fn = test_completion_handling;
> + param[TEST_ERR].iterations = 1;
> + param[TEST_ERR].dev_id = dev_id;
> + param[TEST_ERR].vchan = vchan;
> + param[TEST_ERR].check_err_stats = CHECK_ERRS;
> +
> + param[TEST_FILL].printable = "fill";
> + param[TEST_FILL].test_fn = test_enqueue_fill;
> + param[TEST_FILL].iterations = 1;
> + param[TEST_FILL].dev_id = dev_id;
> + param[TEST_FILL].vchan = vchan;
> + param[TEST_FILL].check_err_stats = CHECK_ERRS;
> +
> + param[TEST_M2D].printable = "m2d_auto_free";
> + param[TEST_M2D].test_fn = test_m2d_auto_free;
> + param[TEST_M2D].iterations = 128;
> + param[TEST_M2D].dev_id = dev_id;
> + param[TEST_M2D].vchan = vchan;
> + param[TEST_M2D].check_err_stats = CHECK_ERRS;
The above param was constant for all dmadev, suggest make them as global variable.
> +
> + for (int i = 0; i < TEST_END; i++) {
> + tc = &ts->unit_test_cases[i];
> + tc->setup = NULL;
> + tc->teardown = NULL;
> + tc->testcase = NULL;
> + tc->testcase_with_data = runtest;
> + tc->data = ¶m[i];
suggest set name, it could be param[i].printable
> + tc->enabled = 0;
> + }
> +
> + tc = &ts->unit_test_cases[TEST_END];
> + tc->setup = NULL;
> + tc->teardown = NULL;
> + tc->testcase = NULL;
> + tc->testcase_with_data = NULL;
> + tc->data = NULL;
> + tc->enabled = 0;
With above global variable, could use TEST_CASE_WITH_DATA here which pass TEST_XXX as data.
> +
> + printf("\n### Test dmadev instance %u [%s]\n",
> + dev_id, dev_info.dev_name);
> +
> /* run the test cases, use many iterations to ensure UINT16_MAX id wraparound */
The comment could consider del or place it to proper context. the same with other comments
> - if (runtest("copy", test_enqueue_copies, 640, dev_id, vchan, CHECK_ERRS) < 0)
> - goto err;
> + ts->unit_test_cases[TEST_COPY].enabled = 1;
>
> /* run tests stopping/starting devices and check jobs still work after restart */
> - if (runtest("stop-start", test_stop_start, 1, dev_id, vchan, CHECK_ERRS) < 0)
> - goto err;
> + ts->unit_test_cases[TEST_START].enabled = 1;
>
> /* run some burst capacity tests */
> - if (rte_dma_burst_capacity(dev_id, vchan) < 64)
> - printf("DMA Dev %u: insufficient burst capacity (64 required), skipping tests\n",
> - dev_id);
> - else if (runtest("burst capacity", test_burst_capacity, 1, dev_id, vchan, CHECK_ERRS) < 0)
> - goto err;
> + ts->unit_test_cases[TEST_BURST].setup = test_dmadev_burst_setup;
> + ts->unit_test_cases[TEST_BURST].enabled = 1;
>
> /* to test error handling we can provide null pointers for source or dest in copies. This
> * requires VA mode in DPDK, since NULL(0) is a valid physical address.
> @@ -997,55 +1132,40 @@ test_dmadev_instance(int16_t dev_id)
> */
> if (rte_eal_iova_mode() != RTE_IOVA_VA)
> printf("DMA Dev %u: DPDK not in VA mode, skipping error handling tests\n", dev_id);
> - else if ((info.dev_capa & RTE_DMA_CAPA_HANDLES_ERRORS) == 0)
> + else if ((dev_info.dev_capa & RTE_DMA_CAPA_HANDLES_ERRORS) == 0)
> printf("DMA Dev %u: device does not report errors, skipping error handling tests\n",
> dev_id);
> - else if (runtest("error handling", test_completion_handling, 1,
> - dev_id, vchan, !CHECK_ERRS) < 0)
> - goto err;
> + else
> + ts->unit_test_cases[TEST_ERR].enabled = 1;
>
> - if ((info.dev_capa & RTE_DMA_CAPA_OPS_FILL) == 0)
> + if ((dev_info.dev_capa & RTE_DMA_CAPA_OPS_FILL) == 0)
> printf("DMA Dev %u: No device fill support, skipping fill tests\n", dev_id);
> - else if (runtest("fill", test_enqueue_fill, 1, dev_id, vchan, CHECK_ERRS) < 0)
> - goto err;
> + else
> + ts->unit_test_cases[TEST_FILL].enabled = 1;
>
> - if ((info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE) &&
> + if ((dev_info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE) &&
> dma_add_test[TEST_M2D_AUTO_FREE].enabled == true) {
> - if (runtest("m2d_auto_free", test_m2d_auto_free, 128, dev_id, vchan,
> - CHECK_ERRS) < 0)
> - goto err;
> + ts->unit_test_cases[TEST_M2D].enabled = 1;
> }
>
> - rte_mempool_free(pool);
> -
> - if (rte_dma_stop(dev_id) < 0)
> - ERR_RETURN("Error stopping device %u\n", dev_id);
> -
> - rte_dma_stats_reset(dev_id, vchan);
> - return 0;
> + ret = unit_test_suite_runner(ts);
> + test_dev_id = -EINVAL;
> + free(ts);
>
> -err:
> - rte_mempool_free(pool);
> - rte_dma_stop(dev_id);
> - return -1;
> + return ret;
> }
>
> static int
> -test_apis(void)
> +test_apis(const void *args)
> {
> - const char *pmd = "dma_skeleton";
> - int id;
> - int ret;
> + const int16_t dev_id = *(const int16_t *)args;
> + struct rte_dma_info dev_info;
>
> - /* attempt to create skeleton instance - ignore errors due to one being already present */
> - rte_vdev_init(pmd, NULL);
> - id = rte_dma_get_dev_id_by_name(pmd);
> - if (id < 0)
> + if (rte_dma_info_get(dev_id, &dev_info) < 0)
> return TEST_SKIPPED;
> - printf("\n### Test dmadev infrastructure using skeleton driver\n");
> - ret = test_dma_api(id);
>
> - return ret;
> + printf("\n### Test dmadev infrastructure using %s\n", dev_info.dev_name);
suggest place above printf in the beginning of test_dma_api()
> + return test_dma_api(dev_id);
> }
>
> static void
> @@ -1088,16 +1208,28 @@ parse_dma_env_var(void)
> static int
> test_dma(void)
> {
> - int i;
> + const char *pmd = "dma_skeleton";
> + int i, avail;
>
> parse_dma_env_var();
>
> + /* attempt to create skeleton instance - ignore errors due to one being already present*/
> + rte_vdev_init(pmd, NULL);
> + i = rte_dma_get_dev_id_by_name(pmd);
> + if (i < 0)
> + return TEST_SKIPPED;
+1 for place create skeleton invoking here.
> +
> /* basic sanity on dmadev infrastructure */
> - if (test_apis() < 0)
> + if (test_apis(&i) < 0)
> ERR_RETURN("Error performing API tests\n");
>
> - if (rte_dma_count_avail() == 0)
> - return TEST_SKIPPED;
> + avail = rte_dma_count_avail();
> + if (avail == 0)
> + return 0;
> +
> + i = rte_dma_next_dev(0);
> + if (avail > 1 && test_apis(&i) < 0)
> + ERR_RETURN("Error performing API tests\n");
Why only test later dmadev? Maybe it's ok for one of the channels, but should consider multi-vendor DMA devices exist.
So suggest test all or just test skeleton for the API test.
Also, suggest move API related code to test_dmadev_api.c, e.g.:
void
test_api(void) ---place this function in test_dmadev_api.c
{
RTE_DMA_FOREACH_DEV(i) {
// get device info
// check whether support memory-to-memory, because API test will setup memory-to-memory vchan
// if not should skip it
if (test_dma_api(i) < 0)
ERR_RETURN("Error, test failure for device %d\n", i);
}
}
>
> RTE_DMA_FOREACH_DEV(i)
> if (test_dmadev_instance(i) < 0)
> diff --git a/app/test/test_dmadev_api.c b/app/test/test_dmadev_api.c
> index 4a181af90a..da8fddb3ca 100644
> --- a/app/test/test_dmadev_api.c
> +++ b/app/test/test_dmadev_api.c
> @@ -9,31 +9,22 @@
> #include <rte_test.h>
> #include <rte_dmadev.h>
>
> -extern int test_dma_api(uint16_t dev_id);
> +#include "test.h"
>
> -#define DMA_TEST_API_RUN(test) \
> - testsuite_run_test(test, #test)
> +extern int test_dma_api(uint16_t dev_id);
>
> #define TEST_MEMCPY_SIZE 1024
> #define TEST_WAIT_US_VAL 50000
>
> -#define TEST_SUCCESS 0
> -#define TEST_FAILED -1
> -
> static int16_t test_dev_id;
> static int16_t invalid_dev_id;
>
> static char *src;
> static char *dst;
>
> -static int total;
> -static int passed;
> -static int failed;
> -
> static int
> -testsuite_setup(int16_t dev_id)
> +testsuite_setup(void)
> {
> - test_dev_id = dev_id;
> invalid_dev_id = -1;
>
> src = rte_malloc("dmadev_test_src", TEST_MEMCPY_SIZE, 0);
> @@ -46,10 +37,6 @@ testsuite_setup(int16_t dev_id)
> return -ENOMEM;
> }
>
> - total = 0;
> - passed = 0;
> - failed = 0;
> -
> /* Set dmadev log level to critical to suppress unnecessary output
> * during API tests.
> */
> @@ -71,25 +58,6 @@ testsuite_teardown(void)
> rte_log_set_level_pattern("lib.dmadev", RTE_LOG_INFO);
> }
>
> -static void
> -testsuite_run_test(int (*test)(void), const char *name)
> -{
> - int ret = 0;
> -
> - if (test) {
> - ret = test();
> - if (ret < 0) {
> - failed++;
> - printf("%s Failed\n", name);
> - } else {
> - passed++;
> - printf("%s Passed\n", name);
> - }
> - }
> -
> - total++;
> -}
> -
> static int
> test_dma_get_dev_id_by_name(void)
> {
> @@ -301,7 +269,7 @@ setup_one_vchan(void)
>
> ret = rte_dma_info_get(test_dev_id, &dev_info);
> RTE_TEST_ASSERT_SUCCESS(ret, "Failed to obtain device info, %d", ret);
> - dev_conf.nb_vchans = dev_info.max_vchans;
> + dev_conf.nb_vchans = 1;
> ret = rte_dma_configure(test_dev_id, &dev_conf);
> RTE_TEST_ASSERT_SUCCESS(ret, "Failed to configure, %d", ret);
> vchan_conf.direction = RTE_DMA_DIR_MEM_TO_MEM;
> @@ -537,38 +505,33 @@ test_dma_completed_status(void)
> return TEST_SUCCESS;
> }
>
> +static struct unit_test_suite dma_api_testsuite = {
> + .suite_name = "DMA API Test Suite",
> + .setup = testsuite_setup,
> + .teardown = testsuite_teardown,
> + .unit_test_cases = {
> + TEST_CASE(test_dma_get_dev_id_by_name),
> + TEST_CASE(test_dma_is_valid_dev),
> + TEST_CASE(test_dma_count),
> + TEST_CASE(test_dma_info_get),
> + TEST_CASE(test_dma_configure),
> + TEST_CASE(test_dma_vchan_setup),
> + TEST_CASE(test_dma_start_stop),
> + TEST_CASE(test_dma_stats),
> + TEST_CASE(test_dma_dump),
> + TEST_CASE(test_dma_completed),
> + TEST_CASE(test_dma_completed_status),
> + TEST_CASES_END()
> + }
> +};
> +
> int
> test_dma_api(uint16_t dev_id)
> {
> - int ret = testsuite_setup(dev_id);
> - if (ret) {
> - printf("testsuite setup fail!\n");
> - return -1;
> - }
> + test_dev_id = dev_id;
>
> /* If the testcase exit successfully, ensure that the test dmadev exist
> * and the dmadev is in the stopped state.
> */
I think the above comments could delete or place just before 'static struct unit_test_suite dma_api_testsuite = {'
> - DMA_TEST_API_RUN(test_dma_get_dev_id_by_name);
> - DMA_TEST_API_RUN(test_dma_is_valid_dev);
> - DMA_TEST_API_RUN(test_dma_count);
> - DMA_TEST_API_RUN(test_dma_info_get);
> - DMA_TEST_API_RUN(test_dma_configure);
> - DMA_TEST_API_RUN(test_dma_vchan_setup);
> - DMA_TEST_API_RUN(test_dma_start_stop);
> - DMA_TEST_API_RUN(test_dma_stats);
> - DMA_TEST_API_RUN(test_dma_dump);
> - DMA_TEST_API_RUN(test_dma_completed);
> - DMA_TEST_API_RUN(test_dma_completed_status);
> -
> - testsuite_teardown();
> -
> - printf("Total tests : %d\n", total);
> - printf("Passed : %d\n", passed);
> - printf("Failed : %d\n", failed);
> -
> - if (failed)
> - return -1;
> -
> - return 0;
> + return unit_test_suite_runner(&dma_api_testsuite);
> };
>
For the dmadev, which have API test, memory-to-memory test, memory-to-device test, currently packed into two test-suites,
But I think its better use sub testsuite (could refer test_pdcp.c). Anyway, this is further more, we could do it later.
As the first stage, I think current impl is OK with above comments addressed.
Thanks
Chengwen
Hi Fengchengwen,
Thanks for your valuable comments, I have addressed all of them in v4 (sending shortly).
Please review the same.
> >
>
> For the dmadev, which have API test, memory-to-memory test, memory-to-
> device test, currently packed into two test-suites, But I think its better use
> sub testsuite (could refer test_pdcp.c). Anyway, this is further more, we
> could do it later.
>
> As the first stage, I think current impl is OK with above comments addressed.
>
Ack.
Regards,
Gowrishankar
> Thanks
> Chengwen
@@ -22,7 +22,9 @@
#define COPY_LEN 1024
static struct rte_mempool *pool;
+static int16_t test_dev_id;
static uint16_t id_count;
+static int vchan;
enum {
TEST_PARAM_REMOTE_ADDR = 0,
@@ -61,13 +63,35 @@ print_err(const char *func, int lineno, const char *format, ...)
va_end(ap);
}
+struct runtest_param {
+ const char *printable;
+ int (*test_fn)(int16_t dev_id, uint16_t vchan);
+ int iterations;
+ int16_t dev_id;
+ uint16_t vchan;
+ bool check_err_stats;
+};
+
static int
-runtest(const char *printable, int (*test_fn)(int16_t dev_id, uint16_t vchan), int iterations,
- int16_t dev_id, uint16_t vchan, bool check_err_stats)
+runtest(const void *args)
{
+ int (*test_fn)(int16_t dev_id, uint16_t vchan);
+ const struct runtest_param *param = args;
struct rte_dma_stats stats;
+ const char *printable;
+ bool check_err_stats;
+ int iterations;
+ int16_t dev_id;
+ uint16_t vchan;
int i;
+ printable = param->printable;
+ iterations = param->iterations;
+ dev_id = param->dev_id;
+ vchan = param->vchan;
+ check_err_stats = param->check_err_stats;
+ test_fn = param->test_fn;
+
rte_dma_stats_reset(dev_id, vchan);
printf("DMA Dev %d: Running %s Tests %s\n", dev_id, printable,
check_err_stats ? " " : "(errors expected)");
@@ -918,9 +942,21 @@ test_m2d_auto_free(int16_t dev_id, uint16_t vchan)
}
static int
-test_dmadev_instance(int16_t dev_id)
+test_dmadev_burst_setup(void)
{
-#define CHECK_ERRS true
+ if (rte_dma_burst_capacity(test_dev_id, vchan) < 64) {
+ printf("DMA Dev %u: insufficient burst capacity (64 required), skipping tests\n",
+ test_dev_id);
+ return TEST_SKIPPED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_dmadev_setup(void)
+{
+ int16_t dev_id = test_dev_id;
struct rte_dma_stats stats;
struct rte_dma_info info;
const struct rte_dma_conf conf = { .nb_vchans = 1};
@@ -928,16 +964,12 @@ test_dmadev_instance(int16_t dev_id)
.direction = RTE_DMA_DIR_MEM_TO_MEM,
.nb_desc = TEST_RINGSIZE,
};
- const int vchan = 0;
int ret;
ret = rte_dma_info_get(dev_id, &info);
if (ret != 0)
ERR_RETURN("Error with rte_dma_info_get()\n");
- printf("\n### Test dmadev instance %u [%s]\n",
- dev_id, info.dev_name);
-
if (info.max_vchans < 1)
ERR_RETURN("Error, no channels available on device id %u\n", dev_id);
@@ -976,20 +1008,123 @@ test_dmadev_instance(int16_t dev_id)
if (pool == NULL)
ERR_RETURN("Error with mempool creation\n");
+ return 0;
+}
+
+static void
+test_dmadev_teardown(void)
+{
+ rte_mempool_free(pool);
+ rte_dma_stop(test_dev_id);
+ rte_dma_stats_reset(test_dev_id, vchan);
+ test_dev_id = -EINVAL;
+}
+
+static int
+test_dmadev_instance(int16_t dev_id)
+{
+#define CHECK_ERRS true
+ enum {
+ TEST_COPY = 0,
+ TEST_START,
+ TEST_BURST,
+ TEST_ERR,
+ TEST_FILL,
+ TEST_M2D,
+ TEST_END
+ };
+
+ struct runtest_param param[TEST_END];
+ struct rte_dma_info dev_info;
+ struct unit_test_suite *ts;
+ struct unit_test_case *tc;
+ int ret;
+
+ if (rte_dma_info_get(dev_id, &dev_info) < 0)
+ return TEST_SKIPPED;
+
+ test_dev_id = dev_id;
+ vchan = 0;
+
+ ts = calloc(1, sizeof(struct unit_test_suite)
+ + sizeof(struct unit_test_case) * (TEST_END + 1));
+
+ ts->suite_name = "DMA dev instance testsuite";
+ ts->setup = test_dmadev_setup;
+ ts->teardown = test_dmadev_teardown;
+
+ param[TEST_COPY].printable = "copy";
+ param[TEST_COPY].test_fn = test_enqueue_copies;
+ param[TEST_COPY].iterations = 640;
+ param[TEST_COPY].dev_id = dev_id;
+ param[TEST_COPY].vchan = vchan;
+ param[TEST_COPY].check_err_stats = CHECK_ERRS;
+
+ param[TEST_START].printable = "stop-start";
+ param[TEST_START].test_fn = test_stop_start;
+ param[TEST_START].iterations = 1;
+ param[TEST_START].dev_id = dev_id;
+ param[TEST_START].vchan = vchan;
+ param[TEST_START].check_err_stats = CHECK_ERRS;
+
+ param[TEST_BURST].printable = "burst capacity";
+ param[TEST_BURST].test_fn = test_burst_capacity;
+ param[TEST_BURST].iterations = 1;
+ param[TEST_BURST].dev_id = dev_id;
+ param[TEST_BURST].vchan = vchan;
+ param[TEST_BURST].check_err_stats = CHECK_ERRS;
+
+ param[TEST_ERR].printable = "error handling";
+ param[TEST_ERR].test_fn = test_completion_handling;
+ param[TEST_ERR].iterations = 1;
+ param[TEST_ERR].dev_id = dev_id;
+ param[TEST_ERR].vchan = vchan;
+ param[TEST_ERR].check_err_stats = CHECK_ERRS;
+
+ param[TEST_FILL].printable = "fill";
+ param[TEST_FILL].test_fn = test_enqueue_fill;
+ param[TEST_FILL].iterations = 1;
+ param[TEST_FILL].dev_id = dev_id;
+ param[TEST_FILL].vchan = vchan;
+ param[TEST_FILL].check_err_stats = CHECK_ERRS;
+
+ param[TEST_M2D].printable = "m2d_auto_free";
+ param[TEST_M2D].test_fn = test_m2d_auto_free;
+ param[TEST_M2D].iterations = 128;
+ param[TEST_M2D].dev_id = dev_id;
+ param[TEST_M2D].vchan = vchan;
+ param[TEST_M2D].check_err_stats = CHECK_ERRS;
+
+ for (int i = 0; i < TEST_END; i++) {
+ tc = &ts->unit_test_cases[i];
+ tc->setup = NULL;
+ tc->teardown = NULL;
+ tc->testcase = NULL;
+ tc->testcase_with_data = runtest;
+ tc->data = ¶m[i];
+ tc->enabled = 0;
+ }
+
+ tc = &ts->unit_test_cases[TEST_END];
+ tc->setup = NULL;
+ tc->teardown = NULL;
+ tc->testcase = NULL;
+ tc->testcase_with_data = NULL;
+ tc->data = NULL;
+ tc->enabled = 0;
+
+ printf("\n### Test dmadev instance %u [%s]\n",
+ dev_id, dev_info.dev_name);
+
/* run the test cases, use many iterations to ensure UINT16_MAX id wraparound */
- if (runtest("copy", test_enqueue_copies, 640, dev_id, vchan, CHECK_ERRS) < 0)
- goto err;
+ ts->unit_test_cases[TEST_COPY].enabled = 1;
/* run tests stopping/starting devices and check jobs still work after restart */
- if (runtest("stop-start", test_stop_start, 1, dev_id, vchan, CHECK_ERRS) < 0)
- goto err;
+ ts->unit_test_cases[TEST_START].enabled = 1;
/* run some burst capacity tests */
- if (rte_dma_burst_capacity(dev_id, vchan) < 64)
- printf("DMA Dev %u: insufficient burst capacity (64 required), skipping tests\n",
- dev_id);
- else if (runtest("burst capacity", test_burst_capacity, 1, dev_id, vchan, CHECK_ERRS) < 0)
- goto err;
+ ts->unit_test_cases[TEST_BURST].setup = test_dmadev_burst_setup;
+ ts->unit_test_cases[TEST_BURST].enabled = 1;
/* to test error handling we can provide null pointers for source or dest in copies. This
* requires VA mode in DPDK, since NULL(0) is a valid physical address.
@@ -997,55 +1132,40 @@ test_dmadev_instance(int16_t dev_id)
*/
if (rte_eal_iova_mode() != RTE_IOVA_VA)
printf("DMA Dev %u: DPDK not in VA mode, skipping error handling tests\n", dev_id);
- else if ((info.dev_capa & RTE_DMA_CAPA_HANDLES_ERRORS) == 0)
+ else if ((dev_info.dev_capa & RTE_DMA_CAPA_HANDLES_ERRORS) == 0)
printf("DMA Dev %u: device does not report errors, skipping error handling tests\n",
dev_id);
- else if (runtest("error handling", test_completion_handling, 1,
- dev_id, vchan, !CHECK_ERRS) < 0)
- goto err;
+ else
+ ts->unit_test_cases[TEST_ERR].enabled = 1;
- if ((info.dev_capa & RTE_DMA_CAPA_OPS_FILL) == 0)
+ if ((dev_info.dev_capa & RTE_DMA_CAPA_OPS_FILL) == 0)
printf("DMA Dev %u: No device fill support, skipping fill tests\n", dev_id);
- else if (runtest("fill", test_enqueue_fill, 1, dev_id, vchan, CHECK_ERRS) < 0)
- goto err;
+ else
+ ts->unit_test_cases[TEST_FILL].enabled = 1;
- if ((info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE) &&
+ if ((dev_info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE) &&
dma_add_test[TEST_M2D_AUTO_FREE].enabled == true) {
- if (runtest("m2d_auto_free", test_m2d_auto_free, 128, dev_id, vchan,
- CHECK_ERRS) < 0)
- goto err;
+ ts->unit_test_cases[TEST_M2D].enabled = 1;
}
- rte_mempool_free(pool);
-
- if (rte_dma_stop(dev_id) < 0)
- ERR_RETURN("Error stopping device %u\n", dev_id);
-
- rte_dma_stats_reset(dev_id, vchan);
- return 0;
+ ret = unit_test_suite_runner(ts);
+ test_dev_id = -EINVAL;
+ free(ts);
-err:
- rte_mempool_free(pool);
- rte_dma_stop(dev_id);
- return -1;
+ return ret;
}
static int
-test_apis(void)
+test_apis(const void *args)
{
- const char *pmd = "dma_skeleton";
- int id;
- int ret;
+ const int16_t dev_id = *(const int16_t *)args;
+ struct rte_dma_info dev_info;
- /* attempt to create skeleton instance - ignore errors due to one being already present */
- rte_vdev_init(pmd, NULL);
- id = rte_dma_get_dev_id_by_name(pmd);
- if (id < 0)
+ if (rte_dma_info_get(dev_id, &dev_info) < 0)
return TEST_SKIPPED;
- printf("\n### Test dmadev infrastructure using skeleton driver\n");
- ret = test_dma_api(id);
- return ret;
+ printf("\n### Test dmadev infrastructure using %s\n", dev_info.dev_name);
+ return test_dma_api(dev_id);
}
static void
@@ -1088,16 +1208,28 @@ parse_dma_env_var(void)
static int
test_dma(void)
{
- int i;
+ const char *pmd = "dma_skeleton";
+ int i, avail;
parse_dma_env_var();
+ /* attempt to create skeleton instance - ignore errors due to one being already present*/
+ rte_vdev_init(pmd, NULL);
+ i = rte_dma_get_dev_id_by_name(pmd);
+ if (i < 0)
+ return TEST_SKIPPED;
+
/* basic sanity on dmadev infrastructure */
- if (test_apis() < 0)
+ if (test_apis(&i) < 0)
ERR_RETURN("Error performing API tests\n");
- if (rte_dma_count_avail() == 0)
- return TEST_SKIPPED;
+ avail = rte_dma_count_avail();
+ if (avail == 0)
+ return 0;
+
+ i = rte_dma_next_dev(0);
+ if (avail > 1 && test_apis(&i) < 0)
+ ERR_RETURN("Error performing API tests\n");
RTE_DMA_FOREACH_DEV(i)
if (test_dmadev_instance(i) < 0)
@@ -9,31 +9,22 @@
#include <rte_test.h>
#include <rte_dmadev.h>
-extern int test_dma_api(uint16_t dev_id);
+#include "test.h"
-#define DMA_TEST_API_RUN(test) \
- testsuite_run_test(test, #test)
+extern int test_dma_api(uint16_t dev_id);
#define TEST_MEMCPY_SIZE 1024
#define TEST_WAIT_US_VAL 50000
-#define TEST_SUCCESS 0
-#define TEST_FAILED -1
-
static int16_t test_dev_id;
static int16_t invalid_dev_id;
static char *src;
static char *dst;
-static int total;
-static int passed;
-static int failed;
-
static int
-testsuite_setup(int16_t dev_id)
+testsuite_setup(void)
{
- test_dev_id = dev_id;
invalid_dev_id = -1;
src = rte_malloc("dmadev_test_src", TEST_MEMCPY_SIZE, 0);
@@ -46,10 +37,6 @@ testsuite_setup(int16_t dev_id)
return -ENOMEM;
}
- total = 0;
- passed = 0;
- failed = 0;
-
/* Set dmadev log level to critical to suppress unnecessary output
* during API tests.
*/
@@ -71,25 +58,6 @@ testsuite_teardown(void)
rte_log_set_level_pattern("lib.dmadev", RTE_LOG_INFO);
}
-static void
-testsuite_run_test(int (*test)(void), const char *name)
-{
- int ret = 0;
-
- if (test) {
- ret = test();
- if (ret < 0) {
- failed++;
- printf("%s Failed\n", name);
- } else {
- passed++;
- printf("%s Passed\n", name);
- }
- }
-
- total++;
-}
-
static int
test_dma_get_dev_id_by_name(void)
{
@@ -301,7 +269,7 @@ setup_one_vchan(void)
ret = rte_dma_info_get(test_dev_id, &dev_info);
RTE_TEST_ASSERT_SUCCESS(ret, "Failed to obtain device info, %d", ret);
- dev_conf.nb_vchans = dev_info.max_vchans;
+ dev_conf.nb_vchans = 1;
ret = rte_dma_configure(test_dev_id, &dev_conf);
RTE_TEST_ASSERT_SUCCESS(ret, "Failed to configure, %d", ret);
vchan_conf.direction = RTE_DMA_DIR_MEM_TO_MEM;
@@ -537,38 +505,33 @@ test_dma_completed_status(void)
return TEST_SUCCESS;
}
+static struct unit_test_suite dma_api_testsuite = {
+ .suite_name = "DMA API Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE(test_dma_get_dev_id_by_name),
+ TEST_CASE(test_dma_is_valid_dev),
+ TEST_CASE(test_dma_count),
+ TEST_CASE(test_dma_info_get),
+ TEST_CASE(test_dma_configure),
+ TEST_CASE(test_dma_vchan_setup),
+ TEST_CASE(test_dma_start_stop),
+ TEST_CASE(test_dma_stats),
+ TEST_CASE(test_dma_dump),
+ TEST_CASE(test_dma_completed),
+ TEST_CASE(test_dma_completed_status),
+ TEST_CASES_END()
+ }
+};
+
int
test_dma_api(uint16_t dev_id)
{
- int ret = testsuite_setup(dev_id);
- if (ret) {
- printf("testsuite setup fail!\n");
- return -1;
- }
+ test_dev_id = dev_id;
/* If the testcase exit successfully, ensure that the test dmadev exist
* and the dmadev is in the stopped state.
*/
- DMA_TEST_API_RUN(test_dma_get_dev_id_by_name);
- DMA_TEST_API_RUN(test_dma_is_valid_dev);
- DMA_TEST_API_RUN(test_dma_count);
- DMA_TEST_API_RUN(test_dma_info_get);
- DMA_TEST_API_RUN(test_dma_configure);
- DMA_TEST_API_RUN(test_dma_vchan_setup);
- DMA_TEST_API_RUN(test_dma_start_stop);
- DMA_TEST_API_RUN(test_dma_stats);
- DMA_TEST_API_RUN(test_dma_dump);
- DMA_TEST_API_RUN(test_dma_completed);
- DMA_TEST_API_RUN(test_dma_completed_status);
-
- testsuite_teardown();
-
- printf("Total tests : %d\n", total);
- printf("Passed : %d\n", passed);
- printf("Failed : %d\n", failed);
-
- if (failed)
- return -1;
-
- return 0;
+ return unit_test_suite_runner(&dma_api_testsuite);
};