mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
tftpd: Check the server status after each test.
* In the setup phase, wait for the server to start (or fail to start) before proceeding with the test. This makes it possible to write test cases that don't expect a response from the server without ending up in a race over the server PID file. * After running each test, wait up to 30 seconds for the server to exit and check that the exit status matches what the test case says to expect (usually 0). * We still kill and collect the server in the cleanup phase, in case the test ended early. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D44956
This commit is contained in:
parent
7ab7ecfcfe
commit
83a6e984ac
|
@ -208,11 +208,14 @@ ATF_TC_HEAD(name ## _v4, tc) \
|
||||||
} \
|
} \
|
||||||
ATF_TC_BODY(name ## _v4, tc) \
|
ATF_TC_BODY(name ## _v4, tc) \
|
||||||
{ \
|
{ \
|
||||||
|
int exitcode = 0; \
|
||||||
__VA_ARGS__; \
|
__VA_ARGS__; \
|
||||||
protocol = AF_INET; \
|
protocol = AF_INET; \
|
||||||
s = setup(&addr, __COUNTER__); \
|
s = setup(&addr, __COUNTER__); \
|
||||||
name ## _body(); \
|
name ## _body(); \
|
||||||
close(s); \
|
close(s); \
|
||||||
|
if (exitcode >= 0) \
|
||||||
|
check_server(exitcode); \
|
||||||
} \
|
} \
|
||||||
ATF_TC_CLEANUP(name ## _v4, tc) \
|
ATF_TC_CLEANUP(name ## _v4, tc) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -225,11 +228,14 @@ ATF_TC_HEAD(name ## _v6, tc) \
|
||||||
} \
|
} \
|
||||||
ATF_TC_BODY(name ## _v6, tc) \
|
ATF_TC_BODY(name ## _v6, tc) \
|
||||||
{ \
|
{ \
|
||||||
|
int exitcode = 0; \
|
||||||
__VA_ARGS__; \
|
__VA_ARGS__; \
|
||||||
protocol = AF_INET6; \
|
protocol = AF_INET6; \
|
||||||
s = setup(&addr, __COUNTER__); \
|
s = setup(&addr, __COUNTER__); \
|
||||||
name ## _body(); \
|
name ## _body(); \
|
||||||
close(s); \
|
close(s); \
|
||||||
|
if (exitcode >= 0) \
|
||||||
|
check_server(exitcode); \
|
||||||
} \
|
} \
|
||||||
ATF_TC_CLEANUP(name ## _v6, tc) \
|
ATF_TC_CLEANUP(name ## _v6, tc) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -244,6 +250,33 @@ name ## _body(void)
|
||||||
ATF_TP_ADD_TC(tp, name ## _v6); \
|
ATF_TP_ADD_TC(tp, name ## _v6); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static void
|
||||||
|
sigalrm(int signo __unused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that server exits with specific exit code */
|
||||||
|
static void
|
||||||
|
check_server(int exitcode)
|
||||||
|
{
|
||||||
|
struct sigaction sa = { .sa_handler = sigalrm };
|
||||||
|
struct itimerval it = { .it_value = { .tv_sec = 30 } };
|
||||||
|
FILE *f;
|
||||||
|
pid_t pid;
|
||||||
|
int wstatus;
|
||||||
|
|
||||||
|
f = fopen(pidfile, "r");
|
||||||
|
ATF_REQUIRE(f != NULL);
|
||||||
|
ATF_REQUIRE_INTEQ(1, fscanf(f, "%d", &pid));
|
||||||
|
ATF_CHECK_INTEQ(0, fclose(f));
|
||||||
|
ATF_REQUIRE_INTEQ(0, sigaction(SIGALRM, &sa, NULL));
|
||||||
|
ATF_REQUIRE_EQ(0, setitimer(ITIMER_REAL, &it, NULL));
|
||||||
|
ATF_REQUIRE_EQ(pid, waitpid(pid, &wstatus, 0));
|
||||||
|
ATF_CHECK(WIFEXITED(wstatus));
|
||||||
|
ATF_CHECK_INTEQ(exitcode, WEXITSTATUS(wstatus));
|
||||||
|
unlink(pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
/* Standard cleanup used by all testcases */
|
/* Standard cleanup used by all testcases */
|
||||||
static void
|
static void
|
||||||
cleanup(void)
|
cleanup(void)
|
||||||
|
@ -254,12 +287,12 @@ cleanup(void)
|
||||||
f = fopen(pidfile, "r");
|
f = fopen(pidfile, "r");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return;
|
return;
|
||||||
|
unlink(pidfile);
|
||||||
if (fscanf(f, "%d", &pid) == 1) {
|
if (fscanf(f, "%d", &pid) == 1) {
|
||||||
kill(pid, SIGTERM);
|
kill(pid, SIGTERM);
|
||||||
waitpid(pid, NULL, 0);
|
waitpid(pid, NULL, 0);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
unlink(pidfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assert that two binary buffers are identical */
|
/* Assert that two binary buffers are identical */
|
||||||
|
@ -299,6 +332,9 @@ setup(struct sockaddr_storage *to, uint16_t idx)
|
||||||
struct pidfh *pfh;
|
struct pidfh *pfh;
|
||||||
uint16_t port = BASEPORT + idx;
|
uint16_t port = BASEPORT + idx;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
int pd[2];
|
||||||
|
|
||||||
|
ATF_REQUIRE_EQ(0, pipe2(pd, O_CLOEXEC));
|
||||||
|
|
||||||
if (protocol == PF_INET) {
|
if (protocol == PF_INET) {
|
||||||
len = sizeof(addr4);
|
len = sizeof(addr4);
|
||||||
|
@ -358,6 +394,10 @@ setup(struct sockaddr_storage *to, uint16_t idx)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* In parent */
|
/* In parent */
|
||||||
|
ATF_REQUIRE_INTEQ(0, close(pd[1]));
|
||||||
|
/* block until other end is closed on exec() or exit() */
|
||||||
|
ATF_REQUIRE_INTEQ(0, read(pd[0], &pd[1], sizeof(pd[1])));
|
||||||
|
ATF_REQUIRE_INTEQ(0, close(pd[0]));
|
||||||
bzero(to, sizeof(*to));
|
bzero(to, sizeof(*to));
|
||||||
if (protocol == PF_INET) {
|
if (protocol == PF_INET) {
|
||||||
struct sockaddr_in *to4 = (struct sockaddr_in *)to;
|
struct sockaddr_in *to4 = (struct sockaddr_in *)to;
|
||||||
|
@ -374,7 +414,7 @@ setup(struct sockaddr_storage *to, uint16_t idx)
|
||||||
to6->sin6_addr = loopback;
|
to6->sin6_addr = loopback;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(server_s);
|
ATF_REQUIRE_INTEQ(0, close(server_s));
|
||||||
ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0);
|
ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue