3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <sys/signalfd.h>
38 #ifdef HAVE_VALGRIND_MEMCHECK_H
39 #include <valgrind/memcheck.h>
42 #include "src/shared/util.h"
43 #include "src/shared/tester.h"
45 #define COLOR_OFF "\x1B[0m"
46 #define COLOR_BLACK "\x1B[0;30m"
47 #define COLOR_RED "\x1B[0;31m"
48 #define COLOR_GREEN "\x1B[0;32m"
49 #define COLOR_YELLOW "\x1B[0;33m"
50 #define COLOR_BLUE "\x1B[0;34m"
51 #define COLOR_MAGENTA "\x1B[0;35m"
52 #define COLOR_CYAN "\x1B[0;36m"
53 #define COLOR_WHITE "\x1B[0;37m"
54 #define COLOR_HIGHLIGHT "\x1B[1;39m"
56 #define print_text(color, fmt, args...) \
57 printf(color fmt COLOR_OFF "\n", ## args)
59 #define print_summary(label, color, value, fmt, args...) \
60 printf("%-52s " color "%-10s" COLOR_OFF fmt "\n", \
61 label, value, ## args)
63 #define print_progress(name, color, fmt, args...) \
64 printf(COLOR_HIGHLIGHT "%s" COLOR_OFF " - " \
65 color fmt COLOR_OFF "\n", name, ## args)
71 TEST_RESULT_TIMED_OUT,
80 TEST_STAGE_POST_TEARDOWN,
85 enum test_result result;
86 enum test_stage stage;
87 const void *test_data;
88 tester_data_func_t pre_setup_func;
89 tester_data_func_t setup_func;
90 tester_data_func_t test_func;
91 tester_data_func_t teardown_func;
92 tester_data_func_t post_teardown_func;
96 unsigned int timeout_id;
97 unsigned int teardown_id;
98 tester_destroy_func_t destroy;
102 static GMainLoop *main_loop;
104 static GList *test_list;
105 static GList *test_current;
106 static GTimer *test_timer;
108 static gboolean option_version = FALSE;
109 static gboolean option_quiet = FALSE;
110 static gboolean option_debug = FALSE;
111 static gboolean option_list = FALSE;
112 static const char *option_prefix = NULL;
114 static void test_destroy(gpointer data)
116 struct test_case *test = data;
118 if (test->timeout_id > 0)
119 g_source_remove(test->timeout_id);
121 if (test->teardown_id > 0)
122 g_source_remove(test->teardown_id);
125 test->destroy(test->user_data);
131 void tester_print(const char *format, ...)
135 if (tester_use_quiet())
138 printf(" %s", COLOR_WHITE);
139 va_start(ap, format);
142 printf("%s\n", COLOR_OFF);
145 void tester_debug(const char *format, ...)
149 if (!tester_use_debug())
152 printf(" %s", COLOR_WHITE);
153 va_start(ap, format);
156 printf("%s\n", COLOR_OFF);
159 void tester_warn(const char *format, ...)
163 printf(" %s", COLOR_WHITE);
164 va_start(ap, format);
167 printf("%s\n", COLOR_OFF);
170 static void default_pre_setup(const void *test_data)
172 tester_pre_setup_complete();
175 static void default_setup(const void *test_data)
177 tester_setup_complete();
180 static void default_teardown(const void *test_data)
182 tester_teardown_complete();
185 static void default_post_teardown(const void *test_data)
187 tester_post_teardown_complete();
190 void tester_add_full(const char *name, const void *test_data,
191 tester_data_func_t pre_setup_func,
192 tester_data_func_t setup_func,
193 tester_data_func_t test_func,
194 tester_data_func_t teardown_func,
195 tester_data_func_t post_teardown_func,
196 unsigned int timeout,
197 void *user_data, tester_destroy_func_t destroy)
199 struct test_case *test;
204 if (option_prefix && !g_str_has_prefix(name, option_prefix)) {
211 printf("%s\n", name);
217 test = new0(struct test_case, 1);
218 test->name = strdup(name);
219 test->result = TEST_RESULT_NOT_RUN;
220 test->stage = TEST_STAGE_INVALID;
222 test->test_data = test_data;
225 test->pre_setup_func = pre_setup_func;
227 test->pre_setup_func = default_pre_setup;
230 test->setup_func = setup_func;
232 test->setup_func = default_setup;
234 test->test_func = test_func;
237 test->teardown_func = teardown_func;
239 test->teardown_func = default_teardown;
241 if (post_teardown_func)
242 test->post_teardown_func = post_teardown_func;
244 test->post_teardown_func = default_post_teardown;
246 test->timeout = timeout;
248 test->destroy = destroy;
249 test->user_data = user_data;
251 test_list = g_list_append(test_list, test);
254 void tester_add(const char *name, const void *test_data,
255 tester_data_func_t setup_func,
256 tester_data_func_t test_func,
257 tester_data_func_t teardown_func)
259 tester_add_full(name, test_data, NULL, setup_func, test_func,
260 teardown_func, NULL, 0, NULL, NULL);
263 void *tester_get_data(void)
265 struct test_case *test;
270 test = test_current->data;
272 return test->user_data;
275 static int tester_summarize(void)
277 unsigned int not_run = 0, passed = 0, failed = 0;
278 gdouble execution_time;
282 print_text(COLOR_HIGHLIGHT, "");
283 print_text(COLOR_HIGHLIGHT, "Test Summary");
284 print_text(COLOR_HIGHLIGHT, "------------");
286 for (list = g_list_first(test_list); list; list = g_list_next(list)) {
287 struct test_case *test = list->data;
290 exec_time = test->end_time - test->start_time;
292 switch (test->result) {
293 case TEST_RESULT_NOT_RUN:
294 print_summary(test->name, COLOR_YELLOW, "Not Run", "");
297 case TEST_RESULT_PASSED:
298 print_summary(test->name, COLOR_GREEN, "Passed",
299 "%8.3f seconds", exec_time);
302 case TEST_RESULT_FAILED:
303 print_summary(test->name, COLOR_RED, "Failed",
304 "%8.3f seconds", exec_time);
307 case TEST_RESULT_TIMED_OUT:
308 print_summary(test->name, COLOR_RED, "Timed out",
309 "%8.3f seconds", exec_time);
315 printf("\nTotal: %d, "
316 COLOR_GREEN "Passed: %d (%.1f%%)" COLOR_OFF ", "
317 COLOR_RED "Failed: %d" COLOR_OFF ", "
318 COLOR_YELLOW "Not Run: %d" COLOR_OFF "\n",
319 not_run + passed + failed, passed,
320 (not_run + passed + failed) ?
321 (float) passed * 100 / (not_run + passed + failed) : 0,
324 execution_time = g_timer_elapsed(test_timer, NULL);
325 printf("Overall execution time: %.3g seconds\n", execution_time);
330 static gboolean teardown_callback(gpointer user_data)
332 struct test_case *test = user_data;
334 test->teardown_id = 0;
335 test->stage = TEST_STAGE_TEARDOWN;
337 print_progress(test->name, COLOR_MAGENTA, "teardown");
338 test->teardown_func(test->test_data);
340 #ifdef HAVE_VALGRIND_MEMCHECK_H
341 VALGRIND_DO_ADDED_LEAK_CHECK;
347 static gboolean test_timeout(gpointer user_data)
349 struct test_case *test = user_data;
351 test->timeout_id = 0;
356 test->result = TEST_RESULT_TIMED_OUT;
357 print_progress(test->name, COLOR_RED, "test timed out");
359 g_idle_add(teardown_callback, test);
364 static void next_test_case(void)
366 struct test_case *test;
369 test_current = g_list_next(test_current);
371 test_current = test_list;
374 g_timer_stop(test_timer);
376 g_main_loop_quit(main_loop);
380 test = test_current->data;
383 print_progress(test->name, COLOR_BLACK, "init");
385 test->start_time = g_timer_elapsed(test_timer, NULL);
387 if (test->timeout > 0)
388 test->timeout_id = g_timeout_add_seconds(test->timeout,
391 test->stage = TEST_STAGE_PRE_SETUP;
393 test->pre_setup_func(test->test_data);
396 static gboolean setup_callback(gpointer user_data)
398 struct test_case *test = user_data;
400 test->stage = TEST_STAGE_SETUP;
402 print_progress(test->name, COLOR_BLUE, "setup");
403 test->setup_func(test->test_data);
408 static gboolean run_callback(gpointer user_data)
410 struct test_case *test = user_data;
412 test->stage = TEST_STAGE_RUN;
414 print_progress(test->name, COLOR_BLACK, "run");
415 test->test_func(test->test_data);
420 static gboolean done_callback(gpointer user_data)
422 struct test_case *test = user_data;
424 test->end_time = g_timer_elapsed(test_timer, NULL);
426 print_progress(test->name, COLOR_BLACK, "done");
432 void tester_pre_setup_complete(void)
434 struct test_case *test;
439 test = test_current->data;
441 if (test->stage != TEST_STAGE_PRE_SETUP)
444 g_idle_add(setup_callback, test);
447 void tester_pre_setup_failed(void)
449 struct test_case *test;
454 test = test_current->data;
456 if (test->stage != TEST_STAGE_PRE_SETUP)
459 print_progress(test->name, COLOR_RED, "pre setup failed");
461 g_idle_add(done_callback, test);
464 void tester_setup_complete(void)
466 struct test_case *test;
471 test = test_current->data;
473 if (test->stage != TEST_STAGE_SETUP)
476 print_progress(test->name, COLOR_BLUE, "setup complete");
478 g_idle_add(run_callback, test);
481 void tester_setup_failed(void)
483 struct test_case *test;
488 test = test_current->data;
490 if (test->stage != TEST_STAGE_SETUP)
493 test->stage = TEST_STAGE_POST_TEARDOWN;
495 if (test->timeout_id > 0) {
496 g_source_remove(test->timeout_id);
497 test->timeout_id = 0;
500 print_progress(test->name, COLOR_RED, "setup failed");
501 print_progress(test->name, COLOR_MAGENTA, "teardown");
503 test->post_teardown_func(test->test_data);
506 static void test_result(enum test_result result)
508 struct test_case *test;
513 test = test_current->data;
515 if (test->stage != TEST_STAGE_RUN)
518 if (test->timeout_id > 0) {
519 g_source_remove(test->timeout_id);
520 test->timeout_id = 0;
523 test->result = result;
525 case TEST_RESULT_PASSED:
526 print_progress(test->name, COLOR_GREEN, "test passed");
528 case TEST_RESULT_FAILED:
529 print_progress(test->name, COLOR_RED, "test failed");
531 case TEST_RESULT_NOT_RUN:
532 print_progress(test->name, COLOR_YELLOW, "test not run");
534 case TEST_RESULT_TIMED_OUT:
535 print_progress(test->name, COLOR_RED, "test timed out");
539 if (test->teardown_id > 0)
542 test->teardown_id = g_idle_add(teardown_callback, test);
545 void tester_test_passed(void)
547 test_result(TEST_RESULT_PASSED);
550 void tester_test_failed(void)
552 test_result(TEST_RESULT_FAILED);
555 void tester_test_abort(void)
557 test_result(TEST_RESULT_NOT_RUN);
560 void tester_teardown_complete(void)
562 struct test_case *test;
567 test = test_current->data;
569 if (test->stage != TEST_STAGE_TEARDOWN)
572 test->stage = TEST_STAGE_POST_TEARDOWN;
574 test->post_teardown_func(test->test_data);
577 void tester_teardown_failed(void)
579 struct test_case *test;
584 test = test_current->data;
586 if (test->stage != TEST_STAGE_TEARDOWN)
589 test->stage = TEST_STAGE_POST_TEARDOWN;
591 tester_post_teardown_failed();
594 void tester_post_teardown_complete(void)
596 struct test_case *test;
601 test = test_current->data;
603 if (test->stage != TEST_STAGE_POST_TEARDOWN)
606 print_progress(test->name, COLOR_MAGENTA, "teardown complete");
608 g_idle_add(done_callback, test);
611 void tester_post_teardown_failed(void)
613 struct test_case *test;
618 test = test_current->data;
620 if (test->stage != TEST_STAGE_POST_TEARDOWN)
623 print_progress(test->name, COLOR_RED, "teardown failed");
625 g_idle_add(done_callback, test);
628 static gboolean start_tester(gpointer user_data)
630 test_timer = g_timer_new();
638 unsigned int seconds;
639 struct test_case *test;
640 tester_wait_func_t func;
644 static gboolean wait_callback(gpointer user_data)
646 struct wait_data *wait = user_data;
647 struct test_case *test = wait->test;
651 if (wait->seconds > 0) {
652 print_progress(test->name, COLOR_BLACK, "%u seconds left",
657 print_progress(test->name, COLOR_BLACK, "waiting done");
659 wait->func(wait->user_data);
666 void tester_wait(unsigned int seconds, tester_wait_func_t func,
669 struct test_case *test;
670 struct wait_data *wait;
672 if (!func || seconds < 1)
678 test = test_current->data;
680 wait = new0(struct wait_data, 1);
681 wait->seconds = seconds;
684 wait->user_data = user_data;
686 g_timeout_add(1000, wait_callback, wait);
688 print_progress(test->name, COLOR_BLACK, "waiting %u seconds", seconds);
691 static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
694 static bool terminated = false;
695 struct signalfd_siginfo si;
699 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
700 g_main_loop_quit(main_loop);
704 fd = g_io_channel_unix_get_fd(channel);
706 result = read(fd, &si, sizeof(si));
707 if (result != sizeof(si))
710 switch (si.ssi_signo) {
714 g_main_loop_quit(main_loop);
723 static guint setup_signalfd(void)
731 sigaddset(&mask, SIGINT);
732 sigaddset(&mask, SIGTERM);
734 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
735 perror("Failed to set signal mask");
739 fd = signalfd(-1, &mask, 0);
741 perror("Failed to create signal descriptor");
745 channel = g_io_channel_unix_new(fd);
747 g_io_channel_set_close_on_unref(channel, TRUE);
748 g_io_channel_set_encoding(channel, NULL, NULL);
749 g_io_channel_set_buffered(channel, FALSE);
751 source = g_io_add_watch(channel,
752 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
753 signal_handler, NULL);
755 g_io_channel_unref(channel);
760 bool tester_use_quiet(void)
762 return option_quiet == TRUE ? true : false;
765 bool tester_use_debug(void)
767 return option_debug == TRUE ? true : false;
770 static GOptionEntry options[] = {
771 { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
772 "Show version information and exit" },
773 { "quiet", 'q', 0, G_OPTION_ARG_NONE, &option_quiet,
774 "Run tests without logging" },
775 { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
776 "Run tests with debug output" },
777 { "list", 'l', 0, G_OPTION_ARG_NONE, &option_list,
778 "Only list the tests to be run" },
779 { "prefix", 'p', 0, G_OPTION_ARG_STRING, &option_prefix,
780 "Run tests matching provided prefix" },
784 void tester_init(int *argc, char ***argv)
786 GOptionContext *context;
787 GError *error = NULL;
789 context = g_option_context_new(NULL);
790 g_option_context_add_main_entries(context, options, NULL);
792 if (g_option_context_parse(context, argc, argv, &error) == FALSE) {
794 g_printerr("%s\n", error->message);
797 g_printerr("An unknown error occurred\n");
801 g_option_context_free(context);
803 if (option_version == TRUE) {
804 g_print("%s\n", VERSION);
808 main_loop = g_main_loop_new(NULL, FALSE);
823 g_main_loop_unref(main_loop);
827 signal = setup_signalfd();
829 g_idle_add(start_tester, NULL);
830 g_main_loop_run(main_loop);
832 g_source_remove(signal);
834 g_main_loop_unref(main_loop);
836 ret = tester_summarize();
838 g_list_free_full(test_list, test_destroy);
840 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;