Inline outputting of subunit in libtorture.
[gd/samba-autobuild/.git] / lib / torture / subunit.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "lib/torture/torture.h"
22
23 static void subunit_send_event(char const * const event,
24                 char const * const name,
25                 char const * const details)
26 {
27         if (NULL == details) {
28                 printf("%s: %s\n", event, name);
29         } else {
30                 printf("%s: %s [\n", event, name);
31                 printf("%s", details);
32                 if (details[strlen(details) - 1] != '\n')
33                         puts("");
34                 puts("]");
35         }
36         fflush(stdout);
37 }
38
39 static void torture_subunit_suite_start(struct torture_context *ctx,
40                                 struct torture_suite *suite)
41 {
42 }
43
44 static char *torture_subunit_test_name(struct torture_context *ctx,
45                                    struct torture_tcase *tcase,
46                                    struct torture_test *test)
47 {
48         if (!strcmp(tcase->name, test->name)) {
49                 return talloc_strdup(ctx, test->name);
50         } else {
51                 return talloc_asprintf(ctx, "%s.%s", tcase->name, test->name);
52         }
53 }
54
55 static void torture_subunit_report_time(struct torture_context *tctx)
56 {
57         struct timespec tp;
58         struct tm *tmp;
59         char timestr[200];
60         if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
61                 perror("clock_gettime");
62                 return;
63         }
64
65         tmp = localtime(&tp.tv_sec);
66         if (!tmp) {
67                 perror("localtime");
68                 return;
69         }
70
71         if (strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tmp) <= 0) {
72                 perror("strftime");
73                 return;
74         }
75
76         printf("time: %s.%06ld\n", timestr, tp.tv_nsec / 1000);
77 }
78
79 static void torture_subunit_test_start(struct torture_context *context, 
80                                struct torture_tcase *tcase,
81                                struct torture_test *test)
82 {
83         char *fullname = torture_subunit_test_name(context, context->active_tcase, context->active_test);
84         subunit_send_event("test", fullname, NULL);
85         torture_subunit_report_time(context);
86         talloc_free(fullname);
87 }
88
89 static void torture_subunit_test_result(struct torture_context *context, 
90                                 enum torture_result res, const char *reason)
91 {
92         char *fullname = torture_subunit_test_name(context, context->active_tcase, context->active_test);
93         const char *result_str = "unknown";
94         torture_subunit_report_time(context);
95         switch (res) {
96         case TORTURE_OK:
97                 result_str = "success";
98                 break;
99         case TORTURE_FAIL:
100                 result_str = "failure";
101                 break;
102         case TORTURE_ERROR:
103                 result_str = "error";
104                 break;
105         case TORTURE_SKIP:
106                 result_str = "skip";
107                 break;
108         }
109         subunit_send_event(result_str, fullname, reason);
110         talloc_free(fullname);
111 }
112
113 static void torture_subunit_comment(struct torture_context *test,
114                             const char *comment)
115 {
116         fprintf(stderr, "%s", comment);
117 }
118
119 static void torture_subunit_warning(struct torture_context *test,
120                             const char *comment)
121 {
122         fprintf(stderr, "WARNING!: %s\n", comment);
123 }
124
125 static void torture_subunit_progress(struct torture_context *tctx, int offset, enum torture_progress_whence whence)
126 {
127         switch (whence) {
128         case TORTURE_PROGRESS_SET:
129                 printf("progress: %d\n", offset);
130                 break;
131         case TORTURE_PROGRESS_CUR:
132                 printf("progress: %+-d\n", offset);
133                 break;
134         case TORTURE_PROGRESS_POP:
135                 printf("progress: pop\n");
136                 break;
137         case TORTURE_PROGRESS_PUSH:
138                 printf("progress: push\n");
139                 break;
140         default:
141                 fprintf(stderr, "Invalid call to progress()\n");
142                 break;
143         }
144 }
145
146 const struct torture_ui_ops torture_subunit_ui_ops = {
147         .comment = torture_subunit_comment,
148         .warning = torture_subunit_warning,
149         .test_start = torture_subunit_test_start,
150         .test_result = torture_subunit_test_result,
151         .suite_start = torture_subunit_suite_start,
152         .progress = torture_subunit_progress,
153         .report_time = torture_subunit_report_time,
154 };