1 /*
2 * Copyright (c) 2014 Fujitsu Ltd.
3 * Author: Xiaoguang Wang <wangxg.fnst@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
main(int ac,char ** av)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
setup(void)64 void setup(void)
65 {
66 tst_sig(FORK, DEF_HANDLER, cleanup);
67
68 TEST_PAUSE;
69 }
70
test_msg_except(void)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
test_msg_noerror(void)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
wait4child(pid_t child,char * tst_flag)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
cleanup(void)170 void cleanup(void)
171 {
172 }
173