xref: /dpdk/app/test/test.c (revision a620df6df6d61660661afade09760b2dfba4eb42)
1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson  */
4a9de470cSBruce Richardson 
5a9de470cSBruce Richardson #include <string.h>
6a9de470cSBruce Richardson #include <stdio.h>
7a9de470cSBruce Richardson #include <stdint.h>
8a9de470cSBruce Richardson #include <stdarg.h>
9a9de470cSBruce Richardson #include <stdlib.h>
10a9de470cSBruce Richardson #include <errno.h>
11a9de470cSBruce Richardson #include <ctype.h>
12a9de470cSBruce Richardson #include <sys/queue.h>
13a9de470cSBruce Richardson 
14a9de470cSBruce Richardson #include <cmdline_rdline.h>
15a9de470cSBruce Richardson #include <cmdline_parse.h>
16a9de470cSBruce Richardson #include <cmdline_socket.h>
17a9de470cSBruce Richardson #include <cmdline.h>
18a9de470cSBruce Richardson extern cmdline_parse_ctx_t main_ctx[];
19a9de470cSBruce Richardson 
20a9de470cSBruce Richardson #include <rte_memory.h>
21a9de470cSBruce Richardson #include <rte_eal.h>
22a9de470cSBruce Richardson #include <rte_cycles.h>
23a9de470cSBruce Richardson #include <rte_log.h>
24a9de470cSBruce Richardson #include <rte_string_fns.h>
25a8d0d473SBruce Richardson #ifdef RTE_LIB_TIMER
26a9de470cSBruce Richardson #include <rte_timer.h>
27a9de470cSBruce Richardson #endif
28a9de470cSBruce Richardson 
29a9de470cSBruce Richardson #include "test.h"
30a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
31a9de470cSBruce Richardson #include "test_pdump.h"
326d27d8c0SReshma Pattan #endif
33a9de470cSBruce Richardson 
34a9de470cSBruce Richardson #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
35a9de470cSBruce Richardson 
36caa817f0SCiara Power #define FOR_EACH_SUITE_TESTCASE(iter, suite, case)			\
37caa817f0SCiara Power 	for (iter = 0, case = suite->unit_test_cases[0];		\
38e65da89cSCiara Power 		suite->unit_test_cases[iter].testcase ||		\
39e65da89cSCiara Power 		suite->unit_test_cases[iter].testcase_with_data;	\
40caa817f0SCiara Power 		iter++, case = suite->unit_test_cases[iter])
41caa817f0SCiara Power 
42fbc53675SCiara Power #define FOR_EACH_SUITE_TESTSUITE(iter, suite, sub_ts)			\
43fbc53675SCiara Power 	for (iter = 0, sub_ts = suite->unit_test_suites ?		\
44fbc53675SCiara Power 		suite->unit_test_suites[0]:NULL; sub_ts &&		\
45fbc53675SCiara Power 		suite->unit_test_suites[iter]->suite_name != NULL;	\
46fbc53675SCiara Power 		iter++, sub_ts = suite->unit_test_suites[iter])
47fbc53675SCiara Power 
48a9de470cSBruce Richardson const char *prgname; /* to be set to argv[0] */
49a9de470cSBruce Richardson 
50218c4e68SBruce Richardson static const char *recursive_call; /* used in linux for MP and other tests */
51a9de470cSBruce Richardson 
52a9de470cSBruce Richardson static int
no_action(void)53a9de470cSBruce Richardson no_action(void){ return 0; }
54a9de470cSBruce Richardson 
55a9de470cSBruce Richardson static int
do_recursive_call(void)56a9de470cSBruce Richardson do_recursive_call(void)
57a9de470cSBruce Richardson {
58a9de470cSBruce Richardson 	unsigned i;
59a9de470cSBruce Richardson 	struct {
60a9de470cSBruce Richardson 		const char *env_var;
61a9de470cSBruce Richardson 		int (*action_fn)(void);
62a9de470cSBruce Richardson 	} actions[] =  {
63987d40a0SJie Zhou #ifndef RTE_EXEC_ENV_WINDOWS
64a9de470cSBruce Richardson 			{ "run_secondary_instances", test_mp_secondary },
65987d40a0SJie Zhou #endif
66a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
67a8d0d473SBruce Richardson #ifdef RTE_NET_RING
68a9de470cSBruce Richardson 			{ "run_pdump_server_tests", test_pdump },
696d27d8c0SReshma Pattan #endif
70207b1c81SReshma Pattan #endif
71a9de470cSBruce Richardson 			{ "test_missing_c_flag", no_action },
72cb056611SStephen Hemminger 			{ "test_main_lcore_flag", no_action },
73a9de470cSBruce Richardson 			{ "test_invalid_n_flag", no_action },
74a9de470cSBruce Richardson 			{ "test_no_hpet_flag", no_action },
75db27370bSStephen Hemminger 			{ "test_allow_flag", no_action },
76a9de470cSBruce Richardson 			{ "test_invalid_b_flag", no_action },
77a9de470cSBruce Richardson 			{ "test_invalid_vdev_flag", no_action },
78a9de470cSBruce Richardson 			{ "test_invalid_r_flag", no_action },
79a9de470cSBruce Richardson 			{ "test_misc_flags", no_action },
80a9de470cSBruce Richardson 			{ "test_memory_flags", no_action },
81a9de470cSBruce Richardson 			{ "test_file_prefix", no_action },
82a9de470cSBruce Richardson 			{ "test_no_huge_flag", no_action },
83a8d0d473SBruce Richardson #ifdef RTE_LIB_TIMER
84987d40a0SJie Zhou #ifndef RTE_EXEC_ENV_WINDOWS
8550247fe0SErik Gabriel Carrillo 			{ "timer_secondary_spawn_wait", test_timer_secondary },
86d3065379STimothy Redaelli #endif
87987d40a0SJie Zhou #endif
88a9de470cSBruce Richardson 	};
89a9de470cSBruce Richardson 
90a9de470cSBruce Richardson 	if (recursive_call == NULL)
91a9de470cSBruce Richardson 		return -1;
9271bdd8a1SPavan Nikhilesh 	for (i = 0; i < RTE_DIM(actions); i++) {
93a9de470cSBruce Richardson 		if (strcmp(actions[i].env_var, recursive_call) == 0)
94a9de470cSBruce Richardson 			return (actions[i].action_fn)();
95a9de470cSBruce Richardson 	}
96a9de470cSBruce Richardson 	printf("ERROR - missing action to take for %s\n", recursive_call);
97a9de470cSBruce Richardson 	return -1;
98a9de470cSBruce Richardson }
99a9de470cSBruce Richardson 
100a9de470cSBruce Richardson int last_test_result;
101a9de470cSBruce Richardson 
102a9de470cSBruce Richardson #define MAX_EXTRA_ARGS 32
103a9de470cSBruce Richardson 
104a9de470cSBruce Richardson int
main(int argc,char ** argv)105a9de470cSBruce Richardson main(int argc, char **argv)
106a9de470cSBruce Richardson {
107a9de470cSBruce Richardson 	struct cmdline *cl;
108ace2f054SBruce Richardson 	char *tests[argc]; /* store an array of tests to run */
109ace2f054SBruce Richardson 	int test_count = 0;
110ace2f054SBruce Richardson 	int i;
111a9de470cSBruce Richardson 	char *extra_args;
112a9de470cSBruce Richardson 	int ret;
113a9de470cSBruce Richardson 
114a9de470cSBruce Richardson 	extra_args = getenv("DPDK_TEST_PARAMS");
115a9de470cSBruce Richardson 	if (extra_args != NULL && strlen(extra_args) > 0) {
116a9de470cSBruce Richardson 		char **all_argv;
117a9de470cSBruce Richardson 		char *eargv[MAX_EXTRA_ARGS];
118a9de470cSBruce Richardson 		int all_argc;
119a9de470cSBruce Richardson 		int eargc;
120a9de470cSBruce Richardson 		int i;
121a9de470cSBruce Richardson 
122a9de470cSBruce Richardson 		RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n",
123a9de470cSBruce Richardson 				extra_args);
124a9de470cSBruce Richardson 		eargc = rte_strsplit(extra_args, strlen(extra_args),
125a9de470cSBruce Richardson 				eargv, MAX_EXTRA_ARGS, ' ');
126a9de470cSBruce Richardson 
127a9de470cSBruce Richardson 		/* merge argc/argv and the environment args */
128a9de470cSBruce Richardson 		all_argc = argc + eargc;
129a9de470cSBruce Richardson 		all_argv = malloc(sizeof(*all_argv) * (all_argc + 1));
130a9de470cSBruce Richardson 		if (all_argv == NULL) {
131a9de470cSBruce Richardson 			ret = -1;
132a9de470cSBruce Richardson 			goto out;
133a9de470cSBruce Richardson 		}
134a9de470cSBruce Richardson 
135a9de470cSBruce Richardson 		for (i = 0; i < argc; i++)
136a9de470cSBruce Richardson 			all_argv[i] = argv[i];
137a9de470cSBruce Richardson 		for (i = 0; i < eargc; i++)
138a9de470cSBruce Richardson 			all_argv[argc + i] = eargv[i];
139a9de470cSBruce Richardson 		all_argv[all_argc] = NULL;
140a9de470cSBruce Richardson 
141a9de470cSBruce Richardson 		/* call eal_init with combined args */
142a9de470cSBruce Richardson 		ret = rte_eal_init(all_argc, all_argv);
143a9de470cSBruce Richardson 		free(all_argv);
144a9de470cSBruce Richardson 	} else
145a9de470cSBruce Richardson 		ret = rte_eal_init(argc, argv);
146a9de470cSBruce Richardson 	if (ret < 0) {
147a9de470cSBruce Richardson 		ret = -1;
148a9de470cSBruce Richardson 		goto out;
149a9de470cSBruce Richardson 	}
150a9de470cSBruce Richardson 
1513dd7d693SStanislaw Kardach 	argv += ret;
152ace2f054SBruce Richardson 	argc -= ret;
1533dd7d693SStanislaw Kardach 
1543dd7d693SStanislaw Kardach 	prgname = argv[0];
1553dd7d693SStanislaw Kardach 
156a8d0d473SBruce Richardson #ifdef RTE_LIB_TIMER
1573dd7d693SStanislaw Kardach 	ret = rte_timer_subsystem_init();
1583dd7d693SStanislaw Kardach 	if (ret < 0 && ret != -EALREADY) {
15950247fe0SErik Gabriel Carrillo 		ret = -1;
16050247fe0SErik Gabriel Carrillo 		goto out;
16150247fe0SErik Gabriel Carrillo 	}
162a9de470cSBruce Richardson #endif
163a9de470cSBruce Richardson 
164a9de470cSBruce Richardson 	if (commands_init() < 0) {
165a9de470cSBruce Richardson 		ret = -1;
166a9de470cSBruce Richardson 		goto out;
167a9de470cSBruce Richardson 	}
168a9de470cSBruce Richardson 
169a9de470cSBruce Richardson 	recursive_call = getenv(RECURSIVE_ENV_VAR);
170a9de470cSBruce Richardson 	if (recursive_call != NULL) {
171a9de470cSBruce Richardson 		ret = do_recursive_call();
172a9de470cSBruce Richardson 		goto out;
173a9de470cSBruce Richardson 	}
174a9de470cSBruce Richardson 
175a9de470cSBruce Richardson #ifdef RTE_LIBEAL_USE_HPET
176a9de470cSBruce Richardson 	if (rte_eal_hpet_init(1) < 0)
177a9de470cSBruce Richardson #endif
178a9de470cSBruce Richardson 		RTE_LOG(INFO, APP,
179a9de470cSBruce Richardson 				"HPET is not enabled, using TSC as default timer\n");
180a9de470cSBruce Richardson 
181a9de470cSBruce Richardson 
182acdabc45SStephen Hemminger 	char *dpdk_test = getenv("DPDK_TEST");
183ace2f054SBruce Richardson 
184f940a2e3SBruce Richardson 	if (dpdk_test && strlen(dpdk_test) > 0)
185ace2f054SBruce Richardson 		tests[test_count++] = dpdk_test;
186f940a2e3SBruce Richardson 	for (i = 1; i < argc; i++)
187ace2f054SBruce Richardson 		tests[test_count++] = argv[i];
188ace2f054SBruce Richardson 
189ace2f054SBruce Richardson 	if (test_count > 0) {
190acdabc45SStephen Hemminger 		char buf[1024];
1911f48a7d2SBruce Richardson 		char *dpdk_test_skip = getenv("DPDK_TEST_SKIP");
1921f48a7d2SBruce Richardson 		char *skip_tests[128] = {0};
1931f48a7d2SBruce Richardson 		size_t n_skip_tests = 0;
1941f48a7d2SBruce Richardson 
1951f48a7d2SBruce Richardson 		if (dpdk_test_skip != NULL && strlen(dpdk_test_skip) > 0) {
1961f48a7d2SBruce Richardson 			int split_ret;
1971f48a7d2SBruce Richardson 			char *dpdk_test_skip_cp = strdup(dpdk_test_skip);
1981f48a7d2SBruce Richardson 			if (dpdk_test_skip_cp == NULL) {
1991f48a7d2SBruce Richardson 				ret = -1;
2001f48a7d2SBruce Richardson 				goto out;
2011f48a7d2SBruce Richardson 			}
2021f48a7d2SBruce Richardson 			dpdk_test_skip = dpdk_test_skip_cp;
2031f48a7d2SBruce Richardson 			split_ret = rte_strsplit(dpdk_test_skip, strlen(dpdk_test_skip),
2041f48a7d2SBruce Richardson 					skip_tests, RTE_DIM(skip_tests), ',');
2051f48a7d2SBruce Richardson 			if (split_ret > 0)
2061f48a7d2SBruce Richardson 				n_skip_tests = split_ret;
2071f48a7d2SBruce Richardson 			else
2081f48a7d2SBruce Richardson 				free(dpdk_test_skip);
2091f48a7d2SBruce Richardson 		}
210acdabc45SStephen Hemminger 
211acdabc45SStephen Hemminger 		cl = cmdline_new(main_ctx, "RTE>>", 0, 1);
212acdabc45SStephen Hemminger 		if (cl == NULL) {
213acdabc45SStephen Hemminger 			ret = -1;
214acdabc45SStephen Hemminger 			goto out;
215acdabc45SStephen Hemminger 		}
216acdabc45SStephen Hemminger 
217ace2f054SBruce Richardson 		for (i = 0; i < test_count; i++) {
2181f48a7d2SBruce Richardson 			/* check if test is to be skipped */
2191f48a7d2SBruce Richardson 			for (size_t j = 0; j < n_skip_tests; j++) {
2201f48a7d2SBruce Richardson 				if (strcmp(tests[i], skip_tests[j]) == 0) {
2211f48a7d2SBruce Richardson 					fprintf(stderr, "Skipping %s [DPDK_TEST_SKIP]\n", tests[i]);
2221f48a7d2SBruce Richardson 					ret = TEST_SKIPPED;
2231f48a7d2SBruce Richardson 					goto end_of_cmd;
2241f48a7d2SBruce Richardson 				}
2251f48a7d2SBruce Richardson 			}
2261f48a7d2SBruce Richardson 
227ace2f054SBruce Richardson 			snprintf(buf, sizeof(buf), "%s\n", tests[i]);
228f940a2e3SBruce Richardson 			if (cmdline_parse_check(cl, buf) < 0) {
229f940a2e3SBruce Richardson 				printf("Error: invalid test command: '%s'\n", tests[i]);
230f940a2e3SBruce Richardson 				ret = -1;
231f940a2e3SBruce Richardson 			} else if (cmdline_in(cl, buf, strlen(buf)) < 0) {
232acdabc45SStephen Hemminger 				printf("error on cmdline input\n");
233acdabc45SStephen Hemminger 				ret = -1;
234ace2f054SBruce Richardson 			} else
235acdabc45SStephen Hemminger 				ret = last_test_result;
236ace2f054SBruce Richardson 
2371f48a7d2SBruce Richardson end_of_cmd:
238db01e7e8SBruce Richardson 			if (ret != 0 && ret != TEST_SKIPPED)
239ace2f054SBruce Richardson 				break;
240acdabc45SStephen Hemminger 		}
2411f48a7d2SBruce Richardson 		if (n_skip_tests > 0)
2421f48a7d2SBruce Richardson 			free(dpdk_test_skip);
2431f48a7d2SBruce Richardson 
244acdabc45SStephen Hemminger 		cmdline_free(cl);
245acdabc45SStephen Hemminger 		goto out;
246acdabc45SStephen Hemminger 	} else {
247acdabc45SStephen Hemminger 		/* if no DPDK_TEST env variable, go interactive */
248a9de470cSBruce Richardson 		cl = cmdline_stdin_new(main_ctx, "RTE>>");
249a9de470cSBruce Richardson 		if (cl == NULL) {
250a9de470cSBruce Richardson 			ret = -1;
251a9de470cSBruce Richardson 			goto out;
252a9de470cSBruce Richardson 		}
253a9de470cSBruce Richardson 
254a9de470cSBruce Richardson 		cmdline_interact(cl);
255a9de470cSBruce Richardson 		cmdline_stdin_exit(cl);
256acdabc45SStephen Hemminger 	}
257a9de470cSBruce Richardson 	ret = 0;
258a9de470cSBruce Richardson 
259a9de470cSBruce Richardson out:
260a8d0d473SBruce Richardson #ifdef RTE_LIB_TIMER
2618650e935SErik Gabriel Carrillo 	rte_timer_subsystem_finalize();
2628650e935SErik Gabriel Carrillo #endif
263a9de470cSBruce Richardson 	rte_eal_cleanup();
264a9de470cSBruce Richardson 	return ret;
265a9de470cSBruce Richardson }
266a9de470cSBruce Richardson 
267caa817f0SCiara Power static void
unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite * suite,int test_success,unsigned int * sub_ts_failed,unsigned int * sub_ts_skipped,unsigned int * sub_ts_total)268caa817f0SCiara Power unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite *suite,
269fbc53675SCiara Power 		int test_success, unsigned int *sub_ts_failed,
270fbc53675SCiara Power 		unsigned int *sub_ts_skipped, unsigned int *sub_ts_total)
271caa817f0SCiara Power {
272caa817f0SCiara Power 	struct unit_test_case tc;
273fbc53675SCiara Power 	struct unit_test_suite *ts;
274caa817f0SCiara Power 	int i;
275caa817f0SCiara Power 
276fbc53675SCiara Power 	FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
277fbc53675SCiara Power 		unit_test_suite_count_tcs_on_setup_fail(
278fbc53675SCiara Power 			ts, test_success, sub_ts_failed,
279fbc53675SCiara Power 			sub_ts_skipped, sub_ts_total);
280fbc53675SCiara Power 		suite->total += ts->total;
281fbc53675SCiara Power 		suite->failed += ts->failed;
282fbc53675SCiara Power 		suite->skipped += ts->skipped;
283fbc53675SCiara Power 		if (ts->failed)
284fbc53675SCiara Power 			(*sub_ts_failed)++;
285fbc53675SCiara Power 		else
286fbc53675SCiara Power 			(*sub_ts_skipped)++;
287fbc53675SCiara Power 		(*sub_ts_total)++;
288fbc53675SCiara Power 	}
289caa817f0SCiara Power 	FOR_EACH_SUITE_TESTCASE(i, suite, tc) {
290caa817f0SCiara Power 		suite->total++;
291caa817f0SCiara Power 		if (!tc.enabled || test_success == TEST_SKIPPED)
292caa817f0SCiara Power 			suite->skipped++;
293caa817f0SCiara Power 		else
294caa817f0SCiara Power 			suite->failed++;
295caa817f0SCiara Power 	}
296caa817f0SCiara Power }
297caa817f0SCiara Power 
298caa817f0SCiara Power static void
unit_test_suite_reset_counts(struct unit_test_suite * suite)299caa817f0SCiara Power unit_test_suite_reset_counts(struct unit_test_suite *suite)
300caa817f0SCiara Power {
301fbc53675SCiara Power 	struct unit_test_suite *ts;
302fbc53675SCiara Power 	int i;
303fbc53675SCiara Power 
304fbc53675SCiara Power 	FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
305fbc53675SCiara Power 		unit_test_suite_reset_counts(ts);
306caa817f0SCiara Power 	suite->total = 0;
307caa817f0SCiara Power 	suite->executed = 0;
308caa817f0SCiara Power 	suite->succeeded = 0;
309caa817f0SCiara Power 	suite->skipped = 0;
310caa817f0SCiara Power 	suite->failed = 0;
311caa817f0SCiara Power 	suite->unsupported = 0;
312caa817f0SCiara Power }
313a9de470cSBruce Richardson 
314a9de470cSBruce Richardson int
unit_test_suite_runner(struct unit_test_suite * suite)315a9de470cSBruce Richardson unit_test_suite_runner(struct unit_test_suite *suite)
316a9de470cSBruce Richardson {
317fbc53675SCiara Power 	int test_success, i, ret;
318a9de470cSBruce Richardson 	const char *status;
319caa817f0SCiara Power 	struct unit_test_case tc;
320fbc53675SCiara Power 	struct unit_test_suite *ts;
321fbc53675SCiara Power 	unsigned int sub_ts_succeeded = 0, sub_ts_failed = 0;
322fbc53675SCiara Power 	unsigned int sub_ts_skipped = 0, sub_ts_total = 0;
323caa817f0SCiara Power 
324caa817f0SCiara Power 	unit_test_suite_reset_counts(suite);
325a9de470cSBruce Richardson 
326a9de470cSBruce Richardson 	if (suite->suite_name) {
327a9de470cSBruce Richardson 		printf(" + ------------------------------------------------------- +\n");
328a9de470cSBruce Richardson 		printf(" + Test Suite : %s\n", suite->suite_name);
329a9de470cSBruce Richardson 	}
330a9de470cSBruce Richardson 
331e0f4a0edSDavid Marchand 	if (suite->setup) {
332e0f4a0edSDavid Marchand 		test_success = suite->setup();
333e0f4a0edSDavid Marchand 		if (test_success != 0) {
334a9de470cSBruce Richardson 			/*
335e0f4a0edSDavid Marchand 			 * setup did not pass, so count all enabled tests and
336e0f4a0edSDavid Marchand 			 * mark them as failed/skipped
337a9de470cSBruce Richardson 			 */
338caa817f0SCiara Power 			unit_test_suite_count_tcs_on_setup_fail(suite,
339fbc53675SCiara Power 					test_success, &sub_ts_failed,
340fbc53675SCiara Power 					&sub_ts_skipped, &sub_ts_total);
341a9de470cSBruce Richardson 			goto suite_summary;
342a9de470cSBruce Richardson 		}
343e0f4a0edSDavid Marchand 	}
344a9de470cSBruce Richardson 
345a9de470cSBruce Richardson 	printf(" + ------------------------------------------------------- +\n");
346a9de470cSBruce Richardson 
347caa817f0SCiara Power 	FOR_EACH_SUITE_TESTCASE(suite->total, suite, tc) {
348caa817f0SCiara Power 		if (!tc.enabled) {
349caa817f0SCiara Power 			suite->skipped++;
350a9de470cSBruce Richardson 			continue;
351a9de470cSBruce Richardson 		} else {
352caa817f0SCiara Power 			suite->executed++;
353a9de470cSBruce Richardson 		}
354a9de470cSBruce Richardson 
355a9de470cSBruce Richardson 		/* run test case setup */
356caa817f0SCiara Power 		if (tc.setup)
357caa817f0SCiara Power 			test_success = tc.setup();
358a9de470cSBruce Richardson 		else
359a9de470cSBruce Richardson 			test_success = TEST_SUCCESS;
360a9de470cSBruce Richardson 
361a9de470cSBruce Richardson 		if (test_success == TEST_SUCCESS) {
362a9de470cSBruce Richardson 			/* run the test case */
363e65da89cSCiara Power 			if (tc.testcase)
364caa817f0SCiara Power 				test_success = tc.testcase();
365e65da89cSCiara Power 			else if (tc.testcase_with_data)
366e65da89cSCiara Power 				test_success = tc.testcase_with_data(tc.data);
367e65da89cSCiara Power 			else
368e65da89cSCiara Power 				test_success = -ENOTSUP;
369e65da89cSCiara Power 
370a9de470cSBruce Richardson 			if (test_success == TEST_SUCCESS)
371caa817f0SCiara Power 				suite->succeeded++;
372*a620df6dSBruce Richardson 			else if (test_success == TEST_SKIPPED) {
373caa817f0SCiara Power 				suite->skipped++;
374*a620df6dSBruce Richardson 				suite->executed--;
375*a620df6dSBruce Richardson 			} else if (test_success == -ENOTSUP) {
376caa817f0SCiara Power 				suite->unsupported++;
377*a620df6dSBruce Richardson 				suite->executed--;
378*a620df6dSBruce Richardson 			} else
379caa817f0SCiara Power 				suite->failed++;
380a9de470cSBruce Richardson 		} else if (test_success == -ENOTSUP) {
381caa817f0SCiara Power 			suite->unsupported++;
38296b5d4f9SAnoob Joseph 		} else if (test_success == TEST_SKIPPED) {
38396b5d4f9SAnoob Joseph 			suite->skipped++;
384a9de470cSBruce Richardson 		} else {
385caa817f0SCiara Power 			suite->failed++;
386a9de470cSBruce Richardson 		}
387a9de470cSBruce Richardson 
388a9de470cSBruce Richardson 		/* run the test case teardown */
389caa817f0SCiara Power 		if (tc.teardown)
390caa817f0SCiara Power 			tc.teardown();
391a9de470cSBruce Richardson 
392a9de470cSBruce Richardson 		if (test_success == TEST_SUCCESS)
393a9de470cSBruce Richardson 			status = "succeeded";
394e0f4a0edSDavid Marchand 		else if (test_success == TEST_SKIPPED)
395e0f4a0edSDavid Marchand 			status = "skipped";
396a9de470cSBruce Richardson 		else if (test_success == -ENOTSUP)
397a9de470cSBruce Richardson 			status = "unsupported";
398a9de470cSBruce Richardson 		else
399a9de470cSBruce Richardson 			status = "failed";
400a9de470cSBruce Richardson 
401caa817f0SCiara Power 		printf(" + TestCase [%2d] : %s %s\n", suite->total,
402caa817f0SCiara Power 				tc.name, status);
403a9de470cSBruce Richardson 	}
404fbc53675SCiara Power 	FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
405fbc53675SCiara Power 		ret = unit_test_suite_runner(ts);
406fbc53675SCiara Power 		if (ret == TEST_SUCCESS)
407fbc53675SCiara Power 			sub_ts_succeeded++;
408fbc53675SCiara Power 		else if (ret == TEST_SKIPPED)
409fbc53675SCiara Power 			sub_ts_skipped++;
410fbc53675SCiara Power 		else
411fbc53675SCiara Power 			sub_ts_failed++;
412fbc53675SCiara Power 		sub_ts_total++;
413fbc53675SCiara Power 
414fbc53675SCiara Power 		suite->total += ts->total;
415fbc53675SCiara Power 		suite->succeeded += ts->succeeded;
416fbc53675SCiara Power 		suite->failed += ts->failed;
417fbc53675SCiara Power 		suite->skipped += ts->skipped;
418fbc53675SCiara Power 		suite->unsupported += ts->unsupported;
419fbc53675SCiara Power 		suite->executed += ts->executed;
420fbc53675SCiara Power 	}
421a9de470cSBruce Richardson 
422a9de470cSBruce Richardson 	/* Run test suite teardown */
423a9de470cSBruce Richardson 	if (suite->teardown)
424a9de470cSBruce Richardson 		suite->teardown();
425a9de470cSBruce Richardson 
426a9de470cSBruce Richardson 	goto suite_summary;
427a9de470cSBruce Richardson 
428a9de470cSBruce Richardson suite_summary:
429a9de470cSBruce Richardson 	printf(" + ------------------------------------------------------- +\n");
430caa817f0SCiara Power 	printf(" + Test Suite Summary : %s\n", suite->suite_name);
431fbc53675SCiara Power 	printf(" + ------------------------------------------------------- +\n");
432fbc53675SCiara Power 
433fbc53675SCiara Power 	FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
434fbc53675SCiara Power 		printf(" + %s : %d/%d passed, %d/%d skipped, "
435fbc53675SCiara Power 			"%d/%d failed, %d/%d unsupported\n", ts->suite_name,
436fbc53675SCiara Power 			ts->succeeded, ts->total, ts->skipped, ts->total,
437fbc53675SCiara Power 			ts->failed, ts->total, ts->unsupported, ts->total);
438fbc53675SCiara Power 
439fbc53675SCiara Power 	if (suite->unit_test_suites) {
440fbc53675SCiara Power 		printf(" + ------------------------------------------------------- +\n");
441fbc53675SCiara Power 		printf(" + Sub Testsuites Total :     %2d\n", sub_ts_total);
442fbc53675SCiara Power 		printf(" + Sub Testsuites Skipped :   %2d\n", sub_ts_skipped);
443fbc53675SCiara Power 		printf(" + Sub Testsuites Passed :    %2d\n", sub_ts_succeeded);
444fbc53675SCiara Power 		printf(" + Sub Testsuites Failed :    %2d\n", sub_ts_failed);
445fbc53675SCiara Power 		printf(" + ------------------------------------------------------- +\n");
446fbc53675SCiara Power 	}
447fbc53675SCiara Power 
448caa817f0SCiara Power 	printf(" + Tests Total :       %2d\n", suite->total);
449caa817f0SCiara Power 	printf(" + Tests Skipped :     %2d\n", suite->skipped);
450caa817f0SCiara Power 	printf(" + Tests Executed :    %2d\n", suite->executed);
451caa817f0SCiara Power 	printf(" + Tests Unsupported:  %2d\n", suite->unsupported);
452caa817f0SCiara Power 	printf(" + Tests Passed :      %2d\n", suite->succeeded);
453caa817f0SCiara Power 	printf(" + Tests Failed :      %2d\n", suite->failed);
454a9de470cSBruce Richardson 	printf(" + ------------------------------------------------------- +\n");
455a9de470cSBruce Richardson 
456caa817f0SCiara Power 	last_test_result = suite->failed;
457a9de470cSBruce Richardson 
458caa817f0SCiara Power 	if (suite->failed)
459e0f4a0edSDavid Marchand 		return TEST_FAILED;
460caa817f0SCiara Power 	if (suite->total == suite->skipped)
461e0f4a0edSDavid Marchand 		return TEST_SKIPPED;
462e0f4a0edSDavid Marchand 	return TEST_SUCCESS;
463a9de470cSBruce Richardson }
464