1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2014-2020 Fujitsu Ltd. 4f08c3bdfSopenharmony_ci * Author: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com> 5f08c3bdfSopenharmony_ci * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com> 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * Basic test for msgrcv(2) using MSG_EXCEPT, MSG_NOERROR, MSG_COPY and 8f08c3bdfSopenharmony_ci * different msg_typ(zero,positive,negative). 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * * With MSG_EXCEPT flag any message type but the one passed to the function 11f08c3bdfSopenharmony_ci * is received. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * * With MSG_NOERROR and buffer size less than message size only part of the 14f08c3bdfSopenharmony_ci * buffer is received. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * * With MSG_COPY and IPC_NOWAIT flag read the msg but don't destroy it in 17f08c3bdfSopenharmony_ci * msg queue. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * * With msgtyp is 0, then the first message in the queue is read. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * * With msgtyp is greater than 0, then the first message in the queue of type 22f08c3bdfSopenharmony_ci * msgtyp is read. 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * * With msgtyp is less than 0, then the first message in the queue with the 25f08c3bdfSopenharmony_ci * lowest type less than or equal to absolute value of msgtyp is received. 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#define _GNU_SOURCE 29f08c3bdfSopenharmony_ci#include <sys/wait.h> 30f08c3bdfSopenharmony_ci#include "tst_test.h" 31f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h" 32f08c3bdfSopenharmony_ci#include "libnewipc.h" 33f08c3bdfSopenharmony_ci#include "lapi/msg.h" 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#define MSGTYPE1 1 36f08c3bdfSopenharmony_ci#define MSGTYPE2 2 37f08c3bdfSopenharmony_ci#define MSG1 "messagetype1" 38f08c3bdfSopenharmony_ci#define MSG2 "messagetype2" 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_cistatic key_t msgkey; 41f08c3bdfSopenharmony_cistatic int queue_id = -1, msg_copy_sup; 42f08c3bdfSopenharmony_cistatic struct buf { 43f08c3bdfSopenharmony_ci long type; 44f08c3bdfSopenharmony_ci char mtext[MSGSIZE]; 45f08c3bdfSopenharmony_ci} rcv_buf, snd_buf[2] = { 46f08c3bdfSopenharmony_ci {MSGTYPE1, MSG1}, 47f08c3bdfSopenharmony_ci {MSGTYPE2, MSG2} 48f08c3bdfSopenharmony_ci}; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic void prepare_queue(void) 51f08c3bdfSopenharmony_ci{ 52f08c3bdfSopenharmony_ci queue_id = SAFE_MSGGET(msgkey, IPC_CREAT | IPC_EXCL | MSG_RW); 53f08c3bdfSopenharmony_ci SAFE_MSGSND(queue_id, &snd_buf[0], MSGSIZE, 0); 54f08c3bdfSopenharmony_ci SAFE_MSGSND(queue_id, &snd_buf[1], MSGSIZE, 0); 55f08c3bdfSopenharmony_ci memset(&rcv_buf, 0, sizeof(rcv_buf)); 56f08c3bdfSopenharmony_ci} 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_cistatic void test_msg_except(void) 59f08c3bdfSopenharmony_ci{ 60f08c3bdfSopenharmony_ci prepare_queue(); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, MSGTYPE2, MSG_EXCEPT)); 63f08c3bdfSopenharmony_ci if (TST_RET == -1) { 64f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(MSG_EXCEPT) failed"); 65f08c3bdfSopenharmony_ci goto exit; 66f08c3bdfSopenharmony_ci } 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(MSG_EXCEPT) succeeded"); 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG1) == 0 && rcv_buf.type == MSGTYPE1) 71f08c3bdfSopenharmony_ci tst_res(TPASS, "MSG_EXCEPT excepted MSGTYPE2 and got MSGTYPE1"); 72f08c3bdfSopenharmony_ci else 73f08c3bdfSopenharmony_ci tst_res(TFAIL, "MSG_EXCEPT didn't get MSGTYPE1 message"); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ciexit: 76f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 77f08c3bdfSopenharmony_ci queue_id = -1; 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic void test_msg_noerror(void) 81f08c3bdfSopenharmony_ci{ 82f08c3bdfSopenharmony_ci int msg_len; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci queue_id = SAFE_MSGGET(msgkey, IPC_CREAT | IPC_EXCL | MSG_RW); 85f08c3bdfSopenharmony_ci SAFE_MSGSND(queue_id, &snd_buf[0], MSGSIZE, 0); 86f08c3bdfSopenharmony_ci msg_len = sizeof(MSG1) / 2; 87f08c3bdfSopenharmony_ci memset(&rcv_buf, 0, sizeof(rcv_buf)); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, msg_len, MSGTYPE1, MSG_NOERROR)); 90f08c3bdfSopenharmony_ci if (TST_RET == -1) { 91f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(MSG_NOERROR) failed"); 92f08c3bdfSopenharmony_ci goto exit; 93f08c3bdfSopenharmony_ci } 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(MSG_NOERROR) succeeded"); 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci if (strncmp(rcv_buf.mtext, MSG1, msg_len) == 0 && rcv_buf.type == MSGTYPE1) 98f08c3bdfSopenharmony_ci tst_res(TPASS, "MSG_NOERROR truncated message correctly"); 99f08c3bdfSopenharmony_ci else 100f08c3bdfSopenharmony_ci tst_res(TFAIL, "MSG_NOERROR truncated message incorrectly"); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ciexit: 103f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 104f08c3bdfSopenharmony_ci queue_id = -1; 105f08c3bdfSopenharmony_ci} 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_cistatic void test_msg_copy(void) 108f08c3bdfSopenharmony_ci{ 109f08c3bdfSopenharmony_ci struct msqid_ds buf = {0}; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci if (!msg_copy_sup) { 112f08c3bdfSopenharmony_ci tst_res(TCONF, "MSG_COPY not supported"); 113f08c3bdfSopenharmony_ci return; 114f08c3bdfSopenharmony_ci } 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci prepare_queue(); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci /* 119f08c3bdfSopenharmony_ci * If MSG_COPY flag was specified, then mtype is interpreted as number 120f08c3bdfSopenharmony_ci * of the message to copy. 121f08c3bdfSopenharmony_ci */ 122f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, 0, MSG_COPY | IPC_NOWAIT)); 123f08c3bdfSopenharmony_ci if (TST_RET == -1) { 124f08c3bdfSopenharmony_ci if (TST_ERR == ENOSYS) { 125f08c3bdfSopenharmony_ci tst_res(TCONF, 126f08c3bdfSopenharmony_ci "MSG_COPY needs CONFIG_CHECKPORINT_RESTORE"); 127f08c3bdfSopenharmony_ci msg_copy_sup = 0; 128f08c3bdfSopenharmony_ci } else { 129f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(0, MSG_COPY) failed"); 130f08c3bdfSopenharmony_ci } 131f08c3bdfSopenharmony_ci goto exit; 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(0, MSG_COPY) succeeded"); 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG1) == 0 && rcv_buf.type == MSGTYPE1) 137f08c3bdfSopenharmony_ci tst_res(TPASS, "MSG_COPY got MSGTYPE1 data correctly"); 138f08c3bdfSopenharmony_ci else 139f08c3bdfSopenharmony_ci tst_res(TFAIL, "MSG_COPY got MSGTYPE1 data incorrectly"); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci memset(&rcv_buf, 0, sizeof(rcv_buf)); 142f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, 1, MSG_COPY | IPC_NOWAIT)); 143f08c3bdfSopenharmony_ci if (TST_RET == -1) { 144f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(1, MSG_COPY) failed"); 145f08c3bdfSopenharmony_ci goto exit; 146f08c3bdfSopenharmony_ci } 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(1, MSG_COPY) succeeded"); 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG2) == 0 && rcv_buf.type == MSGTYPE2) 151f08c3bdfSopenharmony_ci tst_res(TPASS, "MSG_COPY got MSGTYPE2 data correctly"); 152f08c3bdfSopenharmony_ci else 153f08c3bdfSopenharmony_ci tst_res(TFAIL, "MSG_COPY got MSGTYPE2 data incorrectly"); 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_STAT, &buf); 156f08c3bdfSopenharmony_ci if (buf.msg_qnum == 2) { 157f08c3bdfSopenharmony_ci tst_res(TPASS, "Two messages still in queue"); 158f08c3bdfSopenharmony_ci } else { 159f08c3bdfSopenharmony_ci tst_res(TFAIL, "Expected 2 msgs in queue got %d", 160f08c3bdfSopenharmony_ci (int)buf.msg_qnum); 161f08c3bdfSopenharmony_ci } 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ciexit: 164f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 165f08c3bdfSopenharmony_ci queue_id = -1; 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_cistatic void test_zero_msgtyp(void) 169f08c3bdfSopenharmony_ci{ 170f08c3bdfSopenharmony_ci prepare_queue(); 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, 0, 0)); 173f08c3bdfSopenharmony_ci if (TST_RET == -1) { 174f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(zero_msgtyp) failed"); 175f08c3bdfSopenharmony_ci goto exit; 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(zero_msgtyp) succeeded"); 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG1) == 0 && rcv_buf.type == MSGTYPE1) 181f08c3bdfSopenharmony_ci tst_res(TPASS, "zero_msgtyp got the first message"); 182f08c3bdfSopenharmony_ci else 183f08c3bdfSopenharmony_ci tst_res(TFAIL, "zero_msgtyp didn't get the first message"); 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ciexit: 186f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 187f08c3bdfSopenharmony_ci queue_id = -1; 188f08c3bdfSopenharmony_ci} 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_cistatic void test_positive_msgtyp(void) 191f08c3bdfSopenharmony_ci{ 192f08c3bdfSopenharmony_ci prepare_queue(); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, MSGTYPE2, 0)); 195f08c3bdfSopenharmony_ci if (TST_RET == -1) { 196f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(positive_msgtyp) failed"); 197f08c3bdfSopenharmony_ci goto exit; 198f08c3bdfSopenharmony_ci } 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(positive_msgtyp) succeeded"); 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG2) == 0 && rcv_buf.type == MSGTYPE2) { 203f08c3bdfSopenharmony_ci tst_res(TPASS, 204f08c3bdfSopenharmony_ci "msgtyp got the first message in the queue of type msgtyp"); 205f08c3bdfSopenharmony_ci } else { 206f08c3bdfSopenharmony_ci tst_res(TFAIL, 207f08c3bdfSopenharmony_ci "msgtyp didn't get the first message in the queue of type msgtyp"); 208f08c3bdfSopenharmony_ci } 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ciexit: 211f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 212f08c3bdfSopenharmony_ci queue_id = -1; 213f08c3bdfSopenharmony_ci} 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_cistatic void test_negative_msgtyp(void) 216f08c3bdfSopenharmony_ci{ 217f08c3bdfSopenharmony_ci prepare_queue(); 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, -MSGTYPE2, 0)); 220f08c3bdfSopenharmony_ci if (TST_RET == -1) { 221f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgrcv(negative_msgtyp) failed"); 222f08c3bdfSopenharmony_ci goto exit; 223f08c3bdfSopenharmony_ci } 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci tst_res(TPASS, "msgrcv(negative_msgtyp) succeeded"); 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_ci if (strcmp(rcv_buf.mtext, MSG1) == 0 && rcv_buf.type == MSGTYPE1) { 228f08c3bdfSopenharmony_ci tst_res(TPASS, 229f08c3bdfSopenharmony_ci "-msgtyp got the first message in the queue with the lowest type"); 230f08c3bdfSopenharmony_ci } else { 231f08c3bdfSopenharmony_ci tst_res(TFAIL, 232f08c3bdfSopenharmony_ci "-msgtyp didn't get the first message in the queue with the lowest type"); 233f08c3bdfSopenharmony_ci } 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ciexit: 236f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 237f08c3bdfSopenharmony_ci queue_id = -1; 238f08c3bdfSopenharmony_ci} 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_cistatic void cleanup(void) 241f08c3bdfSopenharmony_ci{ 242f08c3bdfSopenharmony_ci if (queue_id != -1) 243f08c3bdfSopenharmony_ci SAFE_MSGCTL(queue_id, IPC_RMID, NULL); 244f08c3bdfSopenharmony_ci} 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_cistatic void setup(void) 247f08c3bdfSopenharmony_ci{ 248f08c3bdfSopenharmony_ci msgkey = GETIPCKEY(); 249f08c3bdfSopenharmony_ci 250f08c3bdfSopenharmony_ci msg_copy_sup = 1; 251f08c3bdfSopenharmony_ci} 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_cistatic void (*testfunc[])(void) = {test_msg_except, test_msg_noerror, 254f08c3bdfSopenharmony_ci test_msg_copy, test_zero_msgtyp, 255f08c3bdfSopenharmony_ci test_positive_msgtyp, test_negative_msgtyp}; 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_cistatic void verify_msgcrv(unsigned int n) 258f08c3bdfSopenharmony_ci{ 259f08c3bdfSopenharmony_ci (*testfunc[n])(); 260f08c3bdfSopenharmony_ci} 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_cistatic struct tst_test test = { 263f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 264f08c3bdfSopenharmony_ci .setup = setup, 265f08c3bdfSopenharmony_ci .cleanup = cleanup, 266f08c3bdfSopenharmony_ci .test = verify_msgcrv, 267f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(testfunc), 268f08c3bdfSopenharmony_ci}; 269