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