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
40 #include <sys/types.h>
48 /* 'test_start_nbdkit' below makes assumptions about the format of
51 #define TEST_NBDKIT_TEMPLATE "/tmp/nbdkitXXXXXX"
53 char tmpdir
[ 17 + 1]; /* template, NUL */
54 char sockpath
[ 17 + 5 + 1]; /* template, "/sock", NUL */
55 char unixsockpath
[5 + 17 + 5 + 1]; /* "unix:", template, "/sock", NUL */
56 char pidpath
[ 17 + 4 + 1]; /* template, "/pid", NUL */
58 struct test_nbdkit
*next
;
60 const struct test_nbdkit
template = {
61 .tmpdir
= TEST_NBDKIT_TEMPLATE
,
62 .sockpath
= TEST_NBDKIT_TEMPLATE
"/sock",
63 .unixsockpath
= "unix:" TEST_NBDKIT_TEMPLATE
"/sock",
64 .pidpath
= TEST_NBDKIT_TEMPLATE
"/pid",
67 static struct test_nbdkit
*head
;
70 const char *sock
= NULL
;
71 const char *server
[2] = { NULL
, NULL
};
77 struct test_nbdkit
*next
;
81 assert (!pid
|| pid
== head
->pid
);
83 kill (head
->pid
, SIGTERM
);
85 /* Check the status of nbdkit is normal on exit. */
86 if (waitpid (head
->pid
, &status
, 0) == -1) {
90 if (WIFEXITED (status
) && WEXITSTATUS (status
) != 0) {
91 _exit (WEXITSTATUS (status
));
93 if (WIFSIGNALED (status
)) {
94 /* Note that nbdkit is supposed to catch the signal we send and
95 * exit cleanly, so the following shouldn't happen.
97 fprintf (stderr
, "nbdkit terminated by signal %d\n", WTERMSIG (status
));
100 if (WIFSTOPPED (status
)) {
101 fprintf (stderr
, "nbdkit stopped by signal %d\n", WSTOPSIG (status
));
102 _exit (EXIT_FAILURE
);
106 unlink (head
->pidpath
);
107 unlink (head
->sockpath
);
108 rmdir (head
->tmpdir
);
117 test_start_nbdkit (const char *arg
, ...)
120 struct test_nbdkit
*kit
= malloc (sizeof *kit
);
127 if (mkdtemp (kit
->tmpdir
) == NULL
) {
132 len
= strlen (kit
->tmpdir
);
133 memcpy (kit
->sockpath
, kit
->tmpdir
, len
);
134 memcpy (kit
->unixsockpath
+5, kit
->tmpdir
, len
);
135 memcpy (kit
->pidpath
, kit
->tmpdir
, len
);
138 if (kit
->pid
== 0) { /* Child (nbdkit). */
141 const char *argv
[MAX_ARGS
+1];
146 argv
[2] = kit
->sockpath
;
148 argv
[4] = kit
->pidpath
;
154 va_start (args
, arg
);
155 while ((p
= va_arg (args
, const char *)) != NULL
) {
164 execvp ("nbdkit", (char **) argv
);
165 perror ("exec: nbdkit");
166 _exit (EXIT_FAILURE
);
169 /* Ensure nbdkit is killed and temporary files are deleted when the
170 * main program exits.
178 sock
= kit
->sockpath
;
179 server
[0] = kit
->unixsockpath
;
181 /* Wait for the pidfile to turn up, which indicates that nbdkit has
182 * started up successfully and is ready to serve requests. However
183 * if 'pid' exits in this time it indicates a failure to start up.
184 * Also there is a timeout in case nbdkit hangs.
186 for (i
= 0; i
< NBDKIT_START_TIMEOUT
; ++i
) {
187 if (waitpid (pid
, NULL
, WNOHANG
) == pid
)
190 if (kill (pid
, 0) == -1) {
191 if (errno
== ESRCH
) {
194 "%s FAILED: nbdkit exited before starting to serve files\n",
202 if (access (kit
->pidpath
, F_OK
) == 0)