The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=83a6e984ac01657819418746f722163367ec30db

commit 83a6e984ac01657819418746f722163367ec30db
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2024-04-25 18:35:24 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2024-04-25 18:36:13 +0000

    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
---
 libexec/tftpd/tests/functional.c | 44 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/libexec/tftpd/tests/functional.c b/libexec/tftpd/tests/functional.c
index bbe4f3782192..3b70962854ba 100644
--- a/libexec/tftpd/tests/functional.c
+++ b/libexec/tftpd/tests/functional.c
@@ -208,11 +208,14 @@ ATF_TC_HEAD(name ## _v4, tc)                              
                \
 }                                                                      \
 ATF_TC_BODY(name ## _v4, tc)                                           \
 {                                                                      \
+       int exitcode = 0;                                               \
        __VA_ARGS__;                                                    \
        protocol = AF_INET;                                             \
        s = setup(&addr, __COUNTER__);                                  \
        name ## _body();                                                \
        close(s);                                                       \
+       if (exitcode >= 0)                                              \
+               check_server(exitcode);                                 \
 }                                                                      \
 ATF_TC_CLEANUP(name ## _v4, tc)                                                
\
 {                                                                      \
@@ -225,11 +228,14 @@ ATF_TC_HEAD(name ## _v6, tc)                              
                \
 }                                                                      \
 ATF_TC_BODY(name ## _v6, tc)                                           \
 {                                                                      \
+       int exitcode = 0;                                               \
        __VA_ARGS__;                                                    \
        protocol = AF_INET6;                                            \
        s = setup(&addr, __COUNTER__);                                  \
        name ## _body();                                                \
        close(s);                                                       \
+       if (exitcode >= 0)                                              \
+               check_server(exitcode);                                 \
 }                                                                      \
 ATF_TC_CLEANUP(name ## _v6, tc)                                                
\
 {                                                                      \
@@ -244,6 +250,33 @@ name ## _body(void)
        ATF_TP_ADD_TC(tp, name ## _v6);                                 \
 } 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 */
 static void
 cleanup(void)
@@ -254,12 +287,12 @@ cleanup(void)
        f = fopen(pidfile, "r");
        if (f == NULL)
                return;
+       unlink(pidfile);
        if (fscanf(f, "%d", &pid) == 1) {
                kill(pid, SIGTERM);
                waitpid(pid, NULL, 0);
        }
        fclose(f);
-       unlink(pidfile);
 }
 
 /* Assert that two binary buffers are identical */
@@ -299,6 +332,9 @@ setup(struct sockaddr_storage *to, uint16_t idx)
        struct pidfh *pfh;
        uint16_t port = BASEPORT + idx;
        socklen_t len;
+       int pd[2];
+
+       ATF_REQUIRE_EQ(0, pipe2(pd, O_CLOEXEC));
 
        if (protocol == PF_INET) {
                len = sizeof(addr4);
@@ -358,6 +394,10 @@ setup(struct sockaddr_storage *to, uint16_t idx)
                break;
        default:
                /* 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));
                if (protocol == PF_INET) {
                        struct sockaddr_in *to4 = (struct sockaddr_in *)to;
@@ -374,7 +414,7 @@ setup(struct sockaddr_storage *to, uint16_t idx)
                        to6->sin6_addr = loopback;
                }
 
-               close(server_s);
+               ATF_REQUIRE_INTEQ(0, close(server_s));
                ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0);
                break;
        }

Reply via email to