1 /* 2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 #include <sys/mman.h> 14 #include <sys/msg.h> 15 #include <sys/stat.h> 16 #include <sys/time.h> 17 #include <sys/wait.h> 18 19 #include <OS.h> 20 21 #include "TestUnitUtils.h" 22 23 #define KEY ((key_t)12345) 24 25 static status_t 26 remove_msg_queue(int msgID) 27 { 28 return msgctl(msgID, IPC_RMID, 0); 29 } 30 31 struct message { 32 long type; 33 char text[20]; 34 }; 35 36 37 static void 38 test_msgget() 39 { 40 TEST_SET("msgget({IPC_PRIVATE, key})"); 41 42 const char* currentTest = NULL; 43 44 // Open private set with IPC_PRIVATE 45 TEST("msgget(IPC_PRIVATE) - private"); 46 int msgID = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR); 47 assert_posix_bool_success(msgID != -1); 48 49 // Destroy private msg_queue 50 TEST("msgctl(IPC_RMID) - private"); 51 status_t status = remove_msg_queue(msgID); 52 assert_posix_bool_success(status != -1); 53 54 // Open non-private non-existing set with IPC_CREAT 55 TEST("msgget(KEY, IPC_CREAT) non-existing"); 56 msgID = msgget(KEY, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR 57 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 58 assert_posix_bool_success(status != -1); 59 60 // Re-open non-private existing without IPC_CREAT 61 TEST("msgget(KEY) re-open existing without IPC_CREAT"); 62 int returnID = msgget(KEY, 0); 63 assert_equals(msgID, returnID); 64 65 // Re-open non-private existing with IPC_CREAT 66 TEST("msgget(IPC_CREATE) re-open existing with IPC_CREAT"); 67 returnID = msgget(KEY, IPC_CREAT | IPC_EXCL); 68 assert_posix_bool_success(errno == EEXIST); 69 70 // Destroy non-private msg_queue 71 TEST("msgctl(IPC_RMID)"); 72 status = remove_msg_queue(msgID); 73 assert_posix_bool_success(status != -1); 74 75 // Open non-private non-existing without IPC_CREAT 76 TEST("msgget(IPC_CREATE) non-existing without IPC_CREAT"); 77 msgID = msgget(KEY, IPC_EXCL | S_IRUSR | S_IWUSR 78 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 79 assert_posix_bool_success(errno == ENOENT); 80 81 // Destroy non-existing msg_queue 82 TEST("msgctl()"); 83 status = remove_msg_queue(msgID); 84 assert_posix_bool_success(errno == EINVAL); 85 86 TEST("done"); 87 } 88 89 90 static void 91 test_msgctl() 92 { 93 TEST_SET("msgctl({IPC_STAT, IPC_SET, IPC_RMID})"); 94 95 const char* currentTest = NULL; 96 97 // Open non-private non-existing set with IPC_CREAT 98 TEST("msgget(IPC_CREATE) non-existing"); 99 int msgID = msgget(KEY, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR 100 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 101 assert_posix_bool_success(msgID != -1); 102 103 // IPC_SET 104 TEST("msgctl(IPC_SET)"); 105 struct msqid_ds msg_queue; 106 memset(&msg_queue, 0, sizeof(struct msqid_ds)); 107 msg_queue.msg_perm.uid = getuid() + 3; 108 msg_queue.msg_perm.gid = getgid() + 3; 109 msg_queue.msg_perm.mode = 0666; 110 msg_queue.msg_qbytes = 512; 111 status_t status = msgctl(msgID, IPC_SET, &msg_queue); 112 assert_posix_bool_success(status != 1); 113 114 // IPC_STAT set 115 TEST("msgctl(IPC_STAT)"); 116 memset(&msg_queue, 0, sizeof(struct msqid_ds)); 117 status = msgctl(msgID, IPC_STAT, &msg_queue); 118 assert_posix_bool_success(status != 1); 119 TEST("msgctl(IPC_STAT): number of bytes"); 120 assert_equals((msglen_t)msg_queue.msg_qbytes, (msglen_t)512); 121 TEST("msgctl(IPC_STAT): uid"); 122 assert_equals(msg_queue.msg_perm.uid, getuid() + 3); 123 TEST("msgctl(IPC_STAT): gid"); 124 assert_equals(msg_queue.msg_perm.gid, getgid() + 3); 125 126 // Destroy non-private msg_queue 127 TEST("msgctl(IPC_RMID)"); 128 status = remove_msg_queue(msgID); 129 assert_posix_bool_success(status != 1); 130 131 TEST("done"); 132 } 133 134 135 static void 136 test_msgsnd() 137 { 138 TEST_SET("msgsnd({EAGAIN, send})"); 139 140 const char* currentTest = NULL; 141 142 // Open non-private non-existing set with IPC_CREAT 143 TEST("msgget(IPC_CREATE) non-existing"); 144 int msgID = msgget(KEY, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR 145 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 146 assert_posix_bool_success(msgID != -1); 147 148 // Send simple message 149 TEST("msgsnd(simple message)"); 150 struct message msg; 151 msg.type = 0; 152 strcpy(msg.text, "Message to send\n"); 153 status_t status = msgsnd((key_t)msgID, (void *)&msg, 20, 0); 154 assert_posix_bool_success(status != 1); 155 156 // IPC_SET 157 TEST("msgctl(IPC_SET) - set limit to 512"); 158 struct msqid_ds msg_queue; 159 memset(&msg_queue, 0, sizeof(struct msqid_ds)); 160 msg_queue.msg_perm.uid = getuid() + 3; 161 msg_queue.msg_perm.gid = getgid() + 3; 162 msg_queue.msg_perm.mode = 0666; 163 msg_queue.msg_qbytes = 512; 164 status = msgctl(msgID, IPC_SET, &msg_queue); 165 assert_posix_bool_success(status != 1); 166 167 // Send big message IPC_NOWAIT 168 TEST("msgsnd(IPC_NOWAIT)"); 169 msgsnd((key_t)msgID, (void *)&msg, 500, IPC_NOWAIT); 170 assert_posix_bool_success(errno == EAGAIN); 171 172 // Destroy non-private msg_queue 173 TEST("msgctl(IPC_RMID)"); 174 status = remove_msg_queue(msgID); 175 assert_posix_bool_success(status != 1); 176 177 TEST("done"); 178 } 179 180 181 static void 182 test_msgrcv() 183 { 184 TEST_SET("msgrcv({IPC_STAT, IPC_SET, IPC_RMID})"); 185 186 const char* currentTest = NULL; 187 188 // Open non-private non-existing set with IPC_CREAT 189 TEST("msgget(IPC_CREATE) non-existing"); 190 int msgID = msgget(KEY, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR 191 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 192 assert_posix_bool_success(msgID != -1); 193 194 // Receive simple message 195 TEST("msgrcv(IPC_NOWAIT)"); 196 struct message msg; 197 memset(&msg, 0, sizeof(struct message)); 198 msgrcv((key_t)msgID, (void *)&msg, 20, 0, IPC_NOWAIT); 199 assert_posix_bool_success(errno == ENOMSG); 200 201 pid_t child = fork(); 202 if (child == 0) { 203 // Send a simple message 204 TEST("msgsnd(simple message)"); 205 struct message smsg; 206 msg.type = 0; 207 strcpy(msg.text, "Message to send\n"); 208 status_t status = msgsnd((key_t)msgID, (void *)&smsg, 20, 0); 209 assert_posix_bool_success(status != 1); 210 exit(0); 211 } 212 213 wait_for_child(child); 214 TEST("msgrcv(E2BIG)"); 215 msgrcv((key_t)msgID, (void *)&msg, 10, 0, IPC_NOWAIT); 216 assert_posix_bool_success(errno == E2BIG); 217 218 TEST("msgrcv(MSG_NOERROR)"); 219 status_t status 220 = msgrcv((key_t)msgID, (void *)&msg, 10, 0, IPC_NOWAIT | MSG_NOERROR); 221 assert_posix_bool_success(status != -1); 222 223 // Destroy non-private msg_queue 224 TEST("msgctl(IPC_RMID)"); 225 status = remove_msg_queue(msgID); 226 assert_posix_bool_success(status != 1); 227 228 TEST("done"); 229 } 230 231 232 int 233 main() 234 { 235 test_msgget(); 236 test_msgctl(); 237 test_msgsnd(); 238 test_msgrcv(); 239 240 printf("\nAll tests OK\n"); 241 } 242