headers/bsd: Add sys/queue.h.
[haiku.git] / src / tests / system / libroot / posix / xsi_sem_test1.cpp
blobc894ae29ee5428f64a471f817b4b82f5743d9db8
1 /*
2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
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/sem.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <sys/wait.h>
18 #include <time.h>
20 #include <OS.h>
22 #include "TestUnitUtils.h"
24 #define KEY ((key_t)12345)
25 #define NUM_OF_SEMS 10
27 union semun {
28 int val;
29 struct semid_ds *buf;
30 unsigned short *array;
34 static status_t
35 remove_semaphore(int semID)
37 return semctl(semID, 0, IPC_RMID, 0);
41 static void
42 test_semget()
44 TEST_SET("semget({IPC_PRIVATE, key})");
46 const char* currentTest = NULL;
48 // Open private set with IPC_PRIVATE
49 TEST("semget(IPC_PRIVATE) - private");
50 int semID = semget(IPC_PRIVATE, NUM_OF_SEMS, S_IRUSR | S_IWUSR);
51 assert_posix_bool_success(semID != -1);
53 // Destroy private semaphore
54 TEST("semctl(IPC_RMID) - private");
55 status_t status = remove_semaphore(semID);
56 assert_posix_bool_success(status != -1);
58 // Open non-private non-existing set with IPC_CREAT
59 TEST("semget(KEY, IPC_CREAT) non-existing");
60 semID = semget(KEY, NUM_OF_SEMS, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR
61 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
62 assert_posix_bool_success(status != -1);
64 // Re-open non-private existing without IPC_CREAT
65 TEST("semget(KEY) re-open existing without IPC_CREAT");
66 int returnID = semget(KEY, 0, 0);
67 assert_equals(semID, returnID);
69 // Re-open non-private existing with IPC_CREAT
70 TEST("semget(IPC_CREATE) re-open existing with IPC_CREAT");
71 returnID = semget(KEY, 0, IPC_CREAT | IPC_EXCL);
72 assert_posix_bool_success(errno == EEXIST);
74 // Destroy non-private semaphore
75 TEST("semctl(IPC_RMID)");
76 status = remove_semaphore(semID);
77 assert_posix_bool_success(status != -1);
79 // Open non-private non-existing without IPC_CREAT
80 TEST("semget(IPC_CREATE) non-existing without IPC_CREAT");
81 semID = semget(KEY, NUM_OF_SEMS, IPC_EXCL | S_IRUSR | S_IWUSR
82 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
83 assert_posix_bool_success(errno == ENOENT);
85 // Destroy non-existing semaphore
86 TEST("semctl()");
87 status = remove_semaphore(semID);
88 assert_posix_bool_success(errno == EINVAL);
90 TEST("done");
94 static void
95 test_semop2()
97 TEST_SET("semop2()");
99 const char* currentTest = NULL;
101 // Re-open non-private existing without IPC_CREAT
102 TEST("semget(KEY) re-open existing without IPC_CREAT");
103 int returnedID = semget(KEY, 0, 0);
104 assert_posix_bool_success(returnedID != -1);
106 TEST("semop(IPC_NOWAIT) - wait for zero");
107 // Set up array of semaphores
108 struct sembuf array[NUM_OF_SEMS];
109 for (int i = 0; i < NUM_OF_SEMS; i++) {
110 array[i].sem_num = i;
111 array[i].sem_op = 0;
112 array[i].sem_flg = IPC_NOWAIT;
114 semop(returnedID, array, NUM_OF_SEMS);
115 assert_posix_bool_success(errno == EAGAIN);
117 TEST("semop(IPC_NOWAIT) - wait to increase");
118 for (int i = 0; i < NUM_OF_SEMS; i++) {
119 array[i].sem_num = i;
120 array[i].sem_op = -9;
121 array[i].sem_flg = IPC_NOWAIT;
123 semop(returnedID, array, NUM_OF_SEMS);
124 assert_posix_bool_success(errno == EAGAIN);
126 TEST("semop(IPC_NOWAIT) - acquire resource sem #0");
127 struct sembuf ops;
128 ops.sem_num = 0;
129 ops.sem_op = -8;
130 ops.sem_flg = 0;
131 status_t status = semop(returnedID, &ops, 1);
132 assert_posix_bool_success(status != -1);
134 TEST("semop(IPC_NOWAIT) - acquire zero sem #0");
135 ops.sem_num = 0;
136 ops.sem_op = 0;
137 ops.sem_flg = 0;
138 status = semop(returnedID, &ops, 1);
140 TEST("semop(IPC_NOWAIT) - revert semop sem #0");
141 ops.sem_num = 0;
142 ops.sem_op = 8;
143 ops.sem_flg = 0;
144 status = semop(returnedID, &ops, 1);
146 // Decrease to zero even semaphores and
147 // use SEM_UNDO flag on odd semaphores in order
148 // to wake up the father on exit
149 // Set up array of semaphores
150 for (int i = 0; i < NUM_OF_SEMS; i++) {
151 array[i].sem_num = i;
152 array[i].sem_op = -8;
153 if (i % 2)
154 array[i].sem_flg = 0;
155 else
156 array[i].sem_flg = SEM_UNDO;
158 TEST("semop() - father");
159 status = semop(returnedID, array, NUM_OF_SEMS);
160 assert_posix_bool_success(status != -1);
162 TEST("done");
166 static void
167 test_semop()
169 TEST_SET("semop()");
170 const char* currentTest = NULL;
172 // Open non-private non-existing set with IPC_CREAT
173 TEST("semget(IPC_CREATE) non-existing");
174 int semID = semget(KEY, NUM_OF_SEMS, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR
175 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
176 assert_posix_bool_success(semID != -1);
178 // SETALL
179 TEST("semctl(SETALL)");
180 union semun args;
181 args.array = (unsigned short *)malloc(sizeof(unsigned short) * NUM_OF_SEMS);
182 for (int i = 0; i < NUM_OF_SEMS; i++)
183 args.array[i] = 8;
184 status_t status = semctl(semID, 0, SETALL, args);
185 assert_posix_bool_success(status != -1);
186 free(args.array);
188 pid_t child = fork();
189 if (child == 0) {
190 // The child first will test the IPC_NOWAIT
191 // feature, while the father waits for him,
192 // by waiting for zero on even semaphores,
193 // and to increase for odd semaphores, which
194 // will happen on process exit due to SEM_UNDO
195 // feature.
196 test_semop2();
197 exit(0);
200 wait_for_child(child);
202 // Set up array of semaphores
203 struct sembuf array[NUM_OF_SEMS];
204 for (int i = 0; i < NUM_OF_SEMS; i++) {
205 array[i].sem_num = i;
206 if (i % 2)
207 array[i].sem_op = 0; // wait for zero
208 else
209 array[i].sem_op = -8; // wait to increase
210 array[i].sem_flg = 0;
212 TEST("semop() - father acquired set");
213 status = semop(semID, array, NUM_OF_SEMS);
214 assert_posix_bool_success(status != -1);
216 // Destroy non-private semaphore
217 TEST("semctl(IPC_RMID)");
218 status = remove_semaphore(semID);
219 assert_posix_bool_success(status != 1);
221 TEST("done");
225 static void
226 test_semctl()
228 TEST_SET("semctl({GETVAL, SETVAL, GETPID, GETNCNT, GETZCNT, GETALL, SETALL, IPC_STAT, IPC_SET, IPC_RMID})");
230 const char* currentTest = NULL;
232 // Open non-private non-existing set with IPC_CREAT
233 TEST("semget(IPC_CREATE) non-existing");
234 int semID = semget(KEY, NUM_OF_SEMS, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR
235 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
236 assert_posix_bool_success(semID != -1);
238 // GETVAL
239 TEST("semctl(GETVAL)");
240 union semun args;
241 status_t status = semctl(semID, NUM_OF_SEMS - 1, GETVAL, args);
242 // Semaphore is not initialized. Value is unknown.
243 // We care about not crashing into KDL.
244 assert_posix_bool_success(status != -1);
246 // SETALL
247 TEST("semctl(SETALL)");
248 args.array = (unsigned short *)malloc(sizeof(unsigned short) * NUM_OF_SEMS);
249 for (int i = 0; i < NUM_OF_SEMS; i++)
250 args.array[i] = 5;
251 status = semctl(semID, 0, SETALL, args);
252 assert_posix_bool_success(status != -1);
253 free(args.array);
255 // GETVAL semaphore 4
256 int returnedValue = semctl(semID, 4, GETVAL, 0);
257 assert_equals((unsigned short)returnedValue, (unsigned short)5);
259 // GETALL
260 TEST("semctl(GETALL)");
261 args.array = (unsigned short *)malloc(sizeof(unsigned short) * NUM_OF_SEMS);
262 semctl(semID, 0, GETALL, args);
263 // Check only last semaphore value
264 assert_equals(args.array[NUM_OF_SEMS - 1], (unsigned short)5);
265 free(args.array);
267 // SETVAL semaphore 2
268 TEST("semctl(SETVAL) - semaphore #2");
269 args.val = 7;
270 status = semctl(semID, 2, SETVAL, args);
271 assert_posix_bool_success(status != 1);
273 // GETALL
274 TEST("semctl(GETALL)");
275 args.array = (unsigned short *)malloc(sizeof(unsigned short) * NUM_OF_SEMS);
276 status = semctl(semID, 0, GETALL, args);
277 assert_posix_bool_success(status != -1);
278 TEST("semctl(GETALL) - semaphore #10");
279 assert_equals(args.array[NUM_OF_SEMS - 1], (unsigned short)5);
280 TEST("semctl(GETALL) - semaphore #2");
281 assert_equals(args.array[NUM_OF_SEMS - 1], (unsigned short)5);
282 free(args.array);
284 // IPC_SET
285 TEST("semctl(IPC_SET)");
286 struct semid_ds semaphore;
287 memset(&semaphore, 0, sizeof(struct semid_ds));
288 semaphore.sem_perm.uid = getuid() + 3;
289 semaphore.sem_perm.gid = getgid() + 3;
290 semaphore.sem_perm.mode = 0666;
291 args.buf = &semaphore;
292 status = semctl(semID, 0, IPC_SET, args);
293 assert_posix_bool_success(status != 1);
295 // IPC_STAT set
296 TEST("semctl(IPC_STAT)");
297 memset(&semaphore, 0, sizeof(struct semid_ds));
298 args.buf = &semaphore;
299 status = semctl(semID, 0, IPC_STAT, args);
300 assert_posix_bool_success(status != 1);
301 TEST("semctl(IPC_STAT): number of sems");
302 assert_equals((unsigned short)args.buf->sem_nsems, (unsigned short)NUM_OF_SEMS);
303 TEST("semctl(IPC_STAT): uid");
304 assert_equals(args.buf->sem_perm.uid, getuid() + 3);
305 TEST("semctl(IPC_STAT): gid");
306 assert_equals(args.buf->sem_perm.gid, getgid() + 3);
308 // Destroy non-private semaphore
309 TEST("semctl(IPC_RMID)");
310 status = remove_semaphore(semID);
311 assert_posix_bool_success(status != 1);
313 TEST("done");
318 main()
320 test_semget();
321 test_semctl();
322 test_semop();
324 printf("\nAll tests OK\n");