2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
3 * Distributed under the terms of the MIT License.
22 #include "TestUnitUtils.h"
24 #define KEY ((key_t)12345)
25 #define NUM_OF_SEMS 10
30 unsigned short *array
;
35 remove_semaphore(int semID
)
37 return semctl(semID
, 0, IPC_RMID
, 0);
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
87 status
= remove_semaphore(semID
);
88 assert_posix_bool_success(errno
== EINVAL
);
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
;
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");
131 status_t status
= semop(returnedID
, &ops
, 1);
132 assert_posix_bool_success(status
!= -1);
134 TEST("semop(IPC_NOWAIT) - acquire zero sem #0");
138 status
= semop(returnedID
, &ops
, 1);
140 TEST("semop(IPC_NOWAIT) - revert semop sem #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;
154 array
[i
].sem_flg
= 0;
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);
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);
179 TEST("semctl(SETALL)");
181 args
.array
= (unsigned short *)malloc(sizeof(unsigned short) * NUM_OF_SEMS
);
182 for (int i
= 0; i
< NUM_OF_SEMS
; i
++)
184 status_t status
= semctl(semID
, 0, SETALL
, args
);
185 assert_posix_bool_success(status
!= -1);
188 pid_t child
= fork();
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
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
;
207 array
[i
].sem_op
= 0; // wait for zero
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);
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);
239 TEST("semctl(GETVAL)");
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);
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
++)
251 status
= semctl(semID
, 0, SETALL
, args
);
252 assert_posix_bool_success(status
!= -1);
255 // GETVAL semaphore 4
256 int returnedValue
= semctl(semID
, 4, GETVAL
, 0);
257 assert_equals((unsigned short)returnedValue
, (unsigned short)5);
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);
267 // SETVAL semaphore 2
268 TEST("semctl(SETVAL) - semaphore #2");
270 status
= semctl(semID
, 2, SETVAL
, args
);
271 assert_posix_bool_success(status
!= 1);
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);
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);
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);
324 printf("\nAll tests OK\n");