2 * Copyright (c) 2013 Vojtech Horky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Test-anything-protocol reporting routines.
34 #include "../internal.h"
38 #define _REALLY_WANT_STRING_H
41 #pragma warning(push, 0)
47 /** Counter of all run tests. */
48 static int test_counter
;
50 /** Counter of all failures. */
51 static int failed_test_counter
;
53 /** Counter for tests in a current suite. */
54 static int tests_in_suite
;
56 /** Counter of failed tests in current suite. */
57 static int failed_tests_in_suite
;
59 /** Comma-separated list of failed test names. */
60 static char *failed_test_names
;
62 /** Initialize the TAP output.
64 * @param all_items Start of the list with all items.
66 static void tap_init(pcut_item_t
*all_items
) {
67 int tests_total
= pcut_count_tests(all_items
);
69 failed_test_counter
= 0;
71 printf("1..%d\n", tests_total
);
74 /** Report that a suite was started.
76 * @param suite Suite that just started.
78 static void tap_suite_start(pcut_item_t
*suite
) {
80 failed_tests_in_suite
= 0;
82 printf("#> Starting suite %s.\n", suite
->name
);
85 /** Report that a suite was completed.
87 * @param suite Suite that just ended.
89 static void tap_suite_done(pcut_item_t
*suite
) {
90 if (failed_tests_in_suite
== 0) {
91 printf("#> Finished suite %s (passed).\n",
94 printf("#> Finished suite %s (failed %d of %d).\n",
95 suite
->name
, failed_tests_in_suite
, tests_in_suite
);
99 /** Report that a test was started.
101 * We do nothing - all handling is done after the test completes.
103 * @param test Test that is started.
105 static void tap_test_start(pcut_item_t
*test
) {
112 /** Print the buffer, prefix new line with a given string.
114 * @param message Message to print.
115 * @param prefix Prefix for each new line, such as comment character.
117 static void print_by_lines(const char *message
, const char *prefix
) {
118 char *next_line_start
;
119 if ((message
== NULL
) || (message
[0] == 0)) {
122 next_line_start
= pcut_str_find_char(message
, '\n');
123 while (next_line_start
!= NULL
) {
124 next_line_start
[0] = 0;
125 printf("%s%s\n", prefix
, message
);
126 message
= next_line_start
+ 1;
127 next_line_start
= pcut_str_find_char(message
, '\n');
129 if (message
[0] != 0) {
130 printf("%s%s\n", prefix
, message
);
134 /** Report a completed test.
136 * @param test Test that just finished.
137 * @param outcome Outcome of the test.
138 * @param error_message Buffer with error message.
139 * @param teardown_error_message Buffer with error message from a tear-down function.
140 * @param extra_output Extra output from the test (stdout).
142 static void tap_test_done(pcut_item_t
*test
, int outcome
,
143 const char *error_message
, const char *teardown_error_message
,
144 const char *extra_output
) {
145 const char *test_name
= test
->name
;
146 const char *status_str
= NULL
;
147 const char *fail_error_str
= NULL
;
149 if (outcome
!= PCUT_OUTCOME_PASS
) {
150 failed_tests_in_suite
++;
151 failed_test_counter
++;
155 case PCUT_OUTCOME_PASS
:
159 case PCUT_OUTCOME_FAIL
:
160 status_str
= "not ok";
161 fail_error_str
= " failed";
164 status_str
= "not ok";
165 fail_error_str
= " aborted";
168 printf("%s %d %s%s\n", status_str
, test_counter
, test_name
, fail_error_str
);
170 print_by_lines(error_message
, "# error: ");
171 print_by_lines(teardown_error_message
, "# error: ");
173 print_by_lines(extra_output
, "# stdio: ");
175 if (outcome
!= PCUT_OUTCOME_PASS
) {
176 if (failed_test_names
== NULL
) {
177 failed_test_names
= strdup(test_name
);
180 if (asprintf(&fs
, "%s, %s",
181 failed_test_names
, test_name
) >= 0) {
182 free(failed_test_names
);
183 failed_test_names
= fs
;
189 /** Report testing done. */
190 static void tap_done(void) {
191 if (failed_test_counter
== 0) {
192 printf("#> Done: all tests passed.\n");
194 printf("#> Done: %d of %d tests failed.\n", failed_test_counter
, test_counter
);
195 printf("#> Failed tests: %s\n", failed_test_names
);
200 pcut_report_ops_t pcut_report_tap
= {
202 tap_suite_start
, tap_suite_done
,
203 tap_test_start
, tap_test_done