2 * Copyright (C) 2013 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * 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.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #undef NDEBUG /* Keep test strong even for nbdkit built without assertions */
47 #include <sys/types.h>
49 #ifdef HAVE_SYS_WAIT_H
57 /* 'test_start_nbdkit' below makes assumptions about the format of
60 #define TEST_NBDKIT_TEMPLATE "/tmp/nbdkitXXXXXX"
62 char tmpdir
[ 17 + 1]; /* template, NUL */
63 char sockpath
[ 17 + 5 + 1]; /* template, "/sock", NUL */
64 char unixsockpath
[5 + 17 + 5 + 1]; /* "unix:", template, "/sock", NUL */
65 char pidpath
[ 17 + 4 + 1]; /* template, "/pid", NUL */
67 struct test_nbdkit
*next
;
69 const struct test_nbdkit
template = {
70 .tmpdir
= TEST_NBDKIT_TEMPLATE
,
71 .sockpath
= TEST_NBDKIT_TEMPLATE
"/sock",
72 .unixsockpath
= "unix:" TEST_NBDKIT_TEMPLATE
"/sock",
73 .pidpath
= TEST_NBDKIT_TEMPLATE
"/pid",
76 static struct test_nbdkit
*head
;
79 const char *sock
= NULL
;
80 const char *server
[2] = { NULL
, NULL
};
86 struct test_nbdkit
*next
;
91 assert (!pid
|| pid
== head
->pid
);
94 /* This improves the stability when running the tests under
95 * valgrind. We have to wait a little for nbdkit close
98 s
= getenv ("NBDKIT_VALGRIND");
99 if (s
&& strcmp (s
, "1") == 0)
102 kill (head
->pid
, SIGTERM
);
104 /* Check the status of nbdkit is normal on exit. */
105 if (waitpid (head
->pid
, &status
, 0) == -1) {
107 _exit (EXIT_FAILURE
);
109 if (WIFEXITED (status
) && WEXITSTATUS (status
) != 0) {
110 _exit (WEXITSTATUS (status
));
112 if (WIFSIGNALED (status
)) {
113 /* Note that nbdkit is supposed to catch the signal we send and
114 * exit cleanly, so the following shouldn't happen.
116 fprintf (stderr
, "nbdkit terminated by signal %d\n", WTERMSIG (status
));
117 _exit (EXIT_FAILURE
);
119 if (WIFSTOPPED (status
)) {
120 fprintf (stderr
, "nbdkit stopped by signal %d\n", WSTOPSIG (status
));
121 _exit (EXIT_FAILURE
);
125 unlink (head
->pidpath
);
126 unlink (head
->sockpath
);
127 rmdir (head
->tmpdir
);
136 test_start_nbdkit (const char *arg
, ...)
139 struct test_nbdkit
*kit
= malloc (sizeof *kit
);
147 if (mkdtemp (kit
->tmpdir
) == NULL
) {
152 len
= strlen (kit
->tmpdir
);
153 memcpy (kit
->sockpath
, kit
->tmpdir
, len
);
154 memcpy (kit
->unixsockpath
+5, kit
->tmpdir
, len
);
155 memcpy (kit
->pidpath
, kit
->tmpdir
, len
);
158 if (kit
->pid
== 0) { /* Child (nbdkit). */
161 const char *argv
[MAX_ARGS
+1];
166 argv
[2] = kit
->sockpath
;
168 argv
[4] = kit
->pidpath
;
174 va_start (args
, arg
);
175 while ((p
= va_arg (args
, const char *)) != NULL
) {
184 execvp ("nbdkit", (char **) argv
);
185 perror ("exec: nbdkit");
186 _exit (EXIT_FAILURE
);
189 /* Ensure nbdkit is killed and temporary files are deleted when the
190 * main program exits.
198 sock
= kit
->sockpath
;
199 server
[0] = kit
->unixsockpath
;
201 /* Wait for the pidfile to turn up, which indicates that nbdkit has
202 * started up successfully and is ready to serve requests. However
203 * if 'pid' exits in this time it indicates a failure to start up.
204 * Also there is a timeout in case nbdkit hangs.
206 for (i
= 0; i
< NBDKIT_START_TIMEOUT
; ++i
) {
207 if (waitpid (pid
, NULL
, WNOHANG
) == pid
)
210 if (kill (pid
, 0) == -1) {
211 if (errno
== ESRCH
) {
214 "%s FAILED: nbdkit exited before starting to serve files\n",
222 exists
= access (kit
->pidpath
, F_OK
) == 0;
231 "%s: nbdkit did not create pidfile %s within "
232 "%d seconds, continuing anyway\n",
233 program_name
, kit
->pidpath
, NBDKIT_START_TIMEOUT
);
241 /* All of the above code will require a lot of porting work for
242 * Windows. At the moment the test gets skipped.
245 test_start_nbdkit (const char *arg
, ...)
247 fprintf (stderr
, "%s: test skipped because not ported to Windows.\n",