Home | History | Annotate | Download | only in msgrcv
      1 /*
      2  * Copyright (c) 2014 Fujitsu Ltd.
      3  * Author: Xiaoguang Wang <wangxg.fnst (at) cn.fujitsu.com>
      4  *
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * You should have received a copy of the GNU General Public License along
     14  * with this program; if not, write the Free Software Foundation, Inc.,
     15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16  */
     17 
     18 /*
     19  * Description:
     20  *     Basic test for msgrcv(2) using MSG_EXCEPT, MSG_NOERROR
     21  */
     22 
     23 #define  _GNU_SOURCE
     24 #include <sys/wait.h>
     25 #include "test.h"
     26 #include "ipcmsg.h"
     27 
     28 
     29 #define MSGTYPE1	1
     30 #define MSGTYPE2	2
     31 #define MSG1	"message type1"
     32 #define MSG2	"message type2"
     33 
     34 static void wait4child(pid_t child, char *tst_flag);
     35 
     36 static void test_msg_except(void);
     37 static void test_msg_noerror(void);
     38 
     39 static void (*testfunc[])(void) = { test_msg_except, test_msg_noerror };
     40 
     41 char *TCID = "msgrcv07";
     42 int TST_TOTAL = ARRAY_SIZE(testfunc);
     43 
     44 int main(int ac, char **av)
     45 {
     46 	int lc;
     47 	int i;
     48 
     49 	tst_parse_opts(ac, av, NULL, NULL);
     50 
     51 	setup();
     52 
     53 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     54 		tst_count = 0;
     55 
     56 		for (i = 0; i < TST_TOTAL; i++)
     57 			(*testfunc[i])();
     58 	}
     59 
     60 	cleanup();
     61 	tst_exit();
     62 }
     63 
     64 void setup(void)
     65 {
     66 	tst_sig(FORK, DEF_HANDLER, cleanup);
     67 
     68 	TEST_PAUSE;
     69 }
     70 
     71 static void test_msg_except(void)
     72 {
     73 	pid_t child_pid;
     74 	int msgq_id;
     75 	MSGBUF snd_buf1 = {.mtype = MSGTYPE1, .mtext = MSG1};
     76 	MSGBUF snd_buf2 = {.mtype = MSGTYPE2, .mtext = MSG2};
     77 	MSGBUF rcv_buf;
     78 
     79 	msgq_id = msgget(IPC_PRIVATE, MSG_RW);
     80 	if (msgq_id == -1)
     81 		tst_brkm(TBROK | TERRNO, cleanup, "Can't create message queue");
     82 
     83 	if (msgsnd(msgq_id, &snd_buf1, MSGSIZE, 0) == -1)
     84 		tst_brkm(TBROK | TERRNO, cleanup, "Can't enqueue message");
     85 
     86 	if (msgsnd(msgq_id, &snd_buf2, MSGSIZE, 0) == -1)
     87 		tst_brkm(TBROK | TERRNO, cleanup, "Can't enqueue message");
     88 
     89 	child_pid = tst_fork();
     90 	if (child_pid == -1) {
     91 		tst_brkm(TBROK, cleanup, "fork failed");
     92 	} else if (child_pid > 0) {
     93 		wait4child(child_pid, "MSG_EXCEPT");
     94 	} else {
     95 		memset(&rcv_buf, 0, sizeof(rcv_buf));
     96 		TEST(msgrcv(msgq_id, &rcv_buf, MSGSIZE, MSGTYPE2, MSG_EXCEPT));
     97 		if (TEST_RETURN == -1) {
     98 			fprintf(stderr, "msgrcv(MSG_EXCEPT) failed\n");
     99 			exit(TBROK);
    100 		}
    101 		/* check the received message */
    102 		if (strcmp(rcv_buf.mtext, MSG1) == 0 &&
    103 		    rcv_buf.mtype == MSGTYPE1)
    104 			exit(TPASS);
    105 		else
    106 			exit(TFAIL);
    107 	}
    108 
    109 	rm_queue(msgq_id);
    110 }
    111 
    112 
    113 static void test_msg_noerror(void)
    114 {
    115 	pid_t child_pid;
    116 	int msg_len, msgq_id;
    117 	MSGBUF snd_buf1 = {.mtype = MSGTYPE1, .mtext = MSG1};
    118 	MSGBUF rcv_buf;
    119 
    120 	msgq_id = msgget(IPC_PRIVATE, MSG_RW);
    121 	if (msgq_id == -1)
    122 		tst_brkm(TBROK | TERRNO, cleanup, "Can't create message queue");
    123 
    124 	if (msgsnd(msgq_id, &snd_buf1, MSGSIZE, 0) == -1)
    125 		tst_brkm(TBROK | TERRNO, cleanup, "Can't enqueue message");
    126 
    127 	child_pid = tst_fork();
    128 	if (child_pid == -1) {
    129 		tst_brkm(TBROK, cleanup, "fork failed");
    130 	} else if (child_pid > 0) {
    131 		wait4child(child_pid, "MSG_NOERROR");
    132 	} else {
    133 		msg_len = sizeof(MSG1) / 2;
    134 		memset(&rcv_buf, 0, sizeof(rcv_buf));
    135 
    136 		TEST(msgrcv(msgq_id, &rcv_buf, msg_len, MSGTYPE1, MSG_NOERROR));
    137 		if (TEST_RETURN == -1)
    138 			exit(TFAIL);
    139 
    140 		if (strncmp(rcv_buf.mtext, MSG1, msg_len) == 0 &&
    141 		    rcv_buf.mtype == MSGTYPE1)
    142 			exit(TPASS);
    143 		exit(TFAIL);
    144 	}
    145 
    146 	rm_queue(msgq_id);
    147 }
    148 
    149 static void wait4child(pid_t child, char *tst_flag)
    150 {
    151 	int status;
    152 	int ret;
    153 
    154 	if (waitpid(child, &status, 0) == -1)
    155 		tst_resm(TBROK | TERRNO, "waitpid");
    156 	if (WIFEXITED(status)) {
    157 		ret = WEXITSTATUS(status);
    158 		if (ret == 0)
    159 			tst_resm(TPASS, "test %s success", tst_flag);
    160 		else if (ret == 1)
    161 			tst_resm(TFAIL, "test %s failed", tst_flag);
    162 		else
    163 			tst_brkm(TBROK, cleanup, "msgrcv failed unexpectedly");
    164 	} else {
    165 		tst_brkm(TBROK, cleanup, "child process terminated "
    166 			 "abnormally. status: %d", status);
    167 	}
    168 }
    169 
    170 void cleanup(void)
    171 {
    172 }
    173