diff options
author | alfred <alfred@FreeBSD.org> | 2002-08-15 06:34:37 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2002-08-15 06:34:37 +0000 |
commit | 209edd14cb10d2085f777505ae39fa32893784b7 (patch) | |
tree | 7e7352d791a2def30b0dde36bb8addfd5e55d73b /tools/regression/sysvmsg | |
parent | 3d029bfb1348d5acab80d0b61a0c0845dfba8a7c (diff) | |
download | FreeBSD-src-209edd14cb10d2085f777505ae39fa32893784b7.zip FreeBSD-src-209edd14cb10d2085f777505ae39fa32893784b7.tar.gz |
Add regression tests for sysvipc.
Submitted by: Hiten Pandya <hiten@uk.FreeBSD.org>
Obtained from: NetBSD
Diffstat (limited to 'tools/regression/sysvmsg')
-rw-r--r-- | tools/regression/sysvmsg/Makefile | 15 | ||||
-rw-r--r-- | tools/regression/sysvmsg/README | 13 | ||||
-rw-r--r-- | tools/regression/sysvmsg/msgtest.c | 347 |
3 files changed, 375 insertions, 0 deletions
diff --git a/tools/regression/sysvmsg/Makefile b/tools/regression/sysvmsg/Makefile new file mode 100644 index 0000000..45f7b72 --- /dev/null +++ b/tools/regression/sysvmsg/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ +# SysV Message Queue Regression Utility +# Obtained from: $NetBSD: Makefile,v 1.3 2002/03/05 21:56:59 thorpej Exp $ + +PROG= msgtest +NOMAN= yes + +regress: + @if ./msgtest ./msgtest; then \ + echo "PASS"; \ + else \ + echo "FAIL"; \ + fi + +.include <bsd.prog.mk> diff --git a/tools/regression/sysvmsg/README b/tools/regression/sysvmsg/README new file mode 100644 index 0000000..f115b99 --- /dev/null +++ b/tools/regression/sysvmsg/README @@ -0,0 +1,13 @@ +$FreeBSD$ + +SysV IPC Message Queue Regression Utility. + +This regression utility will test the SysV Message Queue facility +in FreeBSD. You can start the test by running ``make regress'', after +running ``make''. + +Obtained from: The NetBSD Foundation. +Date of port: 13 August 2002 + + -- Hiten Pandya + -- hiten@uk.FreeBSD.org diff --git a/tools/regression/sysvmsg/msgtest.c b/tools/regression/sysvmsg/msgtest.c new file mode 100644 index 0000000..37981d9 --- /dev/null +++ b/tools/regression/sysvmsg/msgtest.c @@ -0,0 +1,347 @@ +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Obtained from: $NetBSD: msgtest.c,v 1.7 2002/07/20 08:36:25 grant Exp $ + * $FreeBSD$ + */ + +/* + * Test the SVID-compatible Message Queue facility. + */ + +#include <sys/param.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +void print_msqid_ds (struct msqid_ds *, mode_t); +void sigsys_handler(int); +void sigchld_handler (int); +void cleanup (void); +void receiver (void); +void usage (void); + +#define MESSAGE_TEXT_LEN 255 + +/* + * Define it as test_mymsg because we already have struct mymsg and we dont + * want to conflict with it. Also, regression fails when the default mymsg + * struct is used, because mtext[] array is '1', so the passed string cannot + * be processed. + */ +struct test_mymsg { + long mtype; + char mtext[MESSAGE_TEXT_LEN]; +}; + +const char *m1_str = "California is overrated."; +const char *m2_str = "The quick brown fox jumped over the lazy dog."; + +#define MTYPE_1 1 +#define MTYPE_1_ACK 2 + +#define MTYPE_2 3 +#define MTYPE_2_ACK 4 + +int sender_msqid = -1; +pid_t child_pid; + +key_t msgkey; + +int +main(int argc, char *argv[]) +{ + struct sigaction sa; + struct msqid_ds m_ds; + struct test_mymsg m; + sigset_t sigmask; + + if (argc != 2) + usage(); + + /* + * Install a SIGSYS handler so that we can exit gracefully if + * System V Message Queue support isn't in the kernel. + */ + sa.sa_handler = sigsys_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGSYS, &sa, NULL) == -1) + err(1, "sigaction SIGSYS"); + + /* + * Install and SIGCHLD handler to deal with all possible exit + * conditions of the receiver. + */ + sa.sa_handler = sigchld_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGCHLD, &sa, NULL) == -1) + err(1, "sigaction SIGCHLD"); + + msgkey = ftok(argv[1], 4160); + + /* + * Initialize child_pid to ourselves to that the cleanup function + * works before we create the receiver. + */ + child_pid = getpid(); + + /* + * Make sure that when the sender exits, the message queue is + * removed. + */ + if (atexit(cleanup) == -1) + err(1, "atexit"); + + if ((sender_msqid = msgget(msgkey, IPC_CREAT | 0640)) == -1) + err(1, "msgget"); + + if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1) + err(1, "msgctl IPC_STAT"); + + print_msqid_ds(&m_ds, 0640); + + m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600; + + if (msgctl(sender_msqid, IPC_SET, &m_ds) == -1) + err(1, "msgctl IPC_SET"); + + bzero(&m_ds, sizeof m_ds); + + if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1) + err(1, "msgctl IPC_STAT"); + + if ((m_ds.msg_perm.mode & 0777) != 0600) + err(1, "IPC_SET of mode didn't hold"); + + print_msqid_ds(&m_ds, 0600); + + switch ((child_pid = fork())) { + case -1: + err(1, "fork"); + /* NOTREACHED */ + + case 0: + receiver(); + break; + + default: + break; + } + + /* + * Send the first message to the receiver and wait for the ACK. + */ + m.mtype = MTYPE_1; + strcpy(m.mtext, m1_str); + if (msgsnd(sender_msqid, &m, sizeof(m), 0) == -1) + err(1, "sender: msgsnd 1"); + + if (msgrcv(sender_msqid, &m, sizeof(m), MTYPE_1_ACK, 0) != sizeof(m)) + err(1, "sender: msgrcv 1 ack"); + + print_msqid_ds(&m_ds, 0600); + + /* + * Send the second message to the receiver and wait for the ACK. + */ + m.mtype = MTYPE_2; + strcpy(m.mtext, m2_str); + if (msgsnd(sender_msqid, &m, sizeof(m), 0) == -1) + err(1, "sender: msgsnd 2"); + + if (msgrcv(sender_msqid, &m, sizeof(m), MTYPE_2_ACK, 0) != sizeof(m)) + err(1, "sender: msgrcv 2 ack"); + + /* + * Suspend forever; when we get SIGCHLD, the handler will exit. + */ + sigemptyset(&sigmask); + (void) sigsuspend(&sigmask); + + /* + * ...and any other signal is an unexpected error. + */ + errx(1, "sender: received unexpected signal"); +} + +void +sigsys_handler(int signo) +{ + + errx(1, "System V Message Queue support is not present in the kernel"); +} + +void +sigchld_handler(int signo) +{ + struct msqid_ds m_ds; + int cstatus; + + /* + * Reap the child; if it exited successfully, then the test passed! + */ + if (waitpid(child_pid, &cstatus, 0) != child_pid) + err(1, "waitpid"); + + if (WIFEXITED(cstatus) == 0) + errx(1, "receiver exited abnormally"); + + if (WEXITSTATUS(cstatus) != 0) + errx(1, "receiver exited with status %d", + WEXITSTATUS(cstatus)); + + /* + * If we get here, the child has exited normally, and thus + * we should exit normally too. First, tho, we print out + * the final stats for the message queue. + */ + + if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1) + err(1, "msgctl IPC_STAT"); + + print_msqid_ds(&m_ds, 0600); + + exit(0); +} + +void +cleanup() +{ + + /* + * If we're the sender, and it exists, remove the message queue. + */ + if (child_pid != 0 && sender_msqid != -1) { + if (msgctl(sender_msqid, IPC_RMID, NULL) == -1) + warn("msgctl IPC_RMID"); + } +} + +void +print_msqid_ds(struct msqid_ds *mp, mode_t mode) +{ + uid_t uid = geteuid(); + gid_t gid = getegid(); + + printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", + mp->msg_perm.uid, mp->msg_perm.gid, + mp->msg_perm.cuid, mp->msg_perm.cgid, + mp->msg_perm.mode & 0777); + + printf("qnum %lu, qbytes %lu, lspid %d, lrpid %d\n", + mp->msg_qnum, (u_long)mp->msg_qbytes, mp->msg_lspid, + mp->msg_lrpid); + + printf("stime: %s", ctime(&mp->msg_stime)); + printf("rtime: %s", ctime(&mp->msg_rtime)); + printf("ctime: %s", ctime(&mp->msg_ctime)); + + /* + * Sanity check a few things. + */ + + if (mp->msg_perm.uid != uid || mp->msg_perm.cuid != uid) + errx(1, "uid mismatch"); + + if (mp->msg_perm.gid != gid || mp->msg_perm.cgid != gid) + errx(1, "gid mismatch"); + + if ((mp->msg_perm.mode & 0777) != mode) + errx(1, "mode mismatch"); +} + +void +usage() +{ + + fprintf(stderr, "usage: %s keypath\n", getprogname()); + exit(1); +} + +void +receiver() +{ + struct test_mymsg m; + int msqid; + + if ((msqid = msgget(msgkey, 0)) == -1) + err(1, "receiver: msgget"); + + /* + * Receive the first message, print it, and send an ACK. + */ + + if (msgrcv(msqid, &m, sizeof(m), MTYPE_1, 0) != sizeof(m)) + err(1, "receiver: msgrcv 1"); + + printf("%s\n", m.mtext); + if (strcmp(m.mtext, m1_str) != 0) + err(1, "receiver: message 1 data isn't correct"); + + m.mtype = MTYPE_1_ACK; + + if (msgsnd(msqid, &m, sizeof(m), 0) == -1) + err(1, "receiver: msgsnd ack 1"); + + /* + * Receive the second message, print it, and send an ACK. + */ + + if (msgrcv(msqid, &m, sizeof(m), MTYPE_2, 0) != sizeof(m)) + err(1, "receiver: msgrcv 2"); + + printf("%s\n", m.mtext); + if (strcmp(m.mtext, m2_str) != 0) + err(1, "receiver: message 2 data isn't correct"); + + m.mtype = MTYPE_2_ACK; + + if (msgsnd(msqid, &m, sizeof(m), 0) == -1) + err(1, "receiver: msgsnd ack 2"); + + exit(0); +} |