2 Unix SMB/CIFS implementation.
4 Copyright (C) Jelmer Vernooij 2006
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 2 of the License, or
9 (at your option) any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "system/dir.h"
23 #include "system/network.h"
24 #include "system/filesys.h"
25 #include "torture/ui.h"
26 #include "torture/torture.h"
27 #include "torture/proto.h"
29 struct torture_suite
*torture_subunit_suite_create(TALLOC_CTX
*mem_ctx
,
32 struct torture_suite
*suite
= talloc_zero(mem_ctx
, struct torture_suite
);
34 suite
->path
= talloc_strdup(suite
, path
);
35 suite
->name
= talloc_strdup(suite
, strrchr(path
, '/')?strrchr(path
, '/')+1:
37 suite
->description
= talloc_asprintf(suite
, "Subunit test %s", suite
->name
);
42 bool torture_subunit_load_testsuites(const char *directory
, bool recursive
,
43 struct torture_suite
*parent
)
51 parent
= torture_root
;
53 dir
= opendir(directory
);
57 while((entry
= readdir(dir
))) {
58 struct torture_suite
*child
;
59 if (entry
->d_name
[0] == '.')
62 filename
= talloc_asprintf(NULL
, "%s/%s", directory
, entry
->d_name
);
64 if (!recursive
&& directory_exist(filename
)) {
65 talloc_free(filename
);
69 if (directory_exist(filename
)) {
70 child
= torture_find_suite(parent
, entry
->d_name
);
71 exists
= (child
!= NULL
);
73 child
= torture_suite_create(parent
, entry
->d_name
);
74 torture_subunit_load_testsuites(filename
, true, child
);
76 child
= torture_subunit_suite_create(parent
, filename
);
81 torture_suite_add_suite(parent
, child
);
84 talloc_free(filename
);
92 static pid_t
piped_child(char* const command
[], int *f_stdout
, int *f_stderr
)
95 int sock_out
[2], sock_err
[2];
97 if (pipe(sock_out
) == -1) {
98 DEBUG(0, ("socketpair: %s", strerror(errno
)));
102 if (pipe(sock_err
) == -1) {
103 DEBUG(0, ("socketpair: %s", strerror(errno
)));
107 *f_stdout
= sock_out
[0];
108 *f_stderr
= sock_err
[0];
113 DEBUG(0, ("fork: %s", strerror(errno
)));
124 open("/dev/null", O_RDONLY
);
125 dup2(sock_out
[1], 1);
126 dup2(sock_err
[1], 2);
127 execvp(command
[0], command
);
137 enum subunit_field
{ SUBUNIT_TEST
, SUBUNIT_SUCCESS
, SUBUNIT_FAILURE
,
140 static void run_subunit_message(struct torture_context
*context
,
141 enum subunit_field field
,
145 struct torture_test test
;
152 test
.description
= comment
;
153 torture_ui_test_start(context
, NULL
, &test
);
155 case SUBUNIT_FAILURE
:
156 context
->active_test
= &test
;
157 torture_ui_test_result(context
, TORTURE_FAIL
, comment
);
158 context
->active_test
= NULL
;
160 case SUBUNIT_SUCCESS
:
161 context
->active_test
= &test
;
162 torture_ui_test_result(context
, TORTURE_OK
, comment
);
163 context
->active_test
= NULL
;
166 context
->active_test
= &test
;
167 torture_ui_test_result(context
, TORTURE_SKIP
, comment
);
168 context
->active_test
= NULL
;
173 bool torture_subunit_run_suite(struct torture_context
*context
,
174 struct torture_suite
*suite
)
176 static char *command
[2];
181 char *comment
= NULL
;
183 enum subunit_field lastfield
;
189 command
[0] = talloc_strdup(context
, suite
->path
);
192 pid
= piped_child(command
, &fd_out
, &fd_err
);
202 FD_SET(fd_out
, &fds
);
203 FD_SET(fd_err
, &fds
);
205 if (select(MAX(fd_out
,fd_err
)+1, &fds
, NULL
, NULL
, NULL
) <= 0) break;
207 if (FD_ISSET(fd_err
, &fds
)) {
208 size
= read(fd_err
, buffer
+offset
, sizeof(buffer
) - (offset
+1));
209 if (size
<= 0) break;
210 write(2, buffer
+offset
, size
);
214 if (!FD_ISSET(fd_out
, &fds
)) continue;
216 size
= read(fd_out
, buffer
+offset
, sizeof(buffer
) - (offset
+1));
218 if (size
<= 0) break;
220 buffer
[offset
+size
] = '\0';
222 write(1, buffer
+offset
, size
);
224 for (p
= buffer
; p
; p
= eol
+1) {
225 eol
= strchr(p
, '\n');
231 if (comment
!= NULL
&& strcmp(p
, "]") == 0) {
232 run_subunit_message(context
, lastfield
, name
, comment
);
233 talloc_free(name
); name
= NULL
;
234 talloc_free(comment
); comment
= NULL
;
235 } else if (comment
!= NULL
) {
236 comment
= talloc_append_string(context
, comment
, p
);
240 torture_comment(context
, "Invalid line `%s'\n", p
);
245 if (!strcmp(p
, "test")) {
246 lastfield
= SUBUNIT_TEST
;
247 } else if (!strcmp(p
, "failure")) {
248 lastfield
= SUBUNIT_FAILURE
;
249 } else if (!strcmp(p
, "success")) {
250 lastfield
= SUBUNIT_SUCCESS
;
251 } else if (!strcmp(p
, "skip")) {
252 lastfield
= SUBUNIT_SKIP
;
254 torture_comment(context
, "Invalid subunit field `%s'\n", p
);
260 name
= talloc_strdup(context
, p
+1);
265 comment
= talloc_strdup(context
, "");
267 run_subunit_message(context
, lastfield
, name
, NULL
);
274 offset
+= size
-(p
-buffer
);
275 memcpy(buffer
, p
, offset
);
278 if (waitpid(pid
, &status
, 0) == -1) {
279 torture_result(context
, TORTURE_ERROR
, "waitpid(%d) failed\n", pid
);
283 if (WEXITSTATUS(status
) != 0) {
284 torture_result(context
, TORTURE_ERROR
, "failed with status %d\n", WEXITSTATUS(status
));
289 torture_result(context
, TORTURE_ERROR
, "Interrupted during %s\n", name
);